1 /*
2 *
3 * File: playlist.c
4 *
5 * Copyright (C) 2009-2014 Darran Kartaschew
6 *
7 * This file is part of the gMTP package.
8 *
9 * gMTP is free software; you can redistribute it and/or modify
10 * it under the terms of the BSD License as included within the
11 * file 'COPYING' located in the root directory
12 *
13 */
14 #include "playlist.h"
15 #include "main.h"
16 #include "mtp.h"
17 #include "interface.h"
18 #include "callbacks.h"
19
20 GtkWidget *windowPlaylistDialog;
21 // Playlist
22
23 GtkWidget *comboboxentry_playlist;
24 gint playlist_number = 0;
25 gint comboboxentry_playlist_entries = 0;
26 gint playlist_track_count = 0;
27 gboolean runPlaylistHandler = TRUE;
28
29 GtkWidget *treeview_Avail_Files;
30 GtkWidget *treeview_Playlist_Files;
31
32 GtkListStore *playlist_TrackList;
33 GtkTreeSelection *playlist_TrackSelection;
34 GList *playlist_Selection_TrackRowReferences = NULL;
35
36 GtkListStore *playlist_PL_List;
37 GtkTreeSelection *playlist_PL_Selection;
38 GList *playlist_Selection_PL_RowReferences = NULL;
39
40 // Buttons for playlist
41 GtkWidget *button_Del_Playlist;
42 GtkWidget *button_Export_Playlist;
43 GtkWidget *button_File_Move_Up;
44 GtkWidget *button_File_Move_Down;
45 GtkWidget *button_Del_File;
46 GtkWidget *button_Add_Files;
47
48 // ************************************************************************************************
49
50 // Playlist support
51
create_windowPlaylist(void)52 GtkWidget* create_windowPlaylist(void) {
53 GtkWidget *window_playlist;
54 GtkWidget *vbox1;
55 GtkWidget *hbox1;
56 GtkWidget *label_Playlist;
57
58 GtkWidget *button_Add_Playlist;
59 GtkWidget *button_Import_Playlist;
60 //GtkWidget *alignment2;
61 GtkWidget *hbox3;
62 GtkWidget *image2;
63 GtkWidget *label3;
64
65 //GtkWidget *alignment1;
66 GtkWidget *hbox2;
67 GtkWidget *image1;
68 GtkWidget *label2;
69 GtkWidget *hbox4;
70 GtkWidget *scrolledwindow2;
71
72 GtkWidget *vbuttonbox1;
73
74 // GtkWidget *alignment6;
75 GtkWidget *hbox8;
76 GtkWidget *image6;
77 GtkWidget *label10;
78
79 //GtkWidget *alignment7;
80 GtkWidget *hbox9;
81 GtkWidget *image7;
82 GtkWidget *label11;
83 GtkWidget *scrolledwindow3;
84
85 GtkWidget *vbuttonbox2;
86
87 GtkWidget *hbuttonbox1;
88 GtkWidget *button_Close;
89
90
91 #if HAVE_GTK3 == 0
92 GtkTooltips *tooltips;
93 tooltips = gtk_tooltips_new();
94 #endif
95
96 window_playlist = gtk_window_new(GTK_WINDOW_TOPLEVEL);
97 gchar * winTitle;
98 winTitle = g_strconcat(PACKAGE_NAME, _(" Playlists"), NULL);
99 gtk_window_set_title(GTK_WINDOW(window_playlist), winTitle);
100 gtk_window_set_modal(GTK_WINDOW(window_playlist), TRUE);
101 gtk_window_set_resizable(GTK_WINDOW(window_playlist), TRUE);
102 gtk_window_set_default_size(GTK_WINDOW(window_playlist), 760, 400);
103 gtk_window_set_transient_for(GTK_WINDOW(window_playlist), GTK_WINDOW(windowMain));
104 gtk_window_set_position(GTK_WINDOW(window_playlist), GTK_WIN_POS_CENTER_ON_PARENT);
105 gtk_window_set_skip_taskbar_hint(GTK_WINDOW(window_playlist), TRUE);
106 gtk_window_set_type_hint(GTK_WINDOW(window_playlist), GDK_WINDOW_TYPE_HINT_DIALOG);
107 gtk_container_set_border_width(GTK_CONTAINER(window_playlist), 5);
108 g_free(winTitle);
109 #if HAVE_GTK3 == 0
110 vbox1 = gtk_vbox_new(FALSE, 0);
111 #else
112 vbox1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
113 #endif
114 gtk_widget_show(vbox1);
115 gtk_container_add(GTK_CONTAINER(window_playlist), vbox1);
116 #if HAVE_GTK3 == 0
117 hbox1 = gtk_hbox_new(FALSE, 5);
118 #else
119 hbox1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
120 #endif
121 gtk_widget_show(hbox1);
122 gtk_box_pack_start(GTK_BOX(vbox1), hbox1, FALSE, TRUE, 5);
123
124 label_Playlist = gtk_label_new(_("Current Playlist: "));
125 gtk_widget_show(label_Playlist);
126 gtk_box_pack_start(GTK_BOX(hbox1), label_Playlist, FALSE, FALSE, 5);
127 #if HAVE_GTK3 == 0
128 gtk_misc_set_padding(GTK_MISC(label_Playlist), 5, 0);
129 #else
130 #if GTK_CHECK_VERSION(3,12,0)
131 gtk_widget_set_margin_start(label_Playlist, 5);
132 gtk_widget_set_margin_end(label_Playlist, 5);
133 #else
134 gtk_widget_set_margin_left(label_Playlist, 5);
135 gtk_widget_set_margin_right(label_Playlist, 5);
136 #endif
137 #endif
138
139 #if HAVE_GTK3 == 0
140 comboboxentry_playlist = gtk_combo_box_new_text();
141 #else
142 comboboxentry_playlist = gtk_combo_box_text_new();
143 #endif
144 gtk_widget_show(comboboxentry_playlist);
145 gtk_box_pack_start(GTK_BOX(hbox1), comboboxentry_playlist, TRUE, TRUE, 0);
146 gtk_container_set_border_width(GTK_CONTAINER(comboboxentry_playlist), 5);
147
148 button_Add_Playlist = gtk_button_new();
149 gtk_widget_show(button_Add_Playlist);
150 gtk_box_pack_start(GTK_BOX(hbox1), button_Add_Playlist, FALSE, FALSE, 0);
151 gtk_container_set_border_width(GTK_CONTAINER(button_Add_Playlist), 5);
152 #if HAVE_GTK3 == 0
153 gtk_tooltips_set_tip(tooltips, button_Add_Playlist, _("Add New Playlist"), NULL);
154 #else
155 gtk_widget_set_tooltip_text(button_Add_Playlist, _("Add New Playlist"));
156 #endif
157
158 // alignment2 = gtk_alignment_new(0.5, 0.5, 0, 0);
159 // gtk_widget_show(alignment2);
160 // gtk_container_add(GTK_CONTAINER(button_Add_Playlist), alignment2);
161 #if HAVE_GTK3 == 0
162 hbox3 = gtk_hbox_new(FALSE, 2);
163 #else
164 hbox3 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 2);
165 #endif
166 gtk_widget_show(hbox3);
167 gtk_container_add(GTK_CONTAINER(button_Add_Playlist), hbox3);
168 #if HAVE_GTK3 == 0
169 image2 = gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_BUTTON);
170 #else
171 image2 = gtk_image_new_from_icon_name("list-add", GTK_ICON_SIZE_BUTTON);
172 #endif
173 gtk_widget_show(image2);
174 gtk_box_pack_start(GTK_BOX(hbox3), image2, FALSE, FALSE, 0);
175
176 label3 = gtk_label_new_with_mnemonic(_("Add"));
177 gtk_widget_show(label3);
178 gtk_box_pack_start(GTK_BOX(hbox3), label3, FALSE, FALSE, 0);
179
180 button_Del_Playlist = gtk_button_new();
181 gtk_widget_show(button_Del_Playlist);
182 gtk_box_pack_start(GTK_BOX(hbox1), button_Del_Playlist, FALSE, FALSE, 0);
183 gtk_container_set_border_width(GTK_CONTAINER(button_Del_Playlist), 5);
184 #if HAVE_GTK3 == 0
185 gtk_tooltips_set_tip(tooltips, button_Del_Playlist, _("Remove Current Selected Playlist"), NULL);
186 #else
187 gtk_widget_set_tooltip_text(button_Del_Playlist, _("Remove Current Selected Playlist"));
188 #endif
189
190 // alignment1 = gtk_alignment_new(0.5, 0.5, 0, 0);
191 // gtk_widget_show(alignment1);
192 // gtk_container_add(GTK_CONTAINER(button_Del_Playlist), alignment1);
193 #if HAVE_GTK3 == 0
194 hbox2 = gtk_hbox_new(FALSE, 2);
195 #else
196 hbox2 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 2);
197 #endif
198
199 gtk_widget_show(hbox2);
200 gtk_container_add(GTK_CONTAINER(button_Del_Playlist), hbox2);
201 #if HAVE_GTK3 == 0
202 image1 = gtk_image_new_from_stock(GTK_STOCK_DELETE, GTK_ICON_SIZE_BUTTON);
203 #else
204 image1 = gtk_image_new_from_icon_name("edit-delete", GTK_ICON_SIZE_BUTTON);
205 #endif
206 gtk_widget_show(image1);
207 gtk_box_pack_start(GTK_BOX(hbox2), image1, FALSE, FALSE, 0);
208
209 label2 = gtk_label_new_with_mnemonic(_("Del"));
210 gtk_widget_show(label2);
211 gtk_box_pack_start(GTK_BOX(hbox2), label2, FALSE, FALSE, 0);
212
213 // Import Button
214 #if HAVE_GTK3 == 0
215 button_Import_Playlist = gtk_button_new_from_stock(GTK_STOCK_OPEN);
216 #else
217 button_Import_Playlist = gtk_button_new_with_label(_("Open"));
218 #endif
219 gtk_widget_show(button_Import_Playlist);
220 gtk_box_pack_start(GTK_BOX(hbox1), button_Import_Playlist, FALSE, FALSE, 0);
221 gtk_container_set_border_width(GTK_CONTAINER(button_Import_Playlist), 5);
222 #if HAVE_GTK3 == 0
223 gtk_tooltips_set_tip(tooltips, button_Import_Playlist, _("Import Playlist"), NULL);
224 #else
225 gtk_widget_set_tooltip_text(button_Import_Playlist, _("Import Playlist"));
226 #endif
227
228 // Export Button
229 #if HAVE_GTK3 == 0
230 button_Export_Playlist = gtk_button_new_from_stock(GTK_STOCK_SAVE_AS);
231 #else
232 button_Export_Playlist = gtk_button_new_with_label(_("Save"));
233 #endif
234 gtk_widget_show(button_Export_Playlist);
235 gtk_box_pack_start(GTK_BOX(hbox1), button_Export_Playlist, FALSE, FALSE, 0);
236 gtk_container_set_border_width(GTK_CONTAINER(button_Export_Playlist), 5);
237 #if HAVE_GTK3 == 0
238 gtk_tooltips_set_tip(tooltips, button_Export_Playlist, _("Export Playlist"), NULL);
239 #else
240 gtk_widget_set_tooltip_text(button_Export_Playlist, _("Export Playlist"));
241 #endif
242
243 // Scrolled Window.
244 #if HAVE_GTK3 == 0
245 hbox4 = gtk_hbox_new(FALSE, 5);
246 #else
247 hbox4 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
248 #endif
249 gtk_widget_show(hbox4);
250 gtk_box_pack_start(GTK_BOX(vbox1), hbox4, TRUE, TRUE, 0);
251
252 scrolledwindow2 = gtk_scrolled_window_new(NULL, NULL);
253 gtk_widget_show(scrolledwindow2);
254 gtk_box_pack_start(GTK_BOX(hbox4), scrolledwindow2, TRUE, TRUE, 0);
255 gtk_container_set_border_width(GTK_CONTAINER(scrolledwindow2), 5);
256
257 treeview_Avail_Files = gtk_tree_view_new();
258 gtk_widget_show(treeview_Avail_Files);
259 gtk_container_add(GTK_CONTAINER(scrolledwindow2), treeview_Avail_Files);
260 gtk_container_set_border_width(GTK_CONTAINER(treeview_Avail_Files), 5);
261 #if HAVE_GTK3 == 0
262 gtk_tooltips_set_tip(tooltips, treeview_Avail_Files, _("Device Audio Tracks"), NULL);
263 #else
264 gtk_widget_set_tooltip_text(treeview_Avail_Files, _("Device Audio Tracks"));
265 #endif
266
267 playlist_TrackSelection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview_Avail_Files));
268 gtk_tree_selection_set_mode(playlist_TrackSelection, GTK_SELECTION_MULTIPLE);
269
270 playlist_TrackList = gtk_list_store_new(NUM_TCOLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING);
271 setupTrackList(GTK_TREE_VIEW(treeview_Avail_Files));
272 gtk_tree_view_set_model(GTK_TREE_VIEW(treeview_Avail_Files), GTK_TREE_MODEL(playlist_TrackList));
273 g_object_unref(playlist_TrackList);
274 #if HAVE_GTK3 == 0
275 vbuttonbox1 = gtk_vbutton_box_new();
276 #else
277 vbuttonbox1 = gtk_button_box_new(GTK_ORIENTATION_VERTICAL);
278 #endif
279 gtk_widget_show(vbuttonbox1);
280 gtk_box_pack_start(GTK_BOX(hbox4), vbuttonbox1, FALSE, FALSE, 0);
281 gtk_button_box_set_layout(GTK_BUTTON_BOX(vbuttonbox1), GTK_BUTTONBOX_SPREAD);
282
283 button_Add_Files = gtk_button_new();
284 gtk_widget_show(button_Add_Files);
285 gtk_container_add(GTK_CONTAINER(vbuttonbox1), button_Add_Files);
286 #if HAVE_GTK3 == 0
287 gtk_tooltips_set_tip(tooltips, button_Add_Files, _("Add file to playlist"), NULL);
288 #else
289 gtk_widget_set_tooltip_text(button_Add_Files, _("Add file to playlist"));
290 #endif
291
292 // alignment6 = gtk_alignment_new(0.5, 0.5, 0, 0);
293 // gtk_widget_show(alignment6);
294 // gtk_container_add(GTK_CONTAINER(button_Add_Files), alignment6);
295 #if HAVE_GTK3 == 0
296 hbox8 = gtk_hbox_new(FALSE, 2);
297 #else
298 hbox8 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 2);
299 #endif
300 gtk_widget_show(hbox8);
301 gtk_container_add(GTK_CONTAINER(button_Add_Files), hbox8);
302 #if HAVE_GTK3 == 0
303 image6 = gtk_image_new_from_stock(GTK_STOCK_GO_FORWARD, GTK_ICON_SIZE_BUTTON);
304 #else
305 image6 = gtk_image_new_from_icon_name("go-next", GTK_ICON_SIZE_BUTTON);
306 #endif
307 gtk_widget_show(image6);
308 gtk_box_pack_start(GTK_BOX(hbox8), image6, FALSE, FALSE, 0);
309
310 label10 = gtk_label_new_with_mnemonic(_("Add File"));
311 gtk_widget_show(label10);
312 gtk_box_pack_start(GTK_BOX(hbox8), label10, FALSE, FALSE, 0);
313
314 button_Del_File = gtk_button_new();
315 gtk_widget_show(button_Del_File);
316 gtk_container_add(GTK_CONTAINER(vbuttonbox1), button_Del_File);
317 #if HAVE_GTK3 == 0
318 gtk_tooltips_set_tip(tooltips, button_Del_File, _("Remove file from playlist"), NULL);
319 #else
320 gtk_widget_set_tooltip_text(button_Del_File, _("Remove file from playlist"));
321 #endif
322
323 // alignment7 = gtk_alignment_new(0.5, 0.5, 0, 0);
324 // gtk_widget_show(alignment7);
325 // gtk_container_add(GTK_CONTAINER(button_Del_File), alignment7);
326 #if HAVE_GTK3 == 0
327 hbox9 = gtk_hbox_new(FALSE, 2);
328 #else
329 hbox9 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 2);
330 #endif
331 gtk_widget_show(hbox9);
332 gtk_container_add(GTK_CONTAINER(button_Del_File), hbox9);
333 #if HAVE_GTK3 == 0
334 image7 = gtk_image_new_from_stock(GTK_STOCK_GO_BACK, GTK_ICON_SIZE_BUTTON);
335 #else
336 image7 = gtk_image_new_from_icon_name("go-previous", GTK_ICON_SIZE_BUTTON);
337 #endif
338 gtk_widget_show(image7);
339 gtk_box_pack_start(GTK_BOX(hbox9), image7, FALSE, FALSE, 0);
340
341 label11 = gtk_label_new_with_mnemonic(_("Del File"));
342 gtk_widget_show(label11);
343 gtk_box_pack_start(GTK_BOX(hbox9), label11, FALSE, FALSE, 0);
344
345 scrolledwindow3 = gtk_scrolled_window_new(NULL, NULL);
346 gtk_widget_show(scrolledwindow3);
347 gtk_box_pack_start(GTK_BOX(hbox4), scrolledwindow3, TRUE, TRUE, 0);
348 gtk_container_set_border_width(GTK_CONTAINER(scrolledwindow3), 5);
349
350 treeview_Playlist_Files = gtk_tree_view_new();
351 gtk_widget_show(treeview_Playlist_Files);
352 gtk_container_add(GTK_CONTAINER(scrolledwindow3), treeview_Playlist_Files);
353 gtk_container_set_border_width(GTK_CONTAINER(treeview_Playlist_Files), 5);
354 #if HAVE_GTK3 == 0
355 gtk_tooltips_set_tip(tooltips, treeview_Playlist_Files, _("Playlist Audio Tracks"), NULL);
356 #else
357 gtk_widget_set_tooltip_text(treeview_Playlist_Files, _("Playlist Audio Tracks"));
358 #endif
359
360 playlist_PL_Selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview_Playlist_Files));
361 gtk_tree_selection_set_mode(playlist_PL_Selection, GTK_SELECTION_MULTIPLE);
362
363 playlist_PL_List = gtk_list_store_new(NUM_PL_COLUMNS, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING);
364 setup_PL_List(GTK_TREE_VIEW(treeview_Playlist_Files));
365 gtk_tree_view_set_model(GTK_TREE_VIEW(treeview_Playlist_Files), GTK_TREE_MODEL(playlist_PL_List));
366 g_object_unref(playlist_PL_List);
367 #if HAVE_GTK3 == 0
368 vbuttonbox2 = gtk_vbutton_box_new();
369 #else
370 vbuttonbox2 = gtk_button_box_new(GTK_ORIENTATION_VERTICAL);
371 #endif
372 gtk_widget_show(vbuttonbox2);
373 gtk_box_pack_start(GTK_BOX(hbox4), vbuttonbox2, FALSE, FALSE, 5);
374 gtk_button_box_set_layout(GTK_BUTTON_BOX(vbuttonbox2), GTK_BUTTONBOX_SPREAD);
375 #if HAVE_GTK3 == 0
376 button_File_Move_Up = gtk_button_new_from_stock(GTK_STOCK_GO_UP);
377 #else
378 #if GTK_CHECK_VERSION(3,10,0)
379 button_File_Move_Up = gtk_button_new_from_icon_name("go-up", GTK_ICON_SIZE_BUTTON);
380 #else
381 button_File_Move_Up = gtk_button_new_from_stock(GTK_STOCK_GO_UP);
382 #endif
383 #endif
384 gtk_widget_show(button_File_Move_Up);
385 gtk_container_add(GTK_CONTAINER(vbuttonbox2), button_File_Move_Up);
386 #if HAVE_GTK3 == 0
387 gtk_tooltips_set_tip(tooltips, button_File_Move_Up, _("Move selected file up in the playlist"), NULL);
388 #else
389 gtk_widget_set_tooltip_text(button_File_Move_Up, _("Move selected file up in the playlist"));
390 #endif
391
392 #if HAVE_GTK3 == 0
393 button_File_Move_Down = gtk_button_new_from_stock(GTK_STOCK_GO_DOWN);
394 #else
395 #if GTK_CHECK_VERSION(3,10,0)
396 button_File_Move_Down = gtk_button_new_from_icon_name("go-down", GTK_ICON_SIZE_BUTTON);
397 #else
398 button_File_Move_Down = gtk_button_new_from_stock(GTK_STOCK_GO_DOWN);
399 #endif
400 #endif
401 gtk_widget_show(button_File_Move_Down);
402 gtk_container_add(GTK_CONTAINER(vbuttonbox2), button_File_Move_Down);
403 #if HAVE_GTK3 == 0
404 gtk_tooltips_set_tip(tooltips, button_File_Move_Down, _("Move selected file down in the playlist"), NULL);
405 #else
406 gtk_widget_set_tooltip_text(button_File_Move_Down, _("Move selected file down in the playlist"));
407 #endif
408 #if HAVE_GTK3 == 0
409 hbuttonbox1 = gtk_hbutton_box_new();
410 #else
411 hbuttonbox1 = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
412 #endif
413 gtk_widget_show(hbuttonbox1);
414 gtk_box_pack_start(GTK_BOX(vbox1), hbuttonbox1, FALSE, FALSE, 5);
415 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbuttonbox1), GTK_BUTTONBOX_END);
416 #if HAVE_GTK3 == 0
417 button_Close = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
418 #else
419 button_Close = gtk_button_new_with_label(_("Close"));
420 #endif
421 gtk_widget_show(button_Close);
422 gtk_container_add(GTK_CONTAINER(hbuttonbox1), button_Close);
423 gtk_container_set_border_width(GTK_CONTAINER(button_Close), 5);
424
425 g_signal_connect((gpointer) window_playlist, "destroy",
426 G_CALLBACK(on_quitPlaylist_activate),
427 NULL);
428
429 g_signal_connect((gpointer) button_Close, "clicked",
430 G_CALLBACK(on_quitPlaylist_activate),
431 NULL);
432
433 g_signal_connect((gpointer) button_Add_Playlist, "clicked",
434 G_CALLBACK(on_Playlist_NewPlaylistButton_activate),
435 NULL);
436
437 g_signal_connect((gpointer) button_Import_Playlist, "clicked",
438 G_CALLBACK(on_Playlist_ImportPlaylistButton_activate),
439 NULL);
440
441 g_signal_connect((gpointer) button_Export_Playlist, "clicked",
442 G_CALLBACK(on_Playlist_ExportPlaylistButton_activate),
443 NULL);
444
445 g_signal_connect((gpointer) button_Del_Playlist, "clicked",
446 G_CALLBACK(on_Playlist_DelPlaylistButton_activate),
447 NULL);
448
449 g_signal_connect((gpointer) button_Del_File, "clicked",
450 G_CALLBACK(on_Playlist_DelFileButton_activate),
451 NULL);
452
453 g_signal_connect((gpointer) button_Add_Files, "clicked",
454 G_CALLBACK(on_Playlist_AddFileButton_activate),
455 NULL);
456
457 g_signal_connect((gpointer) button_File_Move_Up, "clicked",
458 G_CALLBACK(on_Playlist_FileUpButton_activate),
459 NULL);
460
461 g_signal_connect((gpointer) button_File_Move_Down, "clicked",
462 G_CALLBACK(on_Playlist_FileDownButton_activate),
463 NULL);
464
465 g_signal_connect((gpointer) comboboxentry_playlist, "changed",
466 G_CALLBACK(on_Playlist_Combobox_activate),
467 NULL);
468
469 return window_playlist;
470 }
471
472 // ************************************************************************************************
473
on_editPlaylist_activate(GtkWidget * item,gpointer user_data)474 void on_editPlaylist_activate(GtkWidget *item, gpointer user_data) {
475 UNUSED(item);
476 UNUSED(user_data);
477 displayPlaylistDialog();
478 } // end on_editPlaylist_activate()
479
480 // ************************************************************************************************
481
on_fileAddToPlaylist_activate(GtkWidget * item,gpointer user_data)482 void on_fileAddToPlaylist_activate(GtkWidget *item, gpointer user_data) {
483 UNUSED(item);
484 UNUSED(user_data);
485 // Let's check to see if we have anything selected in our treeview?
486 if (fileListGetSelection() == NULL) {
487 displayInformation(_("No files/folders selected?"));
488 return;
489 }
490 // Display the select playlist dialog;
491 int32_t addTrackPlaylistID = displayAddTrackPlaylistDialog(TRUE);
492
493 // Now add the actual files from the MTP device.
494 if (addTrackPlaylistID != GMTP_NO_PLAYLIST) {
495 fileListAddToPlaylist(fileListGetSelection(), addTrackPlaylistID);
496 }
497 }
498
499 // ************************************************************************************************
500
on_fileRemoveFromPlaylist_activate(GtkWidget * item,gpointer user_data)501 void on_fileRemoveFromPlaylist_activate(GtkWidget *item, gpointer user_data) {
502 UNUSED(item);
503 UNUSED(user_data);
504 // Let's check to see if we have anything selected in our treeview?
505 if (fileListGetSelection() == NULL) {
506 displayInformation(_("No files/folders selected?"));
507 return;
508 }
509 // Display the select playlist dialog;
510 int32_t addTrackPlaylistID = displayAddTrackPlaylistDialog(FALSE);
511
512 // Now remove the actual files from the MTP device.
513 if (addTrackPlaylistID != GMTP_NO_PLAYLIST) {
514 fileListRemoveFromPlaylist(fileListGetSelection(), addTrackPlaylistID);
515 }
516 }
517
518 // ************************************************************************************************
519
fileListRemoveFromPlaylist(GList * List,uint32_t PlaylistID)520 gboolean fileListRemoveFromPlaylist(GList *List, uint32_t PlaylistID) {
521 LIBMTP_playlist_t *playlist = NULL;
522 LIBMTP_playlist_t *node = NULL;
523
524 node = devicePlayLists;
525 while (node != NULL) {
526 if (node->playlist_id == PlaylistID) {
527 playlist = node;
528 node = NULL;
529 } else {
530 node = node->next;
531 }
532 }
533 if (playlist != NULL) {
534 g_list_foreach(List, (GFunc) __fileRemoveFromPlaylist, (gpointer) & playlist);
535 }
536 return TRUE;
537 }
538
539 // ************************************************************************************************
540
__fileAddToPlaylist(GtkTreeRowReference * Row,LIBMTP_playlist_t ** playlist)541 void __fileAddToPlaylist(GtkTreeRowReference *Row, LIBMTP_playlist_t **playlist) {
542 GtkTreePath *path;
543 GtkTreeIter iter;
544 uint32_t objectID;
545 gboolean isFolder;
546 LIBMTP_track_t *tracks = deviceTracks;
547 // convert the referenece to a path and retrieve the iterator;
548 path = gtk_tree_row_reference_get_path(Row);
549 gtk_tree_model_get_iter(GTK_TREE_MODEL(fileList), &iter, path);
550 // We have our Iter now.
551 gtk_tree_model_get(GTK_TREE_MODEL(fileList), &iter, COL_ISFOLDER, &isFolder, COL_FILEID, &objectID, -1);
552 if (isFolder == FALSE) {
553 // Now add the file to the playlist.
554 LIBMTP_track_t *node = NULL;
555 // We need the playlist pointer, and the **track** pointer;
556 while (tracks != NULL) {
557 if (tracks->item_id == objectID) {
558 node = tracks;
559 tracks = NULL;
560 } else {
561 tracks = tracks->next;
562 }
563 }
564 if (node != NULL) {
565 playlistAddTrack(*(playlist), node);
566 }
567 }
568 gtk_tree_path_free(path);
569 }
570
571 // ************************************************************************************************
572
__fileRemoveFromPlaylist(GtkTreeRowReference * Row,LIBMTP_playlist_t ** playlist)573 void __fileRemoveFromPlaylist(GtkTreeRowReference *Row, LIBMTP_playlist_t **playlist) {
574 GtkTreePath *path;
575 GtkTreeIter iter;
576 uint32_t objectID;
577 gboolean isFolder;
578 LIBMTP_track_t *tracks = deviceTracks;
579
580 // convert the referenece to a path and retrieve the iterator;
581 path = gtk_tree_row_reference_get_path(Row);
582 gtk_tree_model_get_iter(GTK_TREE_MODEL(fileList), &iter, path);
583 // We have our Iter now.
584 gtk_tree_model_get(GTK_TREE_MODEL(fileList), &iter, COL_ISFOLDER, &isFolder, COL_FILEID, &objectID, -1);
585 if (isFolder == FALSE) {
586 // Now add the file to the playlist.
587 LIBMTP_track_t *node = NULL;
588 // We need the playlist pointer, and the **track** pointer;
589 while (tracks != NULL) {
590 if (tracks->item_id == objectID) {
591 node = tracks;
592 tracks = NULL;
593 } else {
594 tracks = tracks->next;
595 }
596 }
597 if (node != NULL) {
598 playlistRemoveTrack(*(playlist), node, MTP_PLAYLIST_FIRST_INSTANCE);
599 }
600 }
601 gtk_tree_path_free(path);
602 }
603
604 // ************************************************************************************************
605
displayPlaylistDialog(void)606 void displayPlaylistDialog(void) {
607 //LIBMTP_playlist_t* tmpplaylist;
608 LIBMTP_track_t* tmptrack;
609 GtkTreeIter rowIter;
610 //gchar * tmp_string;
611
612 if (windowPlaylistDialog != NULL) {
613 gtk_widget_hide(windowPlaylistDialog);
614 gtk_widget_destroy(windowPlaylistDialog);
615 }
616 windowPlaylistDialog = create_windowPlaylist();
617 playlist_number = 0;
618 // Clear the track and playlist lists;
619 gtk_list_store_clear(GTK_LIST_STORE(playlist_PL_List));
620 gtk_list_store_clear(GTK_LIST_STORE(playlist_TrackList));
621 // Populate the playlist changebox.
622 devicePlayLists = getPlaylists();
623 deviceTracks = getTracks();
624 setPlayListComboBox();
625
626 // Populate the available track list.
627 if (deviceTracks != NULL) {
628 // Populate the track list;
629 tmptrack = deviceTracks;
630 while (tmptrack != NULL) {
631 if ((tmptrack->storage_id == DeviceMgr.devicestorage->id) && (LIBMTP_FILETYPE_IS_AUDIO(tmptrack->filetype))) {
632 gtk_list_store_append(GTK_LIST_STORE(playlist_TrackList), &rowIter);
633 gchar * tmp_string = g_strdup_printf("%d:%.2d", (int) ((tmptrack->duration / 1000) / 60), (int) ((tmptrack->duration / 1000) % 60));
634 gtk_list_store_set(GTK_LIST_STORE(playlist_TrackList), &rowIter, COL_ARTIST, tmptrack->artist, COL_ALBUM, tmptrack->album,
635 COL_TRACKID, tmptrack->item_id, COL_TRACKNAME, tmptrack->title, COL_TRACKDURATION, tmp_string, -1);
636 g_free(tmp_string);
637 tmp_string = NULL;
638 }
639 tmptrack = tmptrack->next;
640 }
641 }
642 gtk_widget_show(GTK_WIDGET(windowPlaylistDialog));
643 // Save the current selected playlist if needed.
644 }
645
646 // ************************************************************************************************
647
setupTrackList(GtkTreeView * treeviewFiles)648 void setupTrackList(GtkTreeView *treeviewFiles) {
649 GtkCellRenderer *renderer;
650 GtkTreeViewColumn *column;
651
652 // Artist
653 renderer = gtk_cell_renderer_text_new();
654 column = gtk_tree_view_column_new_with_attributes(_("Artist"), renderer,
655 "text", COL_ARTIST,
656 NULL);
657 gtk_tree_view_append_column(GTK_TREE_VIEW(treeviewFiles), column);
658 gtk_tree_view_column_set_sort_column_id(column, COL_ARTIST);
659 gtk_tree_view_column_set_resizable(column, TRUE);
660 gtk_tree_view_column_set_spacing(column, 5);
661
662 // Album column
663 renderer = gtk_cell_renderer_text_new();
664 column = gtk_tree_view_column_new_with_attributes(_("Album"), renderer,
665 "text", COL_ALBUM,
666 NULL);
667 gtk_tree_view_append_column(GTK_TREE_VIEW(treeviewFiles), column);
668 gtk_tree_view_column_set_sort_column_id(column, COL_ALBUM);
669 gtk_tree_view_column_set_resizable(column, TRUE);
670 gtk_tree_view_column_set_spacing(column, 5);
671
672 // Folder/FileID column
673 renderer = gtk_cell_renderer_text_new();
674 column = gtk_tree_view_column_new_with_attributes("Object ID", renderer,
675 "text", COL_TRACKID,
676 NULL);
677 gtk_tree_view_append_column(GTK_TREE_VIEW(treeviewFiles), column);
678 gtk_tree_view_column_set_visible(column, FALSE);
679
680 // Track column
681 renderer = gtk_cell_renderer_text_new();
682 column = gtk_tree_view_column_new_with_attributes(_("Track"), renderer,
683 "text", COL_TRACKNAME,
684 NULL);
685 gtk_tree_view_append_column(GTK_TREE_VIEW(treeviewFiles), column);
686 gtk_tree_view_column_set_sort_column_id(column, COL_TRACKNAME);
687 gtk_tree_view_column_set_resizable(column, TRUE);
688 gtk_tree_view_column_set_visible(column, TRUE);
689
690 // Track Duration
691 renderer = gtk_cell_renderer_text_new();
692 column = gtk_tree_view_column_new_with_attributes(_("Duration"), renderer,
693 "text", COL_TRACKDURATION,
694 NULL);
695 gtk_tree_view_append_column(GTK_TREE_VIEW(treeviewFiles), column);
696 gtk_tree_view_column_set_resizable(column, TRUE);
697 gtk_tree_view_column_set_visible(column, TRUE);
698 }
699
700 // ************************************************************************************************
701
setup_PL_List(GtkTreeView * treeviewFiles)702 void setup_PL_List(GtkTreeView *treeviewFiles) {
703 GtkCellRenderer *renderer;
704 GtkTreeViewColumn *column;
705
706 // Order Num
707 renderer = gtk_cell_renderer_text_new();
708 column = gtk_tree_view_column_new_with_attributes(_("Num"), renderer,
709 "text", COL_PL_ORDER_NUM,
710 NULL);
711 gtk_tree_view_append_column(GTK_TREE_VIEW(treeviewFiles), column);
712 //gtk_tree_view_column_set_sort_column_id(column, COL_PL_ORDER_NUM);
713 gtk_tree_view_column_set_resizable(column, TRUE);
714 gtk_tree_view_column_set_spacing(column, 5);
715
716 // Artist
717 renderer = gtk_cell_renderer_text_new();
718 column = gtk_tree_view_column_new_with_attributes(_("Artist"), renderer,
719 "text", COL_PL_ARTIST,
720 NULL);
721 gtk_tree_view_append_column(GTK_TREE_VIEW(treeviewFiles), column);
722 //gtk_tree_view_column_set_sort_column_id(column, COL_PL_ARTIST);
723 gtk_tree_view_column_set_resizable(column, TRUE);
724 gtk_tree_view_column_set_spacing(column, 5);
725
726 // Album column
727 renderer = gtk_cell_renderer_text_new();
728 column = gtk_tree_view_column_new_with_attributes(_("Album"), renderer,
729 "text", COL_PL_ALBUM,
730 NULL);
731 gtk_tree_view_append_column(GTK_TREE_VIEW(treeviewFiles), column);
732 //gtk_tree_view_column_set_sort_column_id(column, COL_PL_ALBUM);
733 gtk_tree_view_column_set_resizable(column, TRUE);
734 gtk_tree_view_column_set_spacing(column, 5);
735
736 // Folder/FileID column
737 renderer = gtk_cell_renderer_text_new();
738 column = gtk_tree_view_column_new_with_attributes("Object ID", renderer,
739 "text", COL_PL_TRACKID,
740 NULL);
741 gtk_tree_view_append_column(GTK_TREE_VIEW(treeviewFiles), column);
742 gtk_tree_view_column_set_visible(column, FALSE);
743
744 // Track column
745 renderer = gtk_cell_renderer_text_new();
746 column = gtk_tree_view_column_new_with_attributes(_("Track"), renderer,
747 "text", COL_PL_TRACKNAME,
748 NULL);
749 gtk_tree_view_append_column(GTK_TREE_VIEW(treeviewFiles), column);
750 //gtk_tree_view_column_set_sort_column_id(column, COL_TRACKNAME);
751 gtk_tree_view_column_set_resizable(column, TRUE);
752 gtk_tree_view_column_set_visible(column, TRUE);
753
754 // Track Duration
755 renderer = gtk_cell_renderer_text_new();
756 column = gtk_tree_view_column_new_with_attributes(_("Duration"), renderer,
757 "text", COL_PL_TRACKDURATION,
758 NULL);
759 gtk_tree_view_append_column(GTK_TREE_VIEW(treeviewFiles), column);
760 gtk_tree_view_column_set_resizable(column, TRUE);
761 gtk_tree_view_column_set_visible(column, TRUE);
762 }
763
764 // ************************************************************************************************
765
SetPlaylistButtonState(gboolean state)766 void SetPlaylistButtonState(gboolean state) {
767 gtk_widget_set_sensitive(GTK_WIDGET(button_Del_Playlist), state);
768 gtk_widget_set_sensitive(GTK_WIDGET(button_Export_Playlist), state);
769 gtk_widget_set_sensitive(GTK_WIDGET(button_File_Move_Up), state);
770 gtk_widget_set_sensitive(GTK_WIDGET(button_File_Move_Down), state);
771 gtk_widget_set_sensitive(GTK_WIDGET(button_Del_File), state);
772 gtk_widget_set_sensitive(GTK_WIDGET(button_Add_Files), state);
773 gtk_widget_set_sensitive(GTK_WIDGET(treeview_Avail_Files), state);
774 gtk_widget_set_sensitive(GTK_WIDGET(treeview_Playlist_Files), state);
775 }
776
777 // ************************************************************************************************
778
setPlayListComboBox(void)779 void setPlayListComboBox(void) {
780 LIBMTP_playlist_t* tmpplaylist = NULL;
781
782 // We need to remove all entries in the combo box before starting.
783 // This is a little bit of a hack - but does work.
784 runPlaylistHandler = FALSE; // disable the handler from running on the control.
785 // For some reason the "changed" event is triggered on a remove_all operation.
786 #if HAVE_GTK3 == 0
787 //gtk_list_store_clear(GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(comboboxentry_playlist))));
788 while (comboboxentry_playlist_entries-- > 0) {
789 gtk_combo_box_remove_text(GTK_COMBO_BOX(comboboxentry_playlist), 0);
790 }
791 #else
792 gtk_combo_box_text_remove_all(GTK_COMBO_BOX_TEXT(comboboxentry_playlist));
793 #endif
794 comboboxentry_playlist_entries = 0;
795
796 if (devicePlayLists != NULL) {
797 // Populate the playlist dropdown box;
798 //comboboxentry_playlist;
799 tmpplaylist = devicePlayLists;
800 while (tmpplaylist != NULL) {
801 if (tmpplaylist->storage_id == DeviceMgr.devicestorage->id) {
802 #if HAVE_GTK3 == 0
803 gtk_combo_box_append_text(GTK_COMBO_BOX(comboboxentry_playlist), (tmpplaylist->name));
804 #else
805 //gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(comboboxentry_playlist), g_strdup(tmpplaylist->name));
806 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(comboboxentry_playlist), (tmpplaylist->name));
807 #endif
808 comboboxentry_playlist_entries++;
809 }
810 tmpplaylist = tmpplaylist->next;
811 }
812 }
813 if (devicePlayLists != NULL) {
814 // Set our playlist to the first one.
815 gtk_combo_box_set_active(GTK_COMBO_BOX(comboboxentry_playlist), 0);
816 playlist_number = 0;
817 // Now populate the playlist screen with it's details.
818 setPlaylistField(0);
819 } else {
820 playlist_number = -1;
821 }
822 // If no playlists set parts of dialog to disabled.
823 if (devicePlayLists == NULL) {
824 SetPlaylistButtonState(FALSE);
825 } else {
826 SetPlaylistButtonState(TRUE);
827 }
828 runPlaylistHandler = TRUE;
829 }
830
831 // ************************************************************************************************
832
setPlaylistField(gint PlayListID)833 void setPlaylistField(gint PlayListID) {
834 // This function will populate the playlist_PL_List widget with the
835 // details of the selected playlist.
836 LIBMTP_playlist_t* tmpplaylist = devicePlayLists;
837 gint tmpplaylistID = PlayListID;
838 guint trackID = 0;
839 GtkTreeIter rowIter;
840 gchar * tmp_string = NULL;
841
842 playlist_track_count = 0;
843
844 gtk_list_store_clear(GTK_LIST_STORE(playlist_PL_List));
845
846 if (PlayListID > 0) {
847 while (tmpplaylistID--)
848 if (tmpplaylist->next != NULL)
849 tmpplaylist = tmpplaylist->next;
850 }
851 // tmpplaylist points to our playlist;
852 for (trackID = 0; trackID < tmpplaylist->no_tracks; trackID++) {
853 LIBMTP_track_t *trackinfo;
854 trackinfo = LIBMTP_Get_Trackmetadata(DeviceMgr.device, tmpplaylist->tracks[trackID]);
855 if (trackinfo != NULL) {
856 playlist_track_count++;
857 gtk_list_store_append(GTK_LIST_STORE(playlist_PL_List), &rowIter);
858 tmp_string = g_strdup_printf("%d:%.2d", (int) ((trackinfo->duration / 1000) / 60), (int) ((trackinfo->duration / 1000) % 60));
859 gtk_list_store_set(GTK_LIST_STORE(playlist_PL_List), &rowIter, COL_PL_ORDER_NUM, playlist_track_count,
860 COL_PL_ARTIST, trackinfo->artist,
861 COL_PL_ALBUM, trackinfo->album, COL_PL_TRACKID, trackinfo->item_id,
862 COL_PL_TRACKNAME, trackinfo->title, COL_PL_TRACKDURATION, tmp_string, -1);
863 g_free(tmp_string);
864 tmp_string = NULL;
865
866 LIBMTP_destroy_track_t(trackinfo);
867 } else {
868 LIBMTP_Dump_Errorstack(DeviceMgr.device);
869 LIBMTP_Clear_Errorstack(DeviceMgr.device);
870 }
871 }
872 }
873
874 // ************************************************************************************************
875
displayPlaylistNewDialog(void)876 gchar* displayPlaylistNewDialog(void) {
877 GtkWidget *dialog, *hbox, *label, *textbox;
878
879 dialog = gtk_dialog_new_with_buttons(_("New Playlist"), GTK_WINDOW(windowMain),
880 (GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
881 _("_OK"), GTK_RESPONSE_OK,
882 _("_Cancel"), GTK_RESPONSE_CANCEL,
883 NULL);
884
885 gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
886 gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
887 gtk_container_set_border_width(GTK_CONTAINER(dialog), 5);
888
889 #if HAVE_GTK3 == 0
890 hbox = gtk_hbox_new(FALSE, 5);
891 #else
892 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
893 #endif
894 gtk_widget_show(hbox);
895
896 #if HAVE_GTK3 == 0
897 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox);
898 #else
899 gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), hbox);
900 #endif
901
902 label = gtk_label_new(_("Playlist Name:"));
903 gtk_widget_show(label);
904 gtk_container_add(GTK_CONTAINER(hbox), label);
905
906 textbox = gtk_entry_new();
907 gtk_widget_show(textbox);
908 gtk_entry_set_max_length(GTK_ENTRY(textbox), 64);
909 gtk_entry_set_has_frame(GTK_ENTRY(textbox), TRUE);
910 gtk_entry_set_activates_default(GTK_ENTRY(textbox), TRUE);
911 gtk_container_add(GTK_CONTAINER(hbox), textbox);
912
913 gint result = gtk_dialog_run(GTK_DIALOG(dialog));
914 if (result == GTK_RESPONSE_OK) {
915 gchar* textfield = g_strdup(gtk_entry_get_text(GTK_ENTRY(textbox)));
916 if (strlen(textfield) == 0) {
917 // We have an emtpy string.
918 gtk_widget_destroy(dialog);
919 return NULL;
920 } else {
921 gtk_widget_destroy(dialog);
922 return textfield;
923 }
924 } else {
925 gtk_widget_destroy(dialog);
926 return NULL;
927 }
928 }
929
930 // ************************************************************************************************
931
playlist_PL_ListGetSelection()932 GList* playlist_PL_ListGetSelection() {
933 GList *selectedFiles, *ptr;
934 // Lets clear up the old list.
935 g_list_free(playlist_Selection_PL_RowReferences);
936 playlist_Selection_PL_RowReferences = NULL;
937
938 if (gtk_tree_selection_count_selected_rows(playlist_PL_Selection) == 0) {
939 // We have no rows.
940 return NULL;
941 }
942 // So now we must convert each selection to a row reference and store it in a new GList variable
943 // which we will return below.
944 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview_Playlist_Files));
945 selectedFiles = gtk_tree_selection_get_selected_rows(playlist_PL_Selection, &model);
946 ptr = selectedFiles;
947 while (ptr != NULL) {
948 GtkTreeRowReference *ref = gtk_tree_row_reference_new(GTK_TREE_MODEL(playlist_PL_List), (GtkTreePath*) ptr->data);
949 playlist_Selection_PL_RowReferences = g_list_append(playlist_Selection_PL_RowReferences, gtk_tree_row_reference_copy(ref));
950 gtk_tree_row_reference_free(ref);
951 ptr = ptr->next;
952 }
953 g_list_foreach(selectedFiles, (GFunc) gtk_tree_path_free, NULL);
954 g_list_free(selectedFiles);
955 return playlist_Selection_PL_RowReferences;
956 }
957
958 // ************************************************************************************************
959
playlist_PL_ListClearSelection()960 gboolean playlist_PL_ListClearSelection() {
961 if (playlist_PL_Selection != NULL)
962 gtk_tree_selection_unselect_all(playlist_PL_Selection);
963 return TRUE;
964 }
965
966 // ************************************************************************************************
967
playlist_PL_ListRemove(GList * List)968 gboolean playlist_PL_ListRemove(GList *List) {
969 GtkTreeIter iter;
970 gint tracknumber = 1;
971
972 playlist_PL_ListClearSelection();
973 g_list_foreach(List, (GFunc) __playlist_PL_Remove, NULL);
974
975 // Now reorder all tracks in this playlist.
976 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(playlist_PL_List), &iter)) {
977 gtk_list_store_set(GTK_LIST_STORE(playlist_PL_List), &iter, COL_PL_ORDER_NUM, tracknumber, -1);
978 tracknumber++;
979 while (gtk_tree_model_iter_next(GTK_TREE_MODEL(playlist_PL_List), &iter)) {
980 gtk_list_store_set(GTK_LIST_STORE(playlist_PL_List), &iter, COL_PL_ORDER_NUM, tracknumber, -1);
981 tracknumber++;
982 }
983 }
984 return TRUE;
985 }
986
987 // ************************************************************************************************
988
__playlist_PL_Remove(GtkTreeRowReference * Row)989 void __playlist_PL_Remove(GtkTreeRowReference *Row) {
990 GtkTreePath *path;
991 GtkTreeIter iter;
992 // convert the referenece to a path and retrieve the iterator;
993 path = gtk_tree_row_reference_get_path(Row);
994 gtk_tree_model_get_iter(GTK_TREE_MODEL(playlist_PL_List), &iter, path);
995 // We have our Iter now.
996 gtk_list_store_remove(GTK_LIST_STORE(playlist_PL_List), &iter);
997 playlist_track_count--;
998 gtk_tree_path_free(path);
999 }
1000
1001 // ************************************************************************************************
1002
playlist_TrackList_GetSelection()1003 GList* playlist_TrackList_GetSelection() {
1004 GList *selectedFiles, *ptr;
1005 // Lets clear up the old list.
1006 g_list_free(playlist_Selection_TrackRowReferences);
1007 playlist_Selection_TrackRowReferences = NULL;
1008
1009 if (gtk_tree_selection_count_selected_rows(playlist_TrackSelection) == 0) {
1010 // We have no rows.
1011 return NULL;
1012 }
1013 // So now we must convert each selection to a row reference and store it in a new GList variable
1014 // which we will return below.
1015 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview_Avail_Files));
1016 selectedFiles = gtk_tree_selection_get_selected_rows(playlist_TrackSelection, &model);
1017 ptr = selectedFiles;
1018 while (ptr != NULL) {
1019 GtkTreeRowReference *ref = gtk_tree_row_reference_new(GTK_TREE_MODEL(playlist_TrackList), (GtkTreePath*) ptr->data);
1020 playlist_Selection_TrackRowReferences = g_list_append(playlist_Selection_TrackRowReferences, gtk_tree_row_reference_copy(ref));
1021 gtk_tree_row_reference_free(ref);
1022 ptr = ptr->next;
1023 }
1024 g_list_foreach(selectedFiles, (GFunc) gtk_tree_path_free, NULL);
1025 g_list_free(selectedFiles);
1026 return playlist_Selection_TrackRowReferences;
1027 }
1028
1029 // ************************************************************************************************
1030
playlist_TrackList_Add(GList * List)1031 gboolean playlist_TrackList_Add(GList *List) {
1032 g_list_foreach(List, (GFunc) __playlist_TrackList_Add, NULL);
1033 return TRUE;
1034 }
1035
1036 // ************************************************************************************************
1037
__playlist_TrackList_Add(GtkTreeRowReference * Row)1038 void __playlist_TrackList_Add(GtkTreeRowReference *Row) {
1039 GtkTreePath *path = NULL;
1040 GtkTreeIter iter;
1041 GtkTreeIter PL_rowIter;
1042 gchar* artist = NULL;
1043 gchar* album = NULL;
1044 gchar* title = NULL;
1045 gint item_id = 0;
1046 gchar * duration = NULL;
1047
1048 // convert the referenece to a path and retrieve the iterator;
1049 path = gtk_tree_row_reference_get_path(Row);
1050 gtk_tree_model_get_iter(GTK_TREE_MODEL(playlist_TrackList), &iter, path);
1051 // We have our Iter now, so get the required information from the track treeview.
1052 gtk_tree_model_get(GTK_TREE_MODEL(playlist_TrackList), &iter, COL_ARTIST, &artist, COL_ALBUM, &album,
1053 COL_TRACKID, &item_id, COL_TRACKNAME, &title, COL_TRACKDURATION, & duration, -1);
1054 // Now store our information in the playlist treeview.
1055 playlist_track_count++;
1056 gtk_list_store_append(GTK_LIST_STORE(playlist_PL_List), &PL_rowIter);
1057 gtk_list_store_set(GTK_LIST_STORE(playlist_PL_List), &PL_rowIter, COL_PL_ORDER_NUM, playlist_track_count, COL_PL_ARTIST, artist,
1058 COL_PL_ALBUM, album, COL_PL_TRACKID, item_id, COL_PL_TRACKNAME, title, COL_PL_TRACKDURATION, duration, -1);
1059
1060 //Need to free our string values
1061 g_free(artist);
1062 g_free(album);
1063 g_free(title);
1064 g_free(duration);
1065 gtk_tree_path_free(path);
1066 }
1067
1068 // ************************************************************************************************
1069
playlist_move_files(gint direction)1070 gboolean playlist_move_files(gint direction) {
1071 GList * playlist_files = NULL;
1072 GtkTreeIter iter;
1073 gint tracknumber = 1;
1074 // Get our files...
1075 playlist_files = playlist_PL_ListGetSelection();
1076 if (playlist_files == NULL)
1077 return FALSE;
1078
1079 // If we are moving files down we need to reverse the rows references...
1080 if (direction == 1) {
1081 playlist_files = g_list_reverse(playlist_files);
1082 g_list_foreach(playlist_files, (GFunc) __playlist_move_files_down, NULL);
1083 } else {
1084 g_list_foreach(playlist_files, (GFunc) __playlist_move_files_up, NULL);
1085 }
1086 // Now reorder all tracks in this playlist.
1087 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(playlist_PL_List), &iter)) {
1088 gtk_list_store_set(GTK_LIST_STORE(playlist_PL_List), &iter, COL_PL_ORDER_NUM, tracknumber, -1);
1089 tracknumber++;
1090 while (gtk_tree_model_iter_next(GTK_TREE_MODEL(playlist_PL_List), &iter)) {
1091 gtk_list_store_set(GTK_LIST_STORE(playlist_PL_List), &iter, COL_PL_ORDER_NUM, tracknumber, -1);
1092 tracknumber++;
1093 }
1094 }
1095 return TRUE;
1096 }
1097
1098 // ************************************************************************************************
1099
__playlist_move_files_up(GtkTreeRowReference * Row)1100 void __playlist_move_files_up(GtkTreeRowReference *Row) {
1101 GtkTreePath *path;
1102 GtkTreeIter iter;
1103 GtkTreeIter iter2;
1104 // convert the referenece to a path and retrieve the iterator;
1105 path = gtk_tree_row_reference_get_path(Row);
1106 gtk_tree_model_get_iter(GTK_TREE_MODEL(playlist_PL_List), &iter, path);
1107 // We have our Iter now.
1108 // Now get it's prev path and turn it into a iter
1109 if (gtk_tree_path_prev(path) == TRUE) {
1110 // we have a previous entry...
1111 gtk_tree_model_get_iter(GTK_TREE_MODEL(playlist_PL_List), &iter2, path);
1112 gtk_list_store_swap(GTK_LIST_STORE(playlist_PL_List), &iter, &iter2);
1113 }
1114 gtk_tree_path_free(path);
1115 }
1116
1117 // ************************************************************************************************
1118
__playlist_move_files_down(GtkTreeRowReference * Row)1119 void __playlist_move_files_down(GtkTreeRowReference *Row) {
1120 GtkTreePath *path;
1121 GtkTreeIter iter;
1122 GtkTreeIter iter2;
1123 // convert the referenece to a path and retrieve the iterator;
1124 path = gtk_tree_row_reference_get_path(Row);
1125 gtk_tree_model_get_iter(GTK_TREE_MODEL(playlist_PL_List), &iter, path);
1126 // We have our Iter now.
1127 iter2 = iter;
1128 if (gtk_tree_model_iter_next(GTK_TREE_MODEL(playlist_PL_List), &iter2) == TRUE) {
1129 // we have something to swap with...
1130 gtk_list_store_swap(GTK_LIST_STORE(playlist_PL_List), &iter, &iter2);
1131 }
1132 gtk_tree_path_free(path);
1133 }
1134
1135 // ************************************************************************************************
1136
playlist_SavePlaylist(gint PlayListID)1137 void playlist_SavePlaylist(gint PlayListID) {
1138 LIBMTP_playlist_t* tmpplaylist = devicePlayLists;
1139 gint tmpplaylistID = PlayListID;
1140 gint item_id = 0;
1141 GtkTreeIter iter;
1142 uint32_t *tmp = NULL;
1143
1144 if (PlayListID > 0) {
1145 while (tmpplaylistID--)
1146 if (tmpplaylist->next != NULL)
1147 tmpplaylist = tmpplaylist->next;
1148 }
1149 // tmpplaylist points to our playlist;
1150 // So all we need to do is - update our current structure with the new details
1151
1152 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(playlist_PL_List), &iter)) {
1153 gtk_tree_model_get(GTK_TREE_MODEL(playlist_PL_List), &iter, COL_PL_TRACKID, &item_id, -1);
1154 tmpplaylist->no_tracks = 1;
1155
1156 // item_id = our track num... so append to tmpplaylist->tracks
1157 if ((tmp = g_realloc(tmpplaylist->tracks, sizeof (uint32_t) * (tmpplaylist->no_tracks))) == NULL) {
1158 g_fprintf(stderr, _("realloc in savePlayList failed\n"));
1159 displayError(_("Updating playlist failed? 'realloc in savePlayList'\n"));
1160 return;
1161 }
1162 tmpplaylist->tracks = tmp;
1163 tmpplaylist->tracks[(tmpplaylist->no_tracks - 1)] = item_id;
1164 //tmpplaylist->no_tracks++;
1165 while (gtk_tree_model_iter_next(GTK_TREE_MODEL(playlist_PL_List), &iter)) {
1166 gtk_tree_model_get(GTK_TREE_MODEL(playlist_PL_List), &iter, COL_PL_TRACKID, &item_id, -1);
1167 tmpplaylist->no_tracks++;
1168 // item_id = our track num... so append to tmpplaylist->tracks
1169 if ((tmp = g_realloc(tmpplaylist->tracks, sizeof (uint32_t) * (tmpplaylist->no_tracks))) == NULL) {
1170 g_fprintf(stderr, _("realloc in savePlayList failed\n"));
1171 displayError(_("Updating playlist failed? 'realloc in savePlayList'\n"));
1172 return;
1173 }
1174 tmpplaylist->tracks = tmp;
1175 tmpplaylist->tracks[(tmpplaylist->no_tracks - 1)] = item_id;
1176 //tmpplaylist->no_tracks++;
1177
1178 }
1179 }
1180 // get libmtp to save it.
1181 playlistUpdate(tmpplaylist);
1182 // Update our own metadata.
1183 devicePlayLists = getPlaylists();
1184 }
1185
1186 // Playlist Callbacks.
1187 // ************************************************************************************************
1188
on_quitPlaylist_activate(GtkWidget * item,gpointer user_data)1189 void on_quitPlaylist_activate(GtkWidget *item, gpointer user_data) {
1190 UNUSED(item);
1191 UNUSED(user_data);
1192 // Save our current selected playlist!
1193 if (devicePlayLists != NULL)
1194 playlist_SavePlaylist(playlist_number);
1195 // Kill our window
1196 gtk_widget_hide(windowPlaylistDialog);
1197 gtk_widget_destroy(windowPlaylistDialog);
1198 windowPlaylistDialog = NULL;
1199 // Do a device rescan to show the new playlists in the file window
1200 deviceRescan();
1201 } // end on_quitPlaylist_activate()
1202
1203 // ************************************************************************************************
1204
on_Playlist_NewPlaylistButton_activate(GtkWidget * item,gpointer user_data)1205 void on_Playlist_NewPlaylistButton_activate(GtkWidget *item, gpointer user_data) {
1206 UNUSED(item);
1207 UNUSED(user_data);
1208
1209 // Save our current selected playlist!
1210 if (devicePlayLists != NULL)
1211 playlist_SavePlaylist(playlist_number);
1212
1213 gchar *playlistname = displayPlaylistNewDialog();
1214 if (playlistname != NULL) {
1215 // Add in playlist to MTP device.
1216 playlistAdd(playlistname);
1217 // Refresh our playlist information.
1218 devicePlayLists = getPlaylists();
1219 gtk_list_store_clear(GTK_LIST_STORE(playlist_PL_List));
1220 // Add it to our combobox
1221
1222 #if HAVE_GTK3 == 0
1223 gtk_combo_box_append_text(GTK_COMBO_BOX(comboboxentry_playlist), (playlistname));
1224 #else
1225 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(comboboxentry_playlist), (playlistname));
1226 #endif
1227 g_free(playlistname);
1228
1229 // Set the active combobox item.
1230 comboboxentry_playlist_entries++;
1231 playlist_number = comboboxentry_playlist_entries - 1;
1232 gtk_combo_box_set_active(GTK_COMBO_BOX(comboboxentry_playlist), comboboxentry_playlist_entries - 1);
1233 SetPlaylistButtonState(TRUE);
1234 setPlaylistField(playlist_number);
1235 }
1236 } // end on_Playlist_NewPlaylistButton_activate()
1237
1238 // ************************************************************************************************
1239
on_Playlist_ImportPlaylistButton_activate(GtkWidget * item,gpointer user_data)1240 void on_Playlist_ImportPlaylistButton_activate(GtkWidget *item, gpointer user_data) {
1241 UNUSED(item);
1242 UNUSED(user_data);
1243 gchar *playlistfilename = NULL;
1244 GtkWidget *FileDialog;
1245 GtkFileFilter *OpenFormFilter, *OpenFormFilter2;
1246
1247 // Save our current selected playlist!
1248 if (devicePlayLists != NULL)
1249 playlist_SavePlaylist(playlist_number);
1250
1251 // Get our filename...
1252
1253 FileDialog = gtk_file_chooser_dialog_new(_("Select Playlist to Import"),
1254 GTK_WINDOW(windowMain), GTK_FILE_CHOOSER_ACTION_OPEN,
1255 _("_Cancel"), GTK_RESPONSE_CANCEL,
1256 _("_Open"), GTK_RESPONSE_ACCEPT,
1257 NULL);
1258 gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(FileDialog), FALSE);
1259 OpenFormFilter = gtk_file_filter_new();
1260 gtk_file_filter_add_pattern(OpenFormFilter, "*.m3u");
1261 gtk_file_filter_set_name(OpenFormFilter, "m3u Playlists");
1262 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(FileDialog), OpenFormFilter);
1263 OpenFormFilter2 = gtk_file_filter_new();
1264 gtk_file_filter_add_pattern(OpenFormFilter2, "*");
1265 gtk_file_filter_set_name(OpenFormFilter2, "All Files");
1266 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(FileDialog), OpenFormFilter2);
1267
1268 if (gtk_dialog_run(GTK_DIALOG(FileDialog)) == GTK_RESPONSE_ACCEPT) {
1269 playlistfilename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(FileDialog));
1270 }
1271
1272 gtk_widget_hide(FileDialog);
1273 gtk_widget_destroy(FileDialog);
1274
1275 if (playlistfilename != NULL) {
1276 // Add in playlist to MTP device.
1277 gchar *playlistname = playlistImport(playlistfilename);
1278
1279 // If our name is NULL, then the import failed...
1280 if (playlistname != NULL) {
1281 // Refresh our playlist information.
1282 devicePlayLists = getPlaylists();
1283 gtk_list_store_clear(GTK_LIST_STORE(playlist_PL_List));
1284 // Add it to our combobox
1285
1286 #if HAVE_GTK3 == 0
1287 gtk_combo_box_append_text(GTK_COMBO_BOX(comboboxentry_playlist), (playlistname));
1288 #else
1289 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(comboboxentry_playlist), (playlistname));
1290 #endif
1291
1292 // Set the active combobox item.
1293 comboboxentry_playlist_entries++;
1294 playlist_number = comboboxentry_playlist_entries - 1;
1295 gtk_combo_box_set_active(GTK_COMBO_BOX(comboboxentry_playlist), comboboxentry_playlist_entries - 1);
1296 SetPlaylistButtonState(TRUE);
1297 setPlaylistField(playlist_number);
1298
1299 // Clean up fields.
1300 g_free(playlistname);
1301 } else {
1302 // Let the user know the import failed.
1303 g_fprintf(stderr, _("The playlist failed to import correctly.\n"));
1304 displayError(_("The playlist failed to import correctly.\n"));
1305 }
1306 // Clean up fields.
1307 g_free(playlistfilename);
1308 }
1309 } // end on_Playlist_ImportPlaylistButton_activate()
1310
1311 // ************************************************************************************************
1312
on_Playlist_ExportPlaylistButton_activate(GtkWidget * item,gpointer user_data)1313 void on_Playlist_ExportPlaylistButton_activate(GtkWidget *item, gpointer user_data) {
1314 UNUSED(item);
1315 UNUSED(user_data);
1316
1317 // Save our current selected playlist!
1318 if (devicePlayLists != NULL)
1319 playlist_SavePlaylist(playlist_number);
1320
1321 gint PlayListID = gtk_combo_box_get_active(GTK_COMBO_BOX(comboboxentry_playlist));
1322
1323 if (PlayListID != -1) {
1324 // We have something selected so lets do the dance.
1325 LIBMTP_playlist_t* tmpplaylist = devicePlayLists;
1326 if (PlayListID > 0) {
1327 while (PlayListID--)
1328 if (tmpplaylist->next != NULL)
1329 tmpplaylist = tmpplaylist->next;
1330 }
1331 // We should be in the correct playlist LIBMTP structure.
1332
1333 gchar *playlistfilename = g_strdup_printf("%s.%s", tmpplaylist->name, "m3u");
1334
1335 GtkWidget *FileDialog = gtk_file_chooser_dialog_new(_("Save as..."),
1336 GTK_WINDOW(windowMain), GTK_FILE_CHOOSER_ACTION_SAVE,
1337 _("_Cancel"), GTK_RESPONSE_CANCEL,
1338 _("_Open"), GTK_RESPONSE_ACCEPT,
1339 NULL);
1340 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(FileDialog), playlistfilename);
1341
1342 if (gtk_dialog_run(GTK_DIALOG(FileDialog)) == GTK_RESPONSE_ACCEPT) {
1343 playlistfilename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(FileDialog));
1344 }
1345
1346 gtk_widget_hide(FileDialog);
1347 gtk_widget_destroy(FileDialog);
1348
1349 if (playlistfilename != NULL) {
1350 playlistExport(playlistfilename, tmpplaylist);
1351 g_free(playlistfilename);
1352 }
1353 }
1354 } // end on_Playlist_ExportPlaylistButton_activate()
1355
1356 // ************************************************************************************************
1357
on_Playlist_DelPlaylistButton_activate(GtkWidget * item,gpointer user_data)1358 void on_Playlist_DelPlaylistButton_activate(GtkWidget *item, gpointer user_data) {
1359 UNUSED(item);
1360 UNUSED(user_data);
1361 gint PlayListID = gtk_combo_box_get_active(GTK_COMBO_BOX(comboboxentry_playlist));
1362 if (PlayListID != -1) {
1363 // We have something selected so lets do the dance.
1364 LIBMTP_playlist_t* tmpplaylist = devicePlayLists;
1365 if (PlayListID > 0) {
1366 while (PlayListID--)
1367 if (tmpplaylist->next != NULL)
1368 tmpplaylist = tmpplaylist->next;
1369 }
1370 // We should be in the correct playlist LIBMTP structure.
1371 playlistDelete(tmpplaylist);
1372 // Clear the PL list view box
1373 gtk_list_store_clear(GTK_LIST_STORE(playlist_PL_List));
1374 // Rebuild the playlist structure and combobox.
1375 devicePlayLists = getPlaylists();
1376 setPlayListComboBox();
1377 }
1378 } // end on_Playlist_DelPlaylistButton_activate()
1379
1380 // ************************************************************************************************
1381
on_Playlist_DelFileButton_activate(GtkWidget * item,gpointer user_data)1382 void on_Playlist_DelFileButton_activate(GtkWidget *item, gpointer user_data) {
1383 UNUSED(item);
1384 UNUSED(user_data);
1385 if (playlist_PL_ListGetSelection() == NULL)
1386 return;
1387 playlist_PL_ListRemove(playlist_PL_ListGetSelection());
1388 } // end on_Playlist_DelFileButton_activate()
1389
1390 // ************************************************************************************************
1391
on_Playlist_AddFileButton_activate(GtkWidget * item,gpointer user_data)1392 void on_Playlist_AddFileButton_activate(GtkWidget *item, gpointer user_data) {
1393 UNUSED(item);
1394 UNUSED(user_data);
1395 //g_printf("Clicked on add file in playlist button\n");
1396 if (playlist_TrackList_GetSelection() == NULL)
1397 return;
1398 playlist_TrackList_Add(playlist_TrackList_GetSelection());
1399 } // end on_Playlist_AddFileButton_activate()
1400
1401 // ************************************************************************************************
1402
on_Playlist_FileUpButton_activate(GtkWidget * item,gpointer user_data)1403 void on_Playlist_FileUpButton_activate(GtkWidget *item, gpointer user_data) {
1404 UNUSED(item);
1405 UNUSED(user_data);
1406 playlist_move_files(-1);
1407 } // end on_Playlist_FileUpButton_activate()
1408
1409 // ************************************************************************************************
1410
on_Playlist_FileDownButton_activate(GtkWidget * item,gpointer user_data)1411 void on_Playlist_FileDownButton_activate(GtkWidget *item, gpointer user_data) {
1412 UNUSED(item);
1413 UNUSED(user_data);
1414 playlist_move_files(1);
1415 } // end on_Playlist_FileDownButton_activate()
1416
1417 // ************************************************************************************************
1418
on_Playlist_Combobox_activate(GtkComboBox * combobox,gpointer user_data)1419 void on_Playlist_Combobox_activate(GtkComboBox *combobox, gpointer user_data) {
1420 UNUSED(combobox);
1421 UNUSED(user_data);
1422 if (runPlaylistHandler == TRUE) {
1423 // Save our current selected playlist
1424 playlist_SavePlaylist(playlist_number);
1425 // Get our new playlist ID, and display the contents of it.
1426 playlist_number = gtk_combo_box_get_active(GTK_COMBO_BOX(comboboxentry_playlist));
1427 setPlaylistField(playlist_number);
1428 }
1429 } // end on_Playlist_Combobox_activate()
1430
1431