1 /*
2 |  Copyright (C) 2003 Corey Donohoe <atmos at atmos dot org>
3 |  Copyright (C) 2003-2007 Jorg Schuler <jcsjcs at users sourceforge net>
4 |  Part of the gtkpod project.
5 |
6 |  URL: http://www.gtkpod.org/
7 |  URL: http://gtkpod.sourceforge.net/
8 |
9 |  This program is free software; you can redistribute it and/or modify
10 |  it under the terms of the GNU General Public License as published by
11 |  the Free Software Foundation; either version 2 of the License, or
12 |  (at your option) any later version.
13 |
14 |  This program is distributed in the hope that it will be useful,
15 |  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 |  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 |  GNU General Public License for more details.
18 |
19 |  You should have received a copy of the GNU General Public License
20 |  along with this program; if not, write to the Free Software
21 |  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 |
23 |  iTunes and iPod are trademarks of Apple
24 |
25 |  This product is not supported/written/published by Apple!
26 |
27 |  $Id$
28 */
29 
30 #ifdef HAVE_CONFIG_H
31 #  include <config.h>
32 #endif
33 
34 #include "itdb.h"
35 #include "info.h"
36 #include "details.h"
37 #include "display.h"
38 #include "display_itdb.h"
39 #include "file.h"
40 #include "misc.h"
41 #include "misc_track.h"
42 #include "prefs.h"
43 #include "tools.h"
44 #include "repository.h"
45 #include "syncdir.h"
46 #include "display_coverart.h"
47 #include "display_photo.h"
48 
49 #define LOCALDEBUG 0
50 
51 static guint entry_inst = -1;
52 static GList *selected_tracks = NULL;
53 static Playlist *selected_playlist = NULL;
54 static TabEntry *selected_entry = NULL;
55 static iTunesDB *active_itdb = NULL;
56 /* types of context menus (PM/ST/TM) */
57 typedef enum {
58     CM_PL = 0,
59     CM_ST,
60     CM_TM,
61     CM_NUM,
62     CM_CAD,
63     CM_PH_AV,
64     CM_PH_IV
65 } CM_type;
66 
67 
68 
69 #if LOCALDEBUG
70 /**
71  * do_special - for debugging: change as needed to obtain information
72  * on selected tracks
73  * @mi - the menu item selected
74  * @data - ignored, should be NULL
75  */
76 static void
do_special(GtkWidget * w,gpointer data)77 do_special(GtkWidget *w, gpointer data)
78 {
79     GList *gl;
80 
81     for (gl=selected_tracks; gl; gl=gl->next)
82     {
83 	gchar *mp;
84 	Track *tr = gl->data;
85 	g_return_if_fail (tr);
86 	g_object_get (tr->itdb->device, "mount-point", &mp, NULL);
87 	printf ("mountpoint: %s\n", mp);
88 	g_free (mp);
89 
90 	printf ("track: %p: thumbnails: %p id: %d num: %d\n",
91 		tr, tr->artwork->thumbnails, tr->artwork->id, g_list_length (tr->artwork->thumbnails));
92 	if (tr->artwork->thumbnails)
93 	{
94 	    GList *gl2;
95 	    for (gl2=tr->artwork->thumbnails; gl2; gl2=gl2->next)
96 	    {
97 		Thumb *img = gl2->data;
98 		g_return_if_fail (img);
99 		printf ("  %s offset: %d size: %d width: %d height: %d\n", img->filename, img->offset, img->size, img->width, img->height);
100 	    }
101 	}
102     }
103 }
104 #endif
105 
106 
107 
108 /**
109  * export_entries - export the currently selected files to disk
110  * @mi - the menu item selected
111  * @data - ignored, should be NULL
112  */
113 static void
export_entries(GtkWidget * w,gpointer data)114 export_entries(GtkWidget *w, gpointer data)
115 {
116     if(selected_tracks)
117 	export_files_init (selected_tracks, NULL, FALSE, NULL);
118 }
119 
120 /**
121  * create_playlist_file - write a playlist file containing the
122  * currently selected tracks.
123  * @mi - the menu item selected
124  * @data - ignored, should be NULL
125  */
126 static void
create_playlist_file(GtkWidget * w,gpointer data)127 create_playlist_file(GtkWidget *w, gpointer data)
128 {
129     if(selected_tracks)
130 	export_playlist_file_init(selected_tracks);
131 }
132 
133 
134 /*
135  * play_entries_now - play the entries currently selected in xmms
136  * @mi - the menu item selected
137  * @data - Ignored, should be NULL
138  */
139 static void
play_entries_now(GtkMenuItem * mi,gpointer data)140 play_entries_now (GtkMenuItem *mi, gpointer data)
141 {
142     tools_play_tracks (selected_tracks);
143 }
144 
145 /*
146  * play_entries_now - play the entries currently selected in xmms
147  * @mi - the menu item selected
148  * @data - Ignored, should be NULL
149  */
150 static void
play_entries_enqueue(GtkMenuItem * mi,gpointer data)151 play_entries_enqueue (GtkMenuItem *mi, gpointer data)
152 {
153     tools_enqueue_tracks (selected_tracks);
154 }
155 
156 
157 /*
158  * show_details_entries - show details of tracks currently selected
159  * @mi - the menu item selected
160  * @data - Ignored, should be NULL
161  */
162 static void
edit_details_entries(GtkMenuItem * mi,gpointer data)163 edit_details_entries(GtkMenuItem *mi, gpointer data)
164 {
165     if (selected_playlist)
166 	details_edit (selected_playlist->members);
167     else if(selected_entry)
168 	details_edit (selected_entry->members);
169     else if(selected_tracks)
170 	details_edit (selected_tracks);
171 }
172 
173 /*
174  * display the dialog with the full size cd artwork cover
175  * @mi - the menu item selected
176  * @data - Ignored, should be NULL
177  */
178 static void
display_track_artwork(GtkMenuItem * mi,gpointer data)179 display_track_artwork(GtkMenuItem *mi, gpointer data)
180 {
181 	if (selected_tracks)
182 		coverart_display_big_artwork (selected_tracks);
183 }
184 
185 /*
186  * update_entries - update the entries currently selected
187  * @mi - the menu item selected
188  * @data - Ignored, should be NULL
189  */
190 static void
update_entries(GtkMenuItem * mi,gpointer data)191 update_entries(GtkMenuItem *mi, gpointer data)
192 {
193     if (selected_playlist)
194 	gp_do_selected_playlist (update_tracks);
195     else if(selected_entry)
196 	gp_do_selected_entry (update_tracks, entry_inst);
197     else if(selected_tracks)
198 	gp_do_selected_tracks (update_tracks);
199 }
200 
201 /*
202  * sync_dirs_ entries - sync the directories of the selected playlist
203  *
204  * @mi - the menu item selected
205  * @data - Ignored, should be NULL
206  */
207 static void
sync_dirs(GtkMenuItem * mi,gpointer data)208 sync_dirs (GtkMenuItem *mi, gpointer data)
209 {
210     if (selected_playlist)
211     {
212 	sync_playlist (selected_playlist, NULL,
213 		       KEY_SYNC_CONFIRM_DIRS, 0,
214 		       KEY_SYNC_DELETE_TRACKS, 0,
215 		       KEY_SYNC_CONFIRM_DELETE, 0,
216 		       KEY_SYNC_SHOW_SUMMARY, 0);
217     }
218     else
219     {
220 	g_return_if_reached ();
221     }
222 }
223 
224 /**
225  * delete_entries - delete the currently selected entry, be it a playlist,
226  * items in a sort tab, or tracks
227  * @mi - the menu item selected
228  * @data - ignored, should be NULL
229  */
230 static void
delete_entries(GtkMenuItem * mi,gpointer data)231 delete_entries(GtkMenuItem *mi, gpointer data)
232 {
233     DeleteAction deleteaction = GPOINTER_TO_INT (data);
234 
235     if (selected_playlist)
236 	delete_playlist_head (deleteaction);
237     else if(selected_entry)
238 	delete_entry_head (entry_inst, deleteaction);
239     else if(selected_tracks)
240 	delete_track_head (deleteaction);
241 }
242 
243 /* Edit selected smart playlist */
edit_spl(GtkMenuItem * mi,gpointer data)244 static void edit_spl (GtkMenuItem *mi, gpointer data)
245 {
246     Playlist *pl = NULL;
247 
248     if (selected_tracks)   pl = pm_get_selected_playlist ();
249     if (selected_entry)    pl = pm_get_selected_playlist ();
250     if (selected_playlist) pl = selected_playlist;
251 
252     spl_edit (pl);
253 }
254 
255 /* Display repository options */
edit_properties(GtkMenuItem * mi,gpointer data)256 static void edit_properties (GtkMenuItem *mi, gpointer data)
257 {
258     g_return_if_fail (selected_playlist);
259 
260     repository_edit (selected_playlist->itdb, selected_playlist);
261 }
262 
263 
264 static void
create_playlist_from_entries(GtkMenuItem * mi,gpointer data)265 create_playlist_from_entries (GtkMenuItem *mi, gpointer data)
266 {
267     generate_new_playlist (active_itdb, selected_tracks);
268 }
269 
270 /**
271  * alphabetize - alphabetize the currently selected entry
272  * sort tab). The sort order is being cycled through.
273  * @mi - the menu item selected
274  * @data - ignored, should be NULL
275  */
276 static void
alphabetize(GtkMenuItem * mi,gpointer data)277 alphabetize(GtkMenuItem *mi, gpointer data)
278 {
279     if (selected_entry)
280     {
281 	switch (prefs_get_int("st_sort"))
282 	{
283 	case SORT_ASCENDING:
284 	    prefs_set_int("st_sort", SORT_DESCENDING);
285 	    break;
286 	case SORT_DESCENDING:
287 	    prefs_set_int("st_sort", SORT_NONE);
288 	    break;
289 	case SORT_NONE:
290 	    prefs_set_int("st_sort", SORT_ASCENDING);
291 	    break;
292 	}
293 	st_sort (prefs_get_int("st_sort"));
294     }
295 }
296 
297 
load_ipod(GtkMenuItem * mi,gpointer data)298 static void load_ipod (GtkMenuItem *mi, gpointer data)
299 {
300     g_return_if_fail (selected_playlist);
301 
302     gp_load_ipod (selected_playlist->itdb);
303 }
304 
305 
eject_ipod(GtkMenuItem * mi,gpointer data)306 static void eject_ipod (GtkMenuItem *mi, gpointer data)
307 {
308     iTunesDB *itdb;
309     ExtraiTunesDBData *eitdb;
310 
311     /* all of the checks below indicate a programming error -> give a
312        warning through the g_..._fail macros */
313     g_return_if_fail (selected_playlist);
314     itdb = selected_playlist->itdb;
315     g_return_if_fail (itdb);
316     g_return_if_fail (itdb->usertype & GP_ITDB_TYPE_IPOD);
317     eitdb = itdb->userdata;
318     g_return_if_fail (eitdb);
319     g_return_if_fail (eitdb->itdb_imported == TRUE);
320 
321     gp_eject_ipod (itdb);
322     /* Set the coverart display based on the selected playlist */
323     coverart_display_update(TRUE);
324 }
325 
326 
save_changes(GtkMenuItem * mi,gpointer data)327 static void save_changes (GtkMenuItem *mi, gpointer data)
328 {
329     g_return_if_fail (selected_playlist);
330 
331     gp_save_itdb (selected_playlist->itdb);
332 }
333 
334 
335 
336 
337 /* ------------------------------------------------------------
338 
339       Copying selected item(s) to target destination
340 
341    ------------------------------------------------------------ */
342 
343 
344 /*
345  * Copy the selected playlist to a specified itdb.
346  */
347 void
copy_playlist_to_target_itdb(Playlist * pl,iTunesDB * t_itdb)348 copy_playlist_to_target_itdb (Playlist     *pl,
349 			      iTunesDB     *t_itdb)
350 {
351     Playlist	*pl_n;
352     GList	*addtracks = NULL;
353     g_return_if_fail (pl);
354     g_return_if_fail (t_itdb);
355     if (pl->itdb != t_itdb)
356     {
357 	addtracks = export_trackglist_when_necessary (pl->itdb,
358 						      t_itdb,
359 						      pl->members);
360 	if (addtracks || !pl->members)
361 	{
362 	    pl_n = gp_playlist_add_new(t_itdb, pl->name, FALSE, -1);
363 	    add_trackglist_to_playlist (pl_n, addtracks);
364 	    gtkpod_statusbar_message (_("Copied \"%s\" playlist to %s"),
365 				      pl->name, (itdb_playlist_mpl (t_itdb))->name);
366 	}
367 	g_list_free (addtracks);
368 	addtracks = NULL;
369     }
370     else
371     {
372 	pl_n = itdb_playlist_duplicate (pl);
373 	g_return_if_fail (pl_n);
374 	gp_playlist_add (t_itdb, pl_n, -1);
375     }
376 }
377 
378 
379 /*
380  * Copy selected tracks to a specified itdb.
381  */
382 void
copy_tracks_to_target_itdb(GList * tracks,iTunesDB * t_itdb)383 copy_tracks_to_target_itdb (GList        *tracks,
384 			    iTunesDB     *t_itdb)
385 {
386     GList       *addtracks = NULL;
387     Track	*first = tracks->data;
388     Playlist    *mpl;
389     gint        n;
390 
391     g_return_if_fail(tracks);
392     g_return_if_fail(t_itdb);
393 
394     mpl = itdb_playlist_mpl (t_itdb);
395     g_return_if_fail(mpl);
396 
397     addtracks = export_trackglist_when_necessary (first->itdb, t_itdb, tracks);
398 
399     if (addtracks)
400     {
401 	add_trackglist_to_playlist (mpl, addtracks);
402 	n = g_list_length (addtracks);
403 	gtkpod_statusbar_message (ngettext ("Copied %d track to '%s'",
404 					    "Copied %d tracks to '%s'", n),
405 				  n, mpl->name);
406 	g_list_free (addtracks);
407 	addtracks = NULL;
408     }
409 }
410 
411 
412 void
copy_playlist_to_target_playlist(Playlist * pl,Playlist * t_pl)413 copy_playlist_to_target_playlist (Playlist     *pl,
414 				  Playlist     *t_pl)
415 {
416     GList	*addtracks = NULL;
417     Playlist    *t_mpl;
418 
419     g_return_if_fail (pl);
420     g_return_if_fail (t_pl);
421 
422     t_mpl = itdb_playlist_mpl (t_pl->itdb);
423     g_return_if_fail(t_mpl);
424 
425     addtracks = export_trackglist_when_necessary (pl->itdb,
426 						  t_pl->itdb,
427 						  pl->members);
428     if (addtracks || !pl->members)
429     {
430 	add_trackglist_to_playlist (t_pl, addtracks);
431 	gtkpod_statusbar_message (_("Copied '%s' playlist to '%s' in '%s'"),
432 				  pl->name, t_pl->name, t_mpl->name);
433 	g_list_free(addtracks);
434 	addtracks = NULL;
435     }
436 }
437 
438 
439 
440 void
copy_tracks_to_target_playlist(GList * tracks,Playlist * t_pl)441 copy_tracks_to_target_playlist (GList        *tracks,
442 				Playlist     *t_pl)
443 {
444     GList	*addtracks = NULL;
445     Track	*first;
446     Playlist    *mpl;
447     gint        n;
448 
449     g_return_if_fail (tracks);
450     g_return_if_fail (t_pl);
451     g_return_if_fail (t_pl->itdb);
452 
453     mpl = itdb_playlist_mpl (t_pl->itdb);
454     g_return_if_fail(mpl);
455 
456     if (tracks)
457     {
458 	first = tracks->data;
459 	g_return_if_fail (first);
460 	addtracks = export_trackglist_when_necessary (first->itdb, t_pl->itdb, tracks);
461 	add_trackglist_to_playlist (t_pl, addtracks);
462     }
463     n = g_list_length (addtracks);
464     gtkpod_statusbar_message (ngettext ("Copied %d track to '%s' in '%s'",
465 					"Copied %d tracks to %s in '%s'", n),
466 			      n, t_pl->name, mpl->name);
467     g_list_free (addtracks);
468     addtracks = NULL;
469 }
470 
471 
472 
copy_selected_to_target_itdb(GtkMenuItem * mi,gpointer * userdata)473 static void copy_selected_to_target_itdb (GtkMenuItem *mi, gpointer *userdata)
474 {
475     iTunesDB *t_itdb = *userdata;
476     g_return_if_fail (t_itdb);
477     if (selected_playlist)
478 	copy_playlist_to_target_itdb (selected_playlist, t_itdb);
479     else if (selected_entry)
480 	copy_tracks_to_target_itdb (selected_entry->members, t_itdb);
481     else if (selected_tracks)
482 	copy_tracks_to_target_itdb (selected_tracks, t_itdb);
483 }
484 
485 
copy_selected_to_target_playlist(GtkMenuItem * mi,gpointer * userdata)486 static void copy_selected_to_target_playlist (GtkMenuItem *mi, gpointer *userdata)
487 {
488     Playlist *t_pl = *userdata;
489     g_return_if_fail (t_pl);
490     if (selected_playlist)
491 	copy_playlist_to_target_playlist (selected_playlist, t_pl);
492     else if (selected_entry)
493 	copy_tracks_to_target_playlist (selected_entry->members, t_pl);
494     else if (selected_tracks)
495 	copy_tracks_to_target_playlist (selected_tracks, t_pl);
496 }
497 
498 
499 /* Attach a menu item to your context menu */
500 /* @m - the GtkMenu we're attaching to
501  * @str - a gchar* with the menu label
502  * @stock - name of the stock icon (or NULL if none is to be used)
503  * @func - the callback for when the item is selected (or NULL)
504  * @mi - the GtkWidget we're gonna hook into the menu
505  */
hookup_mi(GtkWidget * m,const gchar * str,const gchar * stock,GCallback func,gpointer userdata)506 GtkWidget *hookup_mi (GtkWidget *m,
507 		      const gchar *str,
508 		      const gchar *stock,
509 		      GCallback func,
510 		      gpointer userdata)
511 {
512     GtkWidget *mi;
513 
514     if (stock)
515     {
516 	GtkWidget *image;
517 	mi = gtk_image_menu_item_new_with_mnemonic (str);
518 	image = gtk_image_new_from_stock (stock, GTK_ICON_SIZE_MENU);
519 	gtk_widget_show (image);
520 	gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), image);
521     }
522     else
523     {
524 	mi = gtk_menu_item_new_with_label(str);
525     }
526     gtk_widget_show(mi);
527     gtk_widget_set_sensitive(mi, TRUE);
528     gtk_widget_add_events(mi, GDK_BUTTON_RELEASE_MASK);
529     if (func)
530 	g_signal_connect(G_OBJECT(mi), "activate", func, userdata);
531     gtk_container_add (GTK_CONTAINER (m), mi);
532     return mi;
533 }
534 
535 
536 /* Add separator to Menu @m and return pointer to separator widget */
add_separator(GtkWidget * m)537 GtkWidget *add_separator (GtkWidget *m)
538 {
539     GtkWidget *sep = NULL;
540     if (m)
541     {
542 	sep = gtk_separator_menu_item_new ();
543 	gtk_widget_show(sep);
544 	gtk_widget_set_sensitive(sep, TRUE);
545 	gtk_container_add (GTK_CONTAINER (m), sep);
546     }
547     return sep;
548 }
549 
550 
add_copy_selected_to_target_itdb(GtkWidget * menu,const gchar * title)551 static GtkWidget *add_copy_selected_to_target_itdb (GtkWidget *menu,
552 						    const gchar *title)
553 {
554     GtkWidget *mi;
555     GtkWidget *sub;
556     GtkWidget *pl_mi;
557     GtkWidget *pl_sub;
558     GList *itdbs;
559     GList *db;
560     struct itdbs_head *itdbs_head;
561     iTunesDB *itdb;
562     const gchar *stock_id = NULL;
563     Playlist *pl;
564 
565 
566     g_return_val_if_fail (gtkpod_window, NULL);
567     itdbs_head = g_object_get_data (G_OBJECT (gtkpod_window),
568                                     "itdbs_head");
569 
570     mi = hookup_mi (menu, title,
571 		    GTK_STOCK_COPY,
572 		    NULL, NULL);
573     sub = gtk_menu_new ();
574     gtk_widget_show (sub);
575     gtk_menu_item_set_submenu (GTK_MENU_ITEM (mi), sub);
576 
577     for (itdbs=itdbs_head->itdbs; itdbs; itdbs=itdbs->next)
578 	    {
579 		itdb = itdbs->data;
580 		ExtraiTunesDBData *eitdb=itdb->userdata;
581 		if (itdb->usertype & GP_ITDB_TYPE_LOCAL)
582 		{
583 			stock_id = GTK_STOCK_HARDDISK;
584 		}
585 		else
586 		{
587 		    if (eitdb->itdb_imported)
588 		    {
589 		        stock_id = GTK_STOCK_CONNECT;
590 		    }
591 		    else
592 		    {
593 		        stock_id = GTK_STOCK_DISCONNECT;
594 		    }
595 		}
596 		pl_mi = hookup_mi (sub, _(itdb_playlist_mpl(itdb)->name),
597 				   stock_id, NULL, NULL);
598 		pl_sub = gtk_menu_new ();
599 		gtk_widget_show (pl_sub);
600 		gtk_menu_item_set_submenu (GTK_MENU_ITEM (pl_mi), pl_sub);
601 		hookup_mi (pl_sub, _(itdb_playlist_mpl(itdb)->name),
602 			   stock_id, G_CALLBACK(copy_selected_to_target_itdb), &itdbs->data);
603 		add_separator(pl_sub);
604 		for (db=itdb->playlists; db; db=db->next)
605 		{
606 			pl=db->data;
607 			if (!itdb_playlist_is_mpl (pl))
608 			{
609 				if (pl->is_spl)
610 					stock_id = GTK_STOCK_PROPERTIES;
611 				else
612 					stock_id = GTK_STOCK_JUSTIFY_LEFT;
613 				hookup_mi(pl_sub, _(pl->name), stock_id,
614 				G_CALLBACK(copy_selected_to_target_playlist) , &db->data);
615 			}
616 		}
617 	    }
618     return mi;
619 }
620 
621 
add_play_now(GtkWidget * menu)622 static GtkWidget *add_play_now (GtkWidget *menu)
623 {
624     return hookup_mi (menu, _("Play Now"), GTK_STOCK_CDROM,
625 		      G_CALLBACK (play_entries_now), NULL);
626 }
627 
add_enqueue(GtkWidget * menu)628 static GtkWidget *add_enqueue (GtkWidget *menu)
629 {
630     return hookup_mi (menu, _("Enqueue"), GTK_STOCK_CDROM,
631 		      G_CALLBACK (play_entries_enqueue), NULL);
632 }
633 
add_copy_track_to_filesystem(GtkWidget * menu)634 static GtkWidget *add_copy_track_to_filesystem (GtkWidget *menu)
635 {
636     return hookup_mi (menu, _("Copy Tracks to Filesystem"),
637 		      GTK_STOCK_SAVE_AS,
638 		      G_CALLBACK (export_entries), NULL);
639 }
640 
add_create_playlist_file(GtkWidget * menu)641 static GtkWidget *add_create_playlist_file (GtkWidget *menu)
642 {
643     return hookup_mi (menu, _("Create Playlist File"),
644 		      GTK_STOCK_SAVE_AS,
645 		      G_CALLBACK (create_playlist_file), NULL);
646 }
647 
add_create_new_playlist(GtkWidget * menu)648 static GtkWidget *add_create_new_playlist (GtkWidget *menu)
649 {
650     return hookup_mi (menu, _("Create new Playlist"),
651 		      GTK_STOCK_JUSTIFY_LEFT,
652 		      G_CALLBACK (create_playlist_from_entries), NULL);
653 }
654 
add_update_tracks_from_file(GtkWidget * menu)655 static GtkWidget *add_update_tracks_from_file (GtkWidget *menu)
656 {
657     return hookup_mi (menu, _("Update Tracks from File"),
658 		      GTK_STOCK_REFRESH,
659 		      G_CALLBACK (update_entries), NULL);
660 }
661 
add_edit_smart_playlist(GtkWidget * menu)662 static GtkWidget *add_edit_smart_playlist (GtkWidget *menu)
663 {
664     return hookup_mi (menu, _("Edit Smart Playlist"),
665 		      GTK_STOCK_PROPERTIES,
666 		      G_CALLBACK (edit_spl), NULL);
667 }
668 
add_sync_playlist_with_dirs(GtkWidget * menu)669 static GtkWidget *add_sync_playlist_with_dirs (GtkWidget *menu)
670 {
671     return hookup_mi (menu, _("Sync Playlist with Dir(s)"),
672 		      GTK_STOCK_REFRESH,
673 		      G_CALLBACK (sync_dirs), NULL);
674 }
675 
add_remove_all_tracks_from_ipod(GtkWidget * menu)676 static GtkWidget *add_remove_all_tracks_from_ipod (GtkWidget *menu)
677 {
678     GtkWidget *mi;
679     GtkWidget *sub;
680 
681     mi = hookup_mi (menu, _("Remove All Tracks from iPod"),
682 		    GTK_STOCK_DELETE,
683 		    NULL, NULL);
684     sub = gtk_menu_new ();
685     gtk_widget_show (sub);
686     gtk_menu_item_set_submenu (GTK_MENU_ITEM (mi), sub);
687     hookup_mi (sub, _("I'm sure"),
688 	       NULL,
689 	       G_CALLBACK (delete_entries),
690 	       GINT_TO_POINTER (DELETE_ACTION_IPOD));
691     return mi;
692 }
693 
add_remove_all_podcasts_from_ipod(GtkWidget * menu)694 static GtkWidget *add_remove_all_podcasts_from_ipod (GtkWidget *menu)
695 {
696     GtkWidget *mi;
697     GtkWidget *sub;
698 
699     mi = hookup_mi (menu, _("Remove All Podcasts from iPod"),
700 		    GTK_STOCK_DELETE,
701 		    NULL, NULL);
702     sub = gtk_menu_new ();
703     gtk_widget_show (sub);
704     gtk_menu_item_set_submenu (GTK_MENU_ITEM (mi), sub);
705     hookup_mi (sub, _("I'm sure"),
706 	       NULL,
707 	       G_CALLBACK (delete_entries),
708 	       GINT_TO_POINTER (DELETE_ACTION_IPOD));
709     return mi;
710 }
711 
add_delete_including_tracks(GtkWidget * menu)712 static GtkWidget *add_delete_including_tracks (GtkWidget *menu)
713 {
714     return hookup_mi (menu,  _("Delete Including Tracks"),
715 		      GTK_STOCK_DELETE,
716 		      G_CALLBACK (delete_entries),
717 		      GINT_TO_POINTER (DELETE_ACTION_IPOD));
718 }
719 
add_delete_but_keep_tracks(GtkWidget * menu)720 static GtkWidget *add_delete_but_keep_tracks (GtkWidget *menu)
721 {
722     return hookup_mi (menu,  _("Delete But Keep Tracks"),
723 		      GTK_STOCK_DELETE,
724 		      G_CALLBACK (delete_entries),
725 		      GINT_TO_POINTER (DELETE_ACTION_PLAYLIST));
726 }
727 
add_edit_ipod_properties(GtkWidget * menu)728 static GtkWidget *add_edit_ipod_properties (GtkWidget *menu)
729 {
730     return hookup_mi (menu,  _("Edit iPod Properties"),
731 		      GTK_STOCK_PREFERENCES,
732 		      G_CALLBACK (edit_properties), NULL);
733 }
734 
add_edit_repository_properties(GtkWidget * menu)735 static GtkWidget *add_edit_repository_properties (GtkWidget *menu)
736 {
737     return hookup_mi (menu,  _("Edit Repository Properties"),
738 		      GTK_STOCK_PREFERENCES,
739 		      G_CALLBACK (edit_properties), NULL);
740 }
741 
add_edit_playlist_properties(GtkWidget * menu)742 static GtkWidget *add_edit_playlist_properties (GtkWidget *menu)
743 {
744     return hookup_mi (menu,  _("Edit Playlist Properties"),
745 		      GTK_STOCK_PREFERENCES,
746 		      G_CALLBACK (edit_properties), NULL);
747 }
748 
add_edit_track_details(GtkWidget * menu)749 static GtkWidget *add_edit_track_details (GtkWidget *menu)
750 {
751     return hookup_mi (menu,  _("Edit Track Details"),
752 		      GTK_STOCK_EDIT,
753 		      G_CALLBACK (edit_details_entries), NULL);
754 }
755 
add_display_big_coverart(GtkWidget * menu)756 static GtkWidget *add_display_big_coverart (GtkWidget *menu)
757 {
758     const gchar *icon;
759 /* gets defined in gtk+ V2.8, but we only require V2.6 */
760 #ifndef GTK_STOCK_FULLSCREEN
761 #define GTK_STOCK_FULLSCREEN "gtk-fullscreen"
762 #endif
763     if (gtk_check_version (2,8,0) == NULL)
764     {
765 	icon = GTK_STOCK_FULLSCREEN;
766     }
767     else
768     {
769 	icon = NULL;
770     }
771 
772     return hookup_mi (menu,  _("View Full Size Artwork"),
773 		      icon,
774 		      G_CALLBACK (display_track_artwork), NULL);
775 }
776 
add_get_cover_from_file(GtkWidget * menu)777 static GtkWidget *add_get_cover_from_file (GtkWidget *menu)
778 {
779 		return hookup_mi (menu, _("Select Cover From File"),
780 					GTK_STOCK_FLOPPY,
781 					G_CALLBACK (coverart_set_cover_from_file), NULL);
782 }
783 
add_check_ipod_files(GtkWidget * menu)784 static GtkWidget *add_check_ipod_files (GtkWidget *menu)
785 {
786     /* FIXME */
787     return NULL;
788 }
789 
add_load_ipod(GtkWidget * menu)790 static GtkWidget *add_load_ipod (GtkWidget *menu)
791 {
792     return hookup_mi (menu,  _("Load iPod"),
793 		      GTK_STOCK_CONNECT,
794 		      G_CALLBACK (load_ipod), NULL);
795 }
796 
add_eject_ipod(GtkWidget * menu)797 static GtkWidget *add_eject_ipod (GtkWidget *menu)
798 {
799     return hookup_mi (menu,  _("Eject iPod"),
800 		      GTK_STOCK_DISCONNECT,
801 		      G_CALLBACK (eject_ipod), NULL);
802 }
803 
add_save_changes(GtkWidget * menu)804 static GtkWidget *add_save_changes (GtkWidget *menu)
805 {
806     return hookup_mi (menu,  _("Save Changes"),
807 		      GTK_STOCK_SAVE,
808 		      G_CALLBACK (save_changes), NULL);
809 }
810 
add_remove_all_tracks_from_database(GtkWidget * menu)811 static GtkWidget *add_remove_all_tracks_from_database (GtkWidget *menu)
812 {
813     GtkWidget *mi;
814     GtkWidget *sub;
815 
816     mi = hookup_mi (menu, _("Remove All Tracks from Database"),
817 		    GTK_STOCK_DELETE,
818 		    NULL, NULL);
819     sub = gtk_menu_new ();
820     gtk_widget_show (sub);
821     gtk_menu_item_set_submenu (GTK_MENU_ITEM (mi), sub);
822     hookup_mi (sub, _("I'm sure"),
823 	       NULL,
824 	       G_CALLBACK (delete_entries),
825 	       GINT_TO_POINTER (DELETE_ACTION_DATABASE));
826     return mi;
827 }
828 
add_delete_including_tracks_harddisk(GtkWidget * menu)829 static GtkWidget *add_delete_including_tracks_harddisk (GtkWidget *menu)
830 {
831     return hookup_mi (menu,  _("Delete Including Tracks (Harddisk)"),
832 		      GTK_STOCK_DELETE,
833 		      G_CALLBACK (delete_entries),
834 		      GINT_TO_POINTER (DELETE_ACTION_LOCAL));
835 }
836 
add_delete_including_tracks_database(GtkWidget * menu)837 static GtkWidget *add_delete_including_tracks_database (GtkWidget *menu)
838 {
839     return hookup_mi (menu,  _("Delete Including Tracks (Database)"),
840 		      GTK_STOCK_DELETE,
841 		      G_CALLBACK (delete_entries),
842 		      GINT_TO_POINTER (DELETE_ACTION_DATABASE));
843 }
844 
add_delete_from_ipod(GtkWidget * menu)845 static GtkWidget *add_delete_from_ipod (GtkWidget *menu)
846 {
847     return hookup_mi (menu,  _("Delete From iPod"),
848 		      GTK_STOCK_DELETE,
849 		      G_CALLBACK (delete_entries),
850 		      GINT_TO_POINTER (DELETE_ACTION_IPOD));
851 }
852 
add_delete_from_playlist(GtkWidget * menu)853 static GtkWidget *add_delete_from_playlist (GtkWidget *menu)
854 {
855     return hookup_mi (menu,  _("Delete From Playlist"),
856 		      GTK_STOCK_DELETE,
857 		      G_CALLBACK (delete_entries),
858 		      GINT_TO_POINTER (DELETE_ACTION_PLAYLIST));
859 }
860 
add_delete_from_harddisk(GtkWidget * menu)861 static GtkWidget *add_delete_from_harddisk (GtkWidget *menu)
862 {
863     return hookup_mi (menu,  _("Delete From Harddisk"),
864 		      GTK_STOCK_DELETE,
865 		      G_CALLBACK (delete_entries),
866 		      GINT_TO_POINTER (DELETE_ACTION_LOCAL));
867 }
868 
add_delete_from_database(GtkWidget * menu)869 static GtkWidget *add_delete_from_database (GtkWidget *menu)
870 {
871     return hookup_mi (menu,  _("Delete From Database"),
872 		      GTK_STOCK_DELETE,
873 		      G_CALLBACK (delete_entries),
874 		      GINT_TO_POINTER (DELETE_ACTION_DATABASE));
875 }
876 
add_alphabetize(GtkWidget * menu)877 static GtkWidget *add_alphabetize (GtkWidget *menu)
878 {
879     return hookup_mi (menu,  _("Alphabetize"),
880 		      GTK_STOCK_SORT_ASCENDING,
881 		      G_CALLBACK (alphabetize), NULL);
882 }
883 
884 #if LOCALDEBUG
add_special(GtkWidget * menu)885 static GtkWidget *add_special (GtkWidget *menu)
886 {
887     return hookup_mi (menu, "Special",
888 		      GTK_STOCK_STOP,
889 		      G_CALLBACK (do_special), NULL);
890 }
891 #endif
892 
gphoto_menuitem_remove_album_from_db_item(GtkWidget * menu)893 GtkWidget *gphoto_menuitem_remove_album_from_db_item(GtkWidget *menu)
894 {
895 	return hookup_mi (
896 			menu,
897 			_("Remove Album"),
898 			GTK_STOCK_DELETE,
899 			G_CALLBACK (gphoto_remove_album_from_database),
900 			NULL);
901 }
902 
gphoto_menuitem_remove_photo_from_album_item(GtkWidget * menu)903 GtkWidget *gphoto_menuitem_remove_photo_from_album_item(GtkWidget *menu)
904 {
905 	GtkWidget *mitem = hookup_mi (
906 			menu,
907 			_("Remove Photo"),
908 			GTK_STOCK_DELETE,
909 			G_CALLBACK (gphoto_remove_selected_photos_from_album),
910 			NULL);
911 
912 	if (gphoto_get_selected_photo_count() == 0)
913 		gtk_widget_set_sensitive (mitem, FALSE);
914 	else
915 		gtk_widget_set_sensitive (mitem, TRUE);
916 
917 	return mitem;
918 }
919 
gphoto_menuitem_rename_photoalbum_item(GtkWidget * menu)920 GtkWidget *gphoto_menuitem_rename_photoalbum_item(GtkWidget *menu)
921 {
922 	return hookup_mi (
923 			menu,
924 			_("Rename Album"),
925 			GTK_STOCK_DELETE,
926 			G_CALLBACK (gphoto_rename_selected_album),
927 			NULL);
928 }
929 
create_context_menu(CM_type type)930 void create_context_menu (CM_type type)
931 {
932     static GtkWidget *menu = NULL;
933     Playlist *pl;
934 
935     if (menu)
936     {   /* free memory for last menu */
937 	gtk_widget_destroy (menu);
938 	menu = NULL;
939     }
940 
941     pl = pm_get_selected_playlist();
942     if (pl)
943     {
944 	ExtraiTunesDBData *eitdb;
945 	iTunesDB *itdb = pl->itdb;
946 	g_return_if_fail (itdb);
947 	eitdb = itdb->userdata;
948 	g_return_if_fail (eitdb);
949 
950 	menu = gtk_menu_new ();
951 
952 	switch (type)
953 	{
954 	case CM_PL:
955 	    if (itdb->usertype & GP_ITDB_TYPE_IPOD)
956 	    {
957 		if (eitdb->itdb_imported)
958 		{
959 		    add_play_now (menu);
960 		    add_enqueue (menu);
961 		    add_copy_track_to_filesystem (menu);
962 		    add_create_playlist_file (menu);
963 		    add_update_tracks_from_file (menu);
964 		    if (!pl->is_spl)
965 		    {
966 			add_sync_playlist_with_dirs (menu);
967 		    }
968 		    add_separator (menu);
969 		    if (itdb_playlist_is_mpl (pl))
970 		    {
971 			add_remove_all_tracks_from_ipod (menu);
972 		    }
973 		    else if (itdb_playlist_is_podcasts (pl))
974 		    {
975 			add_remove_all_podcasts_from_ipod (menu);
976 		    }
977 		    else
978 		    {
979 			add_delete_including_tracks (menu);
980 			add_delete_but_keep_tracks (menu);
981 		    }
982 		    add_copy_selected_to_target_itdb (menu,
983 						      _("Copy selected playlist to..."));
984 		    add_separator (menu);
985 		    add_edit_track_details (menu);
986 		    if (pl->is_spl)
987 		    {
988 			add_edit_smart_playlist (menu);
989 		    }
990 		    if (itdb_playlist_is_mpl (pl))
991 		    {
992 			add_edit_ipod_properties (menu);
993 		    }
994 		    else
995 		    {
996 			add_edit_playlist_properties (menu);
997 		    }
998 		    add_check_ipod_files (menu);
999 		    add_eject_ipod (menu);
1000 		}
1001 		else
1002 		{   /* not imported */
1003 		    add_edit_ipod_properties (menu);
1004 		    add_check_ipod_files (menu);
1005 		    add_separator (menu);
1006 		    add_load_ipod (menu);
1007 		}
1008 	    }
1009 	    if (itdb->usertype & GP_ITDB_TYPE_LOCAL)
1010 	    {
1011 		add_play_now (menu);
1012 		add_enqueue (menu);
1013 		add_copy_track_to_filesystem (menu);
1014 		add_create_playlist_file (menu);
1015 		add_update_tracks_from_file (menu);
1016 		if (!pl->is_spl)
1017 		{
1018 		    add_sync_playlist_with_dirs (menu);
1019 		}
1020 		add_separator (menu);
1021 		if (itdb_playlist_is_mpl (pl))
1022 		{
1023 		    add_remove_all_tracks_from_database (menu);
1024 		}
1025 		else
1026 		{
1027 		    add_delete_including_tracks_database (menu);
1028 		    add_delete_including_tracks_harddisk (menu);
1029 		    add_delete_but_keep_tracks (menu);
1030 		}
1031 		add_copy_selected_to_target_itdb (menu,
1032 						  _("Copy selected playlist to..."));
1033 		add_separator (menu);
1034 		add_edit_track_details (menu);
1035 		if (pl->is_spl)
1036 		{
1037 		    add_edit_smart_playlist (menu);
1038 		}
1039 		if (itdb_playlist_is_mpl (pl))
1040 		{
1041 		    add_edit_repository_properties (menu);
1042 		}
1043 		else
1044 		{
1045 		    add_edit_playlist_properties (menu);
1046 		}
1047 		add_save_changes (menu);
1048 	    }
1049 	    break;
1050 	case CM_ST:
1051 	case CM_TM:
1052 	    add_play_now (menu);
1053 	    add_enqueue (menu);
1054 	    add_copy_track_to_filesystem (menu);
1055 	    add_create_playlist_file (menu);
1056 	    add_create_new_playlist (menu);
1057 	    add_update_tracks_from_file (menu);
1058 	    if (!pl->is_spl)
1059 	    {
1060 		add_sync_playlist_with_dirs (menu);
1061 	    }
1062 	    if (type == CM_ST)
1063 	    {
1064 		add_alphabetize (menu);
1065 	    }
1066 	    add_separator (menu);
1067 	    if (itdb->usertype & GP_ITDB_TYPE_IPOD)
1068 	    {
1069 		add_delete_from_ipod (menu);
1070 		if (!itdb_playlist_is_mpl (pl))
1071 		{
1072 		    add_delete_from_playlist (menu);
1073 		}
1074 	    }
1075 	    if (itdb->usertype & GP_ITDB_TYPE_LOCAL)
1076 	    {
1077 		add_delete_from_harddisk (menu);
1078 		add_delete_from_database (menu);
1079 		if (!itdb_playlist_is_mpl (pl))
1080 		{
1081 		    add_delete_from_playlist (menu);
1082 		}
1083 	    }
1084 	    add_copy_selected_to_target_itdb (menu,
1085 					      _("Copy selected track(s) to..."));
1086 	    add_separator (menu);
1087 	    add_edit_track_details (menu);
1088 #if LOCALDEBUG
1089 	    /* This is for debugging purposes -- this allows to inspect
1090 	     * any track with a custom function */
1091 	    if (type == CM_TM)
1092 	    {
1093 		add_special (menu);
1094 	    }
1095 #endif
1096 	    break;
1097 	case CM_CAD:
1098 			add_get_cover_from_file (menu);
1099 			add_display_big_coverart (menu);
1100 			add_edit_track_details (menu);
1101 			break;
1102 	case CM_PH_AV:
1103 			gphoto_menuitem_remove_album_from_db_item (menu);
1104 			gphoto_menuitem_rename_photoalbum_item (menu);
1105 			break;
1106 	case CM_PH_IV:
1107 			gphoto_menuitem_remove_photo_from_album_item (menu);
1108 			break;
1109 	case CM_NUM:
1110 	    g_return_if_reached ();
1111 	}
1112     }
1113     /*
1114      * button should be button 0 as per the docs because we're calling
1115      * from a button release event
1116      */
1117     if (menu)
1118     {
1119 	gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
1120 			NULL, NULL, 0, gtk_get_current_event_time());
1121     }
1122 }
1123 
1124 
1125 /**
1126  * tm_context_menu_init - initialize the right click menu for tracks
1127  */
1128 void
tm_context_menu_init(void)1129 tm_context_menu_init(void)
1130 {
1131     if (widgets_blocked) return;
1132 
1133     tm_stop_editing (TRUE);
1134 
1135     selected_entry = NULL;
1136     selected_playlist = NULL;
1137     active_itdb = gp_get_selected_itdb ();
1138     entry_inst = -1;
1139     if (selected_tracks)  g_list_free (selected_tracks);
1140     selected_tracks = tm_get_selected_tracks();
1141     if(selected_tracks)
1142     {
1143 	create_context_menu (CM_TM);
1144     }
1145 }
1146 
1147 /**
1148  * cad_context_menu_init - initialize the right click menu for coverart display
1149  */
1150 void
cad_context_menu_init(void)1151 cad_context_menu_init(void)
1152 {
1153     if (widgets_blocked) return;
1154 
1155     selected_entry = NULL;
1156     selected_playlist = NULL;
1157     selected_tracks = NULL;
1158     active_itdb = gp_get_selected_itdb ();
1159     entry_inst = -1;
1160 
1161      if (selected_tracks) g_list_free (selected_tracks);
1162     	selected_tracks = g_list_copy (coverart_get_displayed_tracks());
1163 
1164     if(selected_tracks)
1165 			create_context_menu (CM_CAD);
1166 }
1167 
1168 /**
1169  * photo_context_menu_init - initialize the right click menu for photo management display
1170  */
1171 void
gphoto_context_menu_init(gint component)1172 gphoto_context_menu_init (gint component)
1173 {
1174     if (widgets_blocked) return;
1175 
1176     selected_entry = NULL;
1177     selected_playlist = NULL;
1178     selected_tracks = NULL;
1179     active_itdb = gp_get_selected_itdb ();
1180     entry_inst = -1;
1181 
1182      if (selected_tracks) g_list_free (selected_tracks);
1183 
1184      switch (component)
1185      {
1186     	 case GPHOTO_ALBUM_VIEW:
1187     		 create_context_menu (CM_PH_AV);
1188     		 break;
1189     	 case GPHOTO_ICON_VIEW:
1190     		 create_context_menu (CM_PH_IV);
1191      }
1192 }
1193 
1194 /**
1195  * pm_context_menu_init - initialize the right click menu for playlists
1196  */
1197 void
pm_context_menu_init(void)1198 pm_context_menu_init(void)
1199 {
1200     if (widgets_blocked) return;
1201 
1202     pm_stop_editing (TRUE);
1203 
1204     if (selected_tracks)  g_list_free (selected_tracks);
1205     selected_tracks = NULL;
1206     selected_entry = NULL;
1207     entry_inst = -1;
1208     selected_playlist = pm_get_selected_playlist();
1209 
1210     active_itdb = gp_get_selected_itdb ();
1211 
1212     if(selected_playlist)
1213     {
1214 	selected_tracks = g_list_copy (selected_playlist->members);
1215 	create_context_menu (CM_PL);
1216     }
1217 }
1218 
1219 /**
1220  * st_context_menu_init - initialize the right click menu for sort tabs
1221  * FIXME: This needs to be hooked in.
1222  */
1223 void
st_context_menu_init(gint inst)1224 st_context_menu_init(gint inst)
1225 {
1226     if (widgets_blocked) return;
1227 
1228     st_stop_editing (inst, TRUE);
1229 
1230     if (selected_tracks)  g_list_free (selected_tracks);
1231     selected_tracks = NULL;
1232     selected_playlist = NULL;
1233     selected_entry = st_get_selected_entry (inst);
1234     active_itdb = gp_get_selected_itdb ();
1235     if(selected_entry)
1236     {
1237 	entry_inst = inst;
1238 	selected_tracks = g_list_copy (selected_entry->members);
1239 	create_context_menu (CM_ST);
1240     }
1241 }
1242