Skip to content
Snippets Groups Projects
Commit dffdc4c7 authored by Rafaël Carré's avatar Rafaël Carré
Browse files

Rewrite inhibit.c as an "inhibit" interface

Remove libvlc hack, and fixes missing input state changes
parent 771335af
No related branches found
No related tags found
No related merge requests found
......@@ -246,7 +246,6 @@ int main( int i_argc, const char *ppsz_argv[] )
#endif
#ifdef HAVE_DBUS
libvlc_add_intf (vlc, "dbus,none");
libvlc_add_intf (vlc, "inhibit,none");
#endif
if (libvlc_add_intf (vlc, NULL))
goto out;
......
......@@ -21,13 +21,6 @@ endif
EXTRA_LTLIBRARIES += libgnutls_plugin.la
libvlc_LTLIBRARIES += $(LTLIBgnutls)
libinhibit_plugin_la_SOURCES = inhibit.c
libinhibit_plugin_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
libinhibit_plugin_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS)
if HAVE_DBUS
libvlc_LTLIBRARIES += libinhibit_plugin.la
endif
libosd_parser_plugin_la_SOURCES = \
osd/parser.c osd/osd_menu.c osd/osd_menu.h osd/simple.c osd/xml.c
libosd_parser_plugin_la_CFLAGS = $(AM_CFLAGS)
......@@ -48,6 +41,13 @@ libvlc_LTLIBRARIES += \
libxscreensaver_plugin.la
endif
libpower_plugin_la_SOURCES = inhibit/power.c
libpower_plugin_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
libpower_plugin_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS)
if HAVE_DBUS
libvlc_LTLIBRARIES += libpower_plugin.la
endif
libmce_plugin_la_SOURCES = inhibit/mce.c
libmce_plugin_la_CFLAGS = $(AM_CLFAGS) $(DBUS_CFLAGS) $(MCE_CFLAGS)
libmce_plugin_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) $(MCE_LIBS)
......
/*****************************************************************************
* inhibit.c : prevents the computer from suspending when VLC is playing
*****************************************************************************
* Copyright © 2007 Rafaël Carré
* $Id$
*
* Author: Rafaël Carré <funman@videolanorg>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*
* Based on freedesktop Power Management Specification version 0.2
* http://people.freedesktop.org/~hughsient/temp/power-management-spec-0.2.html
*/
/*****************************************************************************
* Preamble
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_input.h>
#include <vlc_interface.h>
#include <vlc_playlist.h>
#include <dbus/dbus.h>
enum {
FREEDESKTOP = 0, /* as used by KDE and gnome <= 2.26 */
GNOME = 1, /* as used by gnome > 2.26 */
};
static const char *dbus_service[] = {
[FREEDESKTOP] = "org.freedesktop.PowerManagement",
[GNOME] = "org.gnome.SessionManager",
};
static const char *dbus_path[] = {
[FREEDESKTOP] = "/org/freedesktop/PowerManagement",
[GNOME] = "/org/gnome/SessionManager",
};
static const char *dbus_interface[] = {
[FREEDESKTOP] = "org.freedesktop.PowerManagement.Inhibit",
[GNOME] = "org.gnome.SessionManager",
};
static const char *dbus_uninhibit_method[] = {
[FREEDESKTOP] = "UnInhibit",
[GNOME] = "Uninhibit",
};
/*****************************************************************************
* Local prototypes
!*****************************************************************************/
static int Activate ( vlc_object_t * );
static void Deactivate ( vlc_object_t * );
static void UnInhibit( intf_thread_t *p_intf, int type );
static int InputChange( vlc_object_t *, const char *,
vlc_value_t, vlc_value_t, void * );
static int StateChange( vlc_object_t *, const char *,
vlc_value_t, vlc_value_t, void * );
struct intf_sys_t
{
playlist_t *p_playlist;
vlc_object_t *p_input;
DBusConnection *p_conn;
dbus_uint32_t i_cookie[2];
};
/*****************************************************************************
* Module descriptor
*****************************************************************************/
vlc_module_begin ()
set_description( N_("Power Management Inhibitor") )
set_capability( "interface", 0 )
set_callbacks( Activate, Deactivate )
vlc_module_end ()
/*****************************************************************************
* Activate: initialize and create stuff
*****************************************************************************/
static int Activate( vlc_object_t *p_this )
{
intf_thread_t *p_intf = (intf_thread_t*)p_this;
intf_sys_t *p_sys;
DBusError error;
p_sys = p_intf->p_sys = (intf_sys_t *) calloc( 1, sizeof( intf_sys_t ) );
if( !p_sys )
return VLC_ENOMEM;
p_sys->i_cookie[FREEDESKTOP] = 0;
p_sys->i_cookie[GNOME] = 0;
p_sys->p_input = NULL;
dbus_error_init( &error );
/* connect privately to the session bus
* the connection will not be shared with other vlc modules which use dbus,
* thus avoiding a whole class of concurrency issues */
p_sys->p_conn = dbus_bus_get_private( DBUS_BUS_SESSION, &error );
if( !p_sys->p_conn )
{
msg_Err( p_this, "Failed to connect to the D-Bus session daemon: %s",
error.message );
dbus_error_free( &error );
free( p_sys );
return VLC_EGENERIC;
}
p_sys->p_playlist = pl_Get( p_intf );
var_AddCallback( p_sys->p_playlist, "activity", InputChange, p_intf );
return VLC_SUCCESS;
}
/*****************************************************************************
* Deactivate: uninitialize and cleanup
*****************************************************************************/
static void Deactivate( vlc_object_t *p_this )
{
intf_thread_t *p_intf = (intf_thread_t*)p_this;
intf_sys_t *p_sys = p_intf->p_sys;
var_DelCallback( p_sys->p_playlist, "activity", InputChange, p_intf );
if( p_sys->p_input ) /* Do delete "state" after "item-changed"! */
{
var_DelCallback( p_sys->p_input, "state", StateChange, p_intf );
vlc_object_release( p_sys->p_input );
}
if( p_sys->i_cookie[FREEDESKTOP] )
UnInhibit( p_intf, FREEDESKTOP );
if( p_sys->i_cookie[GNOME] )
UnInhibit( p_intf, GNOME );
/* The dbus connection is private,
* so we are responsible for closing it */
dbus_connection_close( p_sys->p_conn );
dbus_connection_unref( p_sys->p_conn );
free( p_sys );
}
/*****************************************************************************
* Inhibit: Notify the power management daemon that it shouldn't suspend
* the computer because of inactivity
*****************************************************************************/
static void Inhibit( intf_thread_t *p_intf, int type )
{
intf_sys_t *p_sys = p_intf->p_sys;
DBusMessage *msg = dbus_message_new_method_call(
dbus_service[type], dbus_path[type], dbus_interface[type], "Inhibit" );
if( unlikely(msg == NULL) )
return;
const char *app = PACKAGE;
const char *reason = _("Playing some media.");
p_sys->i_cookie[type] = 0;
dbus_bool_t ret;
dbus_uint32_t xid = 0; // FIXME?
dbus_uint32_t flags = 8 /* Inhibit suspending the session or computer */
| 4;/* Inhibit the session being marked as idle */
switch( type ) {
case FREEDESKTOP:
ret = dbus_message_append_args( msg, DBUS_TYPE_STRING, &app,
DBUS_TYPE_STRING, &reason,
DBUS_TYPE_INVALID );
break;
case GNOME:
default:
ret = dbus_message_append_args( msg, DBUS_TYPE_STRING, &app,
DBUS_TYPE_UINT32, &xid,
DBUS_TYPE_STRING, &reason,
DBUS_TYPE_UINT32, &flags,
DBUS_TYPE_INVALID );
break;
}
if( !ret )
{
dbus_message_unref( msg );
return;
}
/* blocks 50ms maximum */
DBusMessage *reply;
reply = dbus_connection_send_with_reply_and_block( p_sys->p_conn, msg,
50, NULL );
dbus_message_unref( msg );
if( reply == NULL )
/* g-p-m is not active, or too slow. Better luck next time? */
return;
/* extract the cookie from the reply */
dbus_uint32_t i_cookie;
if( dbus_message_get_args( reply, NULL,
DBUS_TYPE_UINT32, &i_cookie,
DBUS_TYPE_INVALID ) )
p_sys->i_cookie[type] = i_cookie;
dbus_message_unref( reply );
}
/*****************************************************************************
* UnInhibit: Notify the power management daemon that we aren't active anymore
*****************************************************************************/
static void UnInhibit( intf_thread_t *p_intf, int type )
{
intf_sys_t *p_sys = p_intf->p_sys;
DBusMessage *msg = dbus_message_new_method_call( dbus_service[type],
dbus_path[type], dbus_interface[type], dbus_uninhibit_method[type] );
if( unlikely(msg == NULL) )
return;
dbus_uint32_t i_cookie = p_sys->i_cookie[type];
if( dbus_message_append_args( msg, DBUS_TYPE_UINT32, &i_cookie,
DBUS_TYPE_INVALID )
&& dbus_connection_send( p_sys->p_conn, msg, NULL ) )
{
dbus_connection_flush( p_sys->p_conn );
p_sys->i_cookie[type] = 0;
}
dbus_message_unref( msg );
}
static int StateChange( vlc_object_t *p_input, const char *var,
vlc_value_t prev, vlc_value_t value, void *data )
{
intf_thread_t *p_intf = data;
intf_sys_t *p_sys = p_intf->p_sys;
const int old = prev.i_int, cur = value.i_int;
if( ( old == PLAYING_S ) == ( cur == PLAYING_S ) )
return VLC_SUCCESS; /* No interesting change */
if( cur == PLAYING_S ) {
if (p_sys->i_cookie[FREEDESKTOP] == 0)
Inhibit( p_intf, FREEDESKTOP );
if (p_sys->i_cookie[GNOME] == 0)
Inhibit( p_intf, GNOME );
}
else {
if (p_sys->i_cookie[FREEDESKTOP] != 0)
UnInhibit( p_intf, FREEDESKTOP );
if (p_sys->i_cookie[GNOME] != 0)
UnInhibit( p_intf, GNOME );
}
(void)p_input; (void)var; (void)prev;
return VLC_SUCCESS;
}
static int InputChange( vlc_object_t *p_playlist, const char *var,
vlc_value_t prev, vlc_value_t value, void *data )
{
intf_thread_t *p_intf = data;
intf_sys_t *p_sys = p_intf->p_sys;
if( p_sys->p_input )
{
var_DelCallback( p_sys->p_input, "state", StateChange, p_intf );
vlc_object_release( p_sys->p_input );
}
p_sys->p_input = VLC_OBJECT(playlist_CurrentInput( p_sys->p_playlist ));
if( p_sys->p_input )
{
Inhibit( p_intf, FREEDESKTOP );
Inhibit( p_intf, GNOME );
var_AddCallback( p_sys->p_input, "state", StateChange, p_intf );
}
(void)var; (void)prev; (void)value; (void)p_playlist;
return VLC_SUCCESS;
}
/*****************************************************************************
* power.c : prevents the computer from suspending when VLC is playing
*****************************************************************************
* Copyright © 2009-2011 Rémi Denis-Courmont
* Copyright © 2007-2012 Rafaël Carré
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*
* Based on freedesktop Power Management Specification version 0.2
* http://people.freedesktop.org/~hughsient/temp/power-management-spec-0.2.html
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_inhibit.h>
#include <dbus/dbus.h>
struct vlc_inhibit_sys
{
DBusConnection *conn;
dbus_uint32_t cookie[2];
};
static void Inhibit (vlc_inhibit_t *ih, unsigned flags)
{
enum {
FREEDESKTOP = 0, /* as used by KDE and gnome <= 2.26 */
GNOME = 1, /* as used by gnome > 2.26 */
};
static const char dbus_service[2][32] = {
[FREEDESKTOP] = "org.freedesktop.PowerManagement",
[GNOME] = "org.gnome.SessionManager",
};
static const char dbus_path[2][33] = {
[FREEDESKTOP] = "/org/freedesktop/PowerManagement",
[GNOME] = "/org/gnome/SessionManager",
};
static const char dbus_interface[2][40] = {
[FREEDESKTOP] = "org.freedesktop.PowerManagement.Inhibit",
[GNOME] = "org.gnome.SessionManager",
};
static const char dbus_method[2][2][10] = {
{
[FREEDESKTOP] = "UnInhibit",
[GNOME] = "Uninhibit",
},
{
[FREEDESKTOP] = "Inhibit",
[GNOME] = "Inhibit",
},
};
static const char *app = PACKAGE;
static const char *reason = N_("Playing some media.");
vlc_inhibit_sys_t *sys = ih->p_sys;
DBusConnection *conn = sys->conn;
const bool suspend = !!flags;
const dbus_uint32_t xid = 0; // FIXME ?
const dbus_uint32_t gnome_flags = ((flags & VLC_INHIBIT_SUSPEND) ? 8 : 0)
| ((flags & VLC_INHIBIT_DISPLAY) ? 4 : 0);
for (int type = 0; type < 2; type++) {
dbus_bool_t ret;
DBusMessage *msg = dbus_message_new_method_call(dbus_service[type],
dbus_path[type], dbus_interface[type], dbus_method[suspend][type]);
if (unlikely(msg == NULL))
return;
if (suspend) {
if (type == FREEDESKTOP)
ret = dbus_message_append_args (msg, DBUS_TYPE_STRING, &app,
DBUS_TYPE_STRING, &reason,
DBUS_TYPE_INVALID);
else if (type == GNOME)
ret = dbus_message_append_args (msg, DBUS_TYPE_STRING, &app,
DBUS_TYPE_UINT32, &xid,
DBUS_TYPE_STRING, &reason,
DBUS_TYPE_UINT32, &gnome_flags,
DBUS_TYPE_INVALID);
} else {
ret = false;
if (sys->cookie[type])
ret = dbus_message_append_args (msg, DBUS_TYPE_UINT32,
&sys->cookie[type], DBUS_TYPE_INVALID);
}
if (!ret)
goto end;
if (suspend) { /* read reply */
/* blocks 50ms maximum */
DBusMessage *reply = dbus_connection_send_with_reply_and_block(
conn, msg, 50, NULL );
if (unlikely(reply == NULL))
goto end; /* gpm is not active, or too slow. Better luck next time? */
if (!dbus_message_get_args(reply, NULL,
DBUS_TYPE_UINT32, &sys->cookie[type],
DBUS_TYPE_INVALID))
sys->cookie[type] = 0;
dbus_message_unref( reply );
} else { /* just send and flush */
if (dbus_connection_send (conn, msg, NULL)) {
sys->cookie[type] = 0;
dbus_connection_flush (conn);
}
}
end:
dbus_message_unref (msg);
}
}
static int Open (vlc_object_t *obj)
{
vlc_inhibit_t *ih = (vlc_inhibit_t *)obj;
vlc_inhibit_sys_t *sys = malloc (sizeof (*sys));
if (unlikely(sys == NULL))
return VLC_ENOMEM;
DBusError err;
dbus_error_init (&err);
sys->conn = dbus_bus_get_private (DBUS_BUS_SESSION, &err);
if (sys->conn == NULL)
{
msg_Err (obj, "cannot connect to session bus: %s", err.message);
dbus_error_free (&err);
free (sys);
return VLC_EGENERIC;
}
sys->cookie[0] = 0;
sys->cookie[1] = 0;
ih->p_sys = sys;
ih->inhibit = Inhibit;
return VLC_SUCCESS;
}
static void Close (vlc_object_t *obj)
{
vlc_inhibit_t *ih = (vlc_inhibit_t *)obj;
vlc_inhibit_sys_t *sys = ih->p_sys;
dbus_connection_close (sys->conn);
dbus_connection_unref (sys->conn);
free (sys);
}
/*
* Module descriptor
*/
vlc_module_begin ()
set_shortname (N_("Power"))
set_description (N_("Inhibits power suspend and session idle timeout."))
set_category (CAT_ADVANCED)
set_subcategory (SUBCAT_ADVANCED_MISC)
set_capability ("inhibit", 20)
set_callbacks (Open, Close)
vlc_module_end ()
......@@ -945,8 +945,8 @@ modules/meta_engine/taglib.cpp
modules/misc/audioscrobbler.c
modules/misc/dhparams.h
modules/misc/gnutls.c
modules/misc/inhibit.c
modules/misc/inhibit/mce.c
modules/misc/inhibit/power.c
modules/misc/inhibit/xdg.c
modules/misc/inhibit/xscreensaver.c
modules/misc/logger.c
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment