Merge branch 'master' of ssh://repo.or.cz/srv/git/gmpc-shout
[gmpc-shout.git] / src / plugin.c
blob3cee2d82bb25d4a934e36cce03703e031492b18c
1 /* gmpc-shout (GMPC plugin)
2 * Copyright (C) 2007-2009 Qball Cow <qball@sarine.nl>
3 * Project homepage: http://gmpcwiki.sarine.nl/
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include <stdio.h>
21 #include <string.h>
22 #include <config.h>
23 #include <glib.h>
24 #include <glib/gi18n-lib.h>
25 #include <gmpc/plugin.h>
26 #include <gmpc/playlist3-messages.h>
27 #ifndef __WIN32__
28 #include <sys/wait.h>
29 #include <unistd.h>
30 #include <signal.h>
31 #else
32 #define WIN32_LEAN_AND_MEAN
33 #include <windows.h>
34 #endif
36 #define SHOUT_COMMAND "mplayer -ao pulse -nocache http://192.150.0.120:8000/mpd.ogg"
37 #include <config.h>
40 gboolean stopped = FALSE;
41 GPid ogg123_pid = -1;
44 static GtkWidget *si_shout = NULL;
45 static GtkWidget *shout_vbox = NULL;
46 static void start_ogg123(void);
47 static void stop_ogg123(void);
48 void shout_mpd_status_changed(MpdObj *mi, ChangedStatusType what, void *data);
49 void shout_construct(GtkWidget *container);
50 void shout_destroy(GtkWidget *container);
51 static int shout_get_enabled(void);
52 static void shout_set_enabled(int enabled);
54 gmpcPrefPlugin shout_gpp = {
55 shout_construct,
56 shout_destroy
58 gmpcPlugin plugin;
61 int plugin_api_version = PLUGIN_API_VERSION;
63 static void shout_plugin_destroy(void);
65 static const char * shout_get_translation_domain(void)
67 return GETTEXT_PACKAGE;
70 static void shout_si_start(void)
72 stopped = FALSE;
73 start_ogg123();
76 static void shout_si_stop(void)
78 stop_ogg123();
79 stopped = TRUE;
82 static void shout_si_show_pref(void)
84 preferences_show_pref_window(plugin.id);
87 static gboolean shout_si_button_press_event(GtkWidget *icon, GdkEventButton *event, gpointer data)
89 if(event->button == 3)
91 GtkWidget *item;
92 GtkMenu *menu = gtk_menu_new();
93 g_object_ref_sink(G_OBJECT(menu));
95 if(ogg123_pid < 0 && mpd_player_get_state(connection) == MPD_STATUS_STATE_PLAY) {
96 item = gtk_image_menu_item_new_with_label(_("Start"));
97 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(shout_si_start), NULL);
98 gtk_menu_shell_append(GTK_MENU(menu), item);
100 else if (ogg123_pid >= 0 && mpd_player_get_state(connection) == MPD_STATUS_STATE_PLAY) {
101 item = gtk_image_menu_item_new_with_label(_("Stop"));
102 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(shout_si_stop), NULL);
103 gtk_menu_shell_append(GTK_MENU(menu), item);
105 item = gtk_image_menu_item_new_with_label(_("Preferences"));
106 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(shout_si_show_pref), NULL);
107 gtk_menu_shell_append(GTK_MENU(menu), item);
109 gtk_widget_show_all(GTK_WIDGET(menu));
110 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, event->button, event->time);
111 g_object_unref(menu);
112 /* Again, check for active page and set button otherwise */
113 return TRUE;
115 return FALSE;
117 static void shout_add_si_icon(void)
119 if(shout_get_enabled() && si_shout == NULL) {
120 GtkWidget *image = gtk_image_new_from_icon_name("add-url", GTK_ICON_SIZE_MENU);
121 si_shout = gtk_event_box_new();
122 gtk_container_add(GTK_CONTAINER(si_shout), image);
123 main_window_add_status_icon(si_shout);
124 gtk_widget_show_all(si_shout);
125 gtk_widget_set_sensitive(gtk_bin_get_child(GTK_BIN(si_shout)), FALSE);
127 g_signal_connect(G_OBJECT(si_shout), "button-press-event", G_CALLBACK(shout_si_button_press_event),NULL);
129 gtk_widget_set_tooltip_text(si_shout, _("Shout plugin"));
132 static void shout_init(void)
134 bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
135 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
137 gtk_init_add((GtkFunction)shout_add_si_icon, NULL);
140 /* main plugin_osd info */
141 gmpcPlugin plugin = {
142 .name = N_("Shout plugin"),
143 .version = {PLUGIN_MAJOR_VERSION,PLUGIN_MINOR_VERSION,PLUGIN_MICRO_VERSION},
144 .plugin_type = GMPC_PLUGIN_NO_GUI,
145 .init = shout_init,
146 .destroy = shout_plugin_destroy, /* Destroy */
147 .mpd_status_changed = &shout_mpd_status_changed,
148 .pref = &shout_gpp,
149 .get_enabled = shout_get_enabled,
150 .set_enabled = shout_set_enabled,
151 .get_translation_domain = shout_get_translation_domain
155 static int shout_get_enabled(void)
157 return cfg_get_single_value_as_int_with_default(config, "shout-plugin", "enable", FALSE);
159 static void shout_set_enabled(int enabled)
161 cfg_set_single_value_as_int(config, "shout-plugin", "enable", enabled);
162 if(enabled )
164 shout_add_si_icon();
165 if(mpd_player_get_state(connection) == MPD_STATUS_STATE_PLAY)
167 start_ogg123();
170 } else {
171 /* stop */
172 stop_ogg123();
174 gtk_widget_destroy(si_shout);
175 si_shout = NULL;
179 void shout_destroy(GtkWidget *container)
181 gtk_container_remove(GTK_CONTAINER(container), shout_vbox);
183 static void shout_entry_edited(GtkWidget *entry)
185 const char *str = gtk_entry_get_text(GTK_ENTRY(entry));
186 if(str)
188 cfg_set_single_value_as_string(config, "shout-plugin", "command",(char *)str);
196 void shout_construct(GtkWidget *container)
198 GtkWidget *entry = NULL, *label;
199 char *entry_str = cfg_get_single_value_as_string_with_default(config, "shout-plugin", "command", SHOUT_COMMAND);
200 shout_vbox = gtk_vbox_new(FALSE,6);
202 gtk_container_add(GTK_CONTAINER(container), shout_vbox);
204 entry = gtk_entry_new();
205 if(entry_str)
207 gtk_entry_set_text(GTK_ENTRY(entry), entry_str);
208 cfg_free_string(entry_str);
210 label = gtk_label_new(_("Playback Command:"));
211 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
212 gtk_box_pack_start(GTK_BOX(shout_vbox), label, FALSE, FALSE,0);
213 gtk_box_pack_start(GTK_BOX(shout_vbox), entry, FALSE, FALSE,0);
215 g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(shout_entry_edited), NULL);
217 gtk_widget_show_all(container);
219 static void shout_pid_callback (GPid pid,
220 gint status,
221 gpointer data)
223 g_spawn_close_pid(ogg123_pid);
224 printf("client died: %i\n", ogg123_pid);
225 ogg123_pid = -1;
228 if(si_shout){
229 gtk_widget_set_sensitive(gtk_bin_get_child(GTK_BIN(si_shout)),FALSE);
230 gtk_widget_set_tooltip_text(si_shout, _("Not Playing"));
233 if(mpd_player_get_state(connection) == MPD_STATUS_STATE_PLAY && !stopped)
235 start_ogg123();
238 static void start_ogg123(void)
240 if(stopped) return;
241 if(ogg123_pid == -1)
243 gchar *uri = cfg_get_single_value_as_string_with_default(config, "shout-plugin", "command", SHOUT_COMMAND);
244 gchar **argv = g_strsplit(uri, " ", 0);
245 GError *error = NULL;
247 if(!g_spawn_async(NULL,argv, NULL, G_SPAWN_SEARCH_PATH|G_SPAWN_DO_NOT_REAP_CHILD,NULL, NULL, &ogg123_pid, &error))
249 if(error)
251 gchar *message = g_strdup_printf("%s: %s", _("Shout plugin: Failed to spawn client. Error"), error->message);
252 playlist3_show_error_message(message, ERROR_WARNING);
253 g_free(message);
254 g_error_free(error);
255 error = NULL;
258 else
260 g_child_watch_add(ogg123_pid, shout_pid_callback, NULL);
262 if(si_shout){
263 gtk_widget_set_sensitive(gtk_bin_get_child(GTK_BIN(si_shout)), TRUE);
264 gtk_widget_set_tooltip_text(si_shout, _("Playing"));
267 printf("spawned pid: %i\n", ogg123_pid);
268 g_strfreev(argv);
269 g_free(uri);
273 static void stop_ogg123(void)
275 if(ogg123_pid >= 0)
277 #ifndef __WIN32__
278 printf("killing: %i\n", ogg123_pid);
279 kill (ogg123_pid, SIGHUP);
280 #else
281 TerminateProcess (ogg123_pid, 1);
282 #endif
284 if(si_shout){
285 gtk_widget_set_sensitive(gtk_bin_get_child(GTK_BIN(si_shout)), FALSE);
286 gtk_widget_set_tooltip_text(si_shout, _("Playing"));
289 /* ogg123_pid = -1;*/
292 /* mpd changed */
294 void shout_mpd_status_changed(MpdObj *mi, ChangedStatusType what, void *data)
296 if(!shout_get_enabled())
297 return;
298 if(what&(MPD_CST_SONGID|MPD_CST_STATE))
300 if(mpd_player_get_state(mi) != MPD_STATUS_STATE_PLAY)
302 stop_ogg123();
304 else
306 start_ogg123();
308 return;
311 static void shout_plugin_destroy(void)
313 stop_ogg123();