Separate stopwatch functionality into unique source file.
[stopish] / src / stopish.c
1 //      stopish.c
2 //
3 //      Copyright 2010 Michael Cronenworth <mike@cchtml.com>
4 //
5 //      This program is free software; you can redistribute it and/or modify
6 //      it under the terms of the GNU General Public License as published by
7 //      the Free Software Foundation; either version 2 of the License, or
8 //      (at your option) any later version.
9 //
10 //      This program is distributed in the hope that it will be useful,
11 //      but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //      GNU General Public License for more details.
14 //
15 //      You should have received a copy of the GNU General Public License
16 //      along with this program; if not, write to the Free Software
17 //      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 //      MA 02110-1301, USA.
19
20 #include <string.h>
21 #include <stdlib.h>
22 #include <sys/time.h>
23 #include <gtk/gtk.h>
24 #include <hildon/hildon.h>
25 #include <dbus/dbus.h>
26 #include <mce/mode-names.h>
27 #include <mce/dbus-names.h>
28 #define MCE_SIGNAL_MATCH "type='signal'," \
29         "interface='" MCE_SIGNAL_IF   "'," \
30         "member='" MCE_DEVICE_ORIENTATION_SIG "'"
31
32 #include "stopish.h"
33
34 // Application data struct
35 typedef struct _AppData AppData;
36 struct _AppData {
37     GtkWindow *main_window;
38     osso_context_t *osso_context;
39     DBusConnection *system_bus;
40 };
41
42
43 static AppData appdata;
44 static int stopishMode = STOPISH_MODE_START;
45 static int stopishOrientation = STOPISH_LANDSCAPE;
46
47
48 //Prototypes
49 gint dbus_callback( const gchar *interface, const gchar *method,
50                         GArray *arguments, gpointer data, osso_rpc_t *retval );
51 static void main_menu( GtkWindow *window );
52 static void close_cb( GtkButton* button, gpointer data );
53 static gboolean focus_in_cb( GtkWidget *widget, GdkEventFocus *event,
54                              gpointer data );
55 static gboolean focus_out_cb( GtkWidget *widget, GdkEventFocus *event,
56                               gpointer data );
57 static void accelerometer_enable( void );
58 static void accelerometer_disable( void );
59 static DBusHandlerResult mce_filter_func( DBusConnection * connection,
60                                           DBusMessage * message,
61                                           void *data );
62
63
64 int main( int argc, char *argv[] )
65 {
66     osso_return_t ret;
67     HildonProgram *program;
68
69     appdata.osso_context = osso_initialize( "com.nokia.stopish",
70                                             PACKAGE_VERSION, TRUE, NULL );
71     if ( appdata.osso_context == NULL ) {
72         fprintf( stderr, "osso_initialize failed.\n" );
73         exit( 1 );
74     }
75
76     // initialize Hildonized GTK libraries
77     hildon_gtk_init( &argc, &argv );
78     program = hildon_program_get_instance(  );
79
80     // create main window
81     appdata.main_window = stopish_stopwatch_new(  );
82
83     // attach signals to main window
84     g_signal_connect( G_OBJECT( appdata.main_window ), "destroy",
85                       G_CALLBACK( close_cb ), appdata.main_window );
86     g_signal_connect( G_OBJECT( appdata.main_window ), "focus-in-event",
87                       G_CALLBACK( focus_in_cb ), NULL );
88     g_signal_connect( G_OBJECT( appdata.main_window ), "focus-out-event",
89                       G_CALLBACK( focus_out_cb ), NULL );
90
91     // setup main menu
92     main_menu( appdata.main_window );
93
94     hildon_program_add_window( program, HILDON_WINDOW( appdata.main_window ) );
95
96     // Connect to session bus, add a match rule, install filter callback
97     appdata.system_bus = osso_get_sys_dbus_connection( appdata.osso_context );
98     if ( appdata.system_bus ) {
99         dbus_bus_add_match( appdata.system_bus, MCE_SIGNAL_MATCH, NULL );
100         dbus_connection_add_filter( appdata.system_bus,
101                                     mce_filter_func,
102                                     NULL, NULL );
103     }
104     else
105         g_printerr( "ERROR: Cannot connect to system dbus.\n" );
106
107     ret = osso_rpc_set_default_cb_f( appdata.osso_context,
108                                      dbus_callback, appdata.main_window );
109     if ( ret != OSSO_OK ) {
110         fprintf( stderr, "osso_rpc_set_default_cb_f failed: %d.\n", ret );
111         exit( 1 );
112     }
113
114     gtk_main(  );
115
116     return 0;
117 }
118
119
120 gint dbus_callback( const gchar *interface, const gchar *method,
121                     GArray *arguments, gpointer data, osso_rpc_t *retval )
122 {
123     //printf( "stopish dbus: %s, %s\n", interface, method );
124
125     if ( !strcmp( method, "top_application" ) )
126         gtk_window_present( GTK_WINDOW( data ) );
127
128     retval->type = DBUS_TYPE_INVALID;
129
130     return OSSO_OK;
131 }
132
133
134 int stopish_get_mode( void )
135 {
136     return stopishMode;
137 }
138
139
140 void stopish_set_mode( int newMode )
141 {
142     stopishMode = newMode;
143 }
144
145
146 int stopish_get_orientation( void )
147 {
148     return stopishOrientation;
149 }
150
151
152 static void main_menu( GtkWindow *window )
153 {
154     GtkWidget *menu, *radio;
155
156     menu = hildon_app_menu_new(  );
157
158     // Hour preference
159     radio = gtk_radio_button_new_with_label( NULL, "Hour" );
160     gtk_toggle_button_set_mode( GTK_TOGGLE_BUTTON( radio ), FALSE );
161     g_signal_connect_after( G_OBJECT( radio ), "clicked",
162                             G_CALLBACK( stopish_stopwatch_perf_timer_hour ), NULL );
163     hildon_app_menu_add_filter( menu, GTK_BUTTON( radio ) );
164
165     // Minute preference
166     radio = gtk_radio_button_new_with_label_from_widget( GTK_RADIO_BUTTON( radio ), "Minute" );
167     gtk_toggle_button_set_mode( GTK_TOGGLE_BUTTON ( radio ), FALSE );
168     g_signal_connect_after( G_OBJECT( radio ), "clicked",
169                             G_CALLBACK( stopish_stopwatch_perf_timer_minute ), NULL );
170     hildon_app_menu_add_filter( menu, GTK_BUTTON( radio ) );
171
172     // default to minute
173     gtk_toggle_button_set_active( radio, TRUE );
174
175     gtk_widget_show_all( menu );
176
177     hildon_window_set_app_menu( HILDON_WINDOW( window ), menu );
178 }
179
180
181 static void close_cb( GtkButton* button, gpointer data )
182 {
183     // disable accelerometer for battery savings
184     accelerometer_disable(  );
185
186     // destroy main window and exit gtk main loop
187     gtk_widget_destroy( GTK_WIDGET( data ) );
188     gtk_main_quit(  );
189 }
190
191
192 static gboolean focus_in_cb( GtkWidget *widget, GdkEventFocus *event,
193                              gpointer data )
194 {
195     // enable accelerometer hardware for portrait mode support
196     accelerometer_enable(  );
197
198     return FALSE;
199 }
200
201
202 static gboolean focus_out_cb( GtkWidget *widget, GdkEventFocus *event,
203                               gpointer data )
204 {
205     // disable accelerometer for battery savings
206     accelerometer_disable(  );
207
208     return FALSE;
209 }
210
211
212 static void accelerometer_enable( void )
213 {
214     if ( osso_rpc_run_system( appdata.osso_context, MCE_SERVICE,
215                               MCE_REQUEST_PATH, MCE_REQUEST_IF,
216                               "req_accelerometer_enable", NULL,
217                               DBUS_TYPE_INVALID ) != OSSO_OK ) {
218         g_printerr("WARN: Cannot enable accelerometers\n");
219     }
220 }
221
222
223 static void accelerometer_disable( void )
224 {
225     if ( osso_rpc_run_system( appdata.osso_context, MCE_SERVICE,
226                               MCE_REQUEST_PATH, MCE_REQUEST_IF,
227                               "req_accelerometer_disable", NULL,
228                               DBUS_TYPE_INVALID ) != OSSO_OK ) {
229         g_printerr("WARN: Cannot disable accelerometers\n");
230     }
231 }
232
233
234 static DBusHandlerResult mce_filter_func( DBusConnection * connection,
235                                           DBusMessage * message,
236                                           void *data )
237 {
238     DBusMessageIter iter;
239     char *rotation = NULL;
240
241     if ( dbus_message_is_signal( message, MCE_SIGNAL_IF,
242                                  MCE_DEVICE_ORIENTATION_SIG ) ) {
243         // here if we received an orientation dbus signal
244         if ( dbus_message_iter_init( message, &iter ) ) {
245             dbus_message_iter_get_basic( &iter, &rotation );
246
247             // Rotate main window
248             if ( !strcmp( rotation, MCE_ORIENTATION_PORTRAIT ) ) {
249                 hildon_gtk_window_set_portrait_flags( GTK_WINDOW( appdata.main_window ),
250                                                       HILDON_PORTRAIT_MODE_REQUEST );
251                 stopish_stopwatch_label_timer_portrait(  );
252                 stopishOrientation = STOPISH_PORTRAIT;
253             }
254             else {
255                 hildon_gtk_window_set_portrait_flags( GTK_WINDOW( appdata.main_window ),
256                                                       ~HILDON_PORTRAIT_MODE_REQUEST );
257                 stopish_stopwatch_label_timer_landscape(  );
258                 stopishOrientation = STOPISH_LANDSCAPE;
259             }
260         }
261         else
262             g_printerr( "ERROR: dbus_message_iter_init() failed.\n" );
263     }
264
265     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
266 }