2 * library.c -- GTK+ 2 melted gui
3 * Copyright (C) 2012 Maksym Veremeyenko <verem@m1stereo.tv>
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
16 * along with this program; if not, write to the Free Software Foundation,
17 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
32 #include <gdk/gdkkeysyms.h>
36 #include <mvcp/mvcp.h>
37 #include <mvcp/mvcp_remote.h>
44 extern GtkTargetEntry drag_targets
[];
46 void library_release(instance_t
* app
)
48 mvcp_close(app
->library
.handle
[0]);
49 mvcp_parser_close(app
->library
.handle
[1]);
52 static void library_add_fake(instance_t
* app
, GtkTreeStore
*tree_store
, GtkTreeIter
* parent
)
55 gtk_tree_store_append(tree_store
, &iter
, parent
);
56 gtk_tree_store_set(tree_store
, &iter
, -1);
59 static int library_init_load(instance_t
* app
)
62 GtkTreeStore
*tree_store
;
64 tree_store
= GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(app
->library_tree
)));
65 gtk_tree_store_clear(tree_store
);
67 gtk_tree_store_append(tree_store
, &iter
, NULL
);
68 gtk_tree_store_set(tree_store
, &iter
,
69 0, app
->library
.icons
[0],
77 library_add_fake(app
, tree_store
, &iter
);
79 gtk_tree_view_collapse_all(GTK_TREE_VIEW(app
->library_tree
));
84 static void library_add_item(instance_t
* app
, GtkTreeStore
*treestore
, GtkTreeIter
*iter
,
85 mvcp_dir_entry e
, mvcp_list_entry p
)
87 GtkTreeIter
this, child
;
91 gtk_tree_store_prepend(treestore
, &this, iter
);
93 gtk_tree_store_set(treestore
, &this,
94 0, app
->library
.icons
[0],
103 gtk_tree_store_append(treestore
, &child
, &this);
104 gtk_tree_store_set(treestore
, &child
, -1);
111 frames2tc(p
->size
, p
->fps
, dur
);
113 strcpy(dur
, "<file>");
115 gtk_tree_store_append(treestore
, &this, iter
);
117 gtk_tree_store_set(treestore
, &this,
118 0, app
->library
.icons
[1],
129 static void on_library_row_expanded
131 GtkTreeView
*treeview
,
144 instance_t
* app
= (instance_t
*)user_data
;
147 // g_warning("on_library_row_expanded: HERE");
149 /* Set busy cursor */
150 cursor
= gdk_cursor_new(GDK_WATCH
);
151 gdk_window_set_cursor(gtk_widget_get_toplevel(GTK_WIDGET(treeview
))->window
, cursor
);
152 gdk_cursor_unref(cursor
);
155 model
= gtk_tree_view_get_model(treeview
);
158 gtk_tree_model_iter_children(GTK_TREE_MODEL(model
), &fake
, iter
);
160 /* request mvcp entry */
161 gtk_tree_model_get(GTK_TREE_MODEL(model
), iter
,
165 /* setup root path */
172 dir
= mvcp_dir_init(app
->library
.handle
[0], p
);
173 for (i
= 0; i
< mvcp_dir_count(dir
); i
++)
175 mvcp_dir_entry_t dir_entry
;
176 mvcp_list_entry_t
*list_e
= NULL
, list_entry
;
178 if(mvcp_ok
!= mvcp_dir_get(dir
, i
, &dir_entry
))
181 // g_warning("on_library_row_expanded: path=[%s], entry.dur=[%d], entry.full=[%s], entry.name[%s]",
182 // p, entry.dir, entry.full, entry.name);
184 e
= (mvcp_dir_entry_t
*)malloc(sizeof(mvcp_dir_entry_t
));
187 snprintf(msg
, sizeof(msg
), "probing [%s]", e
->full
);
188 ui_set_status(app
, msg
, 0);
192 if(!e
->dir
&& mvcp_ok
== mvcp_probe_clip( app
->library
.handle
[0], e
->full
, &list_entry
))
194 list_e
= (mvcp_list_entry_t
*)malloc(sizeof(mvcp_list_entry_t
));
195 *list_e
= list_entry
;
200 library_add_item(app
, GTK_TREE_STORE(model
), iter
, e
, list_e
);
203 snprintf(msg
, sizeof(msg
), "read [%s] done", p
);
204 ui_set_status(app
, msg
, 0);
207 gdk_window_set_cursor(gtk_widget_get_toplevel(GTK_WIDGET(treeview
))->window
, NULL
);
209 /* delete fake item */
210 gtk_tree_store_remove(GTK_TREE_STORE(model
), &fake
);
213 static void on_library_row_collapsed
215 GtkTreeView
*treeview
,
223 // g_warning("on_library_row_collapsed: HERE");
225 /* delete all items */
226 model
= gtk_tree_view_get_model(treeview
);
227 while (gtk_tree_model_iter_children(GTK_TREE_MODEL(model
), &child
, iter
))
230 mvcp_list_entry_t
*l
;
232 /* request mvcp entry */
233 gtk_tree_model_get(GTK_TREE_MODEL(model
), &child
,
242 gtk_tree_store_remove(GTK_TREE_STORE(model
), &child
);
245 /* add a fake element */
246 library_add_fake(user_data
, GTK_TREE_STORE(model
), iter
);
249 static void library_drag_data_get_cb(GtkWidget
*widget
, GdkDragContext
*context
,
250 GtkSelectionData
*selection_data
, guint info
, guint time
, gpointer userdata
)
253 playlist_item_t
* items
;
254 instance_t
* app
= (instance_t
*)userdata
;
256 g_warning("library_drag_data_get_cb");
258 items
= library_get_selected_items(app
, &c
);
263 gtk_selection_data_set(selection_data
, selection_data
->target
, 8,
264 (const guchar
*)items
, sizeof(playlist_item_t
) * c
);
269 static void library_drag_begin_cb(GtkWidget
*widget
, GdkDragContext
*context
, gpointer userdata
)
271 g_warning("library_drag_begin_cb");
272 gtk_drag_source_set_icon_stock(widget
, GTK_STOCK_DND
);
276 void library_init(instance_t
* app
)
278 /* connect to library */
279 app
->library
.handle
[1] = mvcp_parser_init_remote(app
->players
.host
, app
->library
.port
);
280 app
->library
.handle
[0] = mvcp_init(app
->library
.handle
[1]);
281 if(mvcp_connect(app
->library
.handle
[0]) != mvcp_ok
)
283 g_warning("library_init: failed to connect to server %s:%d",
284 app
->players
.host
, app
->library
.port
);
289 app
->library
.icons
[0] = create_pixbuf("Axialis_Team_playlist_open_16x16.png");
290 app
->library
.icons
[1] = create_pixbuf("Axialis_Team_playlist_save_16x16.png");
293 library_init_load(app
);
295 /* allow drag source */
296 gtk_drag_source_set(app
->library_tree
, GDK_BUTTON1_MASK
,
297 drag_targets
, 1, (GdkDragAction
)(GDK_ACTION_COPY
));
300 gtk_signal_connect(GTK_OBJECT(app
->library_tree
), "row-expanded",
301 GTK_SIGNAL_FUNC(on_library_row_expanded
), app
);
302 gtk_signal_connect(GTK_OBJECT(app
->library_tree
), "row-collapsed",
303 GTK_SIGNAL_FUNC(on_library_row_collapsed
), app
);
304 g_signal_connect(GTK_OBJECT(app
->library_tree
), "drag_data_get",
305 G_CALLBACK(library_drag_data_get_cb
), app
);
306 g_signal_connect(GTK_OBJECT(app
->library_tree
), "drag_begin",
307 G_CALLBACK(library_drag_begin_cb
), app
);
311 static void library_get_selected_items_iter
320 mvcp_dir_entry_t
*dir
;
321 mvcp_list_entry_t
*list
;
322 playlist_item_t
** pitems
= (playlist_item_t
**)data
;
323 playlist_item_t
* items
= *pitems
;
325 /* request pointers to list and dir entries of library items */
326 gtk_tree_model_get(model
, iter
,
331 /* check if defined */
337 items
= (playlist_item_t
*)malloc(sizeof(playlist_item_t
));
338 memset(items
, 0, sizeof(playlist_item_t
));
341 /* find numbers of items in list */
342 for(l
= 0; items
[l
].id
[0]; l
++);
343 g_warning("library_get_selected_items_iter: l=%d", l
);
346 items
= (playlist_item_t
*)realloc(items
, (l
+ 2) * sizeof(playlist_item_t
));
348 /* clean last item */
349 memset(&items
[l
+ 1], 0, sizeof(playlist_item_t
));
352 memset(&items
[l
+ 0], 0, sizeof(playlist_item_t
));
353 strncpy(items
[l
].title
, dir
->name
, PATH_MAX
);
354 strncpy(items
[l
].id
, dir
->full
, PATH_MAX
);
355 items
[l
].dur
= list
->size
;
361 playlist_item_t
* library_get_selected_items(instance_t
* app
, int *count
)
364 playlist_item_t
* items
= NULL
;
366 GtkTreeSelection
*selection
;
368 selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(app
->library_tree
));
371 gtk_tree_selection_selected_foreach(
373 library_get_selected_items_iter
,
377 for(; items
[l
].id
[0]; l
++);
384 int library_normalize_item(instance_t
* app
, playlist_item_t
* item
)
388 playlist_item_t
* lib
;
389 playlist_item_t prev
;
391 pthread_mutex_lock(&app
->library
.lock
);
395 lib
= omnplay_library_find(app
, item
->id
);
403 strcpy(item
->title
, lib
->title
);
407 if(item
->in
< lib
->in
|| item
->in
>= (lib
->in
+ lib
->dur
))
413 if(!item
->dur
|| (item
->in
+ item
->dur
) > (lib
->in
+ lib
->dur
))
415 item
->dur
= lib
->in
+ lib
->dur
- item
->in
;
420 g_warning("omnplay_library_normalize_item: [%s,%d,%d]->[%s,%d,%d]\n",
421 prev
.title
, prev
.in
, prev
.dur
, item
->title
, item
->in
, item
->dur
);
426 item
->error
= PLAYLIST_ITEM_ERROR_LIB
;
429 pthread_mutex_unlock(&app
->library
.lock
);
437 int library_relink_item(instance_t
* app
, playlist_item_t
* item
)
441 playlist_item_t
* lib
;
443 pthread_mutex_lock(&app
->library
.lock
);
445 lib
= omnplay_library_find(app
, item
->id
);
452 strcpy(item
->title
, lib
->title
);
453 item
->dur
= lib
->dur
;
459 item
->error
= PLAYLIST_ITEM_ERROR_LIB
;
462 pthread_mutex_unlock(&app
->library
.lock
);