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. r2630 - in trunk/src/target/OM-2007.2/daemons/neod: . src
      ([EMAIL PROTECTED])
   2. r2631 -
      trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src
      ([EMAIL PROTECTED])
--- Begin Message ---
Author: mickey
Date: 2007-08-04 12:36:33 +0200 (Sat, 04 Aug 2007)
New Revision: 2630

Added:
   trunk/src/target/OM-2007.2/daemons/neod/src/buttonactions.c
   trunk/src/target/OM-2007.2/daemons/neod/src/buttonactions.h
Modified:
   trunk/src/target/OM-2007.2/daemons/neod/AUTHORS
   trunk/src/target/OM-2007.2/daemons/neod/README
   trunk/src/target/OM-2007.2/daemons/neod/configure.ac
   trunk/src/target/OM-2007.2/daemons/neod/src/Makefile.am
   trunk/src/target/OM-2007.2/daemons/neod/src/neod-main.c
Log:
neod: extract basic functionality out of former openmoko-panel-mainmenu


Modified: trunk/src/target/OM-2007.2/daemons/neod/AUTHORS
===================================================================
--- trunk/src/target/OM-2007.2/daemons/neod/AUTHORS     2007-08-04 06:02:22 UTC 
(rev 2629)
+++ trunk/src/target/OM-2007.2/daemons/neod/AUTHORS     2007-08-04 10:36:33 UTC 
(rev 2630)
@@ -0,0 +1,2 @@
+Michael Lauer <[EMAIL PROTECTED]>
+

Modified: trunk/src/target/OM-2007.2/daemons/neod/README
===================================================================
--- trunk/src/target/OM-2007.2/daemons/neod/README      2007-08-04 06:02:22 UTC 
(rev 2629)
+++ trunk/src/target/OM-2007.2/daemons/neod/README      2007-08-04 10:36:33 UTC 
(rev 2630)
@@ -0,0 +1,7 @@
+Minimal Button and powermanagement handling daemon
+
+NOTE: Merely throwaway code, since it may be a better idea to base on
+ * HAL / OHM, or
+ * devmand, or
+ * zaurusd ?
+

Modified: trunk/src/target/OM-2007.2/daemons/neod/configure.ac
===================================================================
--- trunk/src/target/OM-2007.2/daemons/neod/configure.ac        2007-08-04 
06:02:22 UTC (rev 2629)
+++ trunk/src/target/OM-2007.2/daemons/neod/configure.ac        2007-08-04 
10:36:33 UTC (rev 2630)
@@ -21,6 +21,7 @@
 AM_GLIB_GNU_GETTEXT
 
 PKG_CHECK_MODULES(GTK, gtk+-2.0 >= $LIBGTK_VERSION)
+PKG_CHECK_MODULES(PULSE, libpulse)
 
 CFLAGS=$GTK_CFLAGS
 AC_CHECK_DECLS([g_date_set_time_t],

Modified: trunk/src/target/OM-2007.2/daemons/neod/src/Makefile.am
===================================================================
--- trunk/src/target/OM-2007.2/daemons/neod/src/Makefile.am     2007-08-04 
06:02:22 UTC (rev 2629)
+++ trunk/src/target/OM-2007.2/daemons/neod/src/Makefile.am     2007-08-04 
10:36:33 UTC (rev 2630)
@@ -4,12 +4,15 @@
                -DNEOD_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \
                -DDATADIR=\""$(datadir)"\" -D_GNU_SOURCE
 
-AM_CFLAGS    = -Wall -pedantic -std=c99 @GTK_CFLAGS@
+AM_CFLAGS    = -Wall -pedantic -std=c99 @GTK_CFLAGS@ @PULSE_CFLAGS@
 
 bin_PROGRAMS = neod
 
 neod_SOURCES = \
-       neod-main.c
+  buttonactions.c \
+  neod-main.c
 
+neod_LDADD = @GTK_LIBS@ @PULSE_LIBS@
+
 MAINTAINERCLEANFILES  = config.h.in Makefile.in
 

Added: trunk/src/target/OM-2007.2/daemons/neod/src/buttonactions.c
===================================================================
--- trunk/src/target/OM-2007.2/daemons/neod/src/buttonactions.c 2007-08-04 
06:02:22 UTC (rev 2629)
+++ trunk/src/target/OM-2007.2/daemons/neod/src/buttonactions.c 2007-08-04 
10:36:33 UTC (rev 2630)
@@ -0,0 +1,525 @@
+/*
+ *  Authored by Michael 'Mickey' Lauer <[EMAIL PROTECTED]>
+ *
+ *  Copyright (C) 2007 OpenMoko, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Public License as published by
+ *  the Free Software Foundation; version 2 of the license.
+ *
+ *  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 Public License for more details.
+ */
+#include "buttonactions.h"
+
+#include <gtk/gtklabel.h>
+#include <gtk/gtkmenu.h>
+#include <gtk/gtkmenuitem.h>
+
+#include <gdk/gdkx.h>
+
+#include <glib.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+#include <pulse/pulseaudio.h>
+
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <linux/input.h>
+
+#undef DEBUG_THIS_FILE
+//#define DEBUG_THIS_FILE
+
+//FIXME load this from sysfs
+static const int MAX_BRIGHTNESS = 5000;
+
+//FIXME find out through sysfs
+#ifndef DEBUG_THIS_FILE
+    #define AUX_BUTTON_EVENT_PATH "/dev/input/event1"
+    #define AUX_BUTTON_KEYCODE 169
+    #define POWER_BUTTON_EVENT_PATH "/dev/input/event2"
+    #define POWER_BUTTON_KEYCODE 116
+    #define TOUCHSCREEN_EVENT_PATH "/dev/input/touchscreen0"
+    #define TOUCHSCREEN_BUTTON_KEYCODE 0x14a
+#else
+    #define AUX_BUTTON_EVENT_PATH "/dev/input/event1"
+    #define AUX_BUTTON_KEYCODE 0x25
+    #define POWER_BUTTON_EVENT_PATH "/dev/input/event0"
+    #define POWER_BUTTON_KEYCODE 0x25
+    #define TOUCHSCREEN_EVENT_PATH "/dev/input/event2"
+    #define TOUCHSCREEN_BUTTON_KEYCODE 0x14a
+#endif
+
+GPollFD aux_fd;
+GPollFD power_fd;
+GIOChannel* touchscreen_io;
+
+int aux_timer = -1;
+int power_timer = -1;
+int powersave_timer1 = -1;
+int powersave_timer2 = -1;
+int powersave_timer3 = -1;
+
+GtkWidget* aux_menu = 0;
+GtkWidget* power_menu = 0;
+
+typedef enum _PowerState
+{
+    NORMAL,
+    DISPLAY_DIM,
+    DISPLAY_OFF,
+    SUSPEND,
+} PowerState;
+PowerState power_state = NORMAL;
+
+static pa_context* pac;
+
+/* Borrowed from libwnck */
+static Window get_window_property( Window xwindow, Atom atom )
+{
+    Atom type;
+    int format;
+    gulong nitems;
+    gulong bytes_after;
+    Window *w;
+    int err, result;
+    Window retval;
+
+    gdk_error_trap_push ();
+
+    type = None;
+    result = XGetWindowProperty (gdk_display,
+                                 xwindow,
+                                 atom,
+                                 0, G_MAXLONG,
+                                 False, XA_WINDOW, &type, &format, &nitems,
+                                 &bytes_after, (unsigned char **) &w);
+    err = gdk_error_trap_pop ();
+
+    if (err != Success ||
+        result != Success)
+        return None;
+
+    if (type != XA_WINDOW)
+    {
+        XFree (w);
+        return None;
+    }
+
+    retval = *w;
+    XFree (w);
+
+    return retval;
+}
+
+gboolean neod_buttonactions_install_watcher()
+{
+    int auxfd = open( AUX_BUTTON_EVENT_PATH, O_RDONLY );
+    if ( auxfd < 0 )
+    {
+        g_debug( "can't open " AUX_BUTTON_EVENT_PATH " (%s)", strerror( errno 
) );
+        return FALSE;
+    }
+    int powerfd = open( POWER_BUTTON_EVENT_PATH, O_RDONLY );
+    if ( powerfd < 0 )
+    {
+        g_debug( "can't open " POWER_BUTTON_EVENT_PATH " (%s)", strerror( 
errno ) );
+        return FALSE;
+    }
+    static GSourceFuncs funcs = {
+        neod_buttonactions_input_prepare,
+        neod_buttonactions_input_check,
+        neod_buttonactions_input_dispatch,
+    NULL,
+    };
+    GSource* button_watcher = g_source_new( &funcs, sizeof (GSource) );
+    aux_fd.fd = auxfd;
+    aux_fd.events = G_IO_IN | G_IO_HUP | G_IO_ERR;
+    aux_fd.revents = 0;
+    g_source_add_poll( button_watcher, &aux_fd );
+    power_fd.fd = powerfd;
+    power_fd.events = G_IO_IN | G_IO_HUP | G_IO_ERR;
+    power_fd.revents = 0;
+    g_source_add_poll( button_watcher, &power_fd );
+    g_source_attach( button_watcher, NULL );
+
+    if ( getenv( "MOKO_POWERSAVE" ) != NULL )
+    {
+
+        int tsfd = open( TOUCHSCREEN_EVENT_PATH, O_RDONLY );
+        if ( tsfd < 0 )
+        {
+            g_debug( "can't open " TOUCHSCREEN_EVENT_PATH " (%s)", strerror( 
errno ) );
+            return FALSE;
+        }
+        touchscreen_io = g_io_channel_unix_new( tsfd );
+        g_io_add_watch( touchscreen_io, G_IO_IN, 
neod_buttonactions_touchscreen_cb, NULL );
+
+        neod_buttonactions_powersave_reset();
+        neod_buttonactions_set_display( 100 );
+        neod_buttonactions_sound_init();
+    }
+    else
+        g_debug( "MOKO_POWERSAVE=yes not set. Not enabling power management." 
);
+
+    return TRUE;
+}
+
+
+gboolean neod_buttonactions_input_prepare( GSource* source, gint* timeout )
+{
+    return FALSE;
+}
+
+
+gboolean neod_buttonactions_input_check( GSource* source )
+{
+    return ( ( aux_fd.revents & G_IO_IN ) || ( power_fd.revents & G_IO_IN ) );
+}
+
+
+gboolean neod_buttonactions_input_dispatch( GSource* source, GSourceFunc 
callback, gpointer data )
+{
+    if ( aux_fd.revents & G_IO_IN )
+    {
+        struct input_event event;
+        int size = read( aux_fd.fd, &event, sizeof( struct input_event ) );
+        //g_debug( "read %d bytes from aux_fd %d", size, aux_fd.fd );
+        //g_debug( "input event = ( %0x, %0x, %0x )", event.type, event.code, 
event.value );
+        if ( event.type == 1 && event.code == AUX_BUTTON_KEYCODE )
+        {
+            if ( event.value == 1 ) /* pressed */
+            {
+                g_debug( "triggering aux timer" );
+                aux_timer = g_timeout_add( 1 * 1000, (GSourceFunc) 
neod_buttonactions_aux_timeout, (gpointer)1 );
+            }
+            else if ( event.value == 0 ) /* released */
+            {
+                g_debug( "resetting aux timer" );
+                if ( aux_timer != -1 )
+                {
+                    g_source_remove( aux_timer );
+                    neod_buttonactions_aux_timeout( 0 );
+                }
+                aux_timer = -1;
+            }
+        }
+    }
+    if ( power_fd.revents & G_IO_IN )
+    {
+        struct input_event event;
+        int size = read( power_fd.fd, &event, sizeof( struct input_event ) );
+        //g_debug( "read %d bytes from power_fd %d", size, power_fd.fd );
+        //g_debug( "input event = ( %0x, %0x, %0x )", event.type, event.code, 
event.value );
+        if ( event.type == 1 && event.code == POWER_BUTTON_KEYCODE )
+        {
+            if ( event.value == 1 ) /* pressed */
+            {
+                g_debug( "triggering power timer" );
+                power_timer = g_timeout_add( 1 * 1000, (GSourceFunc) 
neod_buttonactions_power_timeout, (gpointer)1 );
+            }
+            else if ( event.value == 0 ) /* released */
+            {
+                g_debug( "resetting power timer" );
+                if ( power_timer != -1 )
+                {
+                    g_source_remove( power_timer );
+                    neod_buttonactions_power_timeout( 0 );
+                }
+                power_timer = -1;
+            }
+        }
+    }
+    return TRUE;
+}
+
+gboolean neod_buttonactions_aux_timeout( guint timeout )
+{
+    g_debug( "aux pressed for %d", timeout );
+
+    neod_buttonactions_sound_play( "touchscreen" );
+    neod_buttonactions_powersave_reset();
+
+    aux_timer = -1;
+    if ( timeout < 1 )
+    {
+        // make dialer interface show up
+        // NOTE: temporary hack, will use dbus interface once dialer has it :)
+        system( "openmoko-dialer &" );
+    }
+    else
+    {
+        // make main menu show up
+        // NOTE: temporary hack, will use dbus interface once main menu has it 
:)
+        system( "openmoko-mainmenu &" );
+    }
+    return FALSE;
+}
+
+// this is hardcoded to the Neo1973
+void neod_buttonactions_popup_positioning_cb( GtkMenu* menu, gint* x, gint* y, 
gboolean* push_in, gpointer user_data )
+{
+    GtkRequisition req;
+    gtk_widget_size_request( GTK_WIDGET(menu), &req );
+    gint screen_width = gdk_screen_width();
+    gint screen_height = gdk_screen_height();
+
+    if ( GTK_WIDGET(menu) == aux_menu )
+    {
+        *x = 0;
+        *y = 0;
+    }
+    else if ( GTK_WIDGET(menu) == power_menu )
+    {
+        *x = screen_width - req.width;
+        *y = screen_height - req.height;
+    }
+    else
+        g_assert( FALSE ); // fail here if called for unknown menu
+}
+
+void neod_buttonactions_popup_selected_lock( GtkMenuItem* menu, gpointer 
user_data )
+{
+    //FIXME talk to neod
+    int fd = open( "/sys/power/state", O_WRONLY );
+    if ( fd != -1 )
+    {
+        char command[] = "mem\n";
+        write(fd, &command, sizeof(command) );
+        close( fd );
+    }
+}
+
+void neod_buttonactions_popup_selected_restartUI( GtkMenuItem* menu, gpointer 
user_data )
+{
+    //FIXME talk to neod
+    //FIXME notify user
+    system( "/etc/init.d/xserver-nodm restart");
+}
+
+void neod_buttonactions_popup_selected_reboot( GtkMenuItem* menu, gpointer 
user_data )
+{
+    //FIXME talk to neod
+    //moko_ui_banner_show_text( 4, "Rebooting System..." );
+    system( "/sbin/reboot");
+}
+
+void neod_buttonactions_popup_selected_poweroff( GtkMenuItem* menu, gpointer 
user_data )
+{
+    //FIXME talk to neod
+    //moko_ui_banner_show_text( 4, "Shutting down System..." );
+    system( "/sbin/poweroff");
+}
+
+gboolean neod_buttonactions_power_timeout( guint timeout )
+{
+    g_debug( "power pressed for %d", timeout );
+
+    neod_buttonactions_sound_play( "touchscreen" );
+    neod_buttonactions_powersave_reset();
+
+    power_timer = -1;
+    if ( timeout < 1 )
+    {
+        Window xwindow = get_window_property( 
gdk_x11_get_default_root_xwindow(), 
gdk_x11_get_xatom_by_name("_NET_ACTIVE_WINDOW") );
+        g_debug( "active Window = %d", (int) xwindow );
+
+        Display* display = XOpenDisplay( NULL );
+
+        //xwindow = gdk_x11_drawable_get_xid (window);
+
+        XEvent xev;
+        xev.xclient.type = ClientMessage;
+        xev.xclient.serial = 0;
+        xev.xclient.send_event = True;
+        xev.xclient.display = display;
+        xev.xclient.window = xwindow;
+        xev.xclient.message_type = gdk_x11_get_xatom_by_name( 
"_NET_CLOSE_WINDOW" );
+        xev.xclient.format = 32;
+        xev.xclient.data.l[0] = 0;
+        xev.xclient.data.l[1] = 0;
+        xev.xclient.data.l[2] = 0;
+        xev.xclient.data.l[3] = 0;
+        xev.xclient.data.l[4] = 0;
+
+        //TODO: add timeout checking for response
+
+        XSendEvent (display, gdk_x11_get_default_root_xwindow (), False,
+                    SubstructureRedirectMask | SubstructureNotifyMask, &xev);
+        XCloseDisplay( display );
+
+    }
+    else
+    {
+        // show popup menu requesting for actions
+        if ( !power_menu )
+        {
+            power_menu = gtk_menu_new();
+            GtkWidget* lock = gtk_menu_item_new_with_label( "Lock" );
+            g_signal_connect( G_OBJECT(lock), "activate", 
G_CALLBACK(neod_buttonactions_popup_selected_lock), NULL );
+            gtk_menu_shell_append( GTK_MENU_SHELL(power_menu), lock );
+            GtkWidget* flightmode = gtk_menu_item_new_with_label( "Flight 
Mode" );
+            gtk_menu_shell_append( GTK_MENU_SHELL(power_menu), flightmode );
+            GtkWidget* profilelist = gtk_menu_item_new_with_label( "<Profile 
List>" );
+            gtk_menu_shell_append( GTK_MENU_SHELL(power_menu), profilelist );
+            GtkWidget* restartUI = gtk_menu_item_new_with_label( "Restart UI" 
);
+            g_signal_connect( G_OBJECT(restartUI), "activate", 
G_CALLBACK(neod_buttonactions_popup_selected_restartUI), NULL );
+            GtkWidget* reboot = gtk_menu_item_new_with_label( "Reboot" );
+            g_signal_connect( G_OBJECT(reboot), "activate", 
G_CALLBACK(neod_buttonactions_popup_selected_reboot), NULL );
+            GtkWidget* poweroff = gtk_menu_item_new_with_label( "Power Off" );
+            g_signal_connect( G_OBJECT(poweroff), "activate", 
G_CALLBACK(neod_buttonactions_popup_selected_poweroff), NULL );
+            gtk_menu_shell_append( GTK_MENU_SHELL(power_menu), poweroff );
+            gtk_widget_show_all( GTK_WIDGET(power_menu) );
+        }
+        gtk_menu_popup( GTK_MENU(power_menu), NULL, NULL, 
neod_buttonactions_popup_positioning_cb, 0, 0, GDK_CURRENT_TIME );
+    }
+    return FALSE;
+}
+
+gboolean neod_buttonactions_touchscreen_cb( GIOChannel *source, GIOCondition 
condition, gpointer data )
+{
+    g_debug( "mainmenu touchscreen event" );
+
+    struct input_event event;
+    int size = read( g_io_channel_unix_get_fd( source ), &event, sizeof( 
struct input_event ) );
+
+    if ( event.type == 1 && event.code == TOUCHSCREEN_BUTTON_KEYCODE )
+    {
+        if ( event.value == 1 ) /* pressed */
+        {
+            g_debug( "stylus pressed" );
+            neod_buttonactions_sound_play( "touchscreen" );
+        }
+        else if ( event.value == 0 ) /* released */
+        {
+            g_debug( "stylus released" );
+        }
+
+        neod_buttonactions_powersave_reset();
+        if ( power_state != NORMAL )
+        {
+            neod_buttonactions_set_display( 100 );
+            power_state = NORMAL;
+        }
+    }
+    return TRUE;
+}
+
+void neod_buttonactions_powersave_reset()
+{
+    g_debug( "mainmenu powersave reset" );
+    if ( powersave_timer1 != -1 )
+        g_source_remove( powersave_timer1 );
+    if ( powersave_timer2 != -1 )
+        g_source_remove( powersave_timer2 );
+    if ( powersave_timer3 != -1 )
+        g_source_remove( powersave_timer3 );
+
+    //TODO load this from preferences
+    powersave_timer1 = g_timeout_add( 10 * 1000, (GSourceFunc) 
neod_buttonactions_powersave_timeout1, (gpointer)1 );
+    powersave_timer2 = g_timeout_add( 20 * 1000, (GSourceFunc) 
neod_buttonactions_powersave_timeout2, (gpointer)1 );
+    powersave_timer3 = g_timeout_add( 60 * 5 * 1000, (GSourceFunc) 
neod_buttonactions_powersave_timeout3, (gpointer)1 );
+}
+
+void neod_buttonactions_set_display( int brightness )
+{
+    g_debug( "mainmenu set display %d", brightness );
+    int fd = g_open( "/sys/class/backlight/gta01-bl/brightness", O_WRONLY, 0 );
+    if ( fd == -1 )
+        g_debug( "can't open backlight device: %s", strerror( errno ) );
+    else
+    {
+        char buf[10];
+        int numbytes = g_sprintf( buf, "%d\0", MAX_BRIGHTNESS / 100 * 
(brightness+1 ) );
+        write( fd, buf, numbytes );
+        close( fd );
+    }
+}
+
+gboolean neod_buttonactions_powersave_timeout1( guint timeout )
+{
+    g_debug( "mainmenu powersave timeout 1" );
+    //FIXME talk to neod
+    power_state = DISPLAY_DIM;
+    neod_buttonactions_set_display( 25 );
+    return FALSE;
+}
+
+gboolean neod_buttonactions_powersave_timeout2( guint timeout )
+{
+    g_debug( "mainmenu powersave timeout 2" );
+    //FIXME talk to neod
+    neod_buttonactions_set_display( 0 );
+    power_state = DISPLAY_OFF;
+    return FALSE;
+}
+
+gboolean neod_buttonactions_powersave_timeout3( guint timeout )
+{
+    g_debug( "mainmenu powersave timeout 3" );
+    //FIXME talk to neod
+    power_state = SUSPEND;
+    system( "/usr/bin/apm -s");
+    neod_buttonactions_powersave_reset();
+    neod_buttonactions_set_display( 100 );
+    power_state = NORMAL;
+    return FALSE;
+}
+
+void neod_buttonactions_sound_state_cb( pa_context* pac, void* userdata )
+{
+    g_debug( "mainmenu sound state callback. state = %d", 
pa_context_get_state( pac ) );
+    if ( pa_context_get_state( pac ) == PA_CONTEXT_READY )
+    {
+        neod_buttonactions_sound_play( "startup" );
+    }
+}
+
+void neod_buttonactions_sound_init()
+{
+    g_debug( "panel mainmenu sound init" );
+    pa_threaded_mainloop* mainloop = pa_threaded_mainloop_new();
+
+    if ( !mainloop )
+    {
+        printf( "couldn't create mainloop: %s", strerror( errno ) );
+        return;
+    }
+
+    pa_mainloop_api* mapi = pa_threaded_mainloop_get_api( mainloop );
+
+    pac = pa_context_new( mapi, "test client" );
+    if ( !pac )
+    {
+        printf( "couldn't create pa_context: %s", strerror( errno ) );
+        return;
+    }
+
+    pa_context_set_state_callback( pac, neod_buttonactions_sound_state_cb, 
NULL );
+    pa_context_connect( pac, NULL, 0, NULL );
+    pa_threaded_mainloop_start( mainloop );
+
+    g_debug( "sound init ok. threaded mainloop started" );
+}
+
+void neod_buttonactions_sound_play( const gchar* samplename )
+{
+    g_return_if_fail( pac );
+    pa_context_play_sample( pac,
+                            samplename,      // Name of my sample
+                            NULL,            // Use default sink
+                            PA_VOLUME_NORM,  // Full volume
+                            NULL,            // Don't need a callback
+                            NULL
+                           );
+
+}


Property changes on: trunk/src/target/OM-2007.2/daemons/neod/src/buttonactions.c
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/src/target/OM-2007.2/daemons/neod/src/buttonactions.h
===================================================================
--- trunk/src/target/OM-2007.2/daemons/neod/src/buttonactions.h 2007-08-04 
06:02:22 UTC (rev 2629)
+++ trunk/src/target/OM-2007.2/daemons/neod/src/buttonactions.h 2007-08-04 
10:36:33 UTC (rev 2630)
@@ -0,0 +1,40 @@
+/*
+ *  Authored by Michael 'Mickey' Lauer <[EMAIL PROTECTED]>
+ *
+ *  Copyright (C) 2007 OpenMoko, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Public License as published by
+ *  the Free Software Foundation; version 2.1 of the license.
+ *
+ *  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 Public License for more details.
+ */
+#ifndef BUTTONACTIONS_H
+#define BUTTONACTIONS_H
+
+#include <glib.h>
+#include <gdk/gdk.h>
+
+gboolean neod_buttonactions_input_prepare( GSource* source, gint* timeout );
+gboolean neod_buttonactions_input_check( GSource* source );
+gboolean neod_buttonactions_input_dispatch( GSource* source, GSourceFunc 
callback, gpointer data );
+
+gboolean neod_buttonactions_touchscreen_cb( GIOChannel *source, GIOCondition 
condition, gpointer data );
+
+gboolean neod_buttonactions_aux_timeout( guint timeout );
+gboolean neod_buttonactions_power_timeout( guint timeout );
+
+void neod_buttonactions_powersave_reset();
+
+gboolean neod_buttonactions_powersave_timeout1( guint timeout );
+gboolean neod_buttonactions_powersave_timeout2( guint timeout );
+gboolean neod_buttonactions_powersave_timeout3( guint timeout );
+
+void neod_buttonactions_sound_init();
+void neod_buttonactions_set_display( int brightness );
+void neod_buttonactions_sound_play( const gchar* samplename );
+
+#endif


Property changes on: trunk/src/target/OM-2007.2/daemons/neod/src/buttonactions.h
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: trunk/src/target/OM-2007.2/daemons/neod/src/neod-main.c
===================================================================
--- trunk/src/target/OM-2007.2/daemons/neod/src/neod-main.c     2007-08-04 
06:02:22 UTC (rev 2629)
+++ trunk/src/target/OM-2007.2/daemons/neod/src/neod-main.c     2007-08-04 
10:36:33 UTC (rev 2630)
@@ -1,5 +1,28 @@
+/*
+ *  Authored by Michael 'Mickey' Lauer <[EMAIL PROTECTED]>
+ *
+ *  Copyright (C) 2006-2007 OpenMoko Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Public License as published by
+ *  the Free Software Foundation; version 2 of the license.
+ *
+ *  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 Public License for more details.
+ */
+
+#include "buttonactions.h"
+
+#include <gtk/gtk.h>
+
 int main( int argc, char** argv )
 {
+    //FIXME add daemonizing
+    gtk_init( &argc, &argv );
+
+    gtk_main();
     return 1;
 }
 




--- End Message ---
--- Begin Message ---
Author: abraxa
Date: 2007-08-04 14:50:34 +0200 (Sat, 04 Aug 2007)
New Revision: 2631

Modified:
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/Makefile.am
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/main.c
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/main.h
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/mainwin.c
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/mainwin.h
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playback.c
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playback.h
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playlist.c
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playlist.h
Log:
Continued work on UI<->backend communication and gstreamer wrapping



Modified: 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/Makefile.am
===================================================================
--- 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/Makefile.am    
    2007-08-04 10:36:33 UTC (rev 2630)
+++ 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/Makefile.am    
    2007-08-04 12:50:34 UTC (rev 2631)
@@ -17,7 +17,8 @@
         $(OPENMOKO_CFLAGS) \
        $(OMP_DEFINES) \
         -I$(top_srcdir) \
-        -I$(top_srcdir)/intl
+        -I$(top_srcdir)/intl\
+       -g -DDEBUG
 
 INCLUDES = $(openmoko_mediaplayer_CFLAGS)
 

Modified: 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/main.c
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/main.c     
2007-08-04 10:36:33 UTC (rev 2630)
+++ trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/main.c     
2007-08-04 12:50:34 UTC (rev 2631)
@@ -140,6 +140,10 @@
 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);
 
@@ -158,10 +162,11 @@
        // Check whether playlist_position is valid
        if (!omp_playlist_set_current_track(omp_config->playlist_position))
        {
-               // Reset playlist state as it must have been modified since it 
was last loaded
+               // 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();
@@ -362,15 +367,12 @@
        signal(SIGSEGV, handler_sigsegfault);
        signal(SIGUSR1, handler_sigusr1);
 
-       // Load config and restore playback state
-       omp_config_restore_state();
-
        // Initialize playback, playlist and UI handling
        omp_main_window_create();
        omp_playback_init();
        omp_playlist_init();
        omp_main_connect_signals();
-       omp_main_update_track_info();
+       omp_config_restore_state();
        omp_main_window_show();
 
        gtk_main();
@@ -384,6 +386,7 @@
        omp_playback_free();
        omp_playlist_free();
        gst_deinit();
+       g_free(ui_image_path);
 
 #ifdef DEBUG_MEM_PROFILE
        g_mem_profile();

Modified: 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/main.h
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/main.h     
2007-08-04 10:36:33 UTC (rev 2630)
+++ trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/main.h     
2007-08-04 12:50:34 UTC (rev 2631)
@@ -52,7 +52,7 @@
 //     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
-       gint track_position;                                            ///< 
Position to resume playback from within the last played track
+       glong track_position;                                           ///< 
Position to resume playback from within the last played track
 };
 
 extern struct _omp_config *omp_config;

Modified: 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/mainwin.c
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/mainwin.c  
2007-08-04 10:36:33 UTC (rev 2630)
+++ trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/mainwin.c  
2007-08-04 12:50:34 UTC (rev 2631)
@@ -59,6 +59,8 @@
 
 GtkWidget *omp_main_window = NULL;
 
+gboolean omp_main_time_slider_can_update = TRUE;
+gboolean omp_main_time_slider_was_dragged = FALSE;
 
 
 /**
@@ -67,9 +69,6 @@
 void
 omp_application_terminate()
 {
-       // Free resources
-       g_free(ui_image_path);
-
        // Tell GTK to leave the message loop
        gtk_main_quit();
 }
@@ -190,7 +189,52 @@
        gtk_label_set_text(GTK_LABEL(main_widgets.title_label), title);
 }
 
+/**
+ * Gets called when the time slider's value got changed (yes, that means it 
gets called every second, too)
+ */
 void
+omp_main_time_slider_changed(GtkRange *range, gpointer data)
+{
+       if (omp_main_time_slider_was_dragged)
+       {
+               omp_main_time_slider_was_dragged = FALSE;
+
+               // Set new position and resume playback that was paused when 
dragging started
+               
omp_playback_set_track_position(gtk_range_get_value(GTK_RANGE(range)));
+
+               // Update UI right away
+               gtk_range_set_value(GTK_RANGE(main_widgets.time_hscale), 
omp_playback_get_track_position());
+       }
+}
+
+/**
+ * Gets called when the user starts dragging the time slider
+ */
+gboolean
+omp_main_time_slider_drag_start(GtkWidget *widget, GdkEventButton *event, 
gpointer user_data)
+{
+       while (gtk_events_pending()) gtk_main_iteration();
+
+       // Prevent UI callbacks from messing with the slider position
+       omp_main_time_slider_can_update = FALSE;
+}
+
+/**
+ * Gets called when the user stops dragging the time slider
+ */
+gboolean
+omp_main_time_slider_drag_stop(GtkWidget *widget, GdkEventButton *event, 
gpointer user_data)
+{
+       while (gtk_events_pending()) gtk_main_iteration();
+
+       // Allow UI callbacks to alter the the slider position again
+       omp_main_time_slider_can_update = TRUE;
+
+       // Notify the slider change callback that this time we indeed want to 
change position
+       omp_main_time_slider_was_dragged = TRUE;
+}
+
+void
 omp_shuffle_button_callback(GtkWidget* widget, gpointer data)
 {
 /*    if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
@@ -225,13 +269,46 @@
 }
 
 /**
+ * Event handler for the Fast Forward button
+ */
+void
+omp_main_button_fast_forward_callback()
+{
+       // Set new position and resume playback that was paused when dragging 
started
+       
omp_playback_set_track_position(omp_playback_get_track_position()+BUTTON_SEEK_DISTANCE);
+
+       // Update UI right away
+       gtk_range_set_value(GTK_RANGE(main_widgets.time_hscale), 
omp_playback_get_track_position());
+}
+
+/**
+ * Event handler for the Rewind button
+ */
+void
+omp_main_button_rewind_callback()
+{
+       // Set new position and resume playback that was paused when dragging 
started
+       
omp_playback_set_track_position(omp_playback_get_track_position()-BUTTON_SEEK_DISTANCE);
+
+       // Update UI right away
+       gtk_range_set_value(GTK_RANGE(main_widgets.time_hscale), 
omp_playback_get_track_position());
+}
+
+/**
  * Event handler for the Play/Pause button
- * @todo State change, etc
+ * @todo Pixmap change
  */
 void
 omp_main_button_play_pause_callback()
 {
-       omp_playback_play();
+       if (omp_playback_get_state() != OMP_PLAYBACK_STATE_PLAYING)
+       {
+               omp_playback_play();
+
+       } else {
+
+               omp_playback_pause();
+       }
 }
 
 /**
@@ -282,7 +359,6 @@
 
        image = gtk_image_new_from_icon_name(image_name, 36);
        gtk_container_add(GTK_CONTAINER(button), GTK_WIDGET(image));
-       g_object_unref(image);
 
        return button;
 }
@@ -388,9 +464,11 @@
        gtk_scale_set_draw_value(GTK_SCALE(main_widgets.time_hscale), FALSE);
        GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(main_widgets.time_hscale), 
GTK_CAN_FOCUS);
        gtk_widget_set_size_request(GTK_WIDGET(main_widgets.time_hscale), 338, 
35);
+       gtk_range_set_update_policy(GTK_RANGE(main_widgets.time_hscale), 
GTK_UPDATE_DISCONTINUOUS);
        gtk_range_set_value(GTK_RANGE(main_widgets.time_hscale), 0.0);
-//    g_signal_connect(G_OBJECT(time_hscale), "change_value",
-//                 G_CALLBACK(omp_main_set_time), NULL);
+       g_signal_connect(G_OBJECT(main_widgets.time_hscale), "value_changed",   
                                G_CALLBACK(omp_main_time_slider_changed), NULL);
+       g_signal_connect(G_OBJECT(main_widgets.time_hscale), 
"button-press-event",              G_CALLBACK(omp_main_time_slider_drag_start), 
NULL);
+       g_signal_connect(G_OBJECT(main_widgets.time_hscale), 
"button-release-event",    G_CALLBACK(omp_main_time_slider_drag_stop), NULL);
        gtk_container_add(GTK_CONTAINER(alignment), 
GTK_WIDGET(main_widgets.time_hscale));
 
        // --- --- --- --- --- Middle hbox --- --- --- --- ---
@@ -483,7 +561,7 @@
        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", NULL);
+       button = omp_button_create("gtk-media-rewind-ltr", 
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);
 
@@ -493,7 +571,7 @@
        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", NULL);
+       button = omp_button_create("gtk-media-forward-ltr", 
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);
 
@@ -536,6 +614,7 @@
        // Show everything but the window itself
        gtk_widget_show_all(GTK_WIDGET(bg_muxer));
 
+
        return;
 }
 
@@ -547,20 +626,23 @@
 void
 omp_main_connect_signals()
 {
-       g_signal_connect(G_OBJECT(omp_main_window), OMP_EVENT_PREV_TRACK, 
G_CALLBACK(omp_main_update_track_info), NULL);
-       g_signal_connect(G_OBJECT(omp_main_window), OMP_EVENT_NEXT_TRACK, 
G_CALLBACK(omp_main_update_track_info), NULL);
+       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_POSITION_CHANGED,        
G_CALLBACK(omp_main_update_track_position), NULL);
 }
 
-
 /**
  * Evaluates current track information and updates the config/UI if necessary
+ * @note This function only checks elements that don't change too often - for 
the rest we have specialized functions below
  */
 void
-omp_main_update_track_info()
+omp_main_update_track_change()
 {
        static gint old_track_count = 0;
        static gint old_track_id = 0;
+       static gulong old_track_length = 0;
 
+       gulong track_length, track_position;
        gchar *text;
 
        // Track id/track count changed?
@@ -572,12 +654,68 @@
                // Update config
                omp_config_update();
 
-               // Update UI
+               // Update label
                text = g_strdup_printf(WIDGET_CAPTION_TRACK_NUM, 
omp_playlist_current_track_id+1, omp_playlist_track_count);
                gtk_label_set_text(GTK_LABEL(main_widgets.track_number_label), 
text);
                g_free(text);
        }
 
+       // Got a track length change?
+       track_length = omp_playback_get_track_length();
 
+       if (track_length != old_track_length)
+       {
+               old_track_length = track_length;
+               track_position = omp_playback_get_track_position();
+
+               // Set new time slider increments
+               gtk_range_set_increments(GTK_RANGE(main_widgets.time_hscale), 
track_length/10, track_length/10);
+
+               // Update label and slider
+               text = g_strdup_printf(WIDGET_CAPTION_TRACK_TIME,
+                       track_position / 60, track_position % 60,
+                       track_length / 60, track_length % 60);
+               gtk_label_set_text(GTK_LABEL(main_widgets.time_label), text);
+               g_free(text);
+
+               if (omp_main_time_slider_can_update)
+               {
+                       
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);
+               }
+       }
 }
 
+/**
+ * Updates the UI if the playback position changed
+ */
+void
+omp_main_update_track_position()
+{
+       static gulong old_track_position = 0;
+
+       gulong track_position, track_length;
+       gchar *text;
+
+       // Got a track length change?
+       track_position = omp_playback_get_track_position();
+       {
+               old_track_position = track_position;
+               track_length = omp_playback_get_track_length();
+
+               // Update UI
+               text = g_strdup_printf(WIDGET_CAPTION_TRACK_TIME,
+                       track_position / 60, track_position % 60,
+                       track_length / 60, track_length % 60);
+               gtk_label_set_text(GTK_LABEL(main_widgets.time_label), text);
+               g_free(text);
+
+               if (omp_main_time_slider_can_update)
+               {
+                       
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-mediaplayer/src/mainwin.h
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/mainwin.h  
2007-08-04 10:36:33 UTC (rev 2630)
+++ trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/mainwin.h  
2007-08-04 12:50:34 UTC (rev 2631)
@@ -33,6 +33,9 @@
 #define WIDGET_CAPTION_TRACK_NUM "%.3d / %.3d"
 #define WIDGET_CAPTION_VOLUME "%d%%"
 
+// 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();
@@ -42,6 +45,7 @@
 void omp_main_window_create();
 void omp_main_connect_signals();
 
-void omp_main_update_track_info();
+void omp_main_update_track_change();
+void omp_main_update_track_position();
 
 #endif

Modified: 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playback.c
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playback.c 
2007-08-04 10:36:33 UTC (rev 2630)
+++ trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playback.c 
2007-08-04 12:50:34 UTC (rev 2631)
@@ -30,9 +30,9 @@
 #include "mainwin.h"
 
 GstElement *omp_gst_playbin = NULL;
+guint omp_playback_ui_timeout = 0;
+gboolean omp_playback_ui_timeout_halted;
 
-
-
 /**
  * Initializes gstreamer by setting up pipe, message hooks and bins
  */
@@ -48,7 +48,9 @@
        }
 
        // Create the signals we'll emit
-       g_signal_new(OMP_EVENT_PLAYBACK_EOS, G_TYPE_OBJECT, 0, 0, 0, NULL, 
g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL);
+       g_signal_new(OMP_EVENT_PLAYBACK_EOS,                                    
                        G_TYPE_OBJECT, 0, 0, 0, NULL, 
g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL);
+       g_signal_new(OMP_EVENT_PLAYBACK_STATUS_CHANGED,                 
G_TYPE_OBJECT, 0, 0, 0, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, 
NULL);
+       g_signal_new(OMP_EVENT_PLAYBACK_POSITION_CHANGED,               
G_TYPE_OBJECT, 0, 0, 0, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, 
NULL);
 
        // Set up gstreamer pipe and bins
        omp_gst_playbin = gst_element_factory_make("playbin", "play");
@@ -81,6 +83,7 @@
 
 /**
  * Attempts to load a track from an URI
+ * @return TRUE if successful, FALSE if failed
  */
 gboolean
 omp_playback_load_track_from_uri(gchar *uri)
@@ -91,59 +94,171 @@
                omp_playback_init();
        }
 
-       // DEBUG
-       g_printf("Loading %s\n", uri);
+       #ifdef DEBUG
+               g_printf("Loading track: %s\n", uri);
+       #endif
 
        gst_element_set_state(omp_gst_playbin, GST_STATE_NULL);
        g_object_set(G_OBJECT(omp_gst_playbin), "uri", uri, NULL);
        gst_element_set_state(omp_gst_playbin, GST_STATE_PAUSED);
+
+       return (gst_element_set_state(omp_gst_playbin, GST_STATE_PAUSED) != 
GST_STATE_CHANGE_FAILURE);
 }
 
 /**
+ * This callback gets called at least once per second if a track is playing
+ */
+static gboolean
+omp_playback_ui_timeout_callback(gpointer data)
+{
+       g_signal_emit_by_name(G_OBJECT(omp_main_window), 
OMP_EVENT_PLAYBACK_POSITION_CHANGED);
+       
+       if (omp_playback_ui_timeout_halted)
+       {
+               // Reset the timeout ID so we can prevent race conditions
+               omp_playback_ui_timeout = 0;
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+/**
  * Starts playback of the current stream
  */
 void
 omp_playback_play()
 {
-       // DEBUG
-       g_print("Starting playback\n");
+       #ifdef DEBUG
+               g_print("Starting playback\n");
+       #endif
 
+       // 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
+       // don't want to add another callback since we would have two then
+       omp_playback_ui_timeout_halted = FALSE;
+
+       if (!omp_playback_ui_timeout)
+       {
+               omp_playback_ui_timeout = 
g_timeout_add(PLAYBACK_UI_UPDATE_INTERVAL, omp_playback_ui_timeout_callback, 
NULL);
+       }
 }
 
 /**
+ * Suspends playback of the current stream
+ */
+void
+omp_playback_pause()
+{
+       #ifdef DEBUG
+               g_print("Suspending playback\n");
+       #endif
+
+       // 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?
  */
 gint
 omp_playback_get_state()
 {
        GstState state;
-       GstSystemClock *system_clock;
+       GstClock *clock;
 
        // Poll state with an immediate timeout
-       system_clock = gst_system_clock_obtain();
-       gst_element_get_state(GST_OBJECT(omp_gst_playbin), &state, NULL, 
gst_clock_get_time(system_clock));
-       gst_object_unref(system_clock);
+       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);
 
-       // The NULL element state is no different from READY for more abstract 
layers
-       if (state == GST_STATE_NULL)
+       // The NULL and READY element states are no different from PAUSED for 
more abstract layers
+       if ( (state == GST_STATE_NULL) || (state == GST_STATE_READY) )
        {
-               state = GST_STATE_READY;
+               state = GST_STATE_PAUSED;
        }
 
        return (gint)state;
 }
 
 /**
+ * Returns the number of seconds that the track has been playing so far
+ */
+gulong
+omp_playback_get_track_position()
+{
+       GstFormat format = GST_FORMAT_TIME;
+       gint64 position;
+
+       if (!omp_gst_playbin)
+       {
+               return 0;
+       }
+
+       // Return 0 if function returns FALSE, position otherwise
+       return (gst_element_query_position(omp_gst_playbin, &format, 
&position)) ? (position/GST_SECOND) : 0;
+}
+
+/**
+ * Sets the playback position of the currently loaded track
+ */
+void
+omp_playback_set_track_position(glong position)
+{
+       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);
+
+       g_signal_emit_by_name(G_OBJECT(omp_main_window), 
OMP_EVENT_PLAYBACK_POSITION_CHANGED);
+}
+
+/**
+ * Returns the current track's playing length
+ */
+gulong
+omp_playback_get_track_length()
+{
+       GstFormat format = GST_FORMAT_TIME;
+       gint64 length;
+
+       if (!omp_gst_playbin)
+       {
+               return 0;
+       }
+
+       // Return 0 if function returns FALSE, track length otherwise
+       return (gst_element_query_duration(omp_gst_playbin, &format, &length)) 
? (length/GST_SECOND) : 0;
+}
+
+/**
  * Handles gstreamer's end-of-stream notification
  */
 static gboolean
 omp_gst_message_eos(GstBus *bus, GstMessage *message, gpointer data)
 {
-       // DEBUG
-       g_printf("End of stream reached.\n");
+       #ifdef DEBUG
+               g_printf("End of stream reached.\n");
+       #endif
 
-       gst_element_set_state(omp_gst_playbin, GST_STATE_NULL);
+       // Reset playback engine
+       gst_element_set_state(omp_gst_playbin, GST_STATE_READY);
+       omp_playback_set_track_position(0);
+
        g_signal_emit_by_name(G_OBJECT(omp_main_window), 
OMP_EVENT_PLAYBACK_EOS);
 
        return TRUE;
@@ -157,9 +272,12 @@
 {
        GError *error;
 
-       gst_message_parse_error(message, &error, NULL);
-       g_printerr("gstreamer error: %s\n", error->message);
-       g_error_free(error);
+       #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
 
        return TRUE;
 }
@@ -172,10 +290,12 @@
 {
        GError *error;
 
-       gst_message_parse_error(message, &error, NULL);
-       g_printerr("gstreamer warning: %s\n", error->message);
-       g_error_free(error);
+       #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
 
        return TRUE;
 }
-

Modified: 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playback.h
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playback.h 
2007-08-04 10:36:33 UTC (rev 2630)
+++ trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playback.h 
2007-08-04 12:50:34 UTC (rev 2631)
@@ -30,12 +30,15 @@
 #include <gst/gst.h>
 
 #define OMP_EVENT_PLAYBACK_EOS "playback_end_of_stream"
+#define OMP_EVENT_PLAYBACK_STATUS_CHANGED "playback_status_change"
+#define OMP_EVENT_PLAYBACK_POSITION_CHANGED "playback_position_change"
 
 // Player states masking the gstreamer states so we can be more abstract
-#define OMP_PLAYBACK_STATE_READY GST_STATE_READY
 #define OMP_PLAYBACK_STATE_PAUSED GST_STATE_PAUSED
 #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
 
 void omp_playback_init();
 void omp_playback_free();
@@ -43,7 +46,11 @@
 gboolean omp_playback_load_track_from_uri(gchar *uri);
 
 void omp_playback_play();
+void omp_playback_pause();
 gint omp_playback_get_state();
+gulong omp_playback_get_track_position();
+void omp_playback_set_track_position(glong position);
+gulong omp_playback_get_track_length();
 
 static gboolean omp_gst_message_eos(GstBus *bus, GstMessage *message, gpointer 
data);
 static gboolean omp_gst_message_error(GstBus *bus, GstMessage *message, 
gpointer data);

Modified: 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playlist.c
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playlist.c 
2007-08-04 10:36:33 UTC (rev 2630)
+++ trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playlist.c 
2007-08-04 12:50:34 UTC (rev 2631)
@@ -62,8 +62,7 @@
        g_signal_connect(G_OBJECT(omp_main_window), OMP_EVENT_PLAYBACK_EOS, 
G_CALLBACK(omp_playlist_process_eos_event), NULL);
 
        // Create the signals we emit: no params, no return value
-       g_signal_new(OMP_EVENT_PREV_TRACK, G_TYPE_OBJECT, 0, 0, 0, NULL, 
g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL);
-       g_signal_new(OMP_EVENT_NEXT_TRACK, G_TYPE_OBJECT, 0, 0, 0, NULL, 
g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL);
+       g_signal_new(OMP_EVENT_PLAYLIST_TRACK_CHANGED, G_TYPE_OBJECT, 0, 0, 0, 
NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL);
 }
 
 /**
@@ -93,6 +92,14 @@
 void
 omp_playlist_load(gchar *playlist_file)
 {
+       // Free the track history's memory by deleting the first element until 
the list is empty
+       while (omp_track_history)
+       {
+               g_free(omp_track_history->data);
+               omp_track_history = g_slist_delete_link(omp_track_history, 
omp_track_history);
+       }
+
+       // Let XSPF clean up, too
        if (omp_playlist)
        {
                spiff_free(omp_playlist);
@@ -124,8 +131,9 @@
        struct spiff_track *track;
        gint track_num = 0;
 
-       // DEBUG
-       g_printf("Setting current track to #%d\n", playlist_pos);
+       #ifdef DEBUG
+               g_printf("Setting current track to #%d\n", playlist_pos);
+       #endif
 
        if (!omp_playlist)
        {
@@ -146,6 +154,9 @@
        if (position_valid)
        {
                omp_playlist_track_count = track_num;
+
+               // Emit signal to update UI and the like
+               g_signal_emit_by_name(G_OBJECT(omp_main_window), 
OMP_EVENT_PLAYLIST_TRACK_CHANGED);
        }
 
        return position_valid;
@@ -161,6 +172,7 @@
 {
        struct omp_track_history_entry *history_entry;
        struct spiff_track *track;
+       gboolean was_playing;
        gboolean is_new_track = FALSE;
 
        if (!omp_playlist_current_track)
@@ -168,6 +180,34 @@
                return;
        }
 
+       // If track playing time is >= 10 seconds we just jump back to the 
beginning of the track
+       if (omp_playback_get_track_position() >= 10)
+       {
+               omp_playback_set_track_position(0);
+               return TRUE;
+       }
+
+       // Get player state so we can continue playback if necessary
+       was_playing = (omp_playback_get_state() == OMP_PLAYBACK_STATE_PLAYING);
+
+try_again:
+
+       #ifdef DEBUG
+               if (omp_track_history)
+               {
+                       GSList *list;
+                       g_printf("--- Track History:\n");
+                       list = omp_track_history;
+                       while (list)
+                       {
+                               history_entry = list->data;
+                               g_printf("- %s\n", 
history_entry->track->locations->value);
+                               list = g_slist_next(list);
+                       }
+                       g_printf("---\n");
+               }
+       #endif
+
        // Do we have tracks in the history to go back to?
        if (omp_track_history)
        {
@@ -197,7 +237,7 @@
                        // We only found the previous track if we're not at the 
end of the list
                        if (track->next)
                        {
-                               omp_playlist_current_track              = track;
+                               omp_playlist_current_track = track;
                                omp_playlist_current_track_id--;
                        }
                }
@@ -206,7 +246,19 @@
        if (is_new_track)
        {
                // Emit signal to update UI and the like
-               g_signal_emit_by_name(G_OBJECT(omp_main_window), 
OMP_EVENT_PREV_TRACK);
+               g_signal_emit_by_name(G_OBJECT(omp_main_window), 
OMP_EVENT_PLAYLIST_TRACK_CHANGED);
+
+               // Load track and start playing if needed
+               if (omp_playlist_load_current_track())
+               {
+                       if (was_playing) omp_playback_play();
+
+               } else {
+
+                       // Uh-oh, track failed to load - let's find another 
one, shall we?
+                       is_new_track = FALSE;
+                       goto try_again;
+               }
        }
 
        return is_new_track;
@@ -237,8 +289,8 @@
 
        // Prepare the history entry - if we don't need it we'll just free it 
again
        history_entry = g_new(struct omp_track_history_entry, 1);
-       history_entry->track = omp_playlist_current_track;
-       history_entry->track_id = omp_playlist_current_track_id;
+       history_entry->track            = omp_playlist_current_track;
+       history_entry->track_id = omp_playlist_current_track_id;
 
        // Do we have a track to play?
        if (omp_playlist_current_track->next)
@@ -256,7 +308,7 @@
                omp_track_history = g_slist_prepend(omp_track_history, 
(gpointer)history_entry);
 
                // Emit signal to update UI and the like
-               g_signal_emit_by_name(G_OBJECT(omp_main_window), 
OMP_EVENT_NEXT_TRACK);
+               g_signal_emit_by_name(G_OBJECT(omp_main_window), 
OMP_EVENT_PLAYLIST_TRACK_CHANGED);
 
                // Load track and start playing if needed
                if (omp_playlist_load_current_track())

Modified: 
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playlist.h
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playlist.h 
2007-08-04 10:36:33 UTC (rev 2630)
+++ trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playlist.h 
2007-08-04 12:50:34 UTC (rev 2631)
@@ -29,13 +29,8 @@
 
 #include <spiff/spiff_c.h>
 
-#define OMP_EVENT_PREV_TRACK "prev_track"
-#define OMP_EVENT_NEXT_TRACK "next_track"
+#define OMP_EVENT_PLAYLIST_TRACK_CHANGED "playlist_track_changed"
 
-
-extern struct _omp_playlist_events omp_playlist_events;
-
-
 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