1 /* vim: set sts=2 sw=2 et: */
3 * Copyright (C) 2006 Josep Torra <j.torra@telefonica.net>
4 * 2008-2009 Jari Tenhunen <jari.tenhunen@iki.fi>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
28 #include <hildon/hildon-defines.h>
29 #include <hildon/hildon-program.h>
30 #include <hildon/hildon-number-editor.h>
34 #define OSSO_PACKAGE "tuner-tool"
35 #define OSSO_VERSION VERSION
37 #endif /* ifdef HILDON */
40 # define DEFAULT_AUDIOSRC "pulsesrc"
41 # define DEFAULT_AUDIOSINK "pulsesink"
43 # define DEFAULT_AUDIOSRC "alsasrc"
44 # define DEFAULT_AUDIOSINK "alsasink"
52 #include <gconf/gconf-client.h>
57 #define between(x,a,b) (((x)>=(a)) && ((x)<=(b)))
59 #define MAGIC (1.059463094359f) /* 2^(1/2) */
60 #define CENT (1.0005777895f) /* 1/100th of a half-tone */
61 #define LOG_CENT (0.00057762265046662109f) /* ln (CENT) */
63 extern gboolean plugin_pitch_init (GstPlugin * plugin);
64 extern gboolean plugin_tonesrc_init (GstPlugin * plugin);
74 GtkWidget *targetFrequency;
75 GtkWidget *currentFrequency;
76 GtkWidget *drawingarea1;
77 GtkWidget *drawingarea2;
87 gboolean display_keepalive;
89 osso_context_t *osso_context;
91 guint display_timer_id;
95 typedef struct app_data AppData;
104 #define NUM_LEDS (50)
105 #define NUM_WKEYS (15) /* # of white keys in the piano keyboard */
106 #define WKEY_WIDTH (45)
108 static Note equal_tempered_scale[] = {
182 {"C#6/Db6", 1108.73},
184 {"D#6/Eb6", 1244.51},
187 {"F#6/Gb6", 1479.98},
189 {"G#6/Ab6", 1661.22},
191 {"A#6/Bb6", 1864.66},
194 {"C#7/Db7", 2217.46},
196 {"D#7/Eb7", 2489.02},
199 {"F#7/Gb7", 2959.96},
201 {"G#7/Ab7", 3322.44},
203 {"A#7/Bb7", 3729.31},
207 static GdkColor ledOnColor = { 0, 0 * 255, 180 * 255, 95 * 255 };
208 static GdkColor ledOnColor2 = { 0, 180 * 255, 180 * 255, 0 * 255 };
209 static GdkColor ledOffColor = { 0, 80 * 255, 80 * 255, 80 * 255 };
210 static GdkColor whiteColor = { 0, 65535, 65535, 65535 };
211 static GdkColor blackColor = { 0, 0, 0, 0 };
214 recalculate_scale (double a4)
218 for (i = 0; i < NUM_NOTES; i++) {
219 equal_tempered_scale[i].frequency = a4 * pow (MAGIC, i - 57);
220 /* fprintf(stdout, "%s: %.2f\n", equal_tempered_scale[i].name, equal_tempered_scale[i].frequency); */
225 calibration_changed (GObject * object, GParamSpec * pspec, gpointer user_data)
230 value = hildon_number_editor_get_value (HILDON_NUMBER_EDITOR (object));
232 value = gtk_spin_button_get_value (GTK_SPIN_BUTTON (object));
235 if (value >= CALIB_MIN && value <= CALIB_MAX) {
236 recalculate_scale (value);
237 settings_set_calibration (value);
242 on_window_destroy (GtkObject * object, gpointer user_data)
248 toggle_fullscreen (GtkWindow * window)
250 static gboolean fullscreen = FALSE;
252 fullscreen = !fullscreen;
254 gtk_window_fullscreen (GTK_WINDOW (window));
256 gtk_window_unfullscreen (GTK_WINDOW (window));
260 key_press_event (GtkWidget * widget, GdkEventKey * event, GtkWindow * window)
262 switch (event->keyval) {
264 case HILDON_HARDKEY_FULLSCREEN:
265 toggle_fullscreen (window);
276 draw_leds (AppData * appdata, gint n)
279 static GdkGC *gc = NULL;
280 gint width = appdata->drawingarea1->allocation.width;
281 gint led_width = ((gfloat) width / (gfloat) (NUM_LEDS)) * 0.8;
282 gint led_space = ((gfloat) width / (gfloat) (NUM_LEDS)) * 0.2;
283 gint led_total = led_width + led_space;
284 gint padding = (width - NUM_LEDS * led_total) / 2;
287 gc = gdk_gc_new (appdata->drawingarea1->window);
289 gdk_gc_set_rgb_fg_color (gc, &appdata->drawingarea1->style->fg[0]);
291 gdk_draw_rectangle (appdata->drawingarea1->window, gc, TRUE, 0, 0,
292 appdata->drawingarea1->allocation.width, appdata->drawingarea1->allocation.height);
294 if (abs (n) > (NUM_LEDS / 2))
295 n = n / n * (NUM_LEDS / 2);
298 j = NUM_LEDS / 2 + 1;
299 k = NUM_LEDS / 2 + n;
301 j = NUM_LEDS / 2 + n;
302 k = NUM_LEDS / 2 - 1;
306 for (i = 0; i < NUM_LEDS; i++) {
307 if (i == NUM_LEDS / 2) {
309 gdk_gc_set_rgb_fg_color (gc, &ledOnColor2);
311 gdk_gc_set_rgb_fg_color (gc, &ledOffColor);
313 gdk_draw_rectangle (appdata->drawingarea1->window, gc, TRUE, padding + (i * led_total) + ((led_total - 4) / 2), 2, 4,
316 if ((i >= j) && (i <= k))
317 gdk_gc_set_rgb_fg_color (gc, &ledOnColor);
319 gdk_gc_set_rgb_fg_color (gc, &ledOffColor);
321 gdk_draw_rectangle (appdata->drawingarea1->window, gc, TRUE, padding + (i * led_total), 10, led_width,
327 /* translate the interval (ratio of two freqs) into cents */
329 interval2cent (gfloat freq, gfloat note)
331 //return (gfloat) (log (freq / note) / log (CENT));
332 return (gfloat) (log (freq / note) / LOG_CENT);
335 /* update frequency info */
337 update_frequency (AppData * appdata, gfloat frequency)
341 gfloat diff, min_diff;
343 min_diff = frequency - (equal_tempered_scale[0].frequency - 10);
344 for (i = j = 0; i < NUM_NOTES; i++) {
345 diff = frequency - equal_tempered_scale[i].frequency;
346 if (fabs (diff) <= fabs (min_diff)) {
355 g_strdup_printf ("Nearest note is %s with %.2f Hz frequency",
356 equal_tempered_scale[j].name, equal_tempered_scale[j].frequency);
357 gtk_label_set_text (GTK_LABEL (appdata->targetFrequency), buffer);
360 buffer = g_strdup_printf ("Played frequency is %.2f Hz", frequency);
361 gtk_label_set_text (GTK_LABEL (appdata->currentFrequency), buffer);
364 /* make leds display the difference in steps of two cents */
365 diff = interval2cent (frequency, equal_tempered_scale[j].frequency);
366 draw_leds (appdata, (gint) roundf (diff / 2.0));
369 /* receive spectral data from element message */
371 message_handler (GstBus * bus, GstMessage * message, gpointer data)
373 if (message->type == GST_MESSAGE_ELEMENT) {
374 const GstStructure *s = gst_message_get_structure (message);
375 const gchar *name = gst_structure_get_name (s);
377 if (strcmp (name, "pitch") == 0) {
380 frequency = g_value_get_float (gst_structure_get_value (s, "frequency"));
382 update_frequency (data, frequency);
385 /* we handled the message we want, and ignored the ones we didn't want.
386 * so the core can unref the message for us */
391 keynote2freq (AppData * appdata, gint x, gint y)
393 gint i, j, height, found;
394 gfloat frequency = 0;
396 height = appdata->drawingarea2->allocation.height;
400 for (i = 0; i < NUM_WKEYS; i++) {
401 // Test for a white key
403 if (between (x, i * WKEY_WIDTH, i * WKEY_WIDTH + (WKEY_WIDTH - 1)) && between (y, 0, height))
405 // Test for a black key
406 if (((i % 7) != 2) && ((i % 7) != 6) && (i != 14)) {
408 if (between (x, 24 + i * 45, 24 + i * 45 + 42)
409 && between (y, 0, height / 2))
413 frequency = equal_tempered_scale[48 + found - 1].frequency;
421 expose_event (GtkWidget * widget, GdkEventExpose * event, gpointer user_data)
423 AppData * appdata = (AppData *) user_data;
425 static GdkGC *gc = NULL;
428 gc = gdk_gc_new (appdata->drawingarea2->window);
430 gdk_gc_set_rgb_fg_color (gc, &whiteColor);
431 gdk_draw_rectangle (appdata->drawingarea2->window, gc, TRUE, 0, 0,
432 NUM_WKEYS * WKEY_WIDTH, appdata->drawingarea2->allocation.height - 1);
434 gdk_gc_set_rgb_fg_color (gc, &blackColor);
435 gdk_draw_rectangle (appdata->drawingarea2->window, gc, FALSE, 0, 0,
436 NUM_WKEYS * WKEY_WIDTH, appdata->drawingarea2->allocation.height - 1);
438 for (i = 0; i < NUM_WKEYS - 1; i++)
439 gdk_draw_rectangle (appdata->drawingarea2->window, gc, FALSE, i * WKEY_WIDTH, 0,
440 WKEY_WIDTH, appdata->drawingarea2->allocation.height - 1);
442 for (i = 0; i < NUM_WKEYS - 1; i++) {
443 if (((i % 7) != 2) && ((i % 7) != 6))
444 gdk_draw_rectangle (appdata->drawingarea2->window, gc, TRUE, 24 + i * WKEY_WIDTH, 0,
445 42, appdata->drawingarea2->allocation.height / 2);
451 button_press_event (GtkWidget * widget, GdkEventButton * event, gpointer user_data)
453 AppData * appdata = (AppData *) user_data;
455 if (event->button == 1) {
456 g_object_set (appdata->tonesrc, "freq", (gdouble) keynote2freq (appdata, event->x, event->y),
457 "volume", 0.8, NULL);
464 button_release_event (GtkWidget * widget, GdkEventButton * event,
467 AppData * appdata = (AppData *) user_data;
469 if (event->button == 1) {
470 g_object_set (appdata->tonesrc, "volume", 0.0, NULL);
477 set_pipeline_states (AppData * appdata, GstState state)
480 gst_element_set_state (appdata->bin1, state);
483 gst_element_set_state (appdata->bin2, state);
487 stop_pipelines (gpointer user_data)
489 AppData * appdata = (AppData *) user_data;
491 /* dsppcmsrc needs to go to READY or NULL state to make
492 * the DSP sleep and OMAP reach retention mode */
493 set_pipeline_states (appdata, GST_STATE_READY);
494 appdata->stop_timer_id = 0;
499 #ifdef FAKE_FREQUENCY
501 fake_frequency (gpointer user_data)
503 AppData * appdata = (AppData *) user_data;
505 update_frequency (appdata, 440.0);
513 osso_hw_state_cb (osso_hw_state_t *state, gpointer user_data)
515 AppData * appdata = (AppData *) user_data;
517 if (state->shutdown_ind) {
522 if (state->system_inactivity_ind) {
523 /* do not stop pipelines if the app is on foreground
524 * and display is kept on */
525 if (appdata->display_timer_id == 0) {
526 if (appdata->stop_timer_id != 0)
527 g_source_remove (appdata->stop_timer_id);
529 appdata->stop_timer_id = g_timeout_add (5000, (GSourceFunc) stop_pipelines, user_data);
534 if (hildon_program_get_is_topmost (HILDON_PROGRAM (appdata->app))) {
535 if (appdata->stop_timer_id != 0) {
536 g_source_remove (appdata->stop_timer_id);
537 appdata->stop_timer_id = 0;
540 set_pipeline_states (appdata, GST_STATE_PLAYING);
542 /* not topmost => topmost_notify will set pipelines to PLAYING
543 * when the application is on the foreground again */
545 if (appdata->stop_timer_id != 0) {
546 g_source_remove (appdata->stop_timer_id);
547 appdata->stop_timer_id = 0;
550 set_pipeline_states (appdata, GST_STATE_PLAYING);
559 display_keepalive (gpointer user_data)
561 AppData * appdata = (AppData *) user_data;
563 /* first (direct) call: call blanking_pause and set up timer */
564 if (appdata->display_timer_id == 0) {
565 osso_display_blanking_pause (appdata->osso_context);
566 appdata->display_timer_id = g_timeout_add (55000, (GSourceFunc) display_keepalive, user_data);
567 return TRUE; /* does not really matter */
570 /* callback from main loop */
571 if (hildon_program_get_is_topmost (HILDON_PROGRAM (appdata->app))) {
572 osso_display_blanking_pause (appdata->osso_context);
576 appdata->display_timer_id = 0;
581 display_keepalive_stop (AppData * appdata)
583 if (appdata->display_timer_id) {
584 g_source_remove (appdata->display_timer_id);
585 appdata->display_timer_id = 0;
590 topmost_notify (GObject * object, GParamSpec * pspec, gpointer user_data)
592 AppData * appdata = (AppData *) user_data;
594 if (hildon_program_get_is_topmost (HILDON_PROGRAM (object))) {
595 /* cancel pipeline stop timer if it is ticking */
596 if (appdata->stop_timer_id != 0) {
597 g_source_remove (appdata->stop_timer_id);
598 appdata->stop_timer_id = 0;
601 set_pipeline_states (appdata, GST_STATE_PLAYING);
603 /* keep display on */
604 if (appdata->display_keepalive && appdata->display_timer_id == 0)
605 display_keepalive (user_data);
608 /* pause pipelines so that we don't update the UI needlessly */
609 set_pipeline_states (appdata, GST_STATE_PAUSED);
610 /* stop pipelines fully if the app stays in the background for 30 seconds */
611 appdata->stop_timer_id = g_timeout_add (30000, (GSourceFunc) stop_pipelines, user_data);
612 /* let display dim and switch off */
613 display_keepalive_stop (appdata);
621 settings_notify (GConfClient * client, guint cnxn_id, GConfEntry * entry, gpointer user_data)
623 AppData * appdata = (AppData *) user_data;
625 g_debug ("%s changed", gconf_entry_get_key (entry));
627 if (strcmp (gconf_entry_get_key (entry), GCONF_KEY_ALGORITHM) == 0) {
628 if (gconf_entry_get_value (entry) != NULL && gconf_entry_get_value (entry)->type == GCONF_VALUE_INT) {
629 g_object_set (G_OBJECT (appdata->pitch),
630 "algorithm", gconf_value_get_int (gconf_entry_get_value (entry)),
634 else if (strcmp (gconf_entry_get_key (entry), GCONF_KEY_CALIBRATION) == 0) {
637 else if (strcmp (gconf_entry_get_key (entry), GCONF_KEY_DISPLAY_KEEPALIVE) == 0) {
638 if (gconf_entry_get_value (entry) != NULL && gconf_entry_get_value (entry)->type == GCONF_VALUE_BOOL) {
639 appdata->display_keepalive = gconf_value_get_bool (gconf_entry_get_value (entry));
641 if (appdata->display_keepalive && appdata->display_timer_id == 0)
642 display_keepalive (user_data);
644 display_keepalive_stop (appdata);
648 g_warning ("unknown GConf key `%s'", gconf_entry_get_key (entry));
653 settings_activate (GtkWidget * widget, GtkWidget * main_win)
655 settings_dialog_show (GTK_WINDOW (main_win));
659 about_activate (GtkWidget * widget, GtkWindow * main_win)
665 dialog = gtk_dialog_new_with_buttons("About Tuner", main_win,
667 GTK_DIALOG_DESTROY_WITH_PARENT |
668 GTK_DIALOG_NO_SEPARATOR,
671 g_signal_connect (G_OBJECT (dialog), "delete_event", G_CALLBACK (gtk_widget_destroy), NULL);
673 vbox = gtk_vbox_new (FALSE, HILDON_MARGIN_DEFAULT);
674 gtk_container_set_border_width (GTK_CONTAINER (vbox), HILDON_MARGIN_DEFAULT);
675 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox);
676 label = gtk_label_new ("Version " VERSION
677 "\nTuner Tool is developed by Josep Torra and Jari Tenhunen.\n"
678 "http://n770galaxy.blogspot.com/\n");
679 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 5);
681 gtk_widget_show_all (dialog);
682 gtk_dialog_run (GTK_DIALOG (dialog));
684 gtk_widget_destroy (dialog);
687 static HildonAppMenu *
688 create_menu (GtkWidget *parent)
690 HildonSizeType button_size = HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH;
691 HildonAppMenu *menu = HILDON_APP_MENU (hildon_app_menu_new ());
694 button = GTK_BUTTON (hildon_gtk_button_new (button_size));
695 gtk_button_set_label (button, "Settings");
696 g_signal_connect_after (G_OBJECT (button), "clicked",
697 G_CALLBACK (settings_activate), parent);
698 hildon_app_menu_append (menu, button);
700 button = GTK_BUTTON (hildon_gtk_button_new (button_size));
701 gtk_button_set_label (button, "About");
702 g_signal_connect_after (G_OBJECT (button), "clicked",
703 G_CALLBACK (about_activate), parent);
704 hildon_app_menu_append (menu, button);
706 gtk_widget_show_all (GTK_WIDGET (menu));
712 main (int argc, char *argv[])
714 AppData * appdata = NULL;
716 HildonProgram *app = NULL;
717 osso_hw_state_t hw_state_mask = { TRUE, FALSE, FALSE, TRUE, 0 };
721 GstElement *src1, *src2, *sink1;
729 GtkWidget *alignment;
730 GtkWidget *calibrate;
735 GdkPixbuf *icon = NULL;
736 GError *error = NULL;
738 gboolean piano_enabled = TRUE;
740 appdata = g_new0(AppData, 1);
743 gst_init (&argc, &argv);
744 /* Register the GStreamer plugins */
745 plugin_pitch_init (NULL);
746 plugin_tonesrc_init (NULL);
749 /* Init the gtk - must be called before any hildon stuff */
750 gtk_init (&argc, &argv);
752 app = HILDON_PROGRAM (hildon_program_get_instance ());
753 g_set_application_name ("Tuner");
757 /* Initialize maemo application */
758 appdata->osso_context = osso_initialize (OSSO_PACKAGE, OSSO_VERSION, TRUE, NULL);
760 /* Check that initialization was ok */
761 if (appdata->osso_context == NULL) {
762 g_print ("Bummer, osso failed\n");
764 g_assert (appdata->osso_context);
766 /* could use also display_event_cb but it is available only from chinook onwards */
767 if (osso_hw_set_event_cb (appdata->osso_context, &hw_state_mask, osso_hw_state_cb, appdata) != OSSO_OK)
768 g_warning ("setting osso_hw_state_cb failed!");
770 settings_init (&settings_notify, appdata);
772 calib = settings_get_calibration (CALIB_DEFAULT);
773 recalculate_scale (calib);
775 mainBox = gtk_vbox_new (FALSE, 0);
776 gtk_container_set_border_width (GTK_CONTAINER (mainBox), 0);
777 mainWin = hildon_stackable_window_new ();
778 g_signal_connect (G_OBJECT (app), "notify::is-topmost", G_CALLBACK (topmost_notify), appdata);
780 menu = create_menu (mainWin);
781 hildon_program_set_common_app_menu (app, menu);
783 /* Bin for tuner functionality */
784 appdata->bin1 = gst_pipeline_new ("bin1");
786 src1 = gst_element_factory_make (DEFAULT_AUDIOSRC, "src1");
787 g_object_set (G_OBJECT (src1), "device", "source.voice.raw", NULL);
789 appdata->pitch = gst_element_factory_make ("pitch", "pitch");
791 g_object_set (G_OBJECT (appdata->pitch), "message", TRUE, "minfreq", 10,
793 "algorithm", settings_get_algorithm (DEFAULT_ALGORITHM),
796 sink1 = gst_element_factory_make ("fakesink", "sink1");
797 g_object_set (G_OBJECT (sink1), "silent", 1, NULL);
799 gst_bin_add_many (GST_BIN (appdata->bin1), src1, appdata->pitch, sink1, NULL);
800 if (!gst_element_link_many (src1, appdata->pitch, sink1, NULL)) {
801 fprintf (stderr, "cant link elements\n");
805 bus = gst_element_get_bus (appdata->bin1);
806 gst_bus_add_watch (bus, message_handler, appdata);
807 gst_object_unref (bus);
809 /* Bin for piano functionality */
810 appdata->bin2 = gst_pipeline_new ("bin2");
812 //src2 = gst_element_factory_make ("audiotestsrc", "src2");
813 //g_object_set (G_OBJECT (src2), "volume", 0.0, "wave", 7, NULL);
814 src2 = gst_element_factory_make ("tonesrc", "src2");
815 g_object_set (G_OBJECT (src2), "volume", 0.0, NULL);
816 sink2 = gst_element_factory_make (DEFAULT_AUDIOSINK, "sink2");
818 gst_bin_add_many (GST_BIN (appdata->bin2), src2, sink2, NULL);
819 if (!gst_element_link_many (src2, sink2, NULL)) {
820 piano_enabled = FALSE;
823 appdata->tonesrc = src2;
826 g_signal_connect (G_OBJECT (mainWin), "destroy",
827 G_CALLBACK (on_window_destroy), NULL);
828 g_signal_connect (G_OBJECT(mainWin), "key_press_event",
829 G_CALLBACK (key_press_event), mainWin);
832 appdata->targetFrequency = gtk_label_new ("");
833 gtk_box_pack_start (GTK_BOX (mainBox), appdata->targetFrequency, FALSE, FALSE, 5);
836 appdata->drawingarea1 = gtk_drawing_area_new ();
837 gtk_widget_set_size_request (appdata->drawingarea1, 636, 40);
838 gtk_box_pack_start (GTK_BOX (mainBox), appdata->drawingarea1, FALSE, FALSE, 5);
840 /* Current frequency lable */
841 appdata->currentFrequency = gtk_label_new ("");
842 gtk_box_pack_start (GTK_BOX (mainBox), appdata->currentFrequency, FALSE, FALSE, 5);
844 /* Calibration spinner */
845 box = gtk_hbox_new (FALSE, 0);
846 alignment = gtk_alignment_new (0.5, 0.5, 0, 0);
847 label = gtk_label_new ("Calibration");
848 gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 5);
851 calibrate = calibration_editor_new (CALIB_MIN, CALIB_MAX);
852 hildon_number_editor_set_value (HILDON_NUMBER_EDITOR (calibrate),
854 g_signal_connect (G_OBJECT (calibrate), "notify::value",
855 G_CALLBACK (calibration_changed), NULL);
857 calibrate = gtk_spin_button_new_with_range (CALIB_MIN, CALIB_MAX, 1);
858 gtk_spin_button_set_value (GTK_SPIN_BUTTON (calibrate), calib);
859 g_signal_connect (G_OBJECT (calibrate), "value_changed",
860 G_CALLBACK (calibration_changed), NULL);
862 gtk_box_pack_start (GTK_BOX (box), calibrate, FALSE, FALSE, 5);
863 gtk_container_add (GTK_CONTAINER (alignment), box);
864 gtk_box_pack_start (GTK_BOX (mainBox), alignment, FALSE, FALSE, 5);
867 sep = gtk_hseparator_new ();
868 gtk_box_pack_start (GTK_BOX (mainBox), sep, FALSE, FALSE, 5);
871 alignment = gtk_alignment_new (0.5, 0.5, 0, 0);
872 appdata->drawingarea2 = gtk_drawing_area_new ();
873 gtk_widget_set_size_request (appdata->drawingarea2, NUM_WKEYS * WKEY_WIDTH + 1, 130);
874 gtk_container_add (GTK_CONTAINER (alignment), appdata->drawingarea2);
875 gtk_box_pack_start (GTK_BOX (mainBox), alignment, FALSE, FALSE, 5);
877 g_signal_connect (G_OBJECT (appdata->drawingarea2), "expose_event",
878 G_CALLBACK (expose_event), appdata);
880 g_signal_connect (G_OBJECT (appdata->drawingarea2), "button_press_event",
881 G_CALLBACK (button_press_event), (gpointer) appdata);
883 g_signal_connect (G_OBJECT (appdata->drawingarea2), "button_release_event",
884 G_CALLBACK (button_release_event), (gpointer) appdata);
886 gtk_widget_set_events (appdata->drawingarea2, GDK_EXPOSURE_MASK
887 | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
889 gtk_widget_set_events (appdata->drawingarea2, GDK_EXPOSURE_MASK);
892 gtk_container_add (GTK_CONTAINER (mainWin), mainBox);
893 hildon_program_add_window (app, HILDON_WINDOW (mainWin));
894 gtk_widget_show_all (GTK_WIDGET (mainWin));
896 appdata->display_keepalive = settings_get_display_keepalive (DEFAULT_DISPLAY_KEEPALIVE);
898 if (appdata->display_keepalive)
899 display_keepalive (appdata);
901 draw_leds (appdata, 0);
903 set_pipeline_states (appdata, GST_STATE_PLAYING);
905 #ifdef FAKE_FREQUENCY
906 g_timeout_add (2000, (GSourceFunc) fake_frequency, appdata);
911 set_pipeline_states (appdata, GST_STATE_NULL);
913 gst_object_unref (appdata->bin1);
914 gst_object_unref (appdata->bin2);