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
;
146 // g_warning("on_library_row_expanded: HERE");
148 /* Set busy cursor */
149 cursor
= gdk_cursor_new(GDK_WATCH
);
150 gdk_window_set_cursor(gtk_widget_get_toplevel(GTK_WIDGET(treeview
))->window
, cursor
);
151 gdk_cursor_unref(cursor
);
154 model
= gtk_tree_view_get_model(treeview
);
157 gtk_tree_model_iter_children(GTK_TREE_MODEL(model
), &fake
, iter
);
159 /* request mvcp entry */
160 gtk_tree_model_get(GTK_TREE_MODEL(model
), iter
,
164 /* setup root path */
171 dir
= mvcp_dir_init(app
->library
.handle
[0], p
);
172 for (i
= 0; i
< mvcp_dir_count(dir
); i
++)
174 mvcp_dir_entry_t dir_entry
;
175 mvcp_list_entry_t
*list_e
= NULL
, list_entry
;
177 if(mvcp_ok
!= mvcp_dir_get(dir
, i
, &dir_entry
))
180 // g_warning("on_library_row_expanded: path=[%s], entry.dur=[%d], entry.full=[%s], entry.name[%s]",
181 // p, entry.dir, entry.full, entry.name);
183 e
= (mvcp_dir_entry_t
*)malloc(sizeof(mvcp_dir_entry_t
));
186 if(!e
->dir
&& mvcp_ok
== mvcp_probe_clip( app
->library
.handle
[0], e
->full
, &list_entry
))
188 list_e
= (mvcp_list_entry_t
*)malloc(sizeof(mvcp_list_entry_t
));
189 *list_e
= list_entry
;
192 library_add_item(app
, GTK_TREE_STORE(model
), iter
, e
, list_e
);
196 gdk_window_set_cursor(gtk_widget_get_toplevel(GTK_WIDGET(treeview
))->window
, NULL
);
198 /* delete fake item */
199 gtk_tree_store_remove(GTK_TREE_STORE(model
), &fake
);
202 static void on_library_row_collapsed
204 GtkTreeView
*treeview
,
212 // g_warning("on_library_row_collapsed: HERE");
214 /* delete all items */
215 model
= gtk_tree_view_get_model(treeview
);
216 while (gtk_tree_model_iter_children(GTK_TREE_MODEL(model
), &child
, iter
))
219 mvcp_list_entry_t
*l
;
221 /* request mvcp entry */
222 gtk_tree_model_get(GTK_TREE_MODEL(model
), &child
,
231 gtk_tree_store_remove(GTK_TREE_STORE(model
), &child
);
234 /* add a fake element */
235 library_add_fake(user_data
, GTK_TREE_STORE(model
), iter
);
238 static void library_drag_data_get_cb(GtkWidget
*widget
, GdkDragContext
*context
,
239 GtkSelectionData
*selection_data
, guint info
, guint time
, gpointer userdata
)
242 playlist_item_t
* items
;
243 instance_t
* app
= (instance_t
*)userdata
;
245 g_warning("library_drag_data_get_cb");
247 items
= library_get_selected_items(app
, &c
);
252 gtk_selection_data_set(selection_data
, selection_data
->target
, 8,
253 (const guchar
*)items
, sizeof(playlist_item_t
) * c
);
258 static void library_drag_begin_cb(GtkWidget
*widget
, GdkDragContext
*context
, gpointer userdata
)
260 g_warning("library_drag_begin_cb");
261 gtk_drag_source_set_icon_stock(widget
, GTK_STOCK_DND
);
265 void library_init(instance_t
* app
)
267 /* connect to library */
268 app
->library
.handle
[1] = mvcp_parser_init_remote(app
->players
.host
, app
->library
.port
);
269 app
->library
.handle
[0] = mvcp_init(app
->library
.handle
[1]);
270 if(mvcp_connect(app
->library
.handle
[0]) != mvcp_ok
)
272 g_warning("library_init: failed to connect to server %s:%d",
273 app
->players
.host
, app
->library
.port
);
278 app
->library
.icons
[0] = create_pixbuf("Axialis_Team_playlist_open_16x16.png");
279 app
->library
.icons
[1] = create_pixbuf("Axialis_Team_playlist_save_16x16.png");
282 library_init_load(app
);
284 /* allow drag source */
285 gtk_drag_source_set(app
->library_tree
, GDK_BUTTON1_MASK
,
286 drag_targets
, 1, (GdkDragAction
)(GDK_ACTION_COPY
));
289 gtk_signal_connect(GTK_OBJECT(app
->library_tree
), "row-expanded",
290 GTK_SIGNAL_FUNC(on_library_row_expanded
), app
);
291 gtk_signal_connect(GTK_OBJECT(app
->library_tree
), "row-collapsed",
292 GTK_SIGNAL_FUNC(on_library_row_collapsed
), app
);
293 g_signal_connect(GTK_OBJECT(app
->library_tree
), "drag_data_get",
294 G_CALLBACK(library_drag_data_get_cb
), app
);
295 g_signal_connect(GTK_OBJECT(app
->library_tree
), "drag_begin",
296 G_CALLBACK(library_drag_begin_cb
), app
);
300 static void library_get_selected_items_iter
309 mvcp_dir_entry_t
*dir
;
310 mvcp_list_entry_t
*list
;
311 playlist_item_t
** pitems
= (playlist_item_t
**)data
;
312 playlist_item_t
* items
= *pitems
;
314 /* request pointers to list and dir entries of library items */
315 gtk_tree_model_get(model
, iter
,
320 /* check if defined */
326 items
= (playlist_item_t
*)malloc(sizeof(playlist_item_t
));
327 memset(items
, 0, sizeof(playlist_item_t
));
330 /* find numbers of items in list */
331 for(l
= 0; items
[l
].id
[0]; l
++);
332 g_warning("library_get_selected_items_iter: l=%d", l
);
335 items
= (playlist_item_t
*)realloc(items
, (l
+ 2) * sizeof(playlist_item_t
));
337 /* clean last item */
338 memset(&items
[l
+ 1], 0, sizeof(playlist_item_t
));
341 memset(&items
[l
+ 0], 0, sizeof(playlist_item_t
));
342 strncpy(items
[l
].title
, dir
->name
, PATH_MAX
);
343 strncpy(items
[l
].id
, dir
->full
, PATH_MAX
);
344 items
[l
].dur
= list
->size
;
350 playlist_item_t
* library_get_selected_items(instance_t
* app
, int *count
)
353 playlist_item_t
* items
= NULL
;
355 GtkTreeSelection
*selection
;
357 selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(app
->library_tree
));
360 gtk_tree_selection_selected_foreach(
362 library_get_selected_items_iter
,
366 for(; items
[l
].id
[0]; l
++);
373 int library_normalize_item(instance_t
* app
, playlist_item_t
* item
)
377 playlist_item_t
* lib
;
378 playlist_item_t prev
;
380 pthread_mutex_lock(&app
->library
.lock
);
384 lib
= omnplay_library_find(app
, item
->id
);
392 strcpy(item
->title
, lib
->title
);
396 if(item
->in
< lib
->in
|| item
->in
>= (lib
->in
+ lib
->dur
))
402 if(!item
->dur
|| (item
->in
+ item
->dur
) > (lib
->in
+ lib
->dur
))
404 item
->dur
= lib
->in
+ lib
->dur
- item
->in
;
409 g_warning("omnplay_library_normalize_item: [%s,%d,%d]->[%s,%d,%d]\n",
410 prev
.title
, prev
.in
, prev
.dur
, item
->title
, item
->in
, item
->dur
);
415 item
->error
= PLAYLIST_ITEM_ERROR_LIB
;
418 pthread_mutex_unlock(&app
->library
.lock
);
426 int library_relink_item(instance_t
* app
, playlist_item_t
* item
)
430 playlist_item_t
* lib
;
432 pthread_mutex_lock(&app
->library
.lock
);
434 lib
= omnplay_library_find(app
, item
->id
);
441 strcpy(item
->title
, lib
->title
);
442 item
->dur
= lib
->dur
;
448 item
->error
= PLAYLIST_ITEM_ERROR_LIB
;
451 pthread_mutex_unlock(&app
->library
.lock
);