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.
21 #include <gdk/gdkkeysyms.h>
26 #include "playlist3.h"
27 #include "playlist3-find2-browser.h"
28 #include "gmpc-mpddata-model.h"
29 #include "gmpc-mpddata-treeview.h"
30 #include "advanced-search.h"
31 #include "playlist3-playlist-editor.h"
33 static void pl3_find2_browser_destroy(void);
34 static void pl3_find2_browser_selected(GtkWidget
*);
35 static void pl3_find2_browser_unselected(GtkWidget
*);
36 static void pl3_find2_browser_add(GtkWidget
* cat_tree
);
37 static int pl3_find2_browser_add_go_menu(GtkWidget
*);
38 static void pl3_find2_browser_search(void);
39 static int pl3_find2_browser_playlist_key_press(GtkWidget
*, GdkEventKey
*);
40 static void pl3_find2_browser_connection_changed(MpdObj
* mi
, int connect
, gpointer data
);
41 static gboolean
pl3_find2_entry_key_press_event(GtkWidget
* entry
, GdkEventKey
* event
, gpointer data
);
42 static void pl3_find2_browser_status_changed(MpdObj
* mi
, ChangedStatusType what
, void *data
);
44 static void pl3_find2_entry_changed(GtkWidget
* entry
, gpointer data
);
45 static void pl3_find2_save_myself(void);
47 /* Playlist window row reference */
48 static GtkTreeRowReference
*pl3_find2_ref
= NULL
;
51 static GtkWidget
*pl3_find2_curpl
= NULL
;
52 static GtkListStore
*pl3_find2_curpl_model
= NULL
;
53 static GtkWidget
*pl3_find2_tree
= NULL
;
54 static GmpcMpdDataModel
*pl3_find2_store2
= NULL
;
55 static GtkWidget
*pl3_find2_vbox
= NULL
;
56 static GtkListStore
*pl3_find2_combo_store
= NULL
;
57 static GtkListStore
*pl3_find2_autocomplete
= NULL
;
59 static GtkWidget
*search_combo
= NULL
;
60 static GtkWidget
*search_entry
= NULL
;
62 #define QUERY_ENTRY MPD_TAG_NUM_OF_ITEM_TYPES
63 static void pl3_find2_fill_combo(gmpcPluginParent
* plug
)
66 int i
= 0, max
= MPD_TAG_NUM_OF_ITEM_TYPES
;
67 gtk_list_store_clear(pl3_find2_combo_store
);
69 for (i
= 0; i
< max
; i
++)
71 if (plug
== NULL
|| gmpc_plugin_browser_integrate_search_field_supported(plug
, i
))
73 gtk_list_store_append(pl3_find2_combo_store
, &iter
);
74 gtk_list_store_set(pl3_find2_combo_store
, &iter
, 1, mpdTagItemKeys
[i
], 0, i
, -1);
77 if (plug
== NULL
|| gmpc_plugin_browser_integrate_search_field_supported(plug
, QUERY_ENTRY
))
79 gtk_list_store_append(pl3_find2_combo_store
, &iter
);
80 gtk_list_store_set(pl3_find2_combo_store
, &iter
, 1, _("Query"), 0, QUERY_ENTRY
, -1);
84 static void pl3_find2_combo_box_field_changed(GtkComboBox
* cb
, gpointer data
)
87 if (gtk_combo_box_get_active_iter(cb
, &iter
))
90 gtk_tree_model_get(GTK_TREE_MODEL(pl3_find2_combo_store
), &iter
, 0, &selected_type
, -1);
91 if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(data
), &iter
))
95 gtk_tree_model_get(gtk_combo_box_get_model(GTK_COMBO_BOX(data
)), &iter
, 0, &type
, -1);
98 cfield
= g_strdup_printf("selected_type_%s", type
);
100 cfg_set_single_value_as_int(config
, "find2-browser", cfield
, selected_type
);
107 static void playtime_changed(GmpcMpdDataModel
* model
, gulong playtime
)
111 static void pl3_find2_browser_type_plugin_changed(GtkComboBox
* box
, gpointer user_data
)
114 GtkTreeModel
*model
= gtk_combo_box_get_model(box
);
115 gmpcPluginParent
*plug
= NULL
;
116 gchar
*cfield
= NULL
;
120 /* this should always be active */
121 if (gtk_combo_box_get_active_iter(box
, &iter
))
123 gtk_tree_model_get(GTK_TREE_MODEL(model
), &iter
, 0, &type
, 2, &plug
, -1);
124 pl3_find2_fill_combo(plug
);
127 cfield
= g_strdup_printf("selected_type_%s", type
);
128 selected_type
= cfg_get_single_value_as_int_with_default(config
, "find2-browser", cfield
, 0);
131 /* Loop through the field until the match is found */
132 for (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(pl3_find2_combo_store
), &iter
);
133 gtk_list_store_iter_is_valid(pl3_find2_combo_store
, &iter
);
134 gtk_tree_model_iter_next(GTK_TREE_MODEL(pl3_find2_combo_store
), &iter
))
137 gtk_tree_model_get(GTK_TREE_MODEL(pl3_find2_combo_store
), &iter
, 0, &sel_type
, -1);
138 if (sel_type
== selected_type
)
140 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(search_combo
), &iter
);
144 /* default, if nothing is found. */
145 gtk_combo_box_set_active(GTK_COMBO_BOX(search_combo
), 0);
148 static void pl3_find2_browser_clear_search_entry(GtkEntry
* entry
, GtkEntryIconPosition icon_pos
, GdkEvent
* event
,
151 if (icon_pos
== GTK_ENTRY_ICON_SECONDARY
)
153 gtk_entry_set_text(GTK_ENTRY(entry
), "");
158 * Construct the browser
160 static void pl3_find2_browser_init(void)
163 GtkWidget
*pl3_find2_sw
= NULL
;
164 GtkWidget
*hbox
= NULL
;
165 GtkCellRenderer
*renderer
;
166 GtkEntryCompletion
*entrcomp
;
168 /* autocomplete later on */
169 pl3_find2_autocomplete
= gtk_list_store_new(1, G_TYPE_STRING
);
171 pl3_find2_store2
= gmpc_mpddata_model_new();
172 gmpc_mpddata_model_disable_image(GMPC_MPDDATA_MODEL(pl3_find2_store2
));
173 g_signal_connect(G_OBJECT(pl3_find2_store2
), "playtime_changed", G_CALLBACK(playtime_changed
), NULL
);
175 pl3_find2_combo_store
= gtk_list_store_new(2, G_TYPE_INT
, G_TYPE_STRING
);
177 pl3_find2_fill_combo(NULL
);
180 /* set up the tree */
181 pl3_find2_tree
= (GtkWidget
*)gmpc_data_view_new("find2-browser",FALSE
);
183 g_signal_connect(G_OBJECT(pl3_find2_tree
), "key-press-event", G_CALLBACK(pl3_find2_browser_playlist_key_press
),
186 /* set up the scrolled window */
187 pl3_find2_sw
= gtk_scrolled_window_new(NULL
, NULL
);
188 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(pl3_find2_sw
), GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
189 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(pl3_find2_sw
), GTK_SHADOW_ETCHED_IN
);
190 gtk_container_add(GTK_CONTAINER(pl3_find2_sw
), pl3_find2_tree
);
192 /* set initial state */
194 pl3_find2_vbox
= gtk_box_new(GTK_ORIENTATION_VERTICAL
, 6);
195 gtk_box_pack_start(GTK_BOX(pl3_find2_vbox
), pl3_find2_sw
, TRUE
, TRUE
, 0);
197 /** Add a default item */
198 hbox
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 6);
200 /* search in playlist */
201 pl3_find2_curpl_model
= gtk_list_store_new(3, G_TYPE_STRING
, G_TYPE_INT
, G_TYPE_POINTER
);
202 pl3_find2_curpl
= gtk_combo_box_new_with_model(GTK_TREE_MODEL(pl3_find2_curpl_model
));
203 renderer
= gtk_cell_renderer_text_new();
204 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(pl3_find2_curpl
), renderer
, TRUE
);
205 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(pl3_find2_curpl
), renderer
, "text", 0, NULL
);
207 for (i
= 0; i
< num_plugins
; i
++)
209 if (gmpc_plugin_get_enabled(plugins
[i
]))
211 if (gmpc_plugin_is_browser(plugins
[i
]))
213 if (gmpc_plugin_browser_has_integrate_search(plugins
[i
]))
216 gtk_list_store_append(GTK_LIST_STORE(pl3_find2_curpl_model
), &titer
);
217 gtk_list_store_set(GTK_LIST_STORE(pl3_find2_curpl_model
), &titer
,
218 0, gmpc_plugin_get_name(plugins
[i
]), 1, 0, 2, plugins
[i
], -1);
224 gtk_combo_box_set_active(GTK_COMBO_BOX(pl3_find2_curpl
), 0);
225 g_signal_connect(G_OBJECT(pl3_find2_curpl
), "changed", G_CALLBACK(pl3_find2_browser_type_plugin_changed
), NULL
);
227 gtk_box_pack_start(GTK_BOX(hbox
), pl3_find2_curpl
, FALSE
, TRUE
, 0);
230 search_combo
= gtk_combo_box_new();
232 renderer
= gtk_cell_renderer_text_new();
233 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(search_combo
), renderer
, TRUE
);
234 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(search_combo
), renderer
, "text", 1, NULL
);
235 gtk_combo_box_set_model(GTK_COMBO_BOX(search_combo
), GTK_TREE_MODEL(pl3_find2_combo_store
));
237 /* Update the tag combo to the right field */
238 pl3_find2_browser_type_plugin_changed(GTK_COMBO_BOX(pl3_find2_curpl
), NULL
);
240 gtk_box_pack_start(GTK_BOX(hbox
), search_combo
, FALSE
, TRUE
, 0);
241 g_signal_connect(G_OBJECT(search_combo
), "changed", G_CALLBACK(pl3_find2_combo_box_field_changed
), pl3_find2_curpl
);
245 search_entry
= gtk_entry_new();
246 gtk_entry_set_icon_from_stock(GTK_ENTRY(search_entry
), GTK_ENTRY_ICON_SECONDARY
, GTK_STOCK_CLEAR
);
247 g_signal_connect(GTK_ENTRY(search_entry
), "icon-press", G_CALLBACK(pl3_find2_browser_clear_search_entry
), NULL
);
250 entrcomp
= gtk_entry_completion_new();
251 gtk_entry_completion_set_text_column(entrcomp
, 0);
252 gtk_entry_completion_set_inline_completion(entrcomp
, TRUE
);
253 gtk_entry_completion_set_model(GTK_ENTRY_COMPLETION(entrcomp
), GTK_TREE_MODEL(pl3_find2_autocomplete
));
254 gtk_entry_completion_set_popup_completion(GTK_ENTRY_COMPLETION(entrcomp
), TRUE
);
255 gtk_entry_set_completion(GTK_ENTRY(search_entry
), entrcomp
);
257 g_signal_connect(G_OBJECT(search_entry
), "activate", G_CALLBACK(pl3_find2_browser_search
), NULL
);
258 g_signal_connect(G_OBJECT(search_entry
), "key-press-event", G_CALLBACK(pl3_find2_entry_key_press_event
), NULL
);
259 g_signal_connect(G_OBJECT(search_entry
), "changed", G_CALLBACK(pl3_find2_entry_changed
), NULL
);
260 gtk_box_pack_start(GTK_BOX(hbox
), search_entry
, TRUE
, TRUE
, 0);
263 button
= gtk_button_new_from_stock(GTK_STOCK_FIND
);
264 g_signal_connect(G_OBJECT(button
), "clicked", G_CALLBACK(pl3_find2_browser_search
), NULL
);
265 gtk_box_pack_start(GTK_BOX(hbox
), button
, FALSE
, TRUE
, 0);
267 gtk_box_pack_start(GTK_BOX(pl3_find2_vbox
), hbox
, FALSE
, TRUE
, 0);
269 gtk_widget_show_all(pl3_find2_vbox
);
270 g_object_ref_sink(G_OBJECT(pl3_find2_vbox
));
273 static void pl3_find2_browser_selected(GtkWidget
* container
)
275 if (pl3_find2_tree
== NULL
)
277 pl3_find2_browser_init();
279 gtk_container_add(GTK_CONTAINER(container
), pl3_find2_vbox
);
280 gtk_widget_grab_focus(pl3_find2_tree
);
281 gtk_widget_show(pl3_find2_vbox
);
284 static void pl3_find2_browser_unselected(GtkWidget
* container
)
286 gtk_container_remove(GTK_CONTAINER(container
), pl3_find2_vbox
);
289 /*****************************************************************
292 static void pl3_find2_browser_add(GtkWidget
* cat_tree
)
294 GtkTreePath
*path
= NULL
;
296 gint pos
= cfg_get_single_value_as_int_with_default(config
, "find2-browser", "position", 4);
297 playlist3_insert_browser(&iter
, PL3_CAT_BROWSER_LIBRARY
+pos
%PL3_CAT_BROWSER_LIBRARY
);
298 gtk_list_store_set(GTK_LIST_STORE(pl3_tree
), &iter
,
299 PL3_CAT_TYPE
, find2_browser_plug
.id
,
300 PL3_CAT_TITLE
, _("Search"),
301 PL3_CAT_ICON_ID
, GTK_STOCK_FIND
,
306 gtk_tree_row_reference_free(pl3_find2_ref
);
307 pl3_find2_ref
= NULL
;
310 path
= gtk_tree_model_get_path(GTK_TREE_MODEL(playlist3_get_category_tree_store()), &iter
);
313 pl3_find2_ref
= gtk_tree_row_reference_new(GTK_TREE_MODEL(playlist3_get_category_tree_store()), path
);
314 gtk_tree_path_free(path
);
321 static void pl3_find2_browser_search(void)
323 GtkTreeIter iter
, cc_iter
;
324 if (pl3_find2_vbox
== NULL
)
327 gtk_tree_view_set_model(GTK_TREE_VIEW(pl3_find2_tree
), NULL
);
328 if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(pl3_find2_curpl
), &iter
))
332 gmpcPluginParent
*plug
= NULL
;
333 gtk_tree_model_get(GTK_TREE_MODEL(pl3_find2_curpl_model
), &iter
, 1, &type
, 2, &plug
, -1);
335 if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(search_combo
), &cc_iter
))
337 GError
*error
= NULL
;
338 MpdData
*data_t
= NULL
;
339 const gchar
*real_name
= gtk_entry_get_text(GTK_ENTRY(search_entry
));
340 gchar
*name
= g_strstrip(g_strdup(real_name
));
341 gtk_tree_model_get(GTK_TREE_MODEL(pl3_find2_combo_store
), &cc_iter
, 0, &num_field
, -1);
343 data_t
= gmpc_plugin_browser_integrate_search(plug
, num_field
, name
, &error
);
347 g_markup_printf_escaped("<b>%s</b> %s: %s", gmpc_plugin_get_name(plug
), _("Search failed"),
349 playlist3_show_error_message(mes
, ERROR_WARNING
);
354 gmpc_mpddata_model_set_mpd_data(pl3_find2_store2
, data_t
);
355 /* update autocompletion */
359 for (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(pl3_find2_autocomplete
), &iter
);
360 gtk_list_store_iter_is_valid(pl3_find2_autocomplete
, &iter
) && !found2
;
361 gtk_tree_model_iter_next(GTK_TREE_MODEL(pl3_find2_autocomplete
), &iter
))
364 gtk_tree_model_get(GTK_TREE_MODEL(pl3_find2_autocomplete
), &iter
, 0, &entry
, -1);
365 if (strcmp(entry
, name
) == 0)
373 gtk_list_store_insert_with_values(pl3_find2_autocomplete
, &iter
, -1, 0, name
, -1);
379 gtk_tree_view_set_model(GTK_TREE_VIEW(pl3_find2_tree
), GTK_TREE_MODEL(pl3_find2_store2
));
383 static int pl3_find2_browser_playlist_key_press(GtkWidget
* tree
, GdkEventKey
* event
)
385 /* Make ctrl-f focus the search entry */
386 if (event
->keyval
== GDK_KEY_f
&& event
->state
& GDK_CONTROL_MASK
)
388 gtk_widget_grab_focus(GTK_WIDGET(search_entry
));
391 else if (event
->keyval
== GDK_KEY_slash
)
393 gtk_widget_grab_focus(GTK_WIDGET(search_entry
));
398 return pl3_window_key_press_event(tree
, event
);
405 static void pl3_find2_browser_activate(void)
407 GtkTreeSelection
*selec
= gtk_tree_view_get_selection(GTK_TREE_VIEW(gtk_builder_get_object(pl3_xml
, "cat_tree")));
409 GtkTreePath
*path
= gtk_tree_row_reference_get_path(pl3_find2_ref
);
412 gtk_tree_selection_select_path(selec
, path
);
413 gtk_tree_path_free(path
);
415 gtk_widget_grab_focus(GTK_WIDGET(search_entry
));
418 static int pl3_find2_browser_add_go_menu(GtkWidget
* menu
)
420 GtkWidget
*item
= NULL
;
422 item
= gtk_image_menu_item_new_with_label(_("Search"));
423 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item
),
424 gtk_image_new_from_icon_name("gtk-find", GTK_ICON_SIZE_MENU
));
425 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), item
);
426 gtk_widget_add_accelerator(GTK_WIDGET(item
),
427 "activate", gtk_menu_get_accel_group(GTK_MENU(menu
)), GDK_KEY_F3
, 0, GTK_ACCEL_VISIBLE
);
428 g_signal_connect(G_OBJECT(item
), "activate", G_CALLBACK(pl3_find2_browser_activate
), NULL
);
433 static void pl3_find2_browser_connection_changed(MpdObj
* mi
, int connect
, gpointer data
)
439 pl3_find2_browser_type_plugin_changed(GTK_COMBO_BOX(pl3_find2_curpl
), NULL
);
440 pl3_find2_browser_search();
444 void pl3_find2_select_plugin_id(int id
)
448 pl3_find2_browser_activate();
449 model
= gtk_combo_box_get_model(GTK_COMBO_BOX(pl3_find2_curpl
));
450 if (gtk_tree_model_get_iter_first(model
, &iter
))
455 gmpcPluginParent
*plug
;
456 gtk_tree_model_get(model
, &iter
, 2, &plug
, -1);
457 if (plug
!= NULL
&& gmpc_plugin_get_id(plug
) == id
)
459 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(pl3_find2_curpl
), &iter
);
462 } while (gtk_tree_model_iter_next(model
, &iter
) && found
);
464 gtk_widget_grab_focus(search_entry
);
467 static guint entry_timeout
= 0;
469 static gboolean
do_entry_changed_search(GtkEntry
* entry
)
471 pl3_find2_browser_search();
476 static void pl3_find2_entry_changed(GtkWidget
* entry
, gpointer data
)
478 if (entry_timeout
> 0)
480 g_source_remove(entry_timeout
);
483 if (cfg_get_single_value_as_int_with_default(config
, "general", "search-as-you-type", 0) == 1)
485 entry_timeout
= g_timeout_add(250, (GSourceFunc
) do_entry_changed_search
, entry
);
489 static gboolean
pl3_find2_entry_key_press_event(GtkWidget
* entry
, GdkEventKey
* event
, gpointer data
)
491 if (event
->keyval
== GDK_KEY_Escape
)
492 gtk_entry_set_text(GTK_ENTRY(entry
), "");
497 static void pl3_find2_browser_destroy(void)
503 path
= gtk_tree_row_reference_get_path(pl3_find2_ref
);
506 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(gtk_tree_row_reference_get_model(pl3_find2_ref
)), &iter
, path
))
508 gtk_list_store_remove(GTK_LIST_STORE(gtk_tree_row_reference_get_model(pl3_find2_ref
)), &iter
);
510 gtk_tree_path_free(path
);
512 gtk_tree_row_reference_free(pl3_find2_ref
);
513 pl3_find2_ref
= NULL
;
517 gtk_widget_destroy(pl3_find2_vbox
);
518 pl3_find2_vbox
= NULL
;
520 if (pl3_find2_store2
)
522 g_object_unref(pl3_find2_store2
);
523 pl3_find2_store2
= NULL
;
527 static void pl3_find2_browser_status_changed(MpdObj
* mi
, ChangedStatusType what
, void *data
)
529 if (what
& MPD_CST_DATABASE
)
531 pl3_find2_browser_search();
533 if (what
& MPD_CST_PERMISSION
)
536 pl3_find2_browser_type_plugin_changed(GTK_COMBO_BOX(pl3_find2_curpl
), NULL
);
540 static void pl3_find2_save_myself(void)
544 GtkTreePath
*path
= gtk_tree_row_reference_get_path(pl3_find2_ref
);
547 gint
*indices
= gtk_tree_path_get_indices(path
);
548 cfg_set_single_value_as_int(config
, "find2-browser", "position", indices
[0]);
549 gtk_tree_path_free(path
);
554 /* Easy command integration */
556 void pl3_find2_do_search_any(const char *param
)
560 model
= gtk_combo_box_get_model(GTK_COMBO_BOX(search_combo
));
561 if (gtk_tree_model_get_iter_first(model
, &iter
))
567 gtk_tree_model_get(model
, &iter
, 0, &field
, -1);
568 if (field
== QUERY_ENTRY
)
570 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(search_combo
), &iter
);
573 } while (gtk_tree_model_iter_next(model
, &iter
) && found
);
575 gtk_entry_set_text(GTK_ENTRY(search_entry
), param
);
576 gtk_widget_activate(search_entry
);
579 static void pl3_find2_plugin_init(void)
581 gmpc_easy_command_add_entry(gmpc_easy_command
,
582 _("switch search"), "",
583 _("Switch to the search browser"),
584 (GmpcEasyCommandCallback
*) pl3_find2_browser_activate
, NULL
);
588 static int pl3_find2_get_enabled(void)
590 return cfg_get_single_value_as_int_with_default(config
, "find2-browser", "enable", TRUE
);
594 static void pl3_find2_set_enabled(int enabled
)
596 cfg_set_single_value_as_int(config
, "find2-browser", "enable", enabled
);
597 if (enabled
&& !pl3_find2_ref
)
599 GtkTreeView
*tree
= playlist3_get_category_tree_view();
600 pl3_find2_browser_add((GtkWidget
*) tree
);
601 } else if (!enabled
&& pl3_find2_ref
)
603 pl3_find2_browser_destroy();
609 gmpcPlBrowserPlugin find2_browser_gbp
= {
610 .add
= pl3_find2_browser_add
,
611 .selected
= pl3_find2_browser_selected
,
612 .unselected
= pl3_find2_browser_unselected
,
613 .add_go_menu
= pl3_find2_browser_add_go_menu
,
616 gmpcPlugin find2_browser_plug
= {
617 .name
= N_("Search Browser"),
618 .version
= {1, 1, 1},
619 .plugin_type
= GMPC_PLUGIN_PL_BROWSER
| GMPC_INTERNALL
,
620 .init
= pl3_find2_plugin_init
,
621 .destroy
= pl3_find2_browser_destroy
,
622 .browser
= &find2_browser_gbp
,
623 .mpd_status_changed
= pl3_find2_browser_status_changed
,
624 .mpd_connection_changed
= pl3_find2_browser_connection_changed
,
625 .save_yourself
= pl3_find2_save_myself
,
626 .get_enabled
= pl3_find2_get_enabled
,
627 .set_enabled
= pl3_find2_set_enabled
,