Send commitlog mailing list submissions to
        [email protected]

To subscribe or unsubscribe via the World Wide Web, visit
        http://lists.openmoko.org/mailman/listinfo/commitlog
or, via email, send a message with subject or body 'help' to
        [EMAIL PROTECTED]

You can reach the person managing the list at
        [EMAIL PROTECTED]

When replying, please edit your Subject line so it is more specific
than "Re: Contents of commitlog digest..."
Today's Topics:

   1. r2643 - in
      trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2: .
      src ([EMAIL PROTECTED])
--- Begin Message ---
Author: abraxa
Date: 2007-08-06 12:51:19 +0200 (Mon, 06 Aug 2007)
New Revision: 2643

Added:
   
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/persistent.c
   
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/persistent.h
Modified:
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/TODO
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/Makefile.am
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/main.c
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/main.h
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/mainwin.c
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/mainwin.h
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/playback.c
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/playback.h
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/playlist.c
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/playlist.h
Log:
Session save/restore now implemented
More main window<->playback/playlist interfacing
Some cleaning up, some bugfixing :)



Modified: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/TODO
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/TODO  
2007-08-05 22:50:00 UTC (rev 2642)
+++ trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/TODO  
2007-08-06 10:51:19 UTC (rev 2643)
@@ -1,6 +1,7 @@
 
 UI:
        Add repeat mode indicator (different button pixmaps)
+       Make FFWD/REW buttons trigger repeatedly
        
 Backend:
        Use GConf
@@ -12,7 +13,7 @@
        How to adjust equalizer?
 
 Build process:
-       Add libspiff/libexpat/uriparser dependencies to Makefile.am
+       Bitbake recipe and its integration into OE
 
 Documentation:
-       Dependencies: libspiff->libexpat/uriparser
+       -/-

Modified: 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/Makefile.am
===================================================================
--- 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/Makefile.am   
    2007-08-05 22:50:00 UTC (rev 2642)
+++ 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/Makefile.am   
    2007-08-06 10:51:19 UTC (rev 2643)
@@ -27,4 +27,5 @@
        mainwin.c mainwin.h \
        playlist.c playlist.h \
        playback.c playback.h \
-       guitools.c guitools.h
+       guitools.c guitools.h \
+       persistent.c persistent.h

Modified: 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/main.c
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/main.c    
2007-08-05 22:50:00 UTC (rev 2642)
+++ trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/main.c    
2007-08-06 10:51:19 UTC (rev 2643)
@@ -34,7 +34,6 @@
 #include <gdk/gdk.h>
 
 #include <stdlib.h>
-#include <string.h>
 
 #include <errno.h>
 #include <fcntl.h>
@@ -45,11 +44,12 @@
 #include <dbus/dbus-glib.h>
 #include <dbus/dbus-glib-lowlevel.h>
 
-#include <spiff/spiff_c.h>
-
 #include "main.h"
+#include "mainwin.h"
 #include "guitools.h"
 #include "playlist.h"
+#include "playback.h"
+#include "persistent.h"
 
 /// Determines how the segfault handler terminates the program
 //define HANDLE_SIGSEGV
@@ -58,28 +58,6 @@
 //define DEBUG_MEM_PROFILE
 
 
-/// The default configuration
-struct _omp_config omp_default_config =
-{
-       FALSE,
-       TRUE,
-       OMP_REPEAT_OFF,
-//     FALSE,
-       FALSE,
-       "%f",
-       0.0,
-       {0,0,0,0,0,0,0,0,0,0,0},
-       TRUE,
-       "",
-       "../../test.xspf",
-       0,
-       0
-};
-
-struct _omp_config *omp_config = NULL;                 ///< Global and 
persistent configuration data
-
-
-
 /*
 void
 init_dbus()
@@ -135,81 +113,6 @@
 }
 
 /**
- * Load configuration and restore player state from last session
- */
-void
-omp_config_restore_state()
-{
-       #ifdef DEBUG
-               g_print("Loading playlist and restoring playback state\n");
-       #endif
-
-       // This mustn't be called more than once
-       g_assert(omp_config == NULL);
-
-       // Set default config
-       omp_config = g_new(struct _omp_config, 1);
-       g_memmove(omp_config, &omp_default_config, sizeof(struct _omp_config));
-
-       // Load config and last used playlist if set
-       omp_config_load();
-
-       if (omp_config->playlist_file[0])
-       {
-               omp_playlist_load(omp_config->playlist_file);
-       }
-
-       // Check whether playlist_position is valid
-       if (!omp_playlist_set_current_track(omp_config->playlist_position))
-       {
-               // Reset playlist state as playlist must have been modified 
since it was last loaded
-               omp_config->playlist_position = 0;
-               omp_config->track_position = 0;
-               omp_playlist_set_current_track(0);
-       }
-
-       // Feed the track entity to the playback engine to obtain track 
information
-       omp_playlist_load_current_track();
-}
-
-/**
- * Releases resources allocated for configuration data
- */
-void
-omp_config_free()
-{
-       g_free(omp_config);
-}
-
-/**
- * Saves the current configuration data to persistent storate
- */
-void
-omp_config_save()
-{
-}
-
-/**
- * Reads the configuration data from persistent storage
- */
-void
-omp_config_load()
-{
-}
-
-/**
- * Updates config with current player data and saves it to disk 
- */
-void
-omp_config_update()
-{
-       omp_config->playlist_position = omp_playlist_current_track_id;
-
-       omp_config_save();
-}
-
-
-/**
  * Tests for a lock file and returns the pid of any process already running
  */
 pid_t
@@ -256,7 +159,7 @@
        gint fd;
        struct flock fl;
 
-       fd = open(file_name, O_WRONLY|O_CREAT,  S_IWUSR);
+       fd = open(file_name, O_WRONLY|O_CREAT, S_IWUSR);
        if (fd < 0)
        {
                g_printerr("Failed opening lock file\n");
@@ -302,6 +205,8 @@
 gint
 main(int argc, char *argv[])
 {
+       GError *error;
+
 #ifdef DEBUG_MEM_PROFILE
        g_mem_set_vtable(glib_mem_profiler_table);
 #endif
@@ -348,12 +253,10 @@
        handle_locking();
 
        // Initialize gstreamer, must be last in the chain of command line 
parameter processors
-
-       if (!gst_init_check(&argc, &argv))
+       if (!gst_init_check(&argc, &argv, &error))
        {
-               g_printerr(_("Unable to initialize gstreamer, exiting.\n"
-                       "As gstreamer also fails to initialize when 
encountering unknown "
-                       "command line parameters you should check those as 
well.\n"));
+               g_printerr(_("Exiting due to gstreamer error: %s\n"), 
error->message);
+               g_error_free(error);
                exit(EXIT_FAILURE);
        }
 
@@ -368,26 +271,27 @@
        signal(SIGUSR1, handler_sigusr1);
 
        // Initialize playback, playlist and UI handling
+       omp_config_init();
        omp_main_window_create();
        omp_playback_init();
        omp_playlist_init();
        omp_main_connect_signals();
-       omp_config_restore_state();
+       omp_session_restore_state();
        omp_main_window_show();
 
        gtk_main();
        gdk_threads_leave();
 
-       // Store and free configuration resources
-       omp_config_save();
-       omp_config_free();
-
-       // Free remaining resources
+       // Clean up
+       omp_playback_save_state();
        omp_playback_free();
        omp_playlist_free();
        gst_deinit();
        g_free(ui_image_path);
 
+       omp_session_free();
+       omp_config_free();
+
 #ifdef DEBUG_MEM_PROFILE
        g_mem_profile();
 #endif

Modified: 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/main.h
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/main.h    
2007-08-05 22:50:00 UTC (rev 2642)
+++ trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/main.h    
2007-08-06 10:51:19 UTC (rev 2643)
@@ -27,39 +27,5 @@
 #ifndef _MAIN_H
 #define _MAIN_H
 
-/// Modes available for repetitive track playback
-enum omp_repeat_modes
-{
-       OMP_REPEAT_OFF,                                                         
        ///< Repeat off
-       OMP_REPEAT_CURRENT_ONCE,                                ///< Repeat 
current track once, then proceed with next track
-       OMP_REPEAT_CURRENT,                                                     
///< Repeat current track forever
-       OMP_REPEAT_PLAYLIST                                                     
///< Repeat playlist
-};
 
-/// Session-persistent configuration data
-struct _omp_config
-{
-       gboolean shuffle;                                                       
        ///< Shuffle on/off
-       gboolean resume_playback;                               ///< Resume 
playback on startup where it left off?
-       gint repeat_mode;                                                       
        ///< Repeat mode @see omp_repeat_modes
-//     gboolean auto_scroll;                                           ///< 
Scroll title if it's too long?
-       gboolean convert_underscore;            ///< Convert '_' to ' '?
-       gchar title_format[32];                                 ///< Format 
string used for title display
-       gdouble equalizer_gain;                                 ///< 
Pre-amplification value before audio stream is fed to equalizer [0.0..1.0]
-       gdouble equalizer_bands[11];            ///< The gains for each of the 
equalizer bands [-1.0..1.0]
-       gboolean show_numbers_in_pl;            ///< Show numbers in playlist?
-       gchar filesel_path[256];                                ///< Last path 
used in the file selection dialog
-//     gchar *playlist_path;                                           ///< 
Last path used for the playlist selection dialog
-       gchar playlist_file[256];                               ///< Path and 
file name of current (=last used) playlist
-       gint playlist_position;                                 ///< Position 
within the playlist
-       glong track_position;                                           ///< 
Position to resume playback from within the last played track
-};
-
-extern struct _omp_config *omp_config;
-extern struct _omp_config omp_default_config;
-
-void omp_config_save();
-void omp_config_load();
-void omp_config_update();
-
 #endif

Modified: 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/mainwin.c
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/mainwin.c 
2007-08-05 22:50:00 UTC (rev 2642)
+++ trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/mainwin.c 
2007-08-06 10:51:19 UTC (rev 2643)
@@ -39,6 +39,8 @@
 #include "playlist.h"
 #include "playback.h"
 
+#define OMP_BUTTON_PIXMAP_SIZE 36
+
 /// Contains all main window widgets that need to be changeable
 struct _main_widgets
 {
@@ -51,7 +53,7 @@
        GtkWidget *volume_image;
        GtkWidget *volume_label;
        GtkWidget *balance_image;
-       GtkWidget *play_pause_button;
+       GtkWidget *play_pause_button_image;
        GtkWidget *shuffle_button;
        GtkWidget *repeat_button;
        GtkWidget *playlist_button;
@@ -93,6 +95,9 @@
        if ( (vol < 0) || (vol > 100) )
                g_printerr("Warning: volume passed to omp_change_vol_img() out 
of bounds\n");
 
+       if (vol < 0) vol = 0;
+       if (vol > 100) vol = 100;
+
        gchar *image_file_name = 
g_strdup_printf("%s/ind-music-volume-%02d.png", ui_image_path, vol/10);
        gtk_image_set_from_file(GTK_IMAGE(main_widgets.volume_image), 
image_file_name);
 
@@ -313,6 +318,8 @@
 
 /**
  * Creates a toggle button framed by a GtkAlignment
+ * @param image_name Path and file name of the image to use as pixmap
+ * @return A GtkAlignment containing the button
  */
 GtkWidget*
 omp_toggle_button_create(gchar *image_name, gint pad_left, GCallback callback, 
GtkWidget **button)
@@ -325,7 +332,6 @@
 
        *button = gtk_toggle_button_new();
        gtk_widget_set_size_request(GTK_WIDGET(*button), 66, 66);
-       gtk_widget_set_name(GTK_WIDGET(*button), "mokofingerbutton-white");
        g_signal_connect(G_OBJECT(*button), "clicked", G_CALLBACK(callback), 
NULL);
        GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(*button), GTK_CAN_FOCUS);
        gtk_container_add(GTK_CONTAINER(alignment), GTK_WIDGET(*button));
@@ -341,24 +347,24 @@
 }
 
 /**
- * Creates a button and returns it
+ * Creates a button with a stock pixmap and returns it
  * @param image_name The name of the image resource to use, not a file name
+ * @return The button
  */
 GtkWidget*
-omp_button_create(gchar *image_name, GCallback callback)
+omp_stock_button_create(gchar *image_name, GtkWidget **image, GCallback 
callback)
 {
-       GtkWidget *image, *button;
+       GtkWidget *button;
 
        button = gtk_button_new();
        gtk_widget_set_size_request(GTK_WIDGET(button), 66, 66);
-       gtk_widget_set_name(GTK_WIDGET(button), "mokofingerbutton-white");
        g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(callback), 
NULL);
        GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(button), GTK_CAN_FOCUS);
 
        g_object_set(G_OBJECT(button), "xalign", (gfloat)0.37, "yalign", 
(gfloat)0.37, NULL);
 
-       image = gtk_image_new_from_icon_name(image_name, 36);
-       gtk_container_add(GTK_CONTAINER(button), GTK_WIDGET(image));
+       *image = gtk_image_new_from_icon_name(image_name, 
OMP_BUTTON_PIXMAP_SIZE);
+       gtk_container_add(GTK_CONTAINER(button), GTK_WIDGET(*image));
 
        return button;
 }
@@ -556,27 +562,27 @@
        gtk_box_set_homogeneous(GTK_BOX(controls_hbox), TRUE);
 
        // Previous Track button
-       button = omp_button_create("gtk-media-previous-ltr", 
G_CALLBACK(omp_playlist_set_prev_track));
+       button = omp_stock_button_create("gtk-media-previous-ltr", &image, 
G_CALLBACK(omp_playlist_set_prev_track));
        gtk_box_pack_start(GTK_BOX(controls_hbox), button, TRUE, TRUE, 0);
        gtk_box_set_child_packing(GTK_BOX(controls_hbox), GTK_WIDGET(button), 
FALSE, FALSE, 0, GTK_PACK_START);
 
        // Rewind button
-       button = omp_button_create("gtk-media-rewind-ltr", 
G_CALLBACK(omp_main_button_rewind_callback));
+       button = omp_stock_button_create("gtk-media-rewind-ltr", &image, 
G_CALLBACK(omp_main_button_rewind_callback));
        gtk_box_pack_start(GTK_BOX(controls_hbox), button, TRUE, TRUE, 0);
        gtk_box_set_child_packing(GTK_BOX(controls_hbox), GTK_WIDGET(button), 
FALSE, FALSE, 0, GTK_PACK_START);
 
        // Play/Pause button
-       button = omp_button_create("gtk-media-play-ltr", 
G_CALLBACK(omp_main_button_play_pause_callback));
+       button = omp_stock_button_create("gtk-media-play-ltr", 
&main_widgets.play_pause_button_image, 
G_CALLBACK(omp_main_button_play_pause_callback));
        gtk_box_pack_start(GTK_BOX(controls_hbox), button, TRUE, TRUE, 0);
        gtk_box_set_child_packing(GTK_BOX(controls_hbox), GTK_WIDGET(button), 
FALSE, FALSE, 0, GTK_PACK_START);
 
        // Fast Forward button
-       button = omp_button_create("gtk-media-forward-ltr", 
G_CALLBACK(omp_main_button_fast_forward_callback));
+       button = omp_stock_button_create("gtk-media-forward-ltr", &image, 
G_CALLBACK(omp_main_button_fast_forward_callback));
        gtk_box_pack_start(GTK_BOX(controls_hbox), button, TRUE, TRUE, 0);
        gtk_box_set_child_packing(GTK_BOX(controls_hbox), GTK_WIDGET(button), 
FALSE, FALSE, 0, GTK_PACK_START);
 
        // Next Track button
-       button = omp_button_create("gtk-media-next-ltr", 
G_CALLBACK(omp_playlist_set_next_track));
+       button = omp_stock_button_create("gtk-media-next-ltr", &image, 
G_CALLBACK(omp_playlist_set_next_track));
        gtk_box_pack_start(GTK_BOX(controls_hbox), button, TRUE, TRUE, 0);
        gtk_box_set_child_packing(GTK_BOX(controls_hbox), GTK_WIDGET(button), 
FALSE, FALSE, 0, GTK_PACK_START);
 }
@@ -614,7 +620,6 @@
        // Show everything but the window itself
        gtk_widget_show_all(GTK_WIDGET(bg_muxer));
 
-
        return;
 }
 
@@ -627,7 +632,7 @@
 omp_main_connect_signals()
 {
        g_signal_connect(G_OBJECT(omp_main_window), 
OMP_EVENT_PLAYLIST_TRACK_CHANGED,                   
G_CALLBACK(omp_main_update_track_change), NULL);
-       g_signal_connect(G_OBJECT(omp_main_window), 
OMP_EVENT_PLAYBACK_STATUS_CHANGED,          
G_CALLBACK(omp_main_update_track_change), NULL);
+       g_signal_connect(G_OBJECT(omp_main_window), 
OMP_EVENT_PLAYBACK_STATUS_CHANGED,          
G_CALLBACK(omp_main_update_status_change), NULL);
        g_signal_connect(G_OBJECT(omp_main_window), 
OMP_EVENT_PLAYBACK_POSITION_CHANGED,        
G_CALLBACK(omp_main_update_track_position), NULL);
 }
 
@@ -651,8 +656,8 @@
                old_track_count = omp_playlist_track_count;
                old_track_id = omp_playlist_current_track_id;
 
-               // Update config
-               omp_config_update();
+               // Update session
+               omp_session_set_track_id(omp_playlist_current_track_id);
 
                // Update label
                text = g_strdup_printf(WIDGET_CAPTION_TRACK_NUM, 
omp_playlist_current_track_id+1, omp_playlist_track_count);
@@ -668,7 +673,7 @@
                old_track_length = track_length;
                track_position = omp_playback_get_track_position();
 
-               // Set new time slider increments
+               // Set new time slider increments: one tap is 10% of the 
track's playing time
                gtk_range_set_increments(GTK_RANGE(main_widgets.time_hscale), 
track_length/10, track_length/10);
 
                // Update label and slider
@@ -680,6 +685,7 @@
 
                if (omp_main_time_slider_can_update)
                {
+                       // We don't want to set both min/max to 0 as this 
triggers a critial GTK warning, so we set 0/1 instead in that case
                        
gtk_range_set_range(GTK_RANGE(main_widgets.time_hscale), 0, track_length ? 
track_length : 1);
                        
gtk_range_set_value(GTK_RANGE(main_widgets.time_hscale), track_position);
                }
@@ -687,6 +693,21 @@
 }
 
 /**
+ * Updates the UI if playback engine switched between paused and playing modes
+ */
+void
+omp_main_update_status_change()
+{
+       // Update Play/Pause button pixmap
+       if (omp_playback_get_state() == OMP_PLAYBACK_STATE_PAUSED)
+       {
+               
gtk_image_set_from_icon_name(GTK_IMAGE(main_widgets.play_pause_button_image), 
"gtk-media-play-ltr", OMP_BUTTON_PIXMAP_SIZE);
+       } else {
+               
gtk_image_set_from_icon_name(GTK_IMAGE(main_widgets.play_pause_button_image), 
"gtk-media-pause", OMP_BUTTON_PIXMAP_SIZE);
+       }
+}
+
+/**
  * Updates the UI if the playback position changed
  */
 void
@@ -712,6 +733,7 @@
 
                if (omp_main_time_slider_can_update)
                {
+                       // We don't want to set both min/max to 0 as this 
triggers a critial GTK warning, so we set 0/1 instead in that case
                        
gtk_range_set_range(GTK_RANGE(main_widgets.time_hscale), 0, track_length ? 
track_length : 1);
                        
gtk_range_set_value(GTK_RANGE(main_widgets.time_hscale), track_position);
                }

Modified: 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/mainwin.h
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/mainwin.h 
2007-08-05 22:50:00 UTC (rev 2642)
+++ trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/mainwin.h 
2007-08-06 10:51:19 UTC (rev 2643)
@@ -36,6 +36,7 @@
 // Determines how many seconds the engine will seek if the FFWD/REW buttons 
are clicked
 #define BUTTON_SEEK_DISTANCE 10
 
+
 extern GtkWidget *omp_main_window;
 
 void omp_application_terminate();
@@ -46,6 +47,7 @@
 void omp_main_connect_signals();
 
 void omp_main_update_track_change();
+void omp_main_update_status_change();
 void omp_main_update_track_position();
 
 #endif

Added: 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/persistent.c
===================================================================
--- 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/persistent.c  
    2007-08-05 22:50:00 UTC (rev 2642)
+++ 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/persistent.c  
    2007-08-06 10:51:19 UTC (rev 2643)
@@ -0,0 +1,245 @@
+/*
+ *  OpenMoko Media Player
+ *   http://openmoko.org/
+ *
+ *  Copyright (C) 2007 by the OpenMoko team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * @file persistent.c
+ * Manages application configuration and session data
+ */
+
+#include <glib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "persistent.h"
+
+/// The default configuration
+struct _omp_config omp_default_config =
+{
+       FALSE,
+       TRUE,
+       OMP_REPEAT_OFF,
+//     FALSE,
+       FALSE,
+       "%f",
+       0.0,
+       {0,0,0,0,0,0,0,0,0,0,0},
+       TRUE
+};
+
+struct _omp_config *omp_config = NULL;                 ///< Global and 
persistent configuration data
+struct _omp_session *omp_session = NULL;               ///< Global and 
persistent session data
+
+
+/**
+ * Load application configuration data
+ */
+void
+omp_config_init()
+{
+       #ifdef DEBUG
+               g_print("Loading application configuration\n");
+       #endif
+
+       // This mustn't be called more than once
+       g_assert(omp_config == NULL);
+
+       // Set default config
+       omp_config = g_new(struct _omp_config, 1);
+       g_memmove(omp_config, &omp_default_config, sizeof(struct _omp_config));
+
+       /// @todo GConf
+}
+
+/**
+ * Releases resources allocated for configuration data
+ */
+void
+omp_config_free()
+{
+       g_free(omp_config);
+}
+
+/**
+ * Saves the current application configuration data to persistent storate
+ */
+void
+omp_config_save()
+{
+}
+
+/**
+ * Restores program state from last session
+ */
+void
+omp_session_restore_state()
+{
+       #ifdef DEBUG
+               g_print("Loading session data\n");
+       #endif
+
+       // This mustn't be called more than once
+       g_assert(omp_session == NULL);
+
+       omp_session = g_new0(struct _omp_session, 1);
+
+       // Load config and last used playlist if set
+       omp_session_load();
+
+       if (omp_session->playlist_file[0])
+       {
+               omp_playlist_load(omp_session->playlist_file);
+       }
+
+       // Check whether playlist_position is valid
+       if (!omp_playlist_set_current_track(omp_session->playlist_position))
+       {
+               // Reset playlist state as playlist must have been modified 
since it was last loaded
+               omp_session->playlist_position = 0;
+               omp_session->track_position = 0;
+               omp_playlist_set_current_track(0);
+       }
+
+       // Try to load the track, set the playback position and resume playback 
if needed
+       if (omp_playlist_load_current_track())
+       {
+               if (omp_session->was_playing)
+               {
+                       omp_playback_play();
+               }
+
+               omp_playback_set_track_position(omp_session->track_position);
+       }
+}
+
+/**
+ * Free resources used for session data
+ */
+void
+omp_session_free()
+{
+       g_free(omp_session);
+}
+
+/**
+ * Save session data to persistent storage
+ */
+void
+omp_session_save()
+{
+       gint session_file, result;
+       gchar *file_name;
+
+       // OMP_SESSION_FILE_NAME is relative to user's home dir
+       file_name = g_build_filename(g_get_home_dir(), OMP_SESSION_FILE_NAME, 
NULL);
+
+       // Permissions for created session file are 0600
+       session_file = creat(file_name, S_IRUSR | S_IWUSR);
+       if (session_file == -1) goto io_error;
+
+       result = write(session_file, omp_session, sizeof(struct _omp_session));
+       if (result != sizeof(struct _omp_session)) goto io_error;
+
+       result = close(session_file);
+       if (result == -1) goto io_error;
+
+       g_free(file_name);
+       return;
+
+       // We use a label to avoid duplicating code and improve readability
+io_error:
+       #ifdef DEBUG
+               g_printerr("Failed trying to save session data to %s: %s\n", 
file_name, strerror(errno));
+       #endif
+
+       g_free(file_name);
+}
+
+/**
+ * Load session data from persistent storage
+ */
+void
+omp_session_load()
+{
+       gint session_file, result;
+       gchar *file_name;
+
+       // OMP_SESSION_FILE_NAME is relative to user's home dir
+       file_name = g_build_filename(g_get_home_dir(), OMP_SESSION_FILE_NAME, 
NULL);
+
+       session_file = open(file_name, O_RDONLY);
+       if (session_file == -1) goto io_error;
+
+       result = read(session_file, omp_session, sizeof(struct _omp_session));
+       if (result != sizeof(struct _omp_session)) goto io_error;
+
+       result = close(session_file);
+       if (result == -1) goto io_error;
+
+       g_free(file_name);
+       return;
+
+       // We use a label to avoid duplicating code and improve readability
+io_error:
+       #ifdef DEBUG
+               g_printerr("Failed trying to load session data from %s: %s\n", 
file_name, strerror(errno));
+       #endif
+
+       g_free(file_name);
+
+       // Clear session data on error - just to be safe
+       memset(omp_session, 0, sizeof(struct _omp_session));
+}
+
+/**
+ * Saves values the playback engine needs to resume operation next time the 
player is started
+ */
+void
+omp_session_set_playback_state(glong track_position, gboolean is_playing)
+{
+       omp_session->track_position = track_position;
+       omp_session->was_playing = is_playing;
+
+       omp_session_save();
+}
+
+/**
+ * Set playlist to be loaded next session
+ */
+void
+omp_session_set_playlist(gchar *playlist_file)
+{
+       g_snprintf(omp_session->playlist_file, 
sizeof(omp_session->playlist_file), "%s", playlist_file);
+       omp_session_save();
+}
+
+/**
+ * Set track to be loaded next session
+ */
+void
+omp_session_set_track_id(guint track_id)
+{
+       omp_session->playlist_position = track_id;
+       omp_session_save();
+}
+

Added: 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/persistent.h
===================================================================
--- 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/persistent.h  
    2007-08-05 22:50:00 UTC (rev 2642)
+++ 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/persistent.h  
    2007-08-06 10:51:19 UTC (rev 2643)
@@ -0,0 +1,76 @@
+/*
+ *  OpenMoko Media Player
+ *   http://openmoko.org/
+ *
+ *  Copyright (C) 2007 by the OpenMoko team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * @file persistent.h
+ * Manages application configuration and session data
+ */
+
+#ifndef _PERSISTENT_H
+#define _PERSISTENT_H
+
+#include "playlist.h"
+
+// File name is relative to ~
+#define OMP_SESSION_FILE_NAME "/.openmoko-mediaplayer"
+
+
+/// Application configuration data
+struct _omp_config
+{
+       gboolean shuffle;                                                       
                ///< Shuffle on/off
+       gboolean resume_playback;                                       ///< 
Resume playback on startup where it left off?
+       gint repeat_mode;                                                       
                ///< Repeat mode @see omp_repeat_modes
+//     gboolean auto_scroll;                                           ///< 
Scroll title if it's too long?
+       gboolean convert_underscore;                    ///< Convert '_' to ' '?
+       gchar title_format[32];                                         ///< 
Format string used for title display
+       gdouble equalizer_gain;                                         ///< 
Pre-amplification value before audio stream is fed to equalizer [0.0..1.0]
+       gdouble equalizer_bands[11];                    ///< The gains for each 
of the equalizer bands [-1.0..1.0]
+       gboolean show_numbers_in_pl;                    ///< Show numbers in 
playlist?
+};
+
+/// Session-persistent data
+/// @note Default values should be 0/FALSE as session data will be zeroed on 
error
+struct _omp_session
+{
+       guint playlist_position;                                        ///< 
Position within the playlist
+       glong track_position;                                                   
///< Position to resume playback from within the last played track
+       gboolean was_playing;                                                   
///< Set to TRUE of track was being played as the player was closed
+       gchar filesel_path[256];                                        ///< 
Last path used in the file selection dialog
+       gchar playlist_file[256];                                       ///< 
Path and file name of current (=last used) playlist
+};
+
+extern struct _omp_config *omp_config;
+extern struct _omp_session *omp_session;
+
+void omp_config_init();
+void omp_config_free();
+void omp_config_save();
+
+void omp_session_restore_state();
+void omp_session_free();
+void omp_session_save();
+void omp_session_load();
+
+void omp_session_set_playlist(gchar *playlist_file);
+void omp_session_set_track_id(guint track_id);
+
+#endif

Modified: 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/playback.c
===================================================================
--- 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/playback.c    
    2007-08-05 22:50:00 UTC (rev 2642)
+++ 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/playback.c    
    2007-08-06 10:51:19 UTC (rev 2643)
@@ -29,10 +29,12 @@
 #include "playback.h"
 #include "mainwin.h"
 
-GstElement *omp_gst_playbin = NULL;
-guint omp_playback_ui_timeout = 0;
-gboolean omp_playback_ui_timeout_halted;
+GstElement *omp_gst_playbin = NULL;                                            
///< Our ticket to the gstreamer world
+guint omp_playback_ui_timeout = 0;                                             
///< Handle of the UI-updating timeout
+gboolean omp_playback_ui_timeout_halted;                       ///< Flag that 
tells the UI-updating timeout to exit if set
+gulong omp_playback_pending_position = 0;                      ///< Since we 
can't set a new position if element is not paused or playing we store the 
position here and set it when it reached either state
 
+
 /**
  * Initializes gstreamer by setting up pipe, message hooks and bins
  */
@@ -59,9 +61,10 @@
        bus = gst_pipeline_get_bus(GST_PIPELINE(omp_gst_playbin));
 
        gst_bus_add_signal_watch(bus);
-       g_signal_connect(bus, "message::eos",           
G_CALLBACK(omp_gst_message_eos), NULL);
-       g_signal_connect(bus, "message::error",         
G_CALLBACK(omp_gst_message_error), NULL);
-       g_signal_connect(bus, "message::warning", 
G_CALLBACK(omp_gst_message_warning), NULL); 
+       g_signal_connect(bus, "message::eos",                                   
G_CALLBACK(omp_gst_message_eos), NULL);
+       g_signal_connect(bus, "message::error",                                 
G_CALLBACK(omp_gst_message_error), NULL);
+       g_signal_connect(bus, "message::warning",                       
G_CALLBACK(omp_gst_message_warning), NULL);
+       g_signal_connect(bus, "message::state-changed", 
G_CALLBACK(omp_gst_message_state_changed), NULL);
 
        gst_object_unref(bus);
 }
@@ -72,16 +75,33 @@
 void
 omp_playback_free()
 {
+       GstBus *bus;
+
        if (!omp_gst_playbin)
        {
                return;
        }
 
+       bus = gst_pipeline_get_bus(GST_PIPELINE(omp_gst_playbin));
+       gst_bus_remove_signal_watch(bus);
+       gst_object_unref(bus);
+
        gst_element_set_state(omp_gst_playbin, GST_STATE_NULL);
        gst_object_unref(GST_OBJECT(omp_gst_playbin));
 }
 
 /**
+ * Saves current state to session data
+ */
+void
+omp_playback_save_state()
+{
+       omp_session_set_playback_state(
+               omp_playback_get_track_position(),
+               (omp_playback_get_state() == OMP_PLAYBACK_STATE_PLAYING) );
+}
+
+/**
  * Attempts to load a track from an URI
  * @return TRUE if successful, FALSE if failed
  */
@@ -129,13 +149,24 @@
 void
 omp_playback_play()
 {
+       gchar *track_uri;
+
        #ifdef DEBUG
                g_print("Starting playback\n");
        #endif
 
+       g_object_get(G_OBJECT(omp_gst_playbin), "uri", &track_uri, NULL);
+       if (!track_uri)
+       {
+               #ifdef DEBUG
+                       g_print("No track to play.\n");
+               #endif
+               return;
+       }
+       g_free(track_uri);
+
        // Set state
        gst_element_set_state(omp_gst_playbin, GST_STATE_PLAYING);
-       g_signal_emit_by_name(G_OBJECT(omp_main_window), 
OMP_EVENT_PLAYBACK_STATUS_CHANGED);
 
        // Add timer to update UI if necessary
        // If the halt flag was set but the callback didn't run yet then we
@@ -144,7 +175,7 @@
 
        if (!omp_playback_ui_timeout)
        {
-               omp_playback_ui_timeout = 
g_timeout_add(PLAYBACK_UI_UPDATE_INTERVAL, omp_playback_ui_timeout_callback, 
NULL);
+               omp_playback_ui_timeout = 
g_timeout_add(OMP_PLAYBACK_UI_UPDATE_INTERVAL, 
omp_playback_ui_timeout_callback, NULL);
        }
 }
 
@@ -160,26 +191,21 @@
 
        // Set state
        gst_element_set_state(omp_gst_playbin, GST_STATE_PAUSED);
-       g_signal_emit_by_name(G_OBJECT(omp_main_window), 
OMP_EVENT_PLAYBACK_STATUS_CHANGED);
 
        // Stop timer
        omp_playback_ui_timeout_halted = TRUE;
 }
 
 /**
- * Returns the current state the playback engine is in
- * @todo Don't use system clock, might be out-of-sync with playbin clock?
+ * Returns the current state the playback engine is in, simplifying it a bit 
to hide internal states
  */
 gint
 omp_playback_get_state()
 {
        GstState state;
-       GstClock *clock;
 
        // Poll state with an immediate timeout
-       clock = gst_system_clock_obtain();
-       gst_element_get_state(GST_ELEMENT(omp_gst_playbin), &state, NULL, 
gst_clock_get_time(clock));
-       gst_object_unref(clock);
+       state = GST_STATE(omp_gst_playbin);
 
        // The NULL and READY element states are no different from PAUSED for 
more abstract layers
        if ( (state == GST_STATE_NULL) || (state == GST_STATE_READY) )
@@ -214,16 +240,40 @@
 void
 omp_playback_set_track_position(glong position)
 {
+       GstState pipe_state;
+
        if (!omp_gst_playbin)
        {
                return;
        }
 
-       gst_element_seek_simple(GST_ELEMENT(omp_gst_playbin),
-               GST_FORMAT_TIME,
-               GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE,
-               position*GST_SECOND);
+       // If we don't clamp it to values >= 0 we trigger EOS messages which 
make the playlist mess up
+       if (position < 0) position = 0;
 
+       // Check if the pipe is even ready to seek
+       pipe_state = GST_STATE(omp_gst_playbin);
+
+       if ( (pipe_state != GST_STATE_PAUSED) && (pipe_state != 
GST_STATE_PLAYING) )
+       {
+               // It's not, so make the position change pending
+               omp_playback_pending_position = position;
+
+               #ifdef DEBUG
+                       g_printf("Pended track position change to %d:%.2ds\n", 
position / 60, position % 60);
+               #endif
+               return;
+       }
+       omp_playback_pending_position = 0;
+
+       #ifdef DEBUG
+               g_printf("Setting track position to %d:%.2ds\n", position / 60, 
position % 60);
+       #endif
+
+       gst_element_seek(GST_ELEMENT(omp_gst_playbin), 1.0,
+               GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
+               GST_SEEK_TYPE_SET, position*GST_SECOND,
+               GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
+
        g_signal_emit_by_name(G_OBJECT(omp_main_window), 
OMP_EVENT_PLAYBACK_POSITION_CHANGED);
 }
 
@@ -265,6 +315,31 @@
 }
 
 /**
+ * Handles gstreamer's state change notification
+ */
+static gboolean
+omp_gst_message_state_changed(GstBus *bus, GstMessage *message, gpointer data)
+{
+       static gint previous_state = GST_STATE_VOID_PENDING;
+       gint new_state;
+
+       // Do we have a pending playback position change that we can apply?
+       if ( ( (GST_STATE(omp_gst_playbin) == GST_STATE_PLAYING) || 
(GST_STATE(omp_gst_playbin) == GST_STATE_PAUSED) )
+               && omp_playback_pending_position)
+       {
+               omp_playback_set_track_position(omp_playback_pending_position);
+       }
+
+       // Only propagate this event if it's of interest for higher-level 
routines
+       new_state = omp_playback_get_state();
+       if (new_state != previous_state)
+       {
+               previous_state = new_state;
+               g_signal_emit_by_name(G_OBJECT(omp_main_window), 
OMP_EVENT_PLAYBACK_STATUS_CHANGED);
+       }
+}
+
+/**
  * Handles gstreamer's error messages
  */
 static gboolean
@@ -275,7 +350,6 @@
        #ifdef DEBUG
                gst_message_parse_error(message, &error, NULL);
                g_printerr("gstreamer error: %s\n", error->message);
-               gst_message_unref(error);
                g_error_free(error);
        #endif
 
@@ -293,7 +367,6 @@
        #ifdef DEBUG
                gst_message_parse_warning(message, &error, NULL);
                g_printerr("gstreamer warning: %s\n", error->message);
-               gst_message_unref(error);
                g_error_free(error);
        #endif
 

Modified: 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/playback.h
===================================================================
--- 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/playback.h    
    2007-08-05 22:50:00 UTC (rev 2642)
+++ 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/playback.h    
    2007-08-06 10:51:19 UTC (rev 2643)
@@ -38,10 +38,11 @@
 #define OMP_PLAYBACK_STATE_PLAYING GST_STATE_PLAYING
 
 // The UI will be updated at this interval when a track is playing (in ms)
-#define PLAYBACK_UI_UPDATE_INTERVAL 1000
+#define OMP_PLAYBACK_UI_UPDATE_INTERVAL 1000
 
 void omp_playback_init();
 void omp_playback_free();
+void omp_playback_save_state();
 
 gboolean omp_playback_load_track_from_uri(gchar *uri);
 
@@ -53,6 +54,7 @@
 gulong omp_playback_get_track_length();
 
 static gboolean omp_gst_message_eos(GstBus *bus, GstMessage *message, gpointer 
data);
+static gboolean omp_gst_message_state_changed(GstBus *bus, GstMessage 
*message, gpointer data);
 static gboolean omp_gst_message_error(GstBus *bus, GstMessage *message, 
gpointer data);
 static gboolean omp_gst_message_warning(GstBus *bus, GstMessage *message, 
gpointer data);
 

Modified: 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/playlist.c
===================================================================
--- 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/playlist.c    
    2007-08-05 22:50:00 UTC (rev 2642)
+++ 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/playlist.c    
    2007-08-06 10:51:19 UTC (rev 2643)
@@ -30,9 +30,9 @@
 #include <spiff/spiff_c.h>
 
 #include "playlist.h"
-#include "main.h"
 #include "mainwin.h"
 #include "playback.h"
+#include "persistent.h"
 
 struct spiff_list *omp_playlist = NULL;                                        
                                        ///< Loaded playlist
 guint omp_playlist_track_count = 0;                                            
                                                ///< Number of tracks stored 
within the current playlist
@@ -66,7 +66,7 @@
 }
 
 /**
- * Frees resouces allocated for playlist handling
+ * Frees resources allocated for playlist handling
  */
 void
 omp_playlist_free()
@@ -105,10 +105,10 @@
                spiff_free(omp_playlist);
        }
 
-       // Update config unless target and source are the same
-       if (omp_config->playlist_file != playlist_file)
+       // Update session unless target and source are the same
+       if (omp_session->playlist_file != playlist_file)
        {
-               g_snprintf(omp_config->playlist_file, 
sizeof(omp_config->playlist_file), "%s", playlist_file);
+               omp_session_set_playlist(playlist_file);
        }
 
        // Load playlist
@@ -239,6 +239,7 @@
                        {
                                omp_playlist_current_track = track;
                                omp_playlist_current_track_id--;
+                               is_new_track = TRUE;
                        }
                }
        }

Modified: 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/playlist.h
===================================================================
--- 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/playlist.h    
    2007-08-05 22:50:00 UTC (rev 2642)
+++ 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/playlist.h    
    2007-08-06 10:51:19 UTC (rev 2643)
@@ -31,6 +31,15 @@
 
 #define OMP_EVENT_PLAYLIST_TRACK_CHANGED "playlist_track_changed"
 
+/// Modes available for repetitive track playback
+enum omp_repeat_modes
+{
+       OMP_REPEAT_OFF,                                                         
        ///< Repeat off
+       OMP_REPEAT_CURRENT_ONCE,                                ///< Repeat 
current track once, then proceed with next track
+       OMP_REPEAT_CURRENT,                                                     
///< Repeat current track forever
+       OMP_REPEAT_PLAYLIST                                                     
///< Repeat entire playlist
+};
+
 extern struct spiff_list *omp_playlist;
 extern guint omp_playlist_track_count;
 




--- End Message ---
_______________________________________________
commitlog mailing list
[email protected]
http://lists.openmoko.org/mailman/listinfo/commitlog

Reply via email to