1 /* Gnome Music Player Client (GMPC)
2 * Copyright (C) 2004-2012 Qball Cow <qball@gmpclient.org>
3 * Project homepage: http://gmpclient.org/
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.
22 * Create text file: ~/.config/gmpc/external-command.cfg
23 * Add sections for each command, Each section has a cmd and a name entry.
24 * The cmd should be a path to the executable with possible arguments,
25 * the cmd string is parsed by gmpc.
29 * cmd="/home/me/test.sh -f test3"
32 * The paths (relative to MPD directory) are passed to the script as arguments.
39 private const bool use_transition_externalcommand
= Gmpc
.use_transition
;
40 private const string some_unique_name_externalcommand
= Config
.VERSION
;
41 private const string log_domain_externalcommand
= "Gmpc.Plugins.ExternalCommand";
45 public class ExternalCommand
:
47 Gmpc
.Plugin
.SongListIface
,
48 Gmpc
.Plugin
.PreferencesIface
50 private const int[] version
= {0,0,0};
51 private Gmpc
.Settings cfg_ec
= null;
53 public override unowned
int[] get_version() {
57 public override unowned
string get_name () {
58 return "Call external command";
62 string settings_path
= Gmpc
.user_path("external-command.cfg");
63 cfg_ec
= new Gmpc
.Settings
.from_file(settings_path
);
71 private void start_command(Gtk
.MenuItem item
) {
73 string cmd
= item
.get_data("cmd");
74 // Calculate number of arguments.
77 Gtk
.TreeView tree
= item
.get_data("tree");
78 Gtk
.TreeSelection sel
= tree
.get_selection();
79 args
+= sel
.count_selected_rows();
81 // Parse the command list.
84 Shell
.parse_argv(cmd
, out argv
);
86 Gmpc
.Messages
.show("%s: %s".printf(_("Failed to parse command"), e
.message
), Gmpc
.Messages
.Level
.WARNING
);
90 // Resize the list to fit the songs passed.
94 argv
.resize((args
+1));
98 weak string? music_directory
= null;
99 var cp
= Gmpc
.profiles
.get_current();
102 if(Gmpc
.profiles
.get_music_directory(cp
) != null)
104 music_directory
= Gmpc
.profiles
.get_music_directory(cp
);
108 // Set song paths as arguments.
110 var rows
= sel
.get_selected_rows(out model
);
111 foreach ( Gtk
.TreePath path
in rows
){
114 if(model
.get_iter(out iter
, path
)){
115 model
.get(iter
,3, out file
);
116 if(music_directory
!= null) {
117 argv
[index
] = Path
.build_filename(music_directory
,file
);
129 GLib
.Process
.spawn_async(null, argv
, null, SpawnFlags
.SEARCH_PATH
, null, null);
131 Gmpc
.Messages
.show("%s: %s".printf(_("Failed to start external command"), e
.message
), Gmpc
.Messages
.Level
.WARNING
);
136 public int song_list (Gtk
.Widget tree
, Gtk
.Menu menu
)
140 SettingsList sl
= cfg_ec
.get_class_list();
141 weak SettingsList iter
= sl
;
142 while(iter
!= null) {
143 string cmd
= cfg_ec
.get_string(iter
.key
, "cmd");
144 string name
= cfg_ec
.get_string(iter
.key
, "name");
146 // If both values are not valid, continue.
147 if(cmd
== null || name
== null) continue;
148 var item
= new Gtk
.ImageMenuItem
.with_label("Run external command: "+name
);
150 // Attach tree widget to item and the command.
151 item
.set_data("tree", tree
);
152 item
.set_data("cmd", cmd
);
154 item
.activate
.connect(start_command
);
165 /************************
167 ************************/
168 private Gtk
.Builder pref_builder
= null;
170 private void preferences_pane_combo_changed(Gtk
.ComboBox source
)
173 if(source
.get_active_iter(out titer
)) {
174 Gtk
.TreeModel model
= source
.get_model();
176 model
.get(titer
, 0, out key
);
177 string name
= cfg_ec
.get_string(key
, "name");
178 string cmd
= cfg_ec
.get_string(key
, "cmd");
180 (pref_builder
.get_object("entry_name") as Gtk
.Entry
).set_text(name
);
182 (pref_builder
.get_object("entry_cmd") as Gtk
.Entry
).set_text(cmd
);
184 (pref_builder
.get_object("entry_cmd") as Gtk
.Entry
).set_sensitive(true);
185 (pref_builder
.get_object("entry_name") as Gtk
.Entry
).set_sensitive(true);
187 (pref_builder
.get_object("entry_cmd") as Gtk
.Entry
).set_sensitive(false);
188 (pref_builder
.get_object("entry_name") as Gtk
.Entry
).set_sensitive(false);
192 private void preferences_pane_entry_cmd(Gtk
.Editable entry
)
194 var cb
= (pref_builder
.get_object("commands_cb") as Gtk
.ComboBox
);
196 if(cb
.get_active_iter(out iter
))
199 cb
.get_model().get(iter
, 0, out key
);
200 cfg_ec
.set_string(key
, "cmd", (entry as Gtk
.Entry
).get_text());
203 private void preferences_pane_entry_name(Gtk
.Editable entry
)
205 var cb
= (pref_builder
.get_object("commands_cb") as Gtk
.ComboBox
);
207 if(cb
.get_active_iter(out iter
))
210 cb
.get_model().get(iter
, 0, out key
);
211 cfg_ec
.set_string(key
, "name", (entry as Gtk
.Entry
).get_text());
212 (cb
.get_model() as Gtk
.ListStore
).set(iter
, 1, (entry as Gtk
.Entry
).get_text());
216 private void preferences_pane_remove_button(Gtk
.Button button
)
219 Gtk
.ListStore store
= pref_builder
.get_object("commands_list") as Gtk
.ListStore
;
220 var cb
= (pref_builder
.get_object("commands_cb") as Gtk
.ComboBox
);
222 if(cb
.get_active_iter(out iter
)) {
224 cb
.get_model().get(iter
, 0, out key
);
225 cfg_ec
.remove_class(key
);
228 preferences_pane_enable_remove_button();
229 (pref_builder
.get_object("commands_cb") as Gtk
.ComboBox
).set_active(0);
232 private void preferences_pane_enable_remove_button()
234 Gtk
.ListStore store
= pref_builder
.get_object("commands_list") as Gtk
.ListStore
;
235 var cb
= (pref_builder
.get_object("button_delete") as Gtk
.Button
);
236 if(store
.iter_n_children(null) > 0) {
237 cb
.set_sensitive(true);
239 cb
.set_sensitive(false);
242 private void preferences_pane_add_button(Gtk
.Button button
)
245 stdout
.printf("add button\n");
246 while(cfg_ec
.get_string("%u".printf(id
), "name") != null) id
++;
247 cfg_ec
.set_string("%u".printf(id
), "name", "<Command name>");
248 cfg_ec
.set_string("%u".printf(id
), "cmd", "<Command cmd>");
250 Gtk
.ListStore store
= pref_builder
.get_object("commands_list") as Gtk
.ListStore
;
251 var cb
= (pref_builder
.get_object("commands_cb") as Gtk
.ComboBox
);
253 store
.append(out iter
);
254 store
.set(iter
, 0, "%u".printf(id
), 1, "<Command name>");
255 cb
.set_active_iter(iter
);
258 /* Destroy preferences construct */
259 public void preferences_pane_construct(Gtk
.Container container
)
261 if(pref_builder
!= null) return;
262 pref_builder
= new Gtk
.Builder();
265 pref_builder
.add_from_file(Gmpc
.data_path("preferences-external-command.ui"));
269 GLib
.error("Failed to load GtkBuilder file: %s", e
.message
);
273 Gtk
.ListStore store
= pref_builder
.get_object("commands_list") as Gtk
.ListStore
;
277 SettingsList sl
= cfg_ec
.get_class_list();
278 weak SettingsList iter
= sl
;
279 while(iter
!= null) {
280 string name
= cfg_ec
.get_string(iter
.key
, "name");
282 store
.prepend(out titer
);
283 store
.set(titer
, 0,iter
.key
, 1, name
);
290 (pref_builder
.get_object("button_add") as Gtk
.Button
).clicked
.connect(
291 preferences_pane_add_button
);
292 (pref_builder
.get_object("button_delete") as Gtk
.Button
).clicked
.connect(
293 preferences_pane_remove_button
);
294 (pref_builder
.get_object("entry_cmd") as Gtk
.Entry
).changed
.
295 connect(preferences_pane_entry_cmd
);
296 (pref_builder
.get_object("entry_name") as Gtk
.Entry
).changed
.
297 connect(preferences_pane_entry_name
);
300 (pref_builder
.get_object("commands_cb") as Gtk
.ComboBox
).
301 changed
.connect(preferences_pane_combo_changed
);
303 var b
= pref_builder
.get_object("main_box") as Gtk
.Widget
;
306 (pref_builder
.get_object("commands_cb") as Gtk
.ComboBox
).set_active(0);
308 preferences_pane_enable_remove_button();
310 /* Destroy preferences pane */
311 public void preferences_pane_destroy(Gtk
.Container container
)
313 container
.remove((container as Gtk
.Bin
).get_child());