// stopish.c
//
-// Copyright 2009 Michael Cronenworth <mike@cchtml.com>
+// Copyright 2010 Michael Cronenworth <mike@cchtml.com>
//
// 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
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
// MA 02110-1301, USA.
-
#include <string.h>
#include <stdlib.h>
#include <sys/time.h>
-
#include <gtk/gtk.h>
-#include <libosso.h>
+#include <hildon/hildon.h>
+#include <dbus/dbus.h>
+#include <mce/mode-names.h>
+#include <mce/dbus-names.h>
+#define MCE_SIGNAL_MATCH "type='signal'," \
+ "interface='" MCE_SIGNAL_IF "'," \
+ "member='" MCE_DEVICE_ORIENTATION_SIG "'"
+
+#include "stopish.h"
+
+// Application data struct
+typedef struct _AppData AppData;
+struct _AppData {
+ GtkWindow *main_window;
+ GtkWindow *countdown_window;
+ osso_context_t *osso_context;
+ DBusConnection *system_bus;
+};
+
+
+static AppData appdata;
+static int stopishMode = STOPISH_MODE_START;
+static int stopishOrientation = STOPISH_LANDSCAPE;
+static int stopishType = STOPISH_TYPE_STOPWATCH;
-static GtkWidget *timerLabel = NULL;
-static int stopishMode = 0; // 0 = Start, 1 = Stop
-static int timerHandle = -1;
-static int timerStartTime = 0;
-static int timeTicks = 0;
//Prototypes
gint dbus_callback( const gchar *interface, const gchar *method,
GArray *arguments, gpointer data, osso_rpc_t *retval );
-GtkWindow *stopish_new( void );
-static void start_cb( GtkButton* button, gpointer data );
+static void main_menu( GtkWindow *window );
+static void change_type_cb( GtkButton* button, gpointer data );
static void close_cb( GtkButton* button, gpointer data );
-static gint timeout_cb( gpointer data );
-static int current_time( void );
+static void accelerometer_enable( void );
+static void accelerometer_disable( void );
+static DBusHandlerResult mce_filter_func( DBusConnection * connection,
+ DBusMessage * message,
+ void *data );
int main( int argc, char *argv[] )
{
- osso_context_t *ctxt;
osso_return_t ret;
- GtkWindow *window;
+ HildonProgram *program;
- //printf( "stopish: starting up\n" );
-
- ctxt = osso_initialize( "com.nokia.stopish", PACKAGE_VERSION, TRUE, NULL );
- if ( ctxt == NULL ) {
+ appdata.osso_context = osso_initialize( "com.nokia.stopish",
+ PACKAGE_VERSION, TRUE, NULL );
+ if ( appdata.osso_context == NULL ) {
fprintf( stderr, "osso_initialize failed.\n" );
exit( 1 );
}
- gtk_init( &argc, &argv );
-
- window = stopish_new( );
+ // initialize Hildonized GTK libraries
+ hildon_gtk_init( &argc, &argv );
+ program = hildon_program_get_instance( );
+
+ // create main window
+ appdata.main_window = stopish_stopwatch_new( );
+
+ // attach signals to main window
+ g_signal_connect( G_OBJECT( appdata.main_window ), "destroy",
+ G_CALLBACK( close_cb ), appdata.main_window );
+ g_signal_connect( G_OBJECT( appdata.main_window ), "focus-in-event",
+ G_CALLBACK( stopish_focus_in_cb ), NULL );
+ g_signal_connect( G_OBJECT( appdata.main_window ), "focus-out-event",
+ G_CALLBACK( stopish_focus_out_cb ), NULL );
+
+ // setup main menu
+ main_menu( appdata.main_window );
+
+ hildon_program_add_window( program, HILDON_WINDOW( appdata.main_window ) );
+
+ // Connect to session bus, add a match rule, install filter callback
+ appdata.system_bus = osso_get_sys_dbus_connection( appdata.osso_context );
+ if ( appdata.system_bus ) {
+ dbus_bus_add_match( appdata.system_bus, MCE_SIGNAL_MATCH, NULL );
+ dbus_connection_add_filter( appdata.system_bus,
+ mce_filter_func,
+ NULL, NULL );
+ }
+ else
+ g_printerr( "ERROR: Cannot connect to system dbus.\n" );
- ret = osso_rpc_set_default_cb_f( ctxt, dbus_callback, window );
+ ret = osso_rpc_set_default_cb_f( appdata.osso_context,
+ dbus_callback, appdata.main_window );
if ( ret != OSSO_OK ) {
fprintf( stderr, "osso_rpc_set_default_cb_f failed: %d.\n", ret );
exit( 1 );
}
-GtkWindow *stopish_new( void )
+void stopish_about_cb( GtkButton* button, gpointer data )
+{
+ GdkPixbuf *logo;
+ GError *error;
+ GtkWidget *dialog;
+ char *authors[2];
+
+ authors[0] = strdup( "Michael Cronenworth" );
+ authors[1] = NULL;
+
+ dialog = gtk_about_dialog_new( );
+
+ gtk_about_dialog_set_program_name( GTK_ABOUT_DIALOG( dialog ),
+ "Stopish" );
+ gtk_about_dialog_set_version( GTK_ABOUT_DIALOG( dialog ),
+ STOPISH_VERSION_STR );
+ gtk_about_dialog_set_authors( GTK_ABOUT_DIALOG( dialog ),
+ ( const char ** ) authors );
+ logo = gdk_pixbuf_new_from_file( "/usr/share/icons/hicolor/40x40/hildon/stopish.png",
+ &error );
+ gtk_about_dialog_set_logo( GTK_ABOUT_DIALOG( dialog ),
+ logo );
+
+ gtk_dialog_run( GTK_DIALOG( dialog ) );
+
+ gtk_widget_destroy( dialog );
+ free( authors[0] );
+}
+
+
+int stopish_get_mode( void )
+{
+ return stopishMode;
+}
+
+
+void stopish_set_mode( int newMode )
+{
+ stopishMode = newMode;
+}
+
+
+int stopish_get_type( void )
+{
+ return stopishType;
+}
+
+
+void stopish_set_type( int newType )
+{
+ stopishType = newType;
+}
+
+
+int stopish_get_orientation( void )
{
- GtkWidget *window, *hBox, *label, *button;
- GtkWidget *vBox, *vBox0;
+ return stopishOrientation;
+}
- window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
- gtk_container_set_border_width( GTK_CONTAINER( window ), 20 );
+gboolean stopish_focus_in_cb( GtkWidget *widget, GdkEventFocus *event,
+ gpointer data )
+{
+ // enable accelerometer hardware for portrait mode support
+ accelerometer_enable( );
- gtk_window_set_title( GTK_WINDOW( window ), "Stopish" );
+ return FALSE;
+}
- g_signal_connect( G_OBJECT( window ), "destroy",
- G_CALLBACK( close_cb ), window );
- vBox = gtk_vbox_new( FALSE, 10 );
+gboolean stopish_focus_out_cb( GtkWidget *widget, GdkEventFocus *event,
+ gpointer data )
+{
+ // disable accelerometer for battery savings
+ accelerometer_disable( );
- label = gtk_label_new( "Stopish - The Stopwatch" );
- gtk_box_pack_start( GTK_BOX( vBox ), label, FALSE, FALSE, 0 );
+ return FALSE;
+}
- hBox = gtk_hbox_new( FALSE, 10 );
- // stop watch area
- timerLabel = gtk_label_new( NULL );
- gtk_label_set_markup( GTK_LABEL( timerLabel ), "<big>00:00:00.0</big>" );
- gtk_container_add( GTK_CONTAINER( hBox ), timerLabel );
+static void main_menu( GtkWindow *window )
+{
+ HildonAppMenu *menu;
+ GtkWidget *button, *radio;
- // button area
- vBox0 = gtk_vbox_new( FALSE, 10 );
+ menu = ( HildonAppMenu * ) hildon_app_menu_new( );
- // close button
- button = gtk_button_new( );
- label = gtk_label_new( "Start" );
- gtk_container_add( GTK_CONTAINER( button ), label );
- g_signal_connect( G_OBJECT( button ), "clicked",
- G_CALLBACK( start_cb ), label );
- gtk_box_pack_start( GTK_BOX( vBox0 ), button, FALSE, FALSE, 0 );
+ button = gtk_button_new_with_label( "Countdown" );
+ g_signal_connect_after( G_OBJECT( button ), "clicked",
+ G_CALLBACK( change_type_cb ), NULL );
+ hildon_app_menu_append( menu, GTK_BUTTON( button ) );
- // start stopwatch button
- button = gtk_button_new_with_label( "Close" );
- g_signal_connect( G_OBJECT( button ), "clicked",
- G_CALLBACK( close_cb ), window );
- gtk_box_pack_start( GTK_BOX( vBox0 ), button, FALSE, FALSE, 0 );
+ button = gtk_button_new_with_label( "About" );
+ g_signal_connect_after( G_OBJECT( button ), "clicked",
+ G_CALLBACK( stopish_about_cb ), NULL );
+ hildon_app_menu_append( menu, GTK_BUTTON( button ) );
- gtk_container_add( GTK_CONTAINER( hBox ), vBox0 );
+ // Hour preference
+ radio = gtk_radio_button_new_with_label( NULL, "Hour" );
+ gtk_toggle_button_set_mode( GTK_TOGGLE_BUTTON( radio ), FALSE );
+ g_signal_connect_after( G_OBJECT( radio ), "clicked",
+ G_CALLBACK( stopish_stopwatch_perf_timer_hour ), NULL );
+ hildon_app_menu_add_filter( menu, GTK_BUTTON( radio ) );
- gtk_container_add( GTK_CONTAINER( vBox ), hBox );
+ // Minute preference
+ radio = gtk_radio_button_new_with_label_from_widget( GTK_RADIO_BUTTON( radio ), "Minute" );
+ gtk_toggle_button_set_mode( GTK_TOGGLE_BUTTON ( radio ), FALSE );
+ g_signal_connect_after( G_OBJECT( radio ), "clicked",
+ G_CALLBACK( stopish_stopwatch_perf_timer_minute ), NULL );
+ hildon_app_menu_add_filter( menu, GTK_BUTTON( radio ) );
- gtk_container_add( GTK_CONTAINER( window ), vBox );
+ // default to minute
+ gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( radio ), TRUE );
- gtk_widget_show_all( window );
+ gtk_widget_show_all( GTK_WIDGET( menu ) );
- return GTK_WINDOW( window );
+ hildon_window_set_app_menu( HILDON_WINDOW( window ), menu );
}
-static void start_cb( GtkButton* button, gpointer data )
+static void change_type_cb( GtkButton* button, gpointer data )
{
- if ( stopishMode == 0 ) {
- // set label text and add timer handle
- gtk_label_set_text( GTK_LABEL( data ), "Stop" );
- stopishMode = 1;
- timerHandle = g_timeout_add( 100, timeout_cb, NULL );
- timerStartTime = current_time( ) - timeTicks;
- }
- else {
- // set label text and remove timer handle
- gtk_label_set_text( GTK_LABEL( data ), "Start" );
- stopishMode = 0;
- timerStartTime = 0;
- timeTicks = 0;
- gtk_label_set_markup( GTK_LABEL( timerLabel ),
- "<big>00:00:00.0</big>" );
- g_source_remove( timerHandle );
- }
+ stopish_stopwatch_reset( );
+ stopishType = STOPISH_TYPE_COUNTDOWN;
+ stopish_countdown_new( );
}
static void close_cb( GtkButton* button, gpointer data )
{
+ // disable accelerometer for battery savings
+ accelerometer_disable( );
+
// destroy main window and exit gtk main loop
gtk_widget_destroy( GTK_WIDGET( data ) );
gtk_main_quit( );
}
-static gint timeout_cb( gpointer data )
+static void accelerometer_enable( void )
{
- static char timeBuffer[64];
- int h, m, s, ss, currentTime;
-
- // get current time
- currentTime = current_time( );
-
- // calculate time format
- timeTicks = ( currentTime - timerStartTime );
- ss = timeTicks % 10;
- s = timeTicks / 10;
- m = s / 60;
- s = s % 60;
- h = m / 60;
- m = m % 60;
+ if ( osso_rpc_run_system( appdata.osso_context, MCE_SERVICE,
+ MCE_REQUEST_PATH, MCE_REQUEST_IF,
+ "req_accelerometer_enable", NULL,
+ DBUS_TYPE_INVALID ) != OSSO_OK ) {
+ g_printerr("WARN: Cannot enable accelerometers\n");
+ }
+}
- // print to screen
- sprintf( timeBuffer, "<big>%.02d:%.02d:%.02d.%.1d</big>", h, m, s, ss);
- gtk_label_set_markup( GTK_LABEL( timerLabel ), timeBuffer );
- return TRUE;
+static void accelerometer_disable( void )
+{
+ if ( osso_rpc_run_system( appdata.osso_context, MCE_SERVICE,
+ MCE_REQUEST_PATH, MCE_REQUEST_IF,
+ "req_accelerometer_disable", NULL,
+ DBUS_TYPE_INVALID ) != OSSO_OK ) {
+ g_printerr("WARN: Cannot disable accelerometers\n");
+ }
}
-static int current_time( void )
+static DBusHandlerResult mce_filter_func( DBusConnection * connection,
+ DBusMessage * message,
+ void *data )
{
- struct timeval tv;
- int s, us;
-
- gettimeofday( &tv, NULL );
- s = tv.tv_sec % 100000;
- us = tv.tv_usec / 100000;
+ DBusMessageIter iter;
+ char *rotation = NULL;
+
+ if ( dbus_message_is_signal( message, MCE_SIGNAL_IF,
+ MCE_DEVICE_ORIENTATION_SIG ) ) {
+ // here if we received an orientation dbus signal
+ if ( dbus_message_iter_init( message, &iter ) ) {
+ dbus_message_iter_get_basic( &iter, &rotation );
+
+ // Rotate main window
+ if ( !strcmp( rotation, MCE_ORIENTATION_PORTRAIT ) ) {
+ hildon_gtk_window_set_portrait_flags( GTK_WINDOW( appdata.main_window ),
+ HILDON_PORTRAIT_MODE_REQUEST );
+ if ( stopishType == STOPISH_TYPE_STOPWATCH )
+ stopish_stopwatch_label_timer_portrait( );
+ else
+ stopish_countdown_label_timer_portrait( );
+ stopishOrientation = STOPISH_PORTRAIT;
+ }
+ else {
+ hildon_gtk_window_set_portrait_flags( GTK_WINDOW( appdata.main_window ),
+ ~HILDON_PORTRAIT_MODE_REQUEST );
+ if ( stopishType == STOPISH_TYPE_STOPWATCH )
+ stopish_stopwatch_label_timer_landscape( );
+ else
+ stopish_countdown_label_timer_landscape( );
+ stopishOrientation = STOPISH_LANDSCAPE;
+ }
+ }
+ else
+ g_printerr( "ERROR: dbus_message_iter_init() failed.\n" );
+ }
- return ( s * 10 + us );
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}