hythmbox-2.98/plugins/lirc/rb-lirc-plugin.c

No issues found

  1 /*
  2  * rb-lirc-plugin.c
  3  *
  4  * Copyright (C) 2006  Jonathan Matthew
  5  *
  6  * This program is free software; you can redistribute it and/or modify
  7  * it under the terms of the GNU General Public License as published by
  8  * the Free Software Foundation; either version 2, or (at your option)
  9  * any later version.
 10  *
 11  * The Rhythmbox authors hereby grant permission for non-GPL compatible
 12  * GStreamer plugins to be used and distributed together with GStreamer
 13  * and Rhythmbox. This permission is above and beyond the permissions granted
 14  * by the GPL license by which Rhythmbox is covered. If you modify this code
 15  * you may extend this exception to your version of the code, but you are not
 16  * obligated to do so. If you do not wish to do so, delete this exception
 17  * statement from your version.
 18  *
 19  * This program is distributed in the hope that it will be useful,
 20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 22  * GNU General Public License for more details.
 23  *
 24  * You should have received a copy of the GNU General Public License
 25  * along with this program; if not, write to the Free Software
 26  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA.
 27  */
 28 
 29 #ifdef HAVE_CONFIG_H
 30 #include <config.h>
 31 #endif
 32 
 33 #include <string.h>
 34 #include <unistd.h>
 35 
 36 #include <glib.h>
 37 #include <glib-object.h>
 38 #include <glib/gi18n-lib.h>
 39 #include <gmodule.h>
 40 #include <lirc/lirc_client.h>
 41 
 42 #include "rb-plugin-macros.h"
 43 #include "rb-shell.h"
 44 #include "rb-debug.h"
 45 #include "rb-util.h"
 46 #include "rb-shell-player.h"
 47 #include "rb-file-helpers.h"
 48 
 49 #define RB_TYPE_LIRC_PLUGIN		(rb_lirc_plugin_get_type ())
 50 #define RB_LIRC_PLUGIN(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), RB_TYPE_LIRC_PLUGIN, RBLircPlugin))
 51 #define RB_LIRC_PLUGIN_CLASS(k)		(G_TYPE_CHECK_CLASS_CAST((k), RB_TYPE_LIRC_PLUGIN, RBLircPluginClass))
 52 #define RB_IS_LIRC_PLUGIN(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), RB_TYPE_LIRC_PLUGIN))
 53 #define RB_IS_LIRC_PLUGIN_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), RB_TYPE_LIRC_PLUGIN))
 54 #define RB_LIRC_PLUGIN_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), RB_TYPE_LIRC_PLUGIN, RBLircPluginClass))
 55 
 56 #define RB_IR_COMMAND_PLAY "play"
 57 #define RB_IR_COMMAND_PAUSE "pause"
 58 #define RB_IR_COMMAND_PLAYPAUSE "playpause"
 59 #define RB_IR_COMMAND_STOP "stop"
 60 #define RB_IR_COMMAND_SHUFFLE "shuffle"
 61 #define RB_IR_COMMAND_REPEAT "repeat"
 62 #define RB_IR_COMMAND_NEXT "next"
 63 #define RB_IR_COMMAND_PREVIOUS "previous"
 64 #define RB_IR_COMMAND_SEEK_FORWARD "seek_forward"
 65 #define RB_IR_COMMAND_SEEK_BACKWARD "seek_backward"
 66 #define RB_IR_COMMAND_VOLUME_UP "volume_up"
 67 #define RB_IR_COMMAND_VOLUME_DOWN "volume_down"
 68 #define RB_IR_COMMAND_MUTE "mute"
 69 #define RB_IR_COMMAND_QUIT "quit"
 70 
 71 typedef struct
 72 {
 73 	PeasExtensionBase parent;
 74 	RBShellPlayer *shell_player;
 75 	struct lirc_config *lirc_config;
 76 	GIOChannel *lirc_channel;
 77 } RBLircPlugin;
 78 
 79 typedef struct
 80 {
 81 	PeasExtensionBaseClass parent_class;
 82 } RBLircPluginClass;
 83 
 84 G_MODULE_EXPORT void peas_register_types (PeasObjectModule *module);
 85 
 86 static void rb_lirc_plugin_init (RBLircPlugin *plugin);
 87 
 88 RB_DEFINE_PLUGIN (RB_TYPE_LIRC_PLUGIN, RBLircPlugin, rb_lirc_plugin,)
 89 
 90 static void
 91 rb_lirc_plugin_init (RBLircPlugin *plugin)
 92 {
 93 	rb_debug ("RBLircPlugin initialising");
 94 }
 95 
 96 static gboolean
 97 rb_lirc_plugin_read_code (GIOChannel *source,
 98 			  GIOCondition condition,
 99 			  RBLircPlugin *plugin)
100 {
101 	char *code;
102 	char *str = NULL;	/* owned by lirc config, must not be freed */
103 	int ok;
104 	gboolean processed = FALSE;
105 
106 	if (condition & (G_IO_ERR | G_IO_HUP)) {
107 		/* TODO: retry after a minute? */
108 		rb_debug ("LIRC connection broken.  sorry.");
109 		return FALSE;
110 	}
111 
112 	lirc_nextcode (&code);
113 	if (code == NULL) {
114 		rb_debug ("Got incomplete lirc code");
115 		return TRUE;
116 	}
117 
118 	do {
119 		ok = lirc_code2char (plugin->lirc_config, code, &str);
120 
121 		if (ok != 0) {
122 			rb_debug ("couldn't convert lirc code \"%s\" to string", code);
123 		} else if (str == NULL) {
124 			if (processed == FALSE)
125 				rb_debug ("unknown LIRC code \"%s\"", code);
126 			break;
127 		} else if (strcmp (str, RB_IR_COMMAND_PLAY) == 0) {
128 			gboolean playing;
129 			rb_shell_player_get_playing (plugin->shell_player, &playing, NULL);
130 			if (playing == FALSE)
131 				rb_shell_player_playpause (plugin->shell_player, FALSE, NULL);
132 		} else if (strcmp (str, RB_IR_COMMAND_PAUSE) == 0) {
133 			rb_shell_player_pause (plugin->shell_player, NULL);
134 		} else if (strcmp (str, RB_IR_COMMAND_PLAYPAUSE) == 0) {
135 			rb_shell_player_playpause (plugin->shell_player, FALSE, NULL);
136 		} else if (strcmp (str, RB_IR_COMMAND_STOP) == 0) {
137 			rb_shell_player_stop (plugin->shell_player);
138 		} else if (strcmp (str, RB_IR_COMMAND_SHUFFLE) == 0) {
139 			gboolean shuffle;
140 			gboolean repeat;
141 			if (rb_shell_player_get_playback_state (plugin->shell_player, &shuffle, &repeat)) {
142 				rb_shell_player_set_playback_state (plugin->shell_player, !shuffle, repeat);
143 			}
144 		} else if (strcmp (str, RB_IR_COMMAND_REPEAT) == 0) {
145 			gboolean shuffle;
146 			gboolean repeat;
147 			if (rb_shell_player_get_playback_state (plugin->shell_player, &shuffle, &repeat)) {
148 				rb_shell_player_set_playback_state (plugin->shell_player, shuffle, !repeat);
149 			}
150 		} else if (strcmp (str, RB_IR_COMMAND_NEXT) == 0) {
151 			rb_shell_player_do_next (plugin->shell_player, NULL);
152 		} else if (strcmp (str, RB_IR_COMMAND_PREVIOUS) == 0) {
153 			rb_shell_player_do_previous (plugin->shell_player, NULL);
154 		} else if (strcmp (str, RB_IR_COMMAND_SEEK_FORWARD) == 0) {
155 			rb_shell_player_seek (plugin->shell_player, FFWD_OFFSET, NULL);
156 		} else if (strcmp (str, RB_IR_COMMAND_SEEK_BACKWARD) == 0) {
157 			rb_shell_player_seek (plugin->shell_player, -RWD_OFFSET, NULL);
158 		} else if (strcmp (str, RB_IR_COMMAND_VOLUME_UP) == 0) {
159 			rb_shell_player_set_volume_relative (plugin->shell_player, 0.1, NULL);
160 		} else if (strcmp (str, RB_IR_COMMAND_VOLUME_DOWN) == 0) {
161 			rb_shell_player_set_volume_relative (plugin->shell_player, -0.1, NULL);
162 		} else if (strcmp (str, RB_IR_COMMAND_MUTE) == 0) {
163 			gboolean mute;
164 			if (rb_shell_player_get_mute (plugin->shell_player, &mute, NULL)) {
165 				rb_shell_player_set_mute (plugin->shell_player, !mute, NULL);
166 			}
167 		} else if (strcmp (str,RB_IR_COMMAND_QUIT) == 0) {
168 			RBShell *shell;
169 
170 			g_object_get (plugin, "object", &shell, NULL);
171 			rb_shell_quit (shell, NULL);
172 			g_object_unref (shell);
173 			/* the plugin will have been deactivated, so we can't continue the loop */
174 			break;
175 		}
176 		processed = TRUE;
177 	} while (ok == 0);
178 	g_free (code);
179 
180 	return TRUE;
181 }
182 
183 static void
184 impl_activate (PeasActivatable *bplugin)
185 {
186 	int fd;
187 	char *path;
188 	RBLircPlugin *plugin = RB_LIRC_PLUGIN (bplugin);
189 	RBShell *shell;
190 
191 	g_object_get (plugin, "object", &shell, NULL);
192 
193 	g_object_get (shell, "shell-player", &plugin->shell_player, NULL);
194 
195 	rb_debug ("Activating lirc plugin");
196 
197 	fd = lirc_init ("Rhythmbox", 1);
198 	if (fd < 0) {
199 		rb_debug ("Couldn't initialize lirc");
200 		g_object_unref (shell);
201 		return;
202 	}
203 
204 	/* Load the default Rhythmbox setup */
205 	path = rb_find_plugin_data_file (G_OBJECT (plugin), "rhythmbox_lirc_default");
206 	if (path == NULL || lirc_readconfig (path, &plugin->lirc_config, NULL) == -1) {
207 		g_free (path);
208 		close (fd);
209 		rb_debug ("Couldn't read lirc configuration");
210 		g_object_unref (shell);
211 		return;
212 	}
213 	g_free (path);
214 
215 	lirc_readconfig (NULL, &plugin->lirc_config, NULL);
216 
217 	plugin->lirc_channel = g_io_channel_unix_new (fd);
218 	g_io_channel_set_encoding (plugin->lirc_channel, NULL, NULL);
219 	g_io_channel_set_buffered (plugin->lirc_channel, FALSE);
220 	g_io_add_watch (plugin->lirc_channel, G_IO_IN | G_IO_ERR | G_IO_HUP,
221 			(GIOFunc) rb_lirc_plugin_read_code, plugin);
222 
223 	g_object_unref (shell);
224 }
225 
226 static void
227 impl_deactivate	(PeasActivatable *bplugin)
228 {
229 	RBLircPlugin *plugin = RB_LIRC_PLUGIN (bplugin);
230 	GError *error = NULL;
231 
232 	rb_debug ("Deactivating lirc plugin");
233 
234 	if (plugin->lirc_channel) {
235 		g_io_channel_shutdown (plugin->lirc_channel, FALSE, &error);
236 		if (error != NULL) {
237 			g_warning ("Couldn't destroy lirc connection: %s",
238 				   error->message);
239 			g_error_free (error);
240 		}
241 		plugin->lirc_channel = NULL;
242 	}
243 
244 	if (plugin->lirc_config) {
245 		lirc_freeconfig (plugin->lirc_config);
246 		plugin->lirc_config = NULL;
247 
248 		lirc_deinit ();
249 	}
250 
251 	if (plugin->shell_player) {
252 		g_object_unref (G_OBJECT (plugin->shell_player));
253 		plugin->shell_player = NULL;
254 	}
255 }
256 
257 G_MODULE_EXPORT void
258 peas_register_types (PeasObjectModule *module)
259 {
260 	rb_lirc_plugin_register_type (G_TYPE_MODULE (module));
261 	peas_object_module_register_extension_type (module,
262 						    PEAS_TYPE_ACTIVATABLE,
263 						    RB_TYPE_LIRC_PLUGIN);
264 }