Re-ordered arguments to execvp.
[gssmp.git] / src / gssmp_ui.c
blob25a7e02c5a42c3536d3dde9889f6f6ff7a74f645
1 /*
2 * Gnome Simple Stateful Music Player
3 * Copyright (C) 2007 Andy Balaam
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 **/
20 #include "gssmp_ui.h"
22 #include <stdio.h>
23 #include <libgnomevfs/gnome-vfs.h>
25 #include "interface.h"
26 #include "support.h"
27 #include "gssmp_config.h"
28 #include "gssmp_files.h"
29 #include "gssmp_gstreamer.h"
30 #include "gssmp_util.h"
32 #define STATUS_TIMEOUT_LENGTH 5000
34 // Note: DOC_URI is passed in from the Makefile
35 #define BIN_PKG_DOC_PATH "../share/doc/gssmp/html/use.html"
36 #define SRC_DIR_DOC_PATH "../www/use.html"
37 #define ONLINE_DOCS_URI "http://gssmp.sourceforge.net/use.html"
39 GtkWindow *window1;
40 GtkWindow *aboutdialog1;
41 GtkWidget *hscale1;
42 GtkLabel *label4; // Artist and track name
43 GtkLabel *label5; // Album name etc.
44 GtkLabel *label7; // Current time
45 GtkLabel *label8; // Track length
46 GtkWidget *button2; // Play
47 GtkWidget *button3; // Pause
48 GtkStatusbar *statusbar1;
49 GtkMenuItem *recent1;
50 GtkCheckMenuItem *no_repeat1;
51 GtkCheckMenuItem *repeat_all1;
52 GtkCheckMenuItem *repeat_one1;
53 GtkCheckMenuItem *shuffle1;
55 // last.fm stuff
56 GtkWindow *lastfmwindow;
57 GtkCheckButton* checkbutton1;
58 GtkEntry* entry1;
60 gchar* stored_title;
61 gchar* stored_track_number;
62 gchar* stored_track_length;
63 gchar* stored_track_count;
64 gchar* stored_album;
65 gchar* stored_artist;
67 guint context_id_play_file;
68 guint context_id_error_playing_file;
69 guint context_id_status_callback;
70 guint context_id_not_a_file;
72 gulong menu_number;
74 gboolean skip_errors; // Don't pop up an error when reading an invalid file
75 gboolean moving_forward; // TRUE unless we have just clicked "Previous"
76 guint status_timeout_source;
78 int new_tag; // 0 = first time, 1 = info received, 2 = no info
80 void gssmp_ui_choose_bookmark_clicked (GtkMenuItem* unused, gpointer num);
82 void display_track_info ();
83 void fork_lastfm_exe ();
84 void choose_repeat_menu_item ();
86 void add_bookmark_here ();
87 void redisplay_bookmarks ();
88 void menu_bookmark_callback_create (GssmpBookmark* bmk, gpointer submenu);
90 void play_bookmark (guint num);
92 struct StatusDetails
94 guint context_id;
95 const gchar* msg;
96 const gchar* sub;
99 gboolean status_callback (gpointer details);
101 void play_in_dir (const gchar* dirname);
103 void lastfm_enable_buttons ();
106 * Returns a newly-allocated string saying the time e.g. "1m 30s"
108 gchar* secs_to_time_str (gint secs);
110 void gssmp_ui_init (int argc, char *argv[])
112 window1 = GTK_WINDOW (create_window1 ());
113 aboutdialog1 = NULL;
114 hscale1 = lookup_widget (GTK_WIDGET (window1), "hscale1");
115 label4 = GTK_LABEL (lookup_widget (GTK_WIDGET (window1), "label4"));
116 label5 = GTK_LABEL (lookup_widget (GTK_WIDGET (window1), "label5"));
117 label7 = GTK_LABEL (lookup_widget (GTK_WIDGET (window1), "label7"));
118 label8 = GTK_LABEL (lookup_widget (GTK_WIDGET (window1), "label8"));
119 button2 = lookup_widget (GTK_WIDGET (window1), "button2");
120 button3 = lookup_widget (GTK_WIDGET (window1), "button3");
121 statusbar1 = GTK_STATUSBAR (lookup_widget (GTK_WIDGET (window1),
122 "statusbar1"));
123 recent1 = GTK_MENU_ITEM (lookup_widget (GTK_WIDGET (window1), "recent1"));
124 no_repeat1 = GTK_CHECK_MENU_ITEM (lookup_widget (GTK_WIDGET (window1),
125 "no_repeat1"));
126 repeat_all1 = GTK_CHECK_MENU_ITEM (lookup_widget (GTK_WIDGET (window1),
127 "repeat_all1"));
128 repeat_one1 = GTK_CHECK_MENU_ITEM (lookup_widget (GTK_WIDGET (window1),
129 "repeat_one1"));
130 shuffle1 = GTK_CHECK_MENU_ITEM (lookup_widget (GTK_WIDGET (window1),
131 "shuffle1"));
133 lastfmwindow = NULL;
134 checkbutton1 = NULL;
135 entry1 = NULL;
137 // NOTE: ICON_FILE is passed in via the make file
138 gtk_window_set_icon_from_file (window1, ICON_FILE, NULL);
140 choose_repeat_menu_item ();
142 context_id_play_file = gtk_statusbar_get_context_id (statusbar1,
143 "gssmp_ui_play_file");
144 context_id_error_playing_file = gtk_statusbar_get_context_id (statusbar1,
145 "gssmp_ui_error_callback");
146 context_id_status_callback = gtk_statusbar_get_context_id (statusbar1,
147 "status_callback");
148 context_id_not_a_file = gtk_statusbar_get_context_id (statusbar1,
149 "gssmp_ui_init");
151 skip_errors = TRUE;
152 moving_forward = TRUE;
154 status_timeout_source = 0;
158 gtk_widget_show (GTK_WIDGET (window1));
160 if (argc < 2)
162 play_bookmark (0);
164 else
166 gchar* file_or_dir = gssmp_files_make_absolute (argv[1]);
168 if (g_file_test (file_or_dir, G_FILE_TEST_IS_DIR))
170 play_in_dir (file_or_dir);
171 g_free (file_or_dir);
173 else if (g_file_test (file_or_dir, G_FILE_TEST_IS_REGULAR))
175 gssmp_ui_play_file (file_or_dir, TRUE, FALSE, 0, FALSE);
177 else
179 gssmp_ui_display_status_message ( context_id_not_a_file,
180 _("Could not find file '%s'"), file_or_dir );
181 g_free (file_or_dir);
185 redisplay_bookmarks ();
188 void gssmp_ui_quit ()
190 add_bookmark_here ();
192 g_free (stored_title);
193 g_free (stored_track_number);
194 g_free (stored_track_count);
195 g_free (stored_album);
196 g_free (stored_artist);
198 gtk_main_quit ();
201 void gssmp_ui_about ()
203 if (!aboutdialog1)
205 aboutdialog1 = GTK_WINDOW (create_aboutdialog1 ());
208 gtk_widget_show (GTK_WIDGET (aboutdialog1));
211 void update_buttons ()
213 gtk_widget_set_sensitive (button2, config_paused);
214 gtk_widget_set_sensitive (button3, !config_paused);
217 void gssmp_ui_choose_directory_clicked ()
219 GtkWidget *dialog;
221 dialog = gtk_file_chooser_dialog_new (_("Choose Directory"),
222 window1, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
223 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
224 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
225 NULL);
227 if (current_directory && strlen (current_directory) > 0)
229 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog),
230 current_directory);
232 else
234 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog),
235 g_get_home_dir());
238 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
240 gchar *dirname;
242 gssmp_files_reset_shuffle ();
244 dirname = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
246 play_in_dir (dirname);
248 g_free (dirname);
250 gtk_widget_destroy (dialog);
253 void gssmp_ui_choose_file_clicked ()
255 GtkWidget *dialog;
257 dialog = gtk_file_chooser_dialog_new (_("Choose File"),
258 window1, GTK_FILE_CHOOSER_ACTION_OPEN,
259 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
260 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
261 NULL);
263 if (current_filename && strlen (current_filename) > 0)
265 gchar* dir;
266 dir = g_path_get_dirname (current_filename);
267 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), dir);
268 g_free (dir);
270 else if (current_directory && strlen (current_directory) > 0)
272 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog),
273 current_directory);
275 else
277 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog),
278 g_get_home_dir());
281 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
283 gchar *filename;
285 gssmp_files_reset_shuffle ();
287 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
288 if (filename)
290 add_bookmark_here (); // Remember what we were playing
291 gssmp_ui_play_file (filename, TRUE, TRUE, 0, FALSE);
294 gtk_widget_destroy (dialog);
297 void gssmp_ui_eos_callback ()
299 if (config_repeat_style == repeat_one)
301 gssmp_gstreamer_seek (0);
303 else
305 gssmp_ui_next_clicked ();
309 void gssmp_ui_next_clicked ()
311 gchar *filename;
313 moving_forward = TRUE;
315 if (config_repeat_style == shuffle)
317 filename = gssmp_files_find_next_shuffled_file ();
319 else
321 filename = gssmp_files_find_next_file_after (current_filename);
323 if (!filename && (config_repeat_style == repeat_all))
325 filename = gssmp_files_find_next_file_in_dir (current_directory, NULL);
329 if (filename)
331 gssmp_ui_play_file (filename, FALSE, TRUE, 0, TRUE);
333 else
335 gssmp_ui_pause_clicked ();
339 void gssmp_ui_previous_clicked ()
341 gchar *filename;
343 moving_forward = FALSE;
345 filename = gssmp_files_find_previous_file_before (current_filename);
347 if (filename)
349 gssmp_ui_play_file (filename, FALSE, TRUE, 0, TRUE);
351 else
353 gssmp_ui_pause_clicked ();
357 void gssmp_ui_display_status_message (guint context_id, const gchar* msg,
358 const gchar* sub)
360 gchar* full_msg;
362 full_msg = g_strdup_printf (msg, sub);
364 gtk_statusbar_pop (statusbar1, context_id_status_callback);
365 gtk_statusbar_push (statusbar1, context_id_status_callback, full_msg);
367 printf (full_msg);
368 printf ("\n");
370 g_free (full_msg);
373 void gssmp_ui_display_2_status_messages (guint context_id, const gchar* msg1,
374 const gchar* sub1, const gchar* msg2, const gchar* sub2)
376 struct StatusDetails* details;
378 gssmp_ui_display_status_message (context_id, msg1, sub1);
380 details = g_slice_new (struct StatusDetails);
381 details->context_id = context_id;
382 details->msg = msg2;
383 details->sub = sub2;
385 if (status_timeout_source)
387 g_source_remove (status_timeout_source);
389 status_timeout_source = g_timeout_add (STATUS_TIMEOUT_LENGTH,
390 status_callback, (gpointer)details);
394 * Play the sound file supplied by calling into the gstreamer code and making
395 * the UI ready where required.
397 * @arg filename The full path to a file on disk
398 * @arg change_dir If this file is outside the user's chosen
399 * directory, should we change that directory to
400 * match the file?
401 * @arg new_filename Is the filename a newly-allocated string? I.e.
402 * should we free the old current_filename?
403 * @arg start_offset How many seconds through the file should we start?
404 * @arg skip_to_next_if_fail If this file fails to load, automatically skip to
405 * the next? (If not, we display an error to the
406 * user.)
408 void gssmp_ui_play_file (gchar* filename, gboolean change_dir,
409 gboolean new_filename, gint start_offset, gboolean skip_to_next_if_fail)
411 skip_errors = skip_to_next_if_fail;
413 if (change_dir)
415 if (!current_directory ||
416 strncmp (current_directory, filename, strlen (current_directory)) != 0)
418 current_directory = g_path_get_dirname (filename);
422 if (new_filename && current_filename)
424 g_free (current_filename);
426 current_filename = filename;
428 gssmp_ui_clear_track_info ();
430 new_tag = 0;
432 config_paused = FALSE;
433 update_buttons ();
435 gssmp_ui_display_2_status_messages( context_id_play_file,
436 _("Playing file %s"), current_filename,
437 _("Playing in directory %s"), current_directory );
439 gssmp_gstreamer_play (current_filename, start_offset,
440 gssmp_ui_duration_callback, gssmp_ui_progress_callback,
441 gssmp_ui_tag_callback, gssmp_ui_eos_callback,
442 gssmp_ui_error_callback);
445 void gssmp_ui_play_clicked ()
447 config_paused = FALSE;
448 update_buttons ();
449 gssmp_gstreamer_unpause ();
452 void gssmp_ui_pause_clicked ()
454 config_paused = TRUE;
455 update_buttons ();
456 gssmp_gstreamer_pause ();
459 void gssmp_ui_slider_changed (gdouble value)
461 gchar* time_str;
462 gint secs;
464 secs = (gint)value;
465 if (current_length != -1 && secs >= current_length)
467 secs = current_length - 1;
470 gssmp_gstreamer_seek (secs);
472 current_time = secs;
474 time_str = secs_to_time_str (secs);
475 gtk_label_set_text (label7, time_str);
476 gtk_widget_queue_draw(GTK_WIDGET(label7));
477 g_free (time_str);
480 void gssmp_ui_volume_change (gdouble value)
482 if (value < 0)
484 value = 0;
486 else if (value > 1)
488 value = 1;
490 gssmp_gstreamer_set_volume (value);
493 void gssmp_ui_progress_callback (gint secs)
495 gchar* time_str;
497 current_time = secs;
498 gtk_range_set_value (GTK_RANGE(hscale1), (gdouble)secs);
500 time_str = secs_to_time_str (secs);
501 gtk_label_set_text (label7, time_str);
503 switch (new_tag)
505 case 1:
507 display_track_info ();
508 new_tag = 2;
509 break;
511 case 0:
513 new_tag = 1;
514 break;
516 default:
518 break;
522 gtk_widget_queue_draw(GTK_WIDGET(hscale1));
523 gtk_widget_queue_draw(GTK_WIDGET(label7));
524 g_free (time_str);
527 void gssmp_ui_duration_callback (gint secs)
529 gtk_range_set_range (GTK_RANGE(hscale1), (gdouble)0, (gdouble)secs);
531 stored_track_length = secs_to_time_str (secs);
532 current_length = secs;
535 void gssmp_ui_tag_callback (const gchar* tag, const gchar* value)
537 new_tag = 1;
538 if (strcmp(tag, "title") == 0)
540 stored_title = g_strdup (value);
542 else if (strcmp(tag, "artist") == 0)
544 stored_artist = g_strdup (value);
546 else if (strcmp(tag, "album") == 0)
548 stored_album = g_strdup (value);
550 else if (strcmp(tag, "track-number") == 0)
552 stored_track_number = g_strdup (value);
554 else if (strcmp(tag, "track-count") == 0)
556 stored_track_count = g_strdup (value);
558 else
560 fprintf (stderr, _("Unknown tag: %s -> %s\n"), tag, value);
564 void gssmp_ui_error_callback (const gchar* msg)
566 gssmp_ui_display_status_message (context_id_error_playing_file,
567 _("Unable to play file: %s"), current_filename );
569 if (skip_errors)
571 if (moving_forward)
573 gssmp_ui_next_clicked ();
575 else
577 gssmp_ui_previous_clicked ();
578 moving_forward = FALSE;
581 else
583 GtkMessageDialog* dialog;
584 dialog = GTK_MESSAGE_DIALOG (gtk_message_dialog_new (window1,
585 GTK_DIALOG_DESTROY_WITH_PARENT,
586 GTK_MESSAGE_ERROR,
587 GTK_BUTTONS_CLOSE,
588 _("Error playing file '%s': %s"),
589 current_filename, msg));
590 gtk_dialog_run (GTK_DIALOG (dialog));
591 gtk_widget_destroy (GTK_WIDGET (dialog));
595 void gssmp_ui_clear_track_info ()
597 if (stored_title)
599 g_free (stored_title);
601 if (stored_track_number)
603 g_free (stored_track_number);
605 if (stored_track_length)
607 g_free (stored_track_length);
609 if (stored_track_count)
611 g_free (stored_track_count);
613 if (stored_artist)
615 g_free (stored_artist);
617 if (stored_album)
619 g_free (stored_album);
622 if (current_filename)
624 gchar* tmp1;
625 gchar* tmp2;
627 stored_title = g_path_get_basename (current_filename);
628 tmp1 = g_path_get_dirname (current_filename);
629 stored_album = g_path_get_basename (tmp1);
630 tmp2 = gssmp_files_get_parent_of_dir (tmp1);
631 stored_artist = g_path_get_basename (tmp2);
633 g_free (tmp1);
634 g_free (tmp2);
636 else
638 stored_title = NULL;
639 stored_album = NULL;
640 stored_artist = NULL;
643 stored_track_number = NULL;
644 stored_track_length = NULL;
645 stored_track_count = NULL;
648 // --------------------------------
650 #define MAX_TITLE_LENGTH 2048
651 void display_track_info ()
653 gchar title[MAX_TITLE_LENGTH];
654 gchar tmp[MAX_TITLE_LENGTH];
656 g_strlcpy (title, "<span size=\"large\">", MAX_TITLE_LENGTH);
658 if (stored_artist)
660 if (stored_title)
662 if (stored_track_number)
664 if (stored_track_count)
666 g_snprintf (tmp, MAX_TITLE_LENGTH, _("%s - %s (%s/%s)"),
667 stored_artist, stored_title, stored_track_number,
668 stored_track_count);
670 else
672 g_snprintf (tmp, MAX_TITLE_LENGTH, _("%s - %s (%s)"),
673 stored_artist, stored_title, stored_track_number);
676 else
678 g_snprintf (tmp, MAX_TITLE_LENGTH, _("%s - %s"),
679 stored_artist, stored_title);
682 else
684 g_snprintf (tmp, MAX_TITLE_LENGTH, _("%s - unnamed"), stored_artist);
687 else
689 if (stored_title)
691 if (stored_track_number)
693 if (stored_track_count)
695 g_snprintf (tmp, MAX_TITLE_LENGTH, _("%s (%s/%s)"),
696 stored_title, stored_track_number, stored_track_count);
698 else
700 g_snprintf (tmp, MAX_TITLE_LENGTH, _("%s (%s)"),
701 stored_title, stored_track_number);
704 else
706 g_snprintf (tmp, MAX_TITLE_LENGTH, _("%s"), stored_title);
709 else
711 g_strlcpy (tmp, "", MAX_TITLE_LENGTH);
715 g_strlcat (title, tmp, MAX_TITLE_LENGTH);
717 g_strlcat (title, "</span>", MAX_TITLE_LENGTH);
719 gtk_label_set_markup (label4, title);
721 // Now the album name
722 if (stored_album)
724 g_snprintf (tmp, MAX_TITLE_LENGTH, _("Album: %s"), stored_album);
726 else
728 g_strlcpy (tmp, "", MAX_TITLE_LENGTH);
731 gtk_label_set_text (label5, tmp);
733 // and the track length
734 if (stored_track_length)
736 g_snprintf (tmp, MAX_TITLE_LENGTH, _("Length: %s"), stored_track_length);
738 else
740 g_strlcpy (tmp, "", MAX_TITLE_LENGTH);
742 gtk_label_set_text (label8, tmp);
744 if( config_lastfm_active &&
745 current_length > 0 && stored_title && stored_artist )
747 fork_lastfm_exe ();
750 add_bookmark_here (); // Put this track to the top of the bookmarks list
753 void fork_lastfm_exe ()
755 pid_t pid;
756 char tmp[32];
758 pid = fork();
760 if (pid == -1)
762 fprintf (stderr, "fork() error before launching lastfm exe.");
764 else if( pid == 0 )
766 // We are the child, run lastfm exe
768 char *args[10];
770 args[0] = config_lastfm_exe;
771 args[1] = "--lengtsdsh";
772 g_snprintf (tmp, 32, "%d", current_length);
773 args[2] = tmp;
774 args[3] = "--title";
775 args[4] = stored_title;
776 args[5] = "--artist";
777 args[6] = stored_artist;
779 if( stored_album )
781 args[7] = "--album";
782 args[8] = stored_album;
783 args[9] = NULL;
785 else
787 args[7] = NULL;
790 execvp( args[0], args );
792 // Should never get here.
793 fprintf (stderr, "execvp() error launching lastfm exe '%s'.\n",
794 config_lastfm_exe);
798 gchar* secs_to_time_str (gint secs)
800 if (secs < 0)
802 secs = 0;
805 guint mins = secs / 60;
806 guint remaining_secs = secs % 60;
808 return g_strdup_printf (_("%dm %02ds"), mins, remaining_secs);
811 void gssmp_ui_choose_bookmark_clicked (GtkMenuItem* unused, gpointer num)
813 gssmp_files_reset_shuffle ();
814 config_paused = FALSE;
815 play_bookmark ((gulong)num);
818 void gssmp_ui_launch_help ()
820 gchar* uri;
822 if (g_file_test (DOC_URI, G_FILE_TEST_IS_REGULAR))
824 uri = gnome_vfs_get_uri_from_local_path (DOC_URI);
826 else if (g_file_test (BIN_PKG_DOC_PATH, G_FILE_TEST_IS_REGULAR))
828 gchar* abs;
829 abs = gssmp_files_make_absolute (BIN_PKG_DOC_PATH);
830 uri = gnome_vfs_get_uri_from_local_path (abs);
831 g_free (abs);
833 else if (g_file_test (SRC_DIR_DOC_PATH, G_FILE_TEST_IS_REGULAR))
835 gchar* abs;
836 abs = gssmp_files_make_absolute (SRC_DIR_DOC_PATH);
837 uri = gnome_vfs_get_uri_from_local_path (abs);
838 g_free (abs);
840 else
842 uri = g_strdup (ONLINE_DOCS_URI);
845 gnome_vfs_url_show (uri);
847 g_free (uri);
850 void gssmp_ui_lastfm ()
852 if (!lastfmwindow)
854 lastfmwindow = GTK_WINDOW (create_lastfmwindow ());
855 checkbutton1 = GTK_CHECK_BUTTON (
856 lookup_widget (GTK_WIDGET (lastfmwindow), "checkbutton1"));
857 entry1 = GTK_ENTRY (lookup_widget (GTK_WIDGET (lastfmwindow), "entry1"));
860 gtk_toggle_button_set_active (
861 GTK_TOGGLE_BUTTON (checkbutton1), config_lastfm_active);
862 gtk_entry_set_text (entry1, config_lastfm_exe);
864 lastfm_enable_buttons ();
866 gtk_widget_show (GTK_WIDGET (lastfmwindow));
869 void gssmp_ui_lastfm_close ()
871 gtk_widget_hide (GTK_WIDGET (lastfmwindow));
874 void gssmp_ui_lastfm_statechange ()
876 config_lastfm_active = gtk_toggle_button_get_active (
877 GTK_TOGGLE_BUTTON (checkbutton1));
880 void gssmp_ui_lastfm_exechanged ()
882 lastfm_enable_buttons ();
884 if (config_lastfm_exe)
886 g_free (config_lastfm_exe);
888 config_lastfm_exe = g_strdup( gtk_entry_get_text (entry1) );
891 // --------------------------------
893 void add_bookmark_here ()
895 if (current_filename && stored_title)
897 gssmp_config_add_bookmark (stored_title, stored_artist, stored_album,
898 current_directory, current_filename, current_time, current_length);
899 redisplay_bookmarks ();
903 void play_bookmark (guint num)
905 gboolean keep_paused;
906 GssmpBookmark *bmk;
908 new_tag = 0;
909 stored_track_number = NULL;
910 stored_track_count = NULL;
911 stored_track_length = NULL;
913 bmk = gssmp_config_get_bookmark (num);
914 if (bmk)
916 add_bookmark_here (); // First remember what we were playing before
918 gssmp_ui_duration_callback (bmk->length);
919 gssmp_ui_progress_callback (bmk->time);
921 if (stored_title)
923 g_free (stored_title);
925 stored_title = g_strdup (bmk->track);
927 if (stored_album)
929 g_free (stored_album);
931 stored_album = g_strdup (bmk->album);
933 if (stored_artist)
935 g_free (stored_artist);
937 stored_artist = g_strdup (bmk->artist);
939 if (current_filename)
941 g_free (current_filename);
943 current_filename = g_strdup (bmk->filename);
945 if (current_directory)
947 g_free (current_directory);
949 current_directory = g_strdup (bmk->directory);
951 display_track_info ();
953 else
955 stored_title = NULL;
956 stored_album = NULL;
957 stored_artist = NULL;
960 if (current_filename)
962 keep_paused = config_paused;
963 gssmp_ui_play_file (current_filename, TRUE, FALSE, current_time, TRUE);
964 if (keep_paused)
966 gssmp_ui_pause_clicked ();
970 redisplay_bookmarks ();
973 void choose_repeat_menu_item ()
975 switch (config_repeat_style)
977 case no_repeat:
979 gtk_check_menu_item_set_active (no_repeat1, TRUE);
980 gtk_check_menu_item_set_active (repeat_all1, FALSE);
981 gtk_check_menu_item_set_active (repeat_one1, FALSE);
982 gtk_check_menu_item_set_active (shuffle1, FALSE);
983 break;
985 case repeat_all:
987 gtk_check_menu_item_set_active (no_repeat1, FALSE);
988 gtk_check_menu_item_set_active (repeat_all1, TRUE);
989 gtk_check_menu_item_set_active (repeat_one1, FALSE);
990 gtk_check_menu_item_set_active (shuffle1, FALSE);
991 break;
993 case repeat_one:
995 gtk_check_menu_item_set_active (no_repeat1, FALSE);
996 gtk_check_menu_item_set_active (repeat_all1, FALSE);
997 gtk_check_menu_item_set_active (repeat_one1, TRUE);
998 gtk_check_menu_item_set_active (shuffle1, FALSE);
999 break;
1001 case shuffle:
1003 gtk_check_menu_item_set_active (no_repeat1, FALSE);
1004 gtk_check_menu_item_set_active (repeat_all1, FALSE);
1005 gtk_check_menu_item_set_active (repeat_one1, FALSE);
1006 gtk_check_menu_item_set_active (shuffle1, TRUE);
1007 break;
1012 void redisplay_bookmarks ()
1014 GtkMenu *submenu;
1016 gtk_widget_set_sensitive (GTK_WIDGET (recent1), FALSE);
1018 gtk_menu_item_deselect (GTK_MENU_ITEM (recent1));
1020 submenu = GTK_MENU (gtk_menu_new ());
1022 menu_number = 0;
1023 gssmp_config_bookmarks_foreach (menu_bookmark_callback_create, submenu);
1025 gtk_widget_show (GTK_WIDGET (submenu));
1027 gtk_menu_item_set_submenu (GTK_MENU_ITEM (recent1), GTK_WIDGET (submenu));
1029 gtk_widget_set_sensitive (GTK_WIDGET (recent1), TRUE);
1032 void menu_bookmark_callback_create (GssmpBookmark* bmk, gpointer submenu)
1034 GtkWidget *item;
1035 gchar* item_name;
1036 gchar* time_str;
1038 time_str = secs_to_time_str (bmk->time);
1040 item_name = g_strdup_printf (_("%s - %s (%s)"), bmk->artist, bmk->track,
1041 time_str);
1042 item = gtk_menu_item_new_with_label (item_name);
1043 gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item);
1044 gtk_widget_show (GTK_WIDGET (item));
1046 g_signal_connect ((gpointer) item, "activate",
1047 G_CALLBACK (gssmp_ui_choose_bookmark_clicked),
1048 (gpointer)menu_number);
1050 ++menu_number;
1052 g_free (item_name);
1053 g_free (time_str);
1056 gboolean status_callback (gpointer detailsptr)
1058 struct StatusDetails* details;
1060 status_timeout_source = 0;
1062 details = (struct StatusDetails*)detailsptr;
1064 gssmp_ui_display_status_message (details->context_id, details->msg,
1065 details->sub);
1067 g_slice_free (struct StatusDetails, details);
1069 return FALSE;
1072 void play_in_dir (const gchar* dirname)
1074 gchar* first_file_name;
1076 gssmp_config_set_directory (dirname);
1078 if (config_repeat_style == shuffle)
1080 first_file_name = gssmp_files_find_next_shuffled_file ();
1082 else
1084 first_file_name = gssmp_files_find_next_file_in_dir (
1085 current_directory, NULL);
1088 if (first_file_name)
1090 add_bookmark_here (); // Remember what we were playing
1091 gssmp_ui_play_file (first_file_name, FALSE, TRUE, 0, TRUE);
1095 void lastfm_enable_buttons ()
1097 const gchar* exe;
1098 gchar* fullexe;
1100 exe = gtk_entry_get_text (entry1);
1102 fullexe = g_find_program_in_path (exe);
1104 if (fullexe)
1106 gtk_widget_set_sensitive (GTK_WIDGET (checkbutton1), TRUE);
1107 g_free (fullexe);
1109 else
1111 config_lastfm_active = FALSE;
1112 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbutton1), FALSE);
1113 gtk_widget_set_sensitive (GTK_WIDGET (checkbutton1), FALSE);