1 /*****************************************************************
2  * gmerlin - a general purpose multimedia framework and applications
3  *
4  * Copyright (c) 2001 - 2011 Members of the Gmerlin project
5  * gmerlin-general@lists.sourceforge.net
6  * http://gmerlin.sourceforge.net
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  * *****************************************************************/
21 
22 #include <gtk/gtk.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 
26 #include <config.h>
27 
28 #include <gmerlin/translation.h>
29 
30 #include <gmerlin/pluginregistry.h>
31 #include <gmerlin/utils.h>
32 #include <gmerlin/cfg_dialog.h>
33 
34 #include <gui_gtk/plugin.h>
35 #include <gui_gtk/gtkutils.h>
36 
37 enum
38 {
39   COLUMN_PLUGIN,
40   NUM_COLUMNS
41 };
42 
43 struct bg_gtk_plugin_widget_multi_s
44   {
45   GtkWidget * info_button;
46   GtkWidget * config_button;
47 
48   GtkWidget * treeview;
49   GtkWidget * widget;
50   GtkWidget * protocols;
51   GtkWidget * extensions;
52   GtkWidget * priority;
53 
54   bg_plugin_registry_t * reg;
55   const bg_plugin_info_t * info;
56 
57   bg_parameter_info_t * parameters;
58 
59   bg_cfg_section_t * section;
60 
61   gulong extensions_changed_id;
62   gulong protocols_changed_id;
63   gulong priority_changed_id;
64 
65   uint32_t flag_mask;
66   uint32_t type_mask;
67 
68   };
69 
button_callback(GtkWidget * w,gpointer data)70 static void button_callback(GtkWidget * w, gpointer data)
71   {
72   bg_gtk_plugin_widget_multi_t * win;
73   bg_dialog_t * dialog;
74 
75   win = (bg_gtk_plugin_widget_multi_t *)data;
76 
77   if(w == win->info_button)
78     {
79     bg_gtk_plugin_info_show(win->info, win->info_button);
80     }
81   else if(w == win->config_button)
82     {
83     dialog = bg_dialog_create(win->section,
84                               NULL, NULL, NULL,
85                               win->info->parameters,
86                               TRD(win->info->long_name, win->info->gettext_domain));
87     bg_dialog_show(dialog, win->config_button);
88     bg_dialog_destroy(dialog);
89     }
90   }
91 
select_row_callback(GtkTreeSelection * s,gpointer data)92 static void select_row_callback(GtkTreeSelection * s, gpointer data)
93   {
94   GtkTreeModel * model;
95   GtkTreeIter iter;
96 
97   int selected, i;
98 
99   bg_gtk_plugin_widget_multi_t * win = (bg_gtk_plugin_widget_multi_t*)data;
100 
101   model = gtk_tree_view_get_model(GTK_TREE_VIEW(win->treeview));
102 
103   if(!gtk_tree_model_get_iter_first(model, &iter))
104     return;
105   selected = -1;
106   i = 0;
107   while(1)
108     {
109     if(gtk_tree_selection_iter_is_selected(s, &iter))
110       {
111       selected = i;
112       break;
113       }
114     gtk_tree_model_iter_next(model, &iter);
115     i++;
116     }
117   if(selected == -1)
118     return;
119 
120   win->info = bg_plugin_find_by_index(win->reg, selected, win->type_mask,
121                                       win->flag_mask);
122 
123   if(win->info->parameters)
124     win->parameters = win->info->parameters;
125   else
126     win->parameters = NULL;
127 
128   win->section = bg_plugin_registry_get_section(win->reg, win->info->name);
129 
130   if(win->parameters)
131     gtk_widget_set_sensitive(win->config_button, 1);
132   else
133     gtk_widget_set_sensitive(win->config_button, 0);
134 
135   if(win->extensions)
136     {
137     g_signal_handler_block(G_OBJECT(win->extensions),
138                            win->extensions_changed_id);
139     if((win->info->flags & BG_PLUGIN_FILE) && win->info->extensions)
140       {
141       gtk_entry_set_text(GTK_ENTRY(win->extensions),
142                          win->info->extensions);
143       gtk_widget_set_sensitive(win->extensions, 1);
144       }
145     else
146       {
147       gtk_entry_set_text(GTK_ENTRY(win->extensions), "");
148       gtk_widget_set_sensitive(win->extensions, 0);
149       }
150     g_signal_handler_unblock(G_OBJECT(win->extensions),
151                              win->extensions_changed_id);
152 
153     }
154   if(win->protocols)
155     {
156     g_signal_handler_block(G_OBJECT(win->protocols),
157                            win->protocols_changed_id);
158     if(win->info->flags & BG_PLUGIN_URL)
159       {
160       gtk_entry_set_text(GTK_ENTRY(win->protocols),
161                          win->info->protocols);
162       gtk_widget_set_sensitive(win->protocols, 1);
163       }
164     else if(win->info->flags & (BG_PLUGIN_REMOVABLE | BG_PLUGIN_TUNER))
165       {
166       gtk_entry_set_text(GTK_ENTRY(win->protocols),
167                          win->info->protocols);
168       gtk_widget_set_sensitive(win->protocols, 0);
169       }
170     else
171       {
172       gtk_entry_set_text(GTK_ENTRY(win->protocols), "");
173       gtk_widget_set_sensitive(win->protocols, 0);
174       }
175     g_signal_handler_unblock(G_OBJECT(win->protocols),
176                              win->protocols_changed_id);
177 
178     }
179 
180 
181   gtk_widget_set_sensitive(win->info_button, 1);
182 
183   if(win->priority)
184     {
185     g_signal_handler_block(G_OBJECT(win->priority), win->priority_changed_id);
186     gtk_spin_button_set_value(GTK_SPIN_BUTTON(win->priority), win->info->priority);
187     g_signal_handler_unblock(G_OBJECT(win->priority), win->priority_changed_id);
188 
189     if(win->info->flags & (BG_PLUGIN_URL | BG_PLUGIN_FILE))
190       gtk_widget_set_sensitive(win->priority, 1);
191     else
192       gtk_widget_set_sensitive(win->priority, 0);
193     }
194   }
195 
change_callback(GtkWidget * w,gpointer data)196 static void change_callback(GtkWidget * w, gpointer data)
197   {
198   bg_gtk_plugin_widget_multi_t * win = (bg_gtk_plugin_widget_multi_t*)data;
199   if(w == win->extensions)
200     {
201     bg_plugin_registry_set_extensions(win->reg, win->info->name,
202                                       gtk_entry_get_text(GTK_ENTRY(win->extensions)));
203     }
204   else if(w == win->protocols)
205     {
206     bg_plugin_registry_set_protocols(win->reg, win->info->name,
207                                      gtk_entry_get_text(GTK_ENTRY(win->protocols)));
208 
209     }
210   else if(w == win->priority)
211     {
212     bg_plugin_registry_set_priority(win->reg, win->info->name,
213                                     gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(win->priority)));
214     }
215   }
216 
create_pixmap_button(const char * filename,const char * tooltip)217 static GtkWidget * create_pixmap_button(const char * filename,
218                                         const char * tooltip)
219   {
220   GtkWidget * button;
221   GtkWidget * image;
222   char * path;
223   path = bg_search_file_read("icons", filename);
224   if(path)
225     {
226     image = gtk_image_new_from_file(path);
227     free(path);
228     }
229   else
230     image = gtk_image_new();
231 
232   gtk_widget_show(image);
233   button = gtk_button_new();
234   gtk_container_add(GTK_CONTAINER(button), image);
235 
236   bg_gtk_tooltips_set_tip(button, tooltip, PACKAGE);
237 
238   return button;
239   }
240 
241 bg_gtk_plugin_widget_multi_t *
bg_gtk_plugin_widget_multi_create(bg_plugin_registry_t * reg,uint32_t type_mask,uint32_t flag_mask)242 bg_gtk_plugin_widget_multi_create(bg_plugin_registry_t * reg,
243                                   uint32_t type_mask,
244                                   uint32_t flag_mask)
245   {
246   bg_gtk_plugin_widget_multi_t * ret;
247   GtkListStore *store;
248   GtkTreeViewColumn *column;
249   GtkTreeIter iter;
250   GtkCellRenderer *renderer;
251   GtkWidget * label;
252   GtkWidget * scrolled;
253   GtkWidget * table;
254   GtkTreeSelection * selection;
255   GtkWidget * hbox;
256 
257   const bg_plugin_info_t * info;
258 
259   int num_plugins, i;
260 
261   ret = calloc(1,sizeof(*ret));
262 
263   ret->reg = reg;
264 
265   ret->type_mask = type_mask;
266   ret->flag_mask = flag_mask;
267 
268   /* Create buttons */
269 
270   ret->info_button = create_pixmap_button("info_16.png", TRS("Plugin info"));
271 
272   ret->config_button = create_pixmap_button("config_16.png",
273                                             TRS("Plugin options"));
274 
275   g_signal_connect(G_OBJECT(ret->info_button),
276                    "clicked", G_CALLBACK(button_callback),
277                    (gpointer)ret);
278   g_signal_connect(G_OBJECT(ret->config_button),
279                    "clicked", G_CALLBACK(button_callback),
280                    (gpointer)ret);
281 
282   gtk_widget_show(ret->info_button);
283   gtk_widget_show(ret->config_button);
284 
285   /* Create list */
286 
287   store = gtk_list_store_new(NUM_COLUMNS, G_TYPE_STRING);
288   ret->treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
289 
290   selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ret->treeview));
291 
292   g_signal_connect(G_OBJECT(selection),
293                    "changed", G_CALLBACK(select_row_callback),
294                    (gpointer)ret);
295 
296   renderer = gtk_cell_renderer_text_new ();
297   column = gtk_tree_view_column_new_with_attributes ("Installed Plugins",
298                                                      renderer,
299                                                      "text",
300                                                      COLUMN_PLUGIN,
301                                                      NULL);
302   gtk_tree_view_column_set_sort_column_id (column, COLUMN_PLUGIN);
303   gtk_tree_view_append_column (GTK_TREE_VIEW(ret->treeview), column);
304   gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(ret->treeview), FALSE);
305 
306   gtk_widget_show(ret->treeview);
307 
308   scrolled =
309     gtk_scrolled_window_new(gtk_tree_view_get_hadjustment(GTK_TREE_VIEW(ret->treeview)),
310                             gtk_tree_view_get_vadjustment(GTK_TREE_VIEW(ret->treeview)));
311 
312   gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
313                                  GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
314   gtk_container_add(GTK_CONTAINER(scrolled), ret->treeview);
315   gtk_widget_show(scrolled);
316 
317 
318   /* Add Plugins */
319 
320   num_plugins = bg_plugin_registry_get_num_plugins(reg,
321                                                    type_mask,
322                                                    flag_mask);
323 
324   for(i = 0; i < num_plugins; i++)
325     {
326     info = bg_plugin_find_by_index(reg, i, type_mask, flag_mask);
327     gtk_list_store_append(store, &iter);
328     gtk_list_store_set(store, &iter,
329                        COLUMN_PLUGIN,
330                        TRD(info->long_name, info->gettext_domain),
331                        -1);
332     }
333 
334   /* Create entries */
335 
336   if(type_mask & (BG_PLUGIN_INPUT | BG_PLUGIN_IMAGE_READER))
337     {
338     ret->extensions = gtk_entry_new();
339     ret->protocols = gtk_entry_new();
340     ret->priority = gtk_spin_button_new_with_range(BG_PLUGIN_PRIORITY_MIN,
341                                                    BG_PLUGIN_PRIORITY_MAX, 1.0);
342 
343     ret->extensions_changed_id =
344       g_signal_connect(G_OBJECT(ret->extensions),
345                        "changed", G_CALLBACK(change_callback),
346                        (gpointer)ret);
347 
348     ret->protocols_changed_id =
349       g_signal_connect(G_OBJECT(ret->protocols),
350                        "changed", G_CALLBACK(change_callback),
351                        (gpointer)ret);
352 
353     ret->priority_changed_id =
354       g_signal_connect(G_OBJECT(ret->priority),
355                        "value-changed", G_CALLBACK(change_callback),
356                        (gpointer)ret);
357 
358 
359     gtk_widget_show(ret->protocols);
360     gtk_widget_show(ret->extensions);
361     gtk_widget_show(ret->priority);
362     }
363 
364 
365   /* Pack stuff */
366 
367   table = gtk_table_new(5, 4, 0);
368   gtk_container_set_border_width(GTK_CONTAINER(table), 5);
369   gtk_table_set_row_spacings(GTK_TABLE(table), 5);
370   gtk_table_set_col_spacings(GTK_TABLE(table), 5);
371 
372 
373 
374   //   gtk_table_attach_defaults(GTK_TABLE(table), scrolled, 0, 1, 0, 5);
375 
376   gtk_table_attach(GTK_TABLE(table),
377                    ret->config_button, 0, 1, 0, 1, GTK_FILL, GTK_SHRINK, 0, 0);
378 
379   if(ret->priority)
380     {
381     gtk_table_attach(GTK_TABLE(table),
382                      ret->info_button, 1, 2, 0, 1, GTK_FILL, GTK_SHRINK, 0, 0);
383 
384     label = gtk_label_new(TR("Priority"));
385     gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
386     gtk_widget_show(label);
387     gtk_table_attach(GTK_TABLE(table), label, 2, 3, 0, 1, GTK_FILL,
388                      GTK_SHRINK, 0, 0);
389     gtk_table_attach(GTK_TABLE(table), ret->priority, 3, 4, 0, 1, GTK_FILL|GTK_EXPAND,
390                      GTK_SHRINK, 0, 0);
391 
392 
393 
394     label = gtk_label_new(TR("Protocols"));
395     gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
396     gtk_widget_show(label);
397     gtk_table_attach(GTK_TABLE(table), label, 0, 4, 1, 2, GTK_FILL|GTK_EXPAND,
398                      GTK_SHRINK, 0, 0);
399     gtk_table_attach(GTK_TABLE(table), ret->protocols, 0, 4, 2, 3, GTK_FILL|GTK_EXPAND,
400                      GTK_SHRINK, 0, 0);
401 
402     label = gtk_label_new(TR("Extensions"));
403     gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
404     gtk_widget_show(label);
405 
406     gtk_table_attach(GTK_TABLE(table), label, 0, 4, 3, 4, GTK_FILL|GTK_EXPAND, GTK_SHRINK, 0, 0);
407   gtk_table_attach(GTK_TABLE(table),
408                    ret->extensions, 0, 4, 4, 5, GTK_FILL|GTK_EXPAND, GTK_SHRINK, 0, 0);
409     }
410   else
411     {
412     gtk_table_attach(GTK_TABLE(table),
413                      ret->info_button, 0, 1, 1, 2,
414                      GTK_FILL, GTK_SHRINK, 0, 0);
415 
416     }
417 
418 
419   gtk_widget_show(table);
420 
421   hbox = gtk_hpaned_new();
422 
423   gtk_paned_add1(GTK_PANED(hbox), scrolled);
424   gtk_paned_add2(GTK_PANED(hbox), table);
425   gtk_widget_show(hbox);
426   ret->widget = hbox;
427   /* Make things insensitive, because nothing is selected so far */
428 
429   if(ret->priority)
430     gtk_widget_set_sensitive(ret->priority, 0);
431   if(ret->protocols)
432     gtk_widget_set_sensitive(ret->protocols, 0);
433 
434   if(ret->extensions)
435     gtk_widget_set_sensitive(ret->extensions, 0);
436 
437   gtk_widget_set_sensitive(ret->config_button, 0);
438   gtk_widget_set_sensitive(ret->info_button, 0);
439 
440   return ret;
441   }
442 
443 GtkWidget *
bg_gtk_plugin_widget_multi_get_widget(bg_gtk_plugin_widget_multi_t * w)444 bg_gtk_plugin_widget_multi_get_widget(bg_gtk_plugin_widget_multi_t * w)
445   {
446   return w->widget;
447   }
448 
bg_gtk_plugin_widget_multi_destroy(bg_gtk_plugin_widget_multi_t * w)449 void bg_gtk_plugin_widget_multi_destroy(bg_gtk_plugin_widget_multi_t * w)
450   {
451   free(w);
452   }
453