Added documentation on using lastfmsubmitd, and made ready for 1.2 release.
[gssmp.git] / src / gssmp_ui.c
blobc3a73dfd0ac06e04dc8be7b96a3248cc239010a8
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>
24 #include <sys/wait.h>
26 #include "interface.h"
27 #include "support.h"
28 #include "gssmp_config.h"
29 #include "gssmp_files.h"
30 #include "gssmp_gstreamer.h"
31 #include "gssmp_util.h"
33 #define STATUS_TIMEOUT_LENGTH 5000
35 // Note: DOC_URI is passed in from the Makefile
36 #define BIN_PKG_DOC_PATH "../share/doc/gssmp/html/use.html"
37 #define SRC_DIR_DOC_PATH "../www/use.html"
38 #define ONLINE_DOCS_URI "http://gssmp.sourceforge.net/use.html"
40 GtkWindow *window1;
41 GtkWindow *aboutdialog1;
42 GtkWidget *hscale1;
43 GtkLabel *label4; // Artist and track name
44 GtkLabel *label5; // Album name etc.
45 GtkLabel *label7; // Current time
46 GtkLabel *label8; // Track length
47 GtkWidget *button2; // Play
48 GtkWidget *button3; // Pause
49 GtkStatusbar *statusbar1;
50 GtkMenuItem *recent1;
51 GtkCheckMenuItem *no_repeat1;
52 GtkCheckMenuItem *repeat_all1;
53 GtkCheckMenuItem *repeat_one1;
54 GtkCheckMenuItem *shuffle1;
56 // last.fm stuff
57 GtkWindow *lastfmwindow;
58 GtkCheckButton* checkbutton1;
59 GtkEntry* entry1;
61 gchar* stored_title;
62 gchar* stored_track_number;
63 gchar* stored_track_length;
64 gchar* stored_track_count;
65 gchar* stored_album;
66 gchar* stored_artist;
68 guint context_id_play_file;
69 guint context_id_error_playing_file;
70 guint context_id_status_callback;
71 guint context_id_not_a_file;
73 gulong menu_number;
75 gboolean skip_errors; // Don't pop up an error when reading an invalid file
76 gboolean moving_forward; // TRUE unless we have just clicked "Previous"
77 guint status_timeout_source;
79 int new_tag; // 0 = first time, 1 = info received, 2 = no info
81 void gssmp_ui_choose_bookmark_clicked (GtkMenuItem* unused, gpointer num);
83 void display_track_info (gboolean from_bookmark);
84 void fork_lastfm_exe ();
85 void choose_repeat_menu_item ();
87 void add_bookmark_here ();
88 void redisplay_bookmarks ();
89 void menu_bookmark_callback_create (GssmpBookmark* bmk, gpointer submenu);
91 void play_bookmark (guint num);
93 struct StatusDetails
95 guint context_id;
96 const gchar* msg;
97 const gchar* sub;
100 gboolean status_callback (gpointer details);
102 void play_in_dir (const gchar* dirname);
104 void lastfm_enable_buttons ();
107 * Returns a newly-allocated string saying the time e.g. "1m 30s"
109 gchar* secs_to_time_str (gint secs);
111 void gssmp_ui_init (int argc, char *argv[])
113 window1 = GTK_WINDOW (create_window1 ());
114 aboutdialog1 = NULL;
115 hscale1 = lookup_widget (GTK_WIDGET (window1), "hscale1");
116 label4 = GTK_LABEL (lookup_widget (GTK_WIDGET (window1), "label4"));
117 label5 = GTK_LABEL (lookup_widget (GTK_WIDGET (window1), "label5"));
118 label7 = GTK_LABEL (lookup_widget (GTK_WIDGET (window1), "label7"));
119 label8 = GTK_LABEL (lookup_widget (GTK_WIDGET (window1), "label8"));
120 button2 = lookup_widget (GTK_WIDGET (window1), "button2");
121 button3 = lookup_widget (GTK_WIDGET (window1), "button3");
122 statusbar1 = GTK_STATUSBAR (lookup_widget (GTK_WIDGET (window1),
123 "statusbar1"));
124 recent1 = GTK_MENU_ITEM (lookup_widget (GTK_WIDGET (window1), "recent1"));
125 no_repeat1 = GTK_CHECK_MENU_ITEM (lookup_widget (GTK_WIDGET (window1),
126 "no_repeat1"));
127 repeat_all1 = GTK_CHECK_MENU_ITEM (lookup_widget (GTK_WIDGET (window1),
128 "repeat_all1"));
129 repeat_one1 = GTK_CHECK_MENU_ITEM (lookup_widget (GTK_WIDGET (window1),
130 "repeat_one1"));
131 shuffle1 = GTK_CHECK_MENU_ITEM (lookup_widget (GTK_WIDGET (window1),
132 "shuffle1"));
134 lastfmwindow = NULL;
135 checkbutton1 = NULL;
136 entry1 = NULL;
138 // NOTE: ICON_FILE is passed in via the make file
139 gtk_window_set_icon_from_file (window1, ICON_FILE, NULL);
141 choose_repeat_menu_item ();
143 context_id_play_file = gtk_statusbar_get_context_id (statusbar1,
144 "gssmp_ui_play_file");
145 context_id_error_playing_file = gtk_statusbar_get_context_id (statusbar1,
146 "gssmp_ui_error_callback");
147 context_id_status_callback = gtk_statusbar_get_context_id (statusbar1,
148 "status_callback");
149 context_id_not_a_file = gtk_statusbar_get_context_id (statusbar1,
150 "gssmp_ui_init");
152 skip_errors = TRUE;
153 moving_forward = TRUE;
155 status_timeout_source = 0;
159 gtk_widget_show (GTK_WIDGET (window1));
161 if (argc < 2)
163 play_bookmark (0);
165 else
167 gchar* file_or_dir = gssmp_files_make_absolute (argv[1]);
169 if (g_file_test (file_or_dir, G_FILE_TEST_IS_DIR))
171 play_in_dir (file_or_dir);
172 g_free (file_or_dir);
174 else if (g_file_test (file_or_dir, G_FILE_TEST_IS_REGULAR))
176 gssmp_ui_play_file (file_or_dir, TRUE, FALSE, 0, FALSE);
178 else
180 gssmp_ui_display_status_message ( context_id_not_a_file,
181 _("Could not find file '%s'"), file_or_dir );
182 g_free (file_or_dir);
186 redisplay_bookmarks ();
189 void gssmp_ui_quit ()
191 add_bookmark_here ();
193 g_free (stored_title);
194 g_free (stored_track_number);
195 g_free (stored_track_count);
196 g_free (stored_album);
197 g_free (stored_artist);
199 gtk_main_quit ();
202 void gssmp_ui_about ()
204 if (!aboutdialog1)
206 aboutdialog1 = GTK_WINDOW (create_aboutdialog1 ());
209 gtk_widget_show (GTK_WIDGET (aboutdialog1));
212 void update_buttons ()
214 gtk_widget_set_sensitive (button2, config_paused);
215 gtk_widget_set_sensitive (button3, !config_paused);
218 void gssmp_ui_choose_directory_clicked ()
220 GtkWidget *dialog;
222 dialog = gtk_file_chooser_dialog_new (_("Choose Directory"),
223 window1, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
224 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
225 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
226 NULL);
228 if (current_directory && strlen (current_directory) > 0)
230 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog),
231 current_directory);
233 else
235 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog),
236 g_get_home_dir());
239 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
241 gchar *dirname;
243 gssmp_files_reset_shuffle ();
245 dirname = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
247 play_in_dir (dirname);
249 g_free (dirname);
251 gtk_widget_destroy (dialog);
254 void gssmp_ui_choose_file_clicked ()
256 GtkWidget *dialog;
258 dialog = gtk_file_chooser_dialog_new (_("Choose File"),
259 window1, GTK_FILE_CHOOSER_ACTION_OPEN,
260 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
261 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
262 NULL);
264 if (current_filename && strlen (current_filename) > 0)
266 gchar* dir;
267 dir = g_path_get_dirname (current_filename);
268 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), dir);
269 g_free (dir);
271 else if (current_directory && strlen (current_directory) > 0)
273 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog),
274 current_directory);
276 else
278 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog),
279 g_get_home_dir());
282 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
284 gchar *filename;
286 gssmp_files_reset_shuffle ();
288 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
289 if (filename)
291 add_bookmark_here (); // Remember what we were playing
292 gssmp_ui_play_file (filename, TRUE, TRUE, 0, FALSE);
295 gtk_widget_destroy (dialog);
298 void gssmp_ui_eos_callback ()
300 if (config_repeat_style == repeat_one)
302 gssmp_gstreamer_seek (0);
304 else
306 gssmp_ui_next_clicked ();
310 void gssmp_ui_next_clicked ()
312 gchar *filename;
314 moving_forward = TRUE;
316 if (config_repeat_style == shuffle)
318 filename = gssmp_files_find_next_shuffled_file ();
320 else
322 filename = gssmp_files_find_next_file_after (current_filename);
324 if (!filename && (config_repeat_style == repeat_all))
326 filename = gssmp_files_find_next_file_in_dir (current_directory, NULL);
330 if (filename)
332 gssmp_ui_play_file (filename, FALSE, TRUE, 0, TRUE);
334 else
336 gssmp_ui_pause_clicked ();
340 void gssmp_ui_previous_clicked ()
342 gchar *filename;
344 moving_forward = FALSE;
346 filename = gssmp_files_find_previous_file_before (current_filename);
348 if (filename)
350 gssmp_ui_play_file (filename, FALSE, TRUE, 0, TRUE);
352 else
354 gssmp_ui_pause_clicked ();
358 void gssmp_ui_display_status_message (guint context_id, const gchar* msg,
359 const gchar* sub)
361 gchar* full_msg;
363 full_msg = g_strdup_printf (msg, sub);
365 gtk_statusbar_pop (statusbar1, context_id_status_callback);
366 gtk_statusbar_push (statusbar1, context_id_status_callback, full_msg);
368 printf (full_msg);
369 printf ("\n");
371 g_free (full_msg);
374 void gssmp_ui_display_2_status_messages (guint context_id, const gchar* msg1,
375 const gchar* sub1, const gchar* msg2, const gchar* sub2)
377 struct StatusDetails* details;
379 gssmp_ui_display_status_message (context_id, msg1, sub1);
381 details = g_slice_new (struct StatusDetails);
382 details->context_id = context_id;
383 details->msg = msg2;
384 details->sub = sub2;
386 if (status_timeout_source)
388 g_source_remove (status_timeout_source);
390 status_timeout_source = g_timeout_add (STATUS_TIMEOUT_LENGTH,
391 status_callback, (gpointer)details);
395 * Play the sound file supplied by calling into the gstreamer code and making
396 * the UI ready where required.
398 * @arg filename The full path to a file on disk
399 * @arg change_dir If this file is outside the user's chosen
400 * directory, should we change that directory to
401 * match the file?
402 * @arg new_filename Is the filename a newly-allocated string? I.e.
403 * should we free the old current_filename?
404 * @arg start_offset How many seconds through the file should we start?
405 * @arg skip_to_next_if_fail If this file fails to load, automatically skip to
406 * the next? (If not, we display an error to the
407 * user.)
409 void gssmp_ui_play_file (gchar* filename, gboolean change_dir,
410 gboolean new_filename, gint start_offset, gboolean skip_to_next_if_fail)
412 skip_errors = skip_to_next_if_fail;
414 if (change_dir)
416 if (!current_directory ||
417 strncmp (current_directory, filename, strlen (current_directory)) != 0)
419 current_directory = g_path_get_dirname (filename);
423 if (new_filename && current_filename)
425 g_free (current_filename);
427 current_filename = filename;
429 gssmp_ui_clear_track_info ();
431 new_tag = 0;
433 config_paused = FALSE;
434 update_buttons ();
436 gssmp_ui_display_2_status_messages( context_id_play_file,
437 _("Playing file %s"), current_filename,
438 _("Playing in directory %s"), current_directory );
440 gssmp_gstreamer_play (current_filename, start_offset,
441 gssmp_ui_duration_callback, gssmp_ui_progress_callback,
442 gssmp_ui_tag_callback, gssmp_ui_eos_callback,
443 gssmp_ui_error_callback);
446 void gssmp_ui_play_clicked ()
448 config_paused = FALSE;
449 update_buttons ();
450 gssmp_gstreamer_unpause ();
453 void gssmp_ui_pause_clicked ()
455 config_paused = TRUE;
456 update_buttons ();
457 gssmp_gstreamer_pause ();
460 void gssmp_ui_slider_changed (gdouble value)
462 gchar* time_str;
463 gint secs;
465 secs = (gint)value;
466 if (current_length != -1 && secs >= current_length)
468 secs = current_length - 1;
471 gssmp_gstreamer_seek (secs);
473 current_time = secs;
475 time_str = secs_to_time_str (secs);
476 gtk_label_set_text (label7, time_str);
477 gtk_widget_queue_draw(GTK_WIDGET(label7));
478 g_free (time_str);
481 void gssmp_ui_volume_change (gdouble value)
483 if (value < 0)
485 value = 0;
487 else if (value > 1)
489 value = 1;
491 gssmp_gstreamer_set_volume (value);
494 void gssmp_ui_progress_callback (gint secs)
496 gchar* time_str;
498 current_time = secs;
499 gtk_range_set_value (GTK_RANGE(hscale1), (gdouble)secs);
501 time_str = secs_to_time_str (secs);
502 gtk_label_set_text (label7, time_str);
504 switch (new_tag)
506 case 1:
508 display_track_info (FALSE);
509 new_tag = 2;
510 break;
512 case 0:
514 new_tag = 1;
515 break;
517 default:
519 break;
523 gtk_widget_queue_draw(GTK_WIDGET(hscale1));
524 gtk_widget_queue_draw(GTK_WIDGET(label7));
525 g_free (time_str);
528 void gssmp_ui_duration_callback (gint secs)
530 gtk_range_set_range (GTK_RANGE(hscale1), (gdouble)0, (gdouble)secs);
532 stored_track_length = secs_to_time_str (secs);
533 current_length = secs;
536 void gssmp_ui_tag_callback (const gchar* tag, const gchar* value)
538 new_tag = 1;
539 if (strcmp(tag, "title") == 0)
541 stored_title = g_strdup (value);
543 else if (strcmp(tag, "artist") == 0)
545 stored_artist = g_strdup (value);
547 else if (strcmp(tag, "album") == 0)
549 stored_album = g_strdup (value);
551 else if (strcmp(tag, "track-number") == 0)
553 stored_track_number = g_strdup (value);
555 else if (strcmp(tag, "track-count") == 0)
557 stored_track_count = g_strdup (value);
559 else
561 fprintf (stderr, _("Unknown tag: %s -> %s\n"), tag, value);
565 void gssmp_ui_error_callback (const gchar* msg)
567 gssmp_ui_display_status_message (context_id_error_playing_file,
568 _("Unable to play file: %s"), current_filename );
570 if (skip_errors)
572 if (moving_forward)
574 gssmp_ui_next_clicked ();
576 else
578 gssmp_ui_previous_clicked ();
579 moving_forward = FALSE;
582 else
584 GtkMessageDialog* dialog;
585 dialog = GTK_MESSAGE_DIALOG (gtk_message_dialog_new (window1,
586 GTK_DIALOG_DESTROY_WITH_PARENT,
587 GTK_MESSAGE_ERROR,
588 GTK_BUTTONS_CLOSE,
589 _("Error playing file '%s': %s"),
590 current_filename, msg));
591 gtk_dialog_run (GTK_DIALOG (dialog));
592 gtk_widget_destroy (GTK_WIDGET (dialog));
596 void gssmp_ui_clear_track_info ()
598 if (stored_title)
600 g_free (stored_title);
602 if (stored_track_number)
604 g_free (stored_track_number);
606 if (stored_track_length)
608 g_free (stored_track_length);
610 if (stored_track_count)
612 g_free (stored_track_count);
614 if (stored_artist)
616 g_free (stored_artist);
618 if (stored_album)
620 g_free (stored_album);
623 if (current_filename)
625 gchar* tmp1;
626 gchar* tmp2;
628 stored_title = g_path_get_basename (current_filename);
629 tmp1 = g_path_get_dirname (current_filename);
630 stored_album = g_path_get_basename (tmp1);
631 tmp2 = gssmp_files_get_parent_of_dir (tmp1);
632 stored_artist = g_path_get_basename (tmp2);
634 g_free (tmp1);
635 g_free (tmp2);
637 else
639 stored_title = NULL;
640 stored_album = NULL;
641 stored_artist = NULL;
644 stored_track_number = NULL;
645 stored_track_length = NULL;
646 stored_track_count = NULL;
649 // --------------------------------
651 #define MAX_TITLE_LENGTH 2048
652 void display_track_info (gboolean from_bookmark)
654 gchar title[MAX_TITLE_LENGTH];
655 gchar tmp[MAX_TITLE_LENGTH];
657 g_strlcpy (title, "<span size=\"large\">", MAX_TITLE_LENGTH);
659 if (stored_artist)
661 if (stored_title)
663 if (stored_track_number)
665 if (stored_track_count)
667 g_snprintf (tmp, MAX_TITLE_LENGTH, _("%s - %s (%s/%s)"),
668 stored_artist, stored_title, stored_track_number,
669 stored_track_count);
671 else
673 g_snprintf (tmp, MAX_TITLE_LENGTH, _("%s - %s (%s)"),
674 stored_artist, stored_title, stored_track_number);
677 else
679 g_snprintf (tmp, MAX_TITLE_LENGTH, _("%s - %s"),
680 stored_artist, stored_title);
683 else
685 g_snprintf (tmp, MAX_TITLE_LENGTH, _("%s - unnamed"), stored_artist);
688 else
690 if (stored_title)
692 if (stored_track_number)
694 if (stored_track_count)
696 g_snprintf (tmp, MAX_TITLE_LENGTH, _("%s (%s/%s)"),
697 stored_title, stored_track_number, stored_track_count);
699 else
701 g_snprintf (tmp, MAX_TITLE_LENGTH, _("%s (%s)"),
702 stored_title, stored_track_number);
705 else
707 g_snprintf (tmp, MAX_TITLE_LENGTH, _("%s"), stored_title);
710 else
712 g_strlcpy (tmp, "", MAX_TITLE_LENGTH);
716 g_strlcat (title, tmp, MAX_TITLE_LENGTH);
718 g_strlcat (title, "</span>", MAX_TITLE_LENGTH);
720 gtk_label_set_markup (label4, title);
722 // Now the album name
723 if (stored_album)
725 g_snprintf (tmp, MAX_TITLE_LENGTH, _("Album: %s"), stored_album);
727 else
729 g_strlcpy (tmp, "", MAX_TITLE_LENGTH);
732 gtk_label_set_text (label5, tmp);
734 // and the track length
735 if (stored_track_length)
737 g_snprintf (tmp, MAX_TITLE_LENGTH, _("Length: %s"), stored_track_length);
739 else
741 g_strlcpy (tmp, "", MAX_TITLE_LENGTH);
743 gtk_label_set_text (label8, tmp);
745 if( config_lastfm_active &&
746 current_length > 0 && stored_title && stored_artist
747 && !from_bookmark )
749 fork_lastfm_exe ();
752 add_bookmark_here (); // Put this track to the top of the bookmarks list
755 void fork_lastfm_exe ()
757 pid_t pid;
758 char tmp[32];
760 pid = fork();
762 if (pid == -1)
764 fprintf (stderr, "fork() error before launching lastfm exe.\n");
766 else if( pid == 0 )
768 // We are the child, run lastfm exe
770 char *args[10];
772 args[0] = config_lastfm_exe;
773 args[1] = "--length";
774 g_snprintf (tmp, 32, "%d", current_length);
775 args[2] = tmp;
776 args[3] = "--title";
777 args[4] = stored_title;
778 args[5] = "--artist";
779 args[6] = stored_artist;
781 if( stored_album )
783 args[7] = "--album";
784 args[8] = stored_album;
785 args[9] = NULL;
787 fprintf (stderr, "Running: %s %s %s %s \"%s\" %s \"%s\" %s \"%s\"\n",
788 args[0], args[1], args[2], args[3], args[4],
789 args[5], args[6], args[7], args[8]);
791 else
793 args[7] = NULL;
795 fprintf (stderr, "Running: %s %s %s %s \"%s\" %s \"%s\"\n",
796 args[0], args[1], args[2], args[3], args[4],
797 args[5], args[6]);
800 execvp( args[0], args );
802 // Should never get here.
803 fprintf (stderr, "execvp() error launching lastfm exe '%s'.\n",
804 config_lastfm_exe);
806 else
808 int status;
809 waitpid( pid, &status, 0 );
810 // TODO report status anomalies
814 gchar* secs_to_time_str (gint secs)
816 if (secs < 0)
818 secs = 0;
821 guint mins = secs / 60;
822 guint remaining_secs = secs % 60;
824 return g_strdup_printf (_("%dm %02ds"), mins, remaining_secs);
827 void gssmp_ui_choose_bookmark_clicked (GtkMenuItem* unused, gpointer num)
829 gssmp_files_reset_shuffle ();
830 config_paused = FALSE;
831 play_bookmark ((gulong)num);
834 void gssmp_ui_launch_help ()
836 gchar* uri;
838 if (g_file_test (DOC_URI, G_FILE_TEST_IS_REGULAR))
840 uri = gnome_vfs_get_uri_from_local_path (DOC_URI);
842 else if (g_file_test (BIN_PKG_DOC_PATH, G_FILE_TEST_IS_REGULAR))
844 gchar* abs;
845 abs = gssmp_files_make_absolute (BIN_PKG_DOC_PATH);
846 uri = gnome_vfs_get_uri_from_local_path (abs);
847 g_free (abs);
849 else if (g_file_test (SRC_DIR_DOC_PATH, G_FILE_TEST_IS_REGULAR))
851 gchar* abs;
852 abs = gssmp_files_make_absolute (SRC_DIR_DOC_PATH);
853 uri = gnome_vfs_get_uri_from_local_path (abs);
854 g_free (abs);
856 else
858 uri = g_strdup (ONLINE_DOCS_URI);
861 gnome_vfs_url_show (uri);
863 g_free (uri);
866 void gssmp_ui_lastfm ()
868 if (!lastfmwindow)
870 lastfmwindow = GTK_WINDOW (create_lastfmwindow ());
871 checkbutton1 = GTK_CHECK_BUTTON (
872 lookup_widget (GTK_WIDGET (lastfmwindow), "checkbutton1"));
873 entry1 = GTK_ENTRY (lookup_widget (GTK_WIDGET (lastfmwindow), "entry1"));
876 gtk_toggle_button_set_active (
877 GTK_TOGGLE_BUTTON (checkbutton1), config_lastfm_active);
878 gtk_entry_set_text (entry1, config_lastfm_exe);
880 lastfm_enable_buttons ();
882 gtk_widget_show (GTK_WIDGET (lastfmwindow));
885 void gssmp_ui_lastfm_close ()
887 gtk_widget_hide (GTK_WIDGET (lastfmwindow));
890 void gssmp_ui_lastfm_statechange ()
892 config_lastfm_active = gtk_toggle_button_get_active (
893 GTK_TOGGLE_BUTTON (checkbutton1));
896 void gssmp_ui_lastfm_exechanged ()
898 lastfm_enable_buttons ();
900 if (config_lastfm_exe)
902 g_free (config_lastfm_exe);
904 config_lastfm_exe = g_strdup( gtk_entry_get_text (entry1) );
907 // --------------------------------
909 void add_bookmark_here ()
911 if (current_filename && stored_title)
913 gssmp_config_add_bookmark (stored_title, stored_artist, stored_album,
914 current_directory, current_filename, current_time, current_length);
915 redisplay_bookmarks ();
919 void play_bookmark (guint num)
921 gboolean keep_paused;
922 GssmpBookmark *bmk;
924 new_tag = 0;
925 stored_track_number = NULL;
926 stored_track_count = NULL;
927 stored_track_length = NULL;
929 bmk = gssmp_config_get_bookmark (num);
930 if (bmk)
932 add_bookmark_here (); // First remember what we were playing before
934 gssmp_ui_duration_callback (bmk->length);
935 gssmp_ui_progress_callback (bmk->time);
937 if (stored_title)
939 g_free (stored_title);
941 stored_title = g_strdup (bmk->track);
943 if (stored_album)
945 g_free (stored_album);
947 stored_album = g_strdup (bmk->album);
949 if (stored_artist)
951 g_free (stored_artist);
953 stored_artist = g_strdup (bmk->artist);
955 if (current_filename)
957 g_free (current_filename);
959 current_filename = g_strdup (bmk->filename);
961 if (current_directory)
963 g_free (current_directory);
965 current_directory = g_strdup (bmk->directory);
967 display_track_info (TRUE);
969 else
971 stored_title = NULL;
972 stored_album = NULL;
973 stored_artist = NULL;
976 if (current_filename)
978 keep_paused = config_paused;
979 gssmp_ui_play_file (current_filename, TRUE, FALSE, current_time, TRUE);
980 if (keep_paused)
982 gssmp_ui_pause_clicked ();
986 redisplay_bookmarks ();
989 void choose_repeat_menu_item ()
991 switch (config_repeat_style)
993 case no_repeat:
995 gtk_check_menu_item_set_active (no_repeat1, TRUE);
996 gtk_check_menu_item_set_active (repeat_all1, FALSE);
997 gtk_check_menu_item_set_active (repeat_one1, FALSE);
998 gtk_check_menu_item_set_active (shuffle1, FALSE);
999 break;
1001 case repeat_all:
1003 gtk_check_menu_item_set_active (no_repeat1, FALSE);
1004 gtk_check_menu_item_set_active (repeat_all1, TRUE);
1005 gtk_check_menu_item_set_active (repeat_one1, FALSE);
1006 gtk_check_menu_item_set_active (shuffle1, FALSE);
1007 break;
1009 case repeat_one:
1011 gtk_check_menu_item_set_active (no_repeat1, FALSE);
1012 gtk_check_menu_item_set_active (repeat_all1, FALSE);
1013 gtk_check_menu_item_set_active (repeat_one1, TRUE);
1014 gtk_check_menu_item_set_active (shuffle1, FALSE);
1015 break;
1017 case shuffle:
1019 gtk_check_menu_item_set_active (no_repeat1, FALSE);
1020 gtk_check_menu_item_set_active (repeat_all1, FALSE);
1021 gtk_check_menu_item_set_active (repeat_one1, FALSE);
1022 gtk_check_menu_item_set_active (shuffle1, TRUE);
1023 break;
1028 void redisplay_bookmarks ()
1030 GtkMenu *submenu;
1032 gtk_widget_set_sensitive (GTK_WIDGET (recent1), FALSE);
1034 gtk_menu_item_deselect (GTK_MENU_ITEM (recent1));
1036 submenu = GTK_MENU (gtk_menu_new ());
1038 menu_number = 0;
1039 gssmp_config_bookmarks_foreach (menu_bookmark_callback_create, submenu);
1041 gtk_widget_show (GTK_WIDGET (submenu));
1043 gtk_menu_item_set_submenu (GTK_MENU_ITEM (recent1), GTK_WIDGET (submenu));
1045 gtk_widget_set_sensitive (GTK_WIDGET (recent1), TRUE);
1048 void menu_bookmark_callback_create (GssmpBookmark* bmk, gpointer submenu)
1050 GtkWidget *item;
1051 gchar* item_name;
1052 gchar* time_str;
1054 time_str = secs_to_time_str (bmk->time);
1056 item_name = g_strdup_printf (_("%s - %s (%s)"), bmk->artist, bmk->track,
1057 time_str);
1058 item = gtk_menu_item_new_with_label (item_name);
1059 gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item);
1060 gtk_widget_show (GTK_WIDGET (item));
1062 g_signal_connect ((gpointer) item, "activate",
1063 G_CALLBACK (gssmp_ui_choose_bookmark_clicked),
1064 (gpointer)menu_number);
1066 ++menu_number;
1068 g_free (item_name);
1069 g_free (time_str);
1072 gboolean status_callback (gpointer detailsptr)
1074 struct StatusDetails* details;
1076 status_timeout_source = 0;
1078 details = (struct StatusDetails*)detailsptr;
1080 gssmp_ui_display_status_message (details->context_id, details->msg,
1081 details->sub);
1083 g_slice_free (struct StatusDetails, details);
1085 return FALSE;
1088 void play_in_dir (const gchar* dirname)
1090 gchar* first_file_name;
1092 gssmp_config_set_directory (dirname);
1094 if (config_repeat_style == shuffle)
1096 first_file_name = gssmp_files_find_next_shuffled_file ();
1098 else
1100 first_file_name = gssmp_files_find_next_file_in_dir (
1101 current_directory, NULL);
1104 if (first_file_name)
1106 add_bookmark_here (); // Remember what we were playing
1107 gssmp_ui_play_file (first_file_name, FALSE, TRUE, 0, TRUE);
1111 void lastfm_enable_buttons ()
1113 const gchar* exe;
1114 gchar* fullexe;
1116 exe = gtk_entry_get_text (entry1);
1118 fullexe = g_find_program_in_path (exe);
1120 if (fullexe)
1122 gtk_widget_set_sensitive (GTK_WIDGET (checkbutton1), TRUE);
1123 g_free (fullexe);
1125 else
1127 config_lastfm_active = FALSE;
1128 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbutton1), FALSE);
1129 gtk_widget_set_sensitive (GTK_WIDGET (checkbutton1), FALSE);