inhibit.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:8k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * inhibit.c : prevents the computer from suspending when VLC is playing
  3.  *****************************************************************************
  4.  * Copyright © 2007 Rafaël Carré
  5.  * $Id: 5e880bdd9452b87f9b3f3f346822f5fe77f2998d $
  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.  * Based on freedesktop Power Management Specification version 0.2
  25.  * http://people.freedesktop.org/~hughsient/temp/power-management-spec-0.2.html
  26.  */
  27. /*****************************************************************************
  28.  * Preamble
  29.  *****************************************************************************/
  30. #ifdef HAVE_CONFIG_H
  31. # include "config.h"
  32. #endif
  33. #include <vlc_common.h>
  34. #include <vlc_plugin.h>
  35. #include <vlc_input.h>
  36. #include <vlc_interface.h>
  37. #include <vlc_playlist.h>
  38. #include <dbus/dbus.h>
  39. #define PM_SERVICE   "org.freedesktop.PowerManagement"
  40. #define PM_PATH      "/org/freedesktop/PowerManagement/Inhibit"
  41. #define PM_INTERFACE "org.freedesktop.PowerManagement.Inhibit"
  42. /*****************************************************************************
  43.  * Local prototypes
  44.  *****************************************************************************/
  45. static int  Activate     ( vlc_object_t * );
  46. static void Deactivate   ( vlc_object_t * );
  47. static void Run          ( intf_thread_t *p_intf );
  48. static int Inhibit( intf_thread_t *p_intf );
  49. static int UnInhibit( intf_thread_t *p_intf );
  50. struct intf_sys_t
  51. {
  52.     DBusConnection  *p_conn;
  53.     dbus_uint32_t   i_cookie;
  54. };
  55. /*****************************************************************************
  56.  * Module descriptor
  57.  *****************************************************************************/
  58. vlc_module_begin ()
  59.     set_description( N_("Power Management Inhibitor") )
  60.     set_capability( "interface", 0 )
  61.     set_callbacks( Activate, Deactivate )
  62. vlc_module_end ()
  63. /*****************************************************************************
  64.  * Activate: initialize and create stuff
  65.  *****************************************************************************/
  66. static int Activate( vlc_object_t *p_this )
  67. {
  68.     intf_thread_t *p_intf = (intf_thread_t*)p_this;
  69.     DBusError     error;
  70.     p_intf->pf_run = Run;
  71.     p_intf->p_sys = (intf_sys_t *) calloc( 1, sizeof( intf_sys_t ) );
  72.     if( !p_intf->p_sys )
  73.         return VLC_ENOMEM;
  74.     p_intf->p_sys->i_cookie = 0;
  75.     dbus_error_init( &error );
  76.     p_intf->p_sys->p_conn = dbus_bus_get( DBUS_BUS_SESSION, &error );
  77.     if( !p_intf->p_sys->p_conn )
  78.     {
  79.         msg_Err( p_this, "Failed to connect to the D-Bus session daemon: %s",
  80.                 error.message );
  81.         dbus_error_free( &error );
  82.         free( p_intf->p_sys );
  83.         return VLC_EGENERIC;
  84.     }
  85.     return VLC_SUCCESS;
  86. }
  87. /*****************************************************************************
  88.  * Deactivate: uninitialize and cleanup
  89.  *****************************************************************************/
  90. static void Deactivate( vlc_object_t *p_this )
  91. {
  92.     intf_thread_t *p_intf = (intf_thread_t*)p_this;
  93.     if( p_intf->p_sys->i_cookie )
  94.         UnInhibit( p_intf );
  95.     dbus_connection_unref( p_intf->p_sys->p_conn );
  96.     free( p_intf->p_sys );
  97. }
  98. /*****************************************************************************
  99.  * Inhibit: Notify the power management daemon that it shouldn't suspend
  100.  * the computer because of inactivity
  101.  *
  102.  * returns false if Out of memory, else true
  103.  *****************************************************************************/
  104. static int Inhibit( intf_thread_t *p_intf )
  105. {
  106.     DBusConnection *p_conn;
  107.     DBusMessage *p_msg;
  108.     DBusMessageIter args;
  109.     DBusMessage *p_reply;
  110.     dbus_uint32_t i_cookie;
  111.     p_conn = p_intf->p_sys->p_conn;
  112.     p_msg = dbus_message_new_method_call( PM_SERVICE, PM_PATH, PM_INTERFACE,
  113.                                           "Inhibit" );
  114.     if( !p_msg )
  115.         return false;
  116.     dbus_message_iter_init_append( p_msg, &args );
  117.     char *psz_app = strdup( PACKAGE );
  118.     if( !psz_app ||
  119.         !dbus_message_iter_append_basic( &args, DBUS_TYPE_STRING, &psz_app ) )
  120.     {
  121.         free( psz_app );
  122.         dbus_message_unref( p_msg );
  123.         return false;
  124.     }
  125.     free( psz_app );
  126.     char *psz_inhibit_reason = strdup( _("Playing some media.") );
  127.     if( !psz_inhibit_reason )
  128.     {
  129.         dbus_message_unref( p_msg );
  130.         return false;
  131.     }
  132.     if( !dbus_message_iter_append_basic( &args, DBUS_TYPE_STRING,
  133.                                          &psz_inhibit_reason ) )
  134.     {
  135.         free( psz_inhibit_reason );
  136.         dbus_message_unref( p_msg );
  137.         return false;
  138.     }
  139.     free( psz_inhibit_reason );
  140.     p_reply = dbus_connection_send_with_reply_and_block( p_conn, p_msg,
  141.         50, NULL ); /* blocks 50ms maximum */
  142.     dbus_message_unref( p_msg );
  143.     if( p_reply == NULL )
  144.     {   /* g-p-m is not active, or too slow. Better luck next time? */
  145.         return true;
  146.     }
  147.     /* extract the cookie from the reply */
  148.     if( dbus_message_get_args( p_reply, NULL,
  149.             DBUS_TYPE_UINT32, &i_cookie,
  150.             DBUS_TYPE_INVALID ) == FALSE )
  151.     {
  152.         return false;
  153.     }
  154.     /* Save the cookie */
  155.     p_intf->p_sys->i_cookie = i_cookie;
  156.     return true;
  157. }
  158. /*****************************************************************************
  159.  * UnInhibit: Notify the power management daemon that we aren't active anymore
  160.  *
  161.  * returns false if Out of memory, else true
  162.  *****************************************************************************/
  163. static int UnInhibit( intf_thread_t *p_intf )
  164. {
  165.     DBusConnection *p_conn;
  166.     DBusMessage *p_msg;
  167.     DBusMessageIter args;
  168.     dbus_uint32_t i_cookie;
  169.     p_conn = p_intf->p_sys->p_conn;
  170.     p_msg = dbus_message_new_method_call( PM_SERVICE, PM_PATH, PM_INTERFACE,
  171.                                           "UnInhibit" );
  172.     if( !p_msg )
  173.         return false;
  174.     dbus_message_iter_init_append( p_msg, &args );
  175.     i_cookie = p_intf->p_sys->i_cookie;
  176.     if( !dbus_message_iter_append_basic( &args, DBUS_TYPE_UINT32, &i_cookie ) )
  177.     {
  178.         dbus_message_unref( p_msg );
  179.         return false;
  180.     }
  181.     if( !dbus_connection_send( p_conn, p_msg, NULL ) )
  182.         return false;
  183.     dbus_connection_flush( p_conn );
  184.     dbus_message_unref( p_msg );
  185.     p_intf->p_sys->i_cookie = 0;
  186.     return true;
  187. }
  188. /*****************************************************************************
  189.  * Run: main thread
  190.  *****************************************************************************/
  191. static void vlc_cleanup_playlist( void *p_playlist )
  192. {
  193.     pl_Release( (playlist_t*)p_playlist );
  194. }
  195. static void Run( intf_thread_t *p_intf )
  196. {
  197.     int canc = vlc_savecancel();
  198.     playlist_t *p_playlist = pl_Hold( p_intf );
  199.     vlc_cleanup_push( vlc_cleanup_playlist, p_intf );
  200.     for( ;; )
  201.     {
  202.         vlc_restorecancel( canc );
  203.         /* FIXME wake up on playlist event instead ?
  204.          * Check playing state every 30 seconds */
  205.         msleep( 30 * CLOCK_FREQ );
  206.         canc = vlc_savecancel();
  207.         /* */
  208.         input_thread_t *p_input = playlist_CurrentInput( p_playlist );
  209.         if( p_input )
  210.         {
  211.             const int i_state = var_GetInteger( p_input, "state" );
  212.             vlc_object_release( p_input );
  213.             if( PLAYING_S == i_state )
  214.             {
  215.                if( !p_intf->p_sys->i_cookie )
  216.                {
  217.                    if( !Inhibit( p_intf ) )
  218.                        break;
  219.                }
  220.             }
  221.             else if( p_intf->p_sys->i_cookie )
  222.             {
  223.                 if( !UnInhibit( p_intf ) )
  224.                     break;
  225.             }
  226.         }
  227.         else if( p_intf->p_sys->i_cookie )
  228.         {
  229.             if( !UnInhibit( p_intf ) )
  230.                 break;
  231.         }
  232.     }
  233.     /* */
  234.     vlc_cleanup_run();
  235.     vlc_restorecancel( canc );
  236. }