diff options
Diffstat (limited to 'trunk/src/totem-remote.c')
-rw-r--r-- | trunk/src/totem-remote.c | 364 |
1 files changed, 364 insertions, 0 deletions
diff --git a/trunk/src/totem-remote.c b/trunk/src/totem-remote.c new file mode 100644 index 000000000..074b1a837 --- /dev/null +++ b/trunk/src/totem-remote.c @@ -0,0 +1,364 @@ +/* + * Copyright (C) 2002 James Willcox <jwillcox@gnome.org> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * The Totem project hereby grant permission for non-gpl compatible GStreamer + * plugins to be used and distributed together with GStreamer and Totem. This + * permission are above and beyond the permissions granted by the GPL license + * Totem is covered by. + * + * Monday 7th February 2005: Christian Schaller: Add excemption clause. + * See license_change file for details. + * + */ + + +#include <config.h> +#include <glib.h> +#include <string.h> + +#include "totem-remote.h" + +#ifdef HAVE_REMOTE + +/* Media player keys support */ +#ifdef HAVE_MEDIA_PLAYER_KEYS +#include <gnome-settings-daemon/gnome-settings-client.h> +#include "totem-marshal.h" +#endif /*HAVE_MEDIA_PLAYER_KEYS */ + +#ifdef HAVE_LIRC +#include <stdio.h> +#include <lirc/lirc_client.h> +#include <gconf/gconf-client.h> + +/* strings that we recognize as commands from lirc */ +#define TOTEM_IR_COMMAND_PLAY "play" +#define TOTEM_IR_COMMAND_PAUSE "pause" +#define TOTEM_IR_COMMAND_NEXT "next" +#define TOTEM_IR_COMMAND_PREVIOUS "previous" +#define TOTEM_IR_COMMAND_SEEK_FORWARD "seek_forward" +#define TOTEM_IR_COMMAND_SEEK_BACKWARD "seek_backward" +#define TOTEM_IR_COMMAND_VOLUME_UP "volume_up" +#define TOTEM_IR_COMMAND_VOLUME_DOWN "volume_down" +#define TOTEM_IR_COMMAND_FULLSCREEN "fullscreen" +#define TOTEM_IR_COMMAND_QUIT "quit" +#define TOTEM_IR_COMMAND_UP "up" +#define TOTEM_IR_COMMAND_DOWN "down" +#define TOTEM_IR_COMMAND_LEFT "left" +#define TOTEM_IR_COMMAND_RIGHT "right" +#define TOTEM_IR_COMMAND_SELECT "select" +#define TOTEM_IR_COMMAND_MENU "menu" +#define TOTEM_IR_COMMAND_PLAYPAUSE "play_pause" +#define TOTEM_IR_COMMAND_ZOOM_UP "zoom_up" +#define TOTEM_IR_COMMAND_ZOOM_DOWN "zoom_down" +#define TOTEM_IR_COMMAND_SHOW_PLAYING "show_playing" +#define TOTEM_IR_COMMAND_EJECT "eject" +#define TOTEM_IR_COMMAND_PLAY_DVD "play_dvd" +#define TOTEM_IR_COMMAND_MUTE "mute" +#endif /* HAVE_LIRC */ + +struct _TotemRemote { + GObject parent; + + /* Media player keys suppport */ +#ifdef HAVE_MEDIA_PLAYER_KEYS + DBusGProxy *media_player_keys_proxy; +#endif +}; + +enum +{ + BUTTON_PRESSED, + LAST_SIGNAL +}; + +static guint totem_remote_signals[LAST_SIGNAL] = { 0 }; +#ifdef HAVE_LIRC +static GIOChannel *lirc_channel = NULL; +static GList *listeners = NULL; +#endif /* HAVE_LIRC */ + + +G_DEFINE_TYPE(TotemRemote, totem_remote, G_TYPE_OBJECT) + +#ifdef HAVE_LIRC +static TotemRemoteCommand +totem_lirc_to_command (const gchar *str) +{ + if (strcmp (str, TOTEM_IR_COMMAND_PLAY) == 0) + return TOTEM_REMOTE_COMMAND_PLAY; + else if (strcmp (str, TOTEM_IR_COMMAND_PAUSE) == 0) + return TOTEM_REMOTE_COMMAND_PAUSE; + else if (strcmp (str, TOTEM_IR_COMMAND_PLAYPAUSE) == 0) + return TOTEM_REMOTE_COMMAND_PLAYPAUSE; + else if (strcmp (str, TOTEM_IR_COMMAND_NEXT) == 0) + return TOTEM_REMOTE_COMMAND_NEXT; + else if (strcmp (str, TOTEM_IR_COMMAND_PREVIOUS) == 0) + return TOTEM_REMOTE_COMMAND_PREVIOUS; + else if (strcmp (str, TOTEM_IR_COMMAND_SEEK_FORWARD) == 0) + return TOTEM_REMOTE_COMMAND_SEEK_FORWARD; + else if (strcmp (str, TOTEM_IR_COMMAND_SEEK_BACKWARD) == 0) + return TOTEM_REMOTE_COMMAND_SEEK_BACKWARD; + else if (strcmp (str, TOTEM_IR_COMMAND_VOLUME_UP) == 0) + return TOTEM_REMOTE_COMMAND_VOLUME_UP; + else if (strcmp (str, TOTEM_IR_COMMAND_VOLUME_DOWN) == 0) + return TOTEM_REMOTE_COMMAND_VOLUME_DOWN; + else if (strcmp (str, TOTEM_IR_COMMAND_FULLSCREEN) == 0) + return TOTEM_REMOTE_COMMAND_FULLSCREEN; + else if (strcmp (str, TOTEM_IR_COMMAND_QUIT) == 0) + return TOTEM_REMOTE_COMMAND_QUIT; + else if (strcmp (str, TOTEM_IR_COMMAND_UP) == 0) + return TOTEM_REMOTE_COMMAND_UP; + else if (strcmp (str, TOTEM_IR_COMMAND_DOWN) == 0) + return TOTEM_REMOTE_COMMAND_DOWN; + else if (strcmp (str, TOTEM_IR_COMMAND_LEFT) == 0) + return TOTEM_REMOTE_COMMAND_LEFT; + else if (strcmp (str, TOTEM_IR_COMMAND_RIGHT) == 0) + return TOTEM_REMOTE_COMMAND_RIGHT; + else if (strcmp (str, TOTEM_IR_COMMAND_SELECT) == 0) + return TOTEM_REMOTE_COMMAND_SELECT; + else if (strcmp (str, TOTEM_IR_COMMAND_MENU) == 0) + return TOTEM_REMOTE_COMMAND_DVD_MENU; + else if (strcmp (str, TOTEM_IR_COMMAND_ZOOM_UP) == 0) + return TOTEM_REMOTE_COMMAND_ZOOM_UP; + else if (strcmp (str, TOTEM_IR_COMMAND_ZOOM_DOWN) == 0) + return TOTEM_REMOTE_COMMAND_ZOOM_DOWN; + else if (strcmp (str, TOTEM_IR_COMMAND_SHOW_PLAYING) == 0) + return TOTEM_REMOTE_COMMAND_SHOW_PLAYING; + else if (strcmp (str, TOTEM_IR_COMMAND_EJECT) == 0) + return TOTEM_REMOTE_COMMAND_EJECT; + else if (strcmp (str, TOTEM_IR_COMMAND_PLAY_DVD) == 0) + return TOTEM_REMOTE_COMMAND_PLAY_DVD; + else if (strcmp (str, TOTEM_IR_COMMAND_MUTE) == 0) + return TOTEM_REMOTE_COMMAND_MUTE; + else + return TOTEM_REMOTE_COMMAND_UNKNOWN; +} + +static struct lirc_config *config; + +static gboolean +totem_remote_read_code (GIOChannel *source, GIOCondition condition, + gpointer user_data) +{ + char *code; + char *str = NULL; + GList *tmp; + TotemRemoteCommand cmd; + + /* this _could_ block, but it shouldn't */ + lirc_nextcode (&code); + + if (code == NULL) { + /* the code was incomplete or something */ + return TRUE; + } + + if (lirc_code2char (config, code, &str) != 0) { + g_message ("Couldn't convert lirc code to string."); + return TRUE; + } + + if (str == NULL) { + /* there was no command associated with the code */ + g_free (code); + return TRUE; + } + + cmd = totem_lirc_to_command (str); + + tmp = listeners; + while (tmp) { + TotemRemote *remote = tmp->data; + + g_signal_emit (remote, totem_remote_signals[BUTTON_PRESSED], 0, + cmd); + + tmp = tmp->next; + } + + g_free (code); + + /* this causes a crash, so I guess I'm not supposed to free it? + * g_free (str); + */ + + return TRUE; +} +#endif /* HAVE_LIRC */ + +#ifdef HAVE_MEDIA_PLAYER_KEYS +static void +on_media_player_key_pressed (DBusGProxy *proxy, const gchar *application, const gchar *key, TotemRemote *remote) +{ + if (strcmp ("Totem", application) == 0) { + if (strcmp ("Play", key) == 0) + g_signal_emit (remote, totem_remote_signals[BUTTON_PRESSED], 0, TOTEM_REMOTE_COMMAND_PLAYPAUSE); + else if (strcmp ("Previous", key) == 0) + g_signal_emit (remote, totem_remote_signals[BUTTON_PRESSED], 0, TOTEM_REMOTE_COMMAND_PREVIOUS); + else if (strcmp ("Next", key) == 0) + g_signal_emit (remote, totem_remote_signals[BUTTON_PRESSED], 0, TOTEM_REMOTE_COMMAND_NEXT); + } +} +#endif /* HAVE_MEDIA_PLAYER_KEYS */ + +static void +totem_remote_finalize (GObject *object) +{ + GError *error = NULL; + TotemRemote *remote; + + g_return_if_fail (object != NULL); + g_return_if_fail (TOTEM_IS_REMOTE (object)); + + remote = TOTEM_REMOTE (object); + +#ifdef HAVE_LIRC + lirc_freeconfig (config); + g_free(config); + + listeners = g_list_remove (listeners, remote); + + if (listeners == NULL && lirc_channel != NULL) { + g_io_channel_shutdown (lirc_channel, FALSE, &error); + if (error != NULL) { + g_warning ("Couldn't destroy lirc connection: %s", + error->message); + g_error_free (error); + } + + lirc_deinit (); + } +#endif /* HAVE_LIRC */ + +#ifdef HAVE_MEDIA_PLAYER_KEYS + if (remote->media_player_keys_proxy != NULL) + org_gnome_SettingsDaemon_release_media_player_keys (remote->media_player_keys_proxy, "Totem", NULL); +#endif /* HAVE_MEDIA_PLAYER_KEYS */ +} + +static void +totem_remote_class_init (TotemRemoteClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = totem_remote_finalize; + + totem_remote_signals[BUTTON_PRESSED] = + g_signal_new ("button_pressed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (TotemRemoteClass, button_pressed), + NULL, NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, + 1, + G_TYPE_INT); +} + + +static void +totem_remote_init (TotemRemote *remote) +{ +#ifdef HAVE_MEDIA_PLAYER_KEYS + DBusGConnection *bus; + GError *error = NULL; +#endif /* HAVE_MEDIA_PLAYER_KEYS */ +#ifdef HAVE_LIRC + int fd; +#endif /* HAVE_LIRC */ + +#ifdef HAVE_MEDIA_PLAYER_KEYS + bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error); + if (bus == NULL) { + g_warning ("Error connecting to DBus: %s", error->message); + } else { + remote->media_player_keys_proxy = dbus_g_proxy_new_for_name (bus, + "org.gnome.SettingsDaemon", "/org/gnome/SettingsDaemon", + "org.gnome.SettingsDaemon"); + + org_gnome_SettingsDaemon_grab_media_player_keys (remote->media_player_keys_proxy, + "Totem", 0, NULL); + + dbus_g_object_register_marshaller (totem_marshal_VOID__STRING_STRING, + G_TYPE_NONE, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID); + + dbus_g_proxy_add_signal (remote->media_player_keys_proxy, "MediaPlayerKeyPressed", + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID); + + dbus_g_proxy_connect_signal (remote->media_player_keys_proxy, "MediaPlayerKeyPressed", + G_CALLBACK (on_media_player_key_pressed), remote, NULL); + } +#endif + +#ifdef HAVE_LIRC + if (lirc_channel == NULL) { + fd = lirc_init ("Totem", 0); + + if (fd < 0) { + GConfClient *gc; + + gc = gconf_client_get_default (); + if (gc == NULL) + return; + + if (gconf_client_get_bool (gc, GCONF_PREFIX"/debug", NULL) != FALSE) + g_message ("Couldn't initialize lirc.\n"); + g_object_unref (gc); + return; + } + + config = g_new(struct lirc_config, 1); + + if (lirc_readconfig (NULL, &config, NULL) != 0) { + g_message ("Couldn't read lirc config."); + return; + } + + lirc_channel = g_io_channel_unix_new (fd); + + g_io_add_watch (lirc_channel, G_IO_IN, + (GIOFunc) totem_remote_read_code, NULL); + } + + listeners = g_list_prepend (listeners, remote); +#endif /* HAVE_LIRC */ + +} + +TotemRemote * +totem_remote_new (void) +{ + return g_object_new (TOTEM_TYPE_REMOTE, NULL); +} + + +#ifdef HAVE_MEDIA_PLAYER_KEYS +void +totem_remote_window_activated (TotemRemote *remote) +{ + + g_return_if_fail (TOTEM_IS_REMOTE (remote)); + g_return_if_fail (DBUS_IS_G_PROXY (remote->media_player_keys_proxy)); + + org_gnome_SettingsDaemon_grab_media_player_keys (remote->media_player_keys_proxy, + "Totem", 0, NULL); +} +#endif /* HAVE_MEDIA_PLAYER_KEYS */ + +#endif /* HAVE_REMOTE */ |