]> git.sesse.net Git - vlc/blob - modules/misc/inhibit.c
Remove most stray semi-colons in module descriptions
[vlc] / modules / misc / inhibit.c
1 /*****************************************************************************
2  * inhibit.c : prevents the computer from suspending when VLC is playing
3  *****************************************************************************
4  * Copyright © 2007 Rafaël Carré
5  * $Id$
6  *
7  * Author: Rafaël Carré <funman@videolanorg>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*
25  * Based on freedesktop Power Management Specification version 0.2
26  * http://people.freedesktop.org/~hughsient/temp/power-management-spec-0.2.html
27  */
28
29 /*****************************************************************************
30  * Preamble
31  *****************************************************************************/
32
33 #ifdef HAVE_CONFIG_H
34 # include "config.h"
35 #endif
36
37 #include <vlc_common.h>
38 #include <vlc_plugin.h>
39 #include <vlc_input.h>
40 #include <vlc_interface.h>
41
42 #include <dbus/dbus.h>
43
44 #define PM_SERVICE   "org.freedesktop.PowerManagement"
45 #define PM_PATH      "/org/freedesktop/PowerManagement/Inhibit"
46 #define PM_INTERFACE "org.freedesktop.PowerManagement.Inhibit"
47
48 /*****************************************************************************
49  * Local prototypes
50  *****************************************************************************/
51 static int  Activate     ( vlc_object_t * );
52 static void Deactivate   ( vlc_object_t * );
53
54 static void Run          ( intf_thread_t *p_intf );
55
56 struct intf_sys_t
57 {
58     DBusConnection  *p_conn;
59     dbus_uint32_t   i_cookie;
60 };
61
62 /*****************************************************************************
63  * Module descriptor
64  *****************************************************************************/
65 vlc_module_begin ()
66     set_description( N_("Power Management Inhibitor") )
67     set_capability( "interface", 0 )
68     set_callbacks( Activate, Deactivate )
69 vlc_module_end ()
70
71 /*****************************************************************************
72  * Activate: initialize and create stuff
73  *****************************************************************************/
74 static int Activate( vlc_object_t *p_this )
75 {
76     intf_thread_t *p_intf = (intf_thread_t*)p_this;
77     DBusError     error;
78
79     p_intf->pf_run = Run;
80     p_intf->p_sys = (intf_sys_t *) calloc( 1, sizeof( intf_sys_t ) );
81     if( !p_intf->p_sys )
82         return VLC_ENOMEM;
83
84     p_intf->p_sys->i_cookie = 0;
85
86     dbus_error_init( &error );
87     p_intf->p_sys->p_conn = dbus_bus_get( DBUS_BUS_SESSION, &error );
88     if( !p_intf->p_sys->p_conn )
89     {
90         msg_Err( p_this, "Failed to connect to the D-Bus session daemon: %s",
91                 error.message );
92         dbus_error_free( &error );
93         free( p_intf->p_sys );
94         return VLC_EGENERIC;
95     }
96
97     return VLC_SUCCESS;
98 }
99
100 /*****************************************************************************
101  * Deactivate: uninitialize and cleanup
102  *****************************************************************************/
103 static void Deactivate( vlc_object_t *p_this )
104 {
105     intf_thread_t *p_intf = (intf_thread_t*)p_this;
106     dbus_connection_unref( p_intf->p_sys->p_conn );
107     free( p_intf->p_sys );
108 }
109
110 /*****************************************************************************
111  * Inhibit: Notify the power management daemon that it shouldn't suspend
112  * the computer because of inactivity
113  *
114  * returns false if Out of memory, else true
115  *****************************************************************************/
116 static int Inhibit( intf_thread_t *p_intf )
117 {
118     DBusConnection *p_conn;
119     DBusMessage *p_msg;
120     DBusMessageIter args;
121     DBusMessage *p_reply;
122     dbus_uint32_t i_cookie;
123
124     p_conn = p_intf->p_sys->p_conn;
125
126     p_msg = dbus_message_new_method_call( PM_SERVICE, PM_PATH, PM_INTERFACE,
127                                           "Inhibit" );
128     if( !p_msg )
129         return false;
130
131     dbus_message_iter_init_append( p_msg, &args );
132
133     char *psz_app = strdup( PACKAGE );
134     if( !psz_app ||
135         !dbus_message_iter_append_basic( &args, DBUS_TYPE_STRING, &psz_app ) )
136     {
137         free( psz_app );
138         dbus_message_unref( p_msg );
139         return false;
140     }
141     free( psz_app );
142
143     char *psz_inhibit_reason = strdup( "Playing some media." );
144     if( !psz_inhibit_reason )
145     {
146         dbus_message_unref( p_msg );
147         return false;
148     }
149     if( !dbus_message_iter_append_basic( &args, DBUS_TYPE_STRING,
150                                          &psz_inhibit_reason ) )
151     {
152         free( psz_inhibit_reason );
153         dbus_message_unref( p_msg );
154         return false;
155     }
156     free( psz_inhibit_reason );
157
158     p_reply = dbus_connection_send_with_reply_and_block( p_conn, p_msg,
159         50, NULL ); /* blocks 50ms maximum */
160     dbus_message_unref( p_msg );
161     if( p_reply == NULL )
162     {   /* g-p-m is not active, or too slow. Better luck next time? */
163         return true;
164     }
165
166     /* extract the cookie from the reply */
167     if( dbus_message_get_args( p_reply, NULL,
168             DBUS_TYPE_UINT32, &i_cookie,
169             DBUS_TYPE_INVALID ) == FALSE )
170     {
171         return false;
172     }
173
174     /* Save the cookie */
175     p_intf->p_sys->i_cookie = i_cookie;
176     return true;
177 }
178
179 /*****************************************************************************
180  * UnInhibit: Notify the power management daemon that we aren't active anymore
181  *
182  * returns false if Out of memory, else true
183  *****************************************************************************/
184 static int UnInhibit( intf_thread_t *p_intf )
185 {
186     DBusConnection *p_conn;
187     DBusMessage *p_msg;
188     DBusMessageIter args;
189     dbus_uint32_t i_cookie;
190
191     p_conn = p_intf->p_sys->p_conn;
192
193     p_msg = dbus_message_new_method_call( PM_SERVICE, PM_PATH, PM_INTERFACE,
194                                           "UnInhibit" );
195     if( !p_msg )
196         return false;
197
198     dbus_message_iter_init_append( p_msg, &args );
199
200     i_cookie = p_intf->p_sys->i_cookie;
201     if( !dbus_message_iter_append_basic( &args, DBUS_TYPE_UINT32, &i_cookie ) )
202     {
203         dbus_message_unref( p_msg );
204         return false;
205     }
206
207     if( !dbus_connection_send( p_conn, p_msg, NULL ) )
208         return false;
209     dbus_connection_flush( p_conn );
210
211     dbus_message_unref( p_msg );
212
213     p_intf->p_sys->i_cookie = 0;
214     return true;
215 }
216
217 /*****************************************************************************
218  * Run: main thread
219  *****************************************************************************/
220 static void Run( intf_thread_t *p_intf )
221 {
222     for( ;; )
223     {
224         input_thread_t *p_input;
225
226         /* Check playing state every 30 seconds */
227         msleep( 30 * CLOCK_FREQ );
228
229         p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE );
230         if( p_input )
231         {
232             int i_state = p_input->i_state;
233             vlc_object_release( p_input );
234
235             if( PLAYING_S == i_state && !p_intf->p_sys->i_cookie )
236             {
237                 if( !Inhibit( p_intf ) )
238                     break;
239             }
240             else if( p_intf->p_sys->i_cookie )
241             {
242                 if( !UnInhibit( p_intf ) )
243                     break;
244             }
245         }
246         else if( p_intf->p_sys->i_cookie )
247         {
248             if( !UnInhibit( p_intf ) )
249                 break;
250         }
251     }
252 }