X-Git-Url: http://git.maemo.org/git/?p=maemo-recorder;a=blobdiff_plain;f=src%2Fmaemo-recorder-ui.c;h=6d95261698528b09708216f05b47cd5546c1bf21;hp=9980aa81d364ef8705e1fe468db6a9f758261211;hb=834d84eb136946be66dc33105f57ccfd5fe14c68;hpb=ef8d8d8149bced531b27603ee806dbf816c00bdd diff --git a/src/maemo-recorder-ui.c b/src/maemo-recorder-ui.c index 9980aa8..6d95261 100644 --- a/src/maemo-recorder-ui.c +++ b/src/maemo-recorder-ui.c @@ -20,20 +20,19 @@ * */ - #include #include #include #include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include #include - +#include #include "maemo-recorder.h" #include "maemo-recorder-ui.h" #include "maemo-recorder-file.h" @@ -42,7 +41,7 @@ #define DEFAULT_REC_BLOCKSIZE "160" #define STOP_DELAY 500 -#define REC_UPDATE_INTERVAL 750 +#define REC_UPDATE_INTERVAL 500 #define PLAY_UPDATE_INTERVAL 200 /* MACROs */ @@ -56,7 +55,7 @@ #define GST_TIME_MSECS(t) \ (guint) (((GstClockTime)(t)) % GST_SECOND) -#define RECORDER_APP_TITLE "Maemo Recorder" +#define RECORDER_APP_TITLE "Recorder" #define RECORDER_MSG_READY _("Ready") #define RECORDER_MSG_STOPPED _("Stopped") #define RECORDER_MSG_PAUSED _("Paused") @@ -64,6 +63,8 @@ #define RECORDER_MSG_RECORDING _("Recording") #define RECORDER_FILE_UNTITLED _("Untitled") +#define RECORDER_FMT_STRING_NONE _("N/A") + /* general enumerations */ typedef enum @@ -72,19 +73,6 @@ typedef enum DTX_ON = 1 } DTX; -/* menu codes */ -typedef enum -{ - MENU_FILE_NEW = 1, - MENU_FILE_OPEN, - MENU_FILE_SAVE, - MENU_FILE_SAVE_AS, - MENU_FILE_REC, - MENU_FILE_PLAY, - MENU_FILE_STOP, - MENU_FILE_QUIT -} MenuActionCode; - typedef enum { PIPELINE_PLAY = 1, @@ -107,10 +95,11 @@ static void pipelineStateChanged (GstElement *element, static void seekToTime(GstElement *pipeline, gdouble secs); static gboolean seekToZero(AppData *data, GstElement *pipeline); static void setLength(AppData *data, gdouble secs); +static void setFormatString(AppData *data, AudioFormat afmt); static gboolean cbStopPlayback(AppData *data); -static void cbStop(GtkWidget* widget, AppData *data); -static void cbPlay(GtkWidget* widget, AppData *data); -static void cbRec(GtkWidget* widget, AppData *data); +static void cbStop(GtkWidget* widget, GdkEventButton *event, AppData *data); +static void cbPlay(GtkWidget* widget, GdkEventButton *event, AppData *data); +static void cbRec(GtkWidget* widget, GdkEventButton *event, AppData *data); static void cbNew(GtkWidget* widget, AppData *data); static void cbOpen(GtkWidget* widget, AppData *data); /*static void cbSave(GtkWidget* widget, AppData *data);*/ @@ -129,25 +118,11 @@ static gboolean cbUpdateRecLength(AppData *data); static void cbDestroy(GtkWidget* widget, GdkEvent *event, gpointer data); static gboolean openURI(gpointer user_data); static gboolean closeFile(AppData *data); +static const gchar *getFileName(AppData *data); static gdouble guessMediaLength(AppData *data); static GstCaps *createCapsFilter(AudioFormat format); -static void new_pad_cb (GstElement *wavparse, GstPad *new_pad, gpointer data) -{ - GstElement *sink; - AppData* app = (AppData*) data; - - ULOG_INFO("new pad"); - - sink = gst_element_factory_make ("dsppcmsink", "sink"); - - gst_bin_add (GST_BIN (app->playPipeline), sink); - - if (!gst_element_link (wavparse, sink)) - g_error ("link(wavparse, sink) failed!"); - gst_element_sync_state_with_parent(sink); - -} +static gboolean lengthSet = FALSE; static gboolean createPipeline(AppData *app, PipeLineType type) { @@ -157,31 +132,29 @@ static gboolean createPipeline(AppData *app, PipeLineType type) GstElement *queue = NULL; GstElement *pipeline = NULL; GstElement *parse = NULL; + GstElement *bin = NULL; GstCaps *caps = NULL; g_assert(NULL != app); - pipeline = gst_pipeline_new("pipeline"); - - gst_bus_add_watch(gst_pipeline_get_bus (GST_PIPELINE (pipeline)), - cbBus, app); - /* create elements */ switch (type) { case PIPELINE_PLAY_MP3: ULOG_INFO("mp3 playback - queue"); - src = gst_element_factory_make ("gnomevfssrc", "source"); - queue = gst_element_factory_make ("queue", "queue"); - sink = gst_element_factory_make ("dspmp3sink", "sink"); + bin = gst_element_factory_make ("playbin2", "bin"); + gchar* uri = g_strdup_printf("file://%s", app->openFileName); + g_object_set(G_OBJECT(bin), + "uri", uri, + NULL); + g_free(uri); + gst_bus_add_watch(gst_pipeline_get_bus (GST_PIPELINE (bin)), + cbBus, app); - g_object_set(G_OBJECT (queue), - "min-threshold-bytes", 131072, - NULL ); - g_object_set(G_OBJECT(src), - "location", app->openFileName, - "blocksize", 65536, - NULL); + app->playPipeline = bin; + app->playPipelineType = type; + + return TRUE; break; case PIPELINE_PLAY: @@ -199,12 +172,25 @@ static gboolean createPipeline(AppData *app, PipeLineType type) case FORMAT_PCMU: case FORMAT_PCM: ULOG_INFO("using pcm sink"); - sink = gst_element_factory_make ("dsppcmsink", "sink"); + sink = gst_element_factory_make ("pulsesink", "sink"); break; case FORMAT_WAV: ULOG_INFO("using wavparse & pcm sink"); - parse = gst_element_factory_make ("wavparse", "parse"); + bin = gst_element_factory_make ("playbin2", "bin"); + gchar* uri = g_strdup_printf("file://%s", app->openFileName); + g_object_set(G_OBJECT(bin), + "uri", uri, + NULL); + g_free(uri); + + gst_bus_add_watch(gst_pipeline_get_bus (GST_PIPELINE (bin)), + cbBus, app); + + app->playPipeline = bin; + app->playPipelineType = type; + + return TRUE; break; default: @@ -229,6 +215,7 @@ static gboolean createPipeline(AppData *app, PipeLineType type) src = gst_element_factory_make("dspilbcsrc", "source"); g_object_set(G_OBJECT(src), "dtx", DTX_OFF, + "mode", 1, NULL); break; @@ -236,20 +223,16 @@ static gboolean createPipeline(AppData *app, PipeLineType type) case FORMAT_PCMU: case FORMAT_PCM: ULOG_INFO("using pcm source"); - src = gst_element_factory_make("dsppcmsrc", "source"); - g_object_set(G_OBJECT (src), + src = gst_element_factory_make("pulsesrc", "source"); + /*g_object_set(G_OBJECT (src), "blocksize", DEFAULT_REC_BLOCKSIZE, "dtx", DTX_OFF, - NULL); + NULL);*/ break; case FORMAT_WAV: ULOG_INFO("using pcm source & wavenc"); - src = gst_element_factory_make("dsppcmsrc", "source"); - g_object_set(G_OBJECT (src), - "blocksize", DEFAULT_REC_BLOCKSIZE, - "dtx", DTX_OFF, - NULL); + src = gst_element_factory_make("pulsesrc", "source"); parse = gst_element_factory_make("wavenc", "enc"); break; @@ -273,17 +256,21 @@ static gboolean createPipeline(AppData *app, PipeLineType type) default: ULOG_ERR("Invalid pipeline type!"); - gst_object_unref(pipeline); return FALSE; } + pipeline = gst_pipeline_new("pipeline"); + + gst_bus_add_watch(gst_pipeline_get_bus (GST_PIPELINE (pipeline)), + cbBus, app); + if (!src || !pipeline) { ULOG_ERR("Could not create GstElement!"); return FALSE; } - if (!sink && app->filter != FORMAT_WAV) + if (!sink && app->filter != FORMAT_WAV ) { ULOG_ERR("Could not create GstElement!"); return FALSE; @@ -321,7 +308,7 @@ static gboolean createPipeline(AppData *app, PipeLineType type) ULOG_ERR("gst_element_link failed for src, parse and sink!"); } break; - + default: break; @@ -349,29 +336,16 @@ static gboolean createPipeline(AppData *app, PipeLineType type) break; - case FORMAT_WAV: - gst_bin_add_many(GST_BIN(pipeline), src, parse, NULL); - if (!gst_element_link_many (src, parse, NULL)) - { - ULOG_ERR("gst_element_link failed for src, parse and sink!"); - return FALSE; - } - app->playPipeline = pipeline; - g_signal_connect(parse, "pad_added", - G_CALLBACK(new_pad_cb), app); - break; - default: break; } break; - case PIPELINE_PLAY_MP3: default: - gst_bin_add_many(GST_BIN(pipeline), src, queue, sink, NULL); + gst_bin_add_many(GST_BIN(pipeline), src, sink, NULL); - if(!gst_element_link_many(src, queue, sink, NULL)) + if(!gst_element_link_many(src, sink, NULL)) { ULOG_ERR("gst_element_link failed for src and sink!"); return FALSE; @@ -418,6 +392,10 @@ static gboolean destroyPipeline(AppData *data, PipeLineType type) ULOG_INFO("%s() - Stopping playback/recording", G_STRFUNC); + //hildon_banner_show_information(GTK_WIDGET(data->mainView), NULL, RECORDER_MSG_STOPPED); + gtk_label_set_text(GTK_LABEL(data->mainViewData.stateEntry), ""); + gtk_widget_set_sensitive(data->buttonRec, TRUE); + switch (type) { case PIPELINE_REC: @@ -478,12 +456,12 @@ static void pipelineStateChanged (GstElement *element, g_free(tmp); tmp = NULL; ULOG_INFO("%s() - Recording", G_STRFUNC); - gtk_entry_set_text(GTK_ENTRY(data->mainViewData.stateEntry), + gtk_label_set_text(GTK_LABEL(data->mainViewData.stateEntry), RECORDER_MSG_RECORDING); gtk_widget_set_state(data->buttonRec, GTK_STATE_ACTIVE); - if (data->recUpdateId == 0 && gettimeofday(&data->recStartTv, NULL) == 0) + if (data->recUpdateId == 0) { data->recUpdateId = g_timeout_add_full(G_PRIORITY_DEFAULT_IDLE, REC_UPDATE_INTERVAL, (GSourceFunc) cbUpdateRecLength, data, NULL); } @@ -495,7 +473,7 @@ static void pipelineStateChanged (GstElement *element, g_free(tmp); tmp = NULL; ULOG_INFO("%s() - Playing", G_STRFUNC); - gtk_entry_set_text(GTK_ENTRY(data->mainViewData.stateEntry), + gtk_label_set_text(GTK_LABEL(data->mainViewData.stateEntry), RECORDER_MSG_PLAYING); gtk_widget_set_state(data->buttonPlay, GTK_STATE_ACTIVE); /* @@ -508,8 +486,7 @@ static void pipelineStateChanged (GstElement *element, case GST_STATE_READY: /* hildon_banner_show_information(GTK_WIDGET(data->mainView), NULL, "Ready..."); */ ULOG_INFO("%s() - Ready", G_STRFUNC); - gtk_entry_set_text(GTK_ENTRY(data->mainViewData.stateEntry), - RECORDER_MSG_READY); + gtk_label_set_text(GTK_LABEL(data->mainViewData.stateEntry), ""); break; case GST_STATE_PAUSED: @@ -522,20 +499,8 @@ static void pipelineStateChanged (GstElement *element, if (GST_IS_ELEMENT(data->playPipeline) && gst_element_query_position(data->playPipeline, &fmt, &pos) && pos != 0) { hildon_banner_show_information(GTK_WIDGET(data->mainView), NULL, RECORDER_MSG_PAUSED); - gtk_entry_set_text(GTK_ENTRY(data->mainViewData.stateEntry), + gtk_label_set_text(GTK_LABEL(data->mainViewData.stateEntry), RECORDER_MSG_PAUSED); - /* - gtk_tool_button_set_stock_id(GTK_TOOL_BUTTON(data->buttonPlay), GTK_STOCK_MEDIA_PLAY); - gtk_widget_set_state(data->buttonPlay, GTK_STATE_NORMAL); - */ - } - else - { - hildon_banner_show_information(GTK_WIDGET(data->mainView), NULL, RECORDER_MSG_STOPPED); - gtk_entry_set_text(GTK_ENTRY(data->mainViewData.stateEntry), - RECORDER_MSG_STOPPED); - gtk_widget_set_state(data->buttonPlay, GTK_STATE_NORMAL); - gtk_tool_button_set_stock_id(GTK_TOOL_BUTTON(data->buttonPlay), GTK_STOCK_MEDIA_PLAY); } gtk_widget_set_state(data->buttonRec, GTK_STATE_NORMAL); } @@ -543,9 +508,6 @@ static void pipelineStateChanged (GstElement *element, case GST_STATE_NULL: ULOG_INFO("%s() - Null", G_STRFUNC); - hildon_banner_show_information(GTK_WIDGET(data->mainView), NULL, RECORDER_MSG_STOPPED); - gtk_entry_set_text(GTK_ENTRY(data->mainViewData.stateEntry), - RECORDER_MSG_READY); gtk_widget_set_state(data->buttonPlay, GTK_STATE_NORMAL); gtk_tool_button_set_stock_id(GTK_TOOL_BUTTON(data->buttonPlay), GTK_STOCK_MEDIA_PLAY); gtk_widget_set_state(data->buttonRec, GTK_STATE_NORMAL); @@ -601,6 +563,10 @@ static gboolean cbBus(GstBus *bus, case APPSTATE_PLAYING: /* stop playback after a short break*/ g_timeout_add(STOP_DELAY, (GSourceFunc)cbStopPlayback, data); + //hildon_banner_show_information(GTK_WIDGET(app->mainView), NULL, RECORDER_MSG_STOPPED); + gtk_label_set_text(GTK_LABEL(app->mainViewData.stateEntry), + ""); + break; case APPSTATE_RECORDING: @@ -618,6 +584,7 @@ static gboolean cbBus(GstBus *bus, break; } + case GST_MESSAGE_ASYNC_DONE: case GST_MESSAGE_STATE_CHANGED: { GstState old; @@ -649,8 +616,8 @@ static void cbDestroy(GtkWidget* widget, GdkEvent *event, gpointer data) app = (AppData *) data; - if (!closeFile(app)) - return; + ULOG_DEBUG("delete_event"); + closeFile(app); destroyPipelines(app); if (app->playPipeline) @@ -666,7 +633,6 @@ static gboolean cbCheckPosition (AppData *data) { GstFormat fmt = GST_FORMAT_TIME; gint64 pos = 0, len = 0; - static gboolean lengthSet = FALSE; g_assert(NULL != data); @@ -686,6 +652,9 @@ static gboolean cbCheckPosition (AppData *data) if (gst_element_query_position(data->playPipeline, &fmt, &pos)) { gdouble time = GST_TIME_TO_SECS(pos); + guint mins = 0; + gdouble secs; + gchar* tmp; ULOG_DEBUG("pos = %lld, time = %f", pos, @@ -696,6 +665,18 @@ static gboolean cbCheckPosition (AppData *data) GTK_ADJUSTMENT(data->mainViewData.adjustment), time); gtk_adjustment_value_changed(GTK_ADJUSTMENT(data->mainViewData.adjustment)); + if (secs >= 60.0) + { + mins = secs / 60; + secs -= mins * 60.0; + } + + tmp = g_strdup_printf("%02u:%02d", mins, (int)secs); + + gtk_label_set_text(GTK_LABEL(data->mainViewData.ctime), + tmp); + g_free(tmp); + } if (APPSTATE_PLAYING == getAppState(data)) @@ -714,7 +695,12 @@ static void cbNew(GtkWidget* widget, AppData *data) return; /* remove pipelines if existing */ - destroyPipelines(data); + if (APPSTATE_PLAYING == getAppState(data) || APPSTATE_RECORDING == getAppState(data)) { + cbStop(widget, NULL, data); + destroyPipelines(data); + } + + setAppState(data, APPSTATE_READY); ULOG_DEBUG_F("cbNew"); /* destroy tmp file */ @@ -727,18 +713,17 @@ static void cbNew(GtkWidget* widget, AppData *data) data->file_format = FORMAT_NONE; /* update display */ - gtk_entry_set_text(GTK_ENTRY(data->mainViewData.fileNameEntry), + gtk_label_set_text(GTK_LABEL(data->mainViewData.fileNameEntry), RECORDER_FILE_UNTITLED); setLength(data, 0.0); /* update the display + scale */ gtk_adjustment_set_value(GTK_ADJUSTMENT(data->mainViewData.adjustment), 0); + gtk_label_set_text(GTK_LABEL(data->mainViewData.ctime), "00:00"); gtk_widget_set_sensitive(data->buttonSave, FALSE); gtk_widget_set_sensitive(data->buttonSaveAs, FALSE); data->saved = TRUE; - gtk_window_set_title(GTK_WINDOW(data->mainView), RECORDER_FILE_UNTITLED); - ULOG_DEBUG_F("cbNew end"); } @@ -759,6 +744,10 @@ static void cbOpen(GtkWidget* widget, AppData *data) if (!closeFile(data)) return; + if (APPSTATE_PLAYING == getAppState(data) || APPSTATE_RECORDING == getAppState(data)) { + cbStop(widget, NULL, data); + destroyPipelines(data); + } #if 0 /* create filter */ @@ -794,8 +783,15 @@ static void cbOpen(GtkWidget* widget, AppData *data) */ } - if (NULL == selected) /* no file selected */ + if (NULL == selected) + { + /* no file selected */ + if (!g_file_test(getFileName(data), G_FILE_TEST_EXISTS)) + { + cbNew(widget, data); + } return; + } ULOG_INFO("%s() - selected filename = '%s'", G_STRFUNC, selected); @@ -808,14 +804,13 @@ static void cbOpen(GtkWidget* widget, AppData *data) /* update filenames */ basename = g_path_get_basename(selected); - gtk_entry_set_text(GTK_ENTRY(data->mainViewData.fileNameEntry), selected); - gtk_window_set_title(GTK_WINDOW(data->mainView), basename); + gtk_label_set_text(GTK_LABEL(data->mainViewData.fileNameEntry), basename); g_free(basename); g_free(data->openFileName); data->openFileName = tmpfile; data->file_format = format; - data->filter = format; + //data->filter = format; g_free(data->saveFileName); data->saveFileName = NULL; gtk_widget_set_sensitive(data->buttonSaveAs, TRUE); @@ -826,6 +821,7 @@ static void cbOpen(GtkWidget* widget, AppData *data) else setLength(data, 0.0); + setFormatString(data, data->file_format); data->saved = TRUE; } else @@ -881,14 +877,13 @@ openURI(gpointer user_data) /* update filenames */ basename = g_path_get_basename(selected); - gtk_entry_set_text(GTK_ENTRY(data->mainViewData.fileNameEntry), selected); - gtk_window_set_title(GTK_WINDOW(data->mainView), basename); + gtk_label_set_text(GTK_LABEL(data->mainViewData.fileNameEntry), basename); g_free(basename); g_free(data->openFileName); data->openFileName = tmpfile; data->file_format = format; - data->filter = format; + //data->filter = format; g_free(data->saveFileName); data->saveFileName = NULL; gtk_widget_set_sensitive(data->buttonSaveAs, TRUE); @@ -899,6 +894,7 @@ openURI(gpointer user_data) else setLength(data, 0.0); + setFormatString(data, data->file_format); data->saved = TRUE; } else @@ -918,6 +914,7 @@ static void openPlayPipeline( AppData *data ) GstFormat fmt = GST_FORMAT_TIME; gint64 len; gdouble size = 0; + lengthSet = FALSE; /* create pipelines */ /* check file type */ switch (data->file_format) @@ -927,14 +924,14 @@ static void openPlayPipeline( AppData *data ) case FORMAT_PCM: case FORMAT_ILBC: case FORMAT_WAV: - destroyPipelines(data); - data->filter = data->file_format; + //destroyPipelines(data); + //data->filter = data->file_format; createPipeline(data, PIPELINE_PLAY); break; case FORMAT_MP3: destroyPipelines(data); - data->filter = data->file_format; + //data->filter = data->file_format; createPipeline(data, PIPELINE_PLAY_MP3); break; @@ -965,13 +962,11 @@ static void openPlayPipeline( AppData *data ) setLength(data, size); } } - /* else { - ULOG_INFO("playSize else"); setLength(data, 0.0); } - */ + } /* returns whether the action can proceed or should be aborted */ @@ -987,7 +982,6 @@ closeFile(AppData *data) note = hildon_note_new_confirmation_add_buttons(GTK_WINDOW(data->mainView), _("Save recording?"), _("Yes"), GTK_RESPONSE_YES, _("No"), GTK_RESPONSE_NO, - _("Cancel"), GTK_RESPONSE_CANCEL, NULL); i = gtk_dialog_run(GTK_DIALOG(note)); @@ -999,6 +993,9 @@ closeFile(AppData *data) return FALSE; case GTK_RESPONSE_NO: + if (data->saveFileName) + g_unlink(data->saveFileName); + data->saved = TRUE; return TRUE; case GTK_RESPONSE_YES: @@ -1011,84 +1008,49 @@ closeFile(AppData *data) } return FALSE; } - -#if 0 -static void cbSave(GtkWidget* widget, AppData *data) + +static const gchar * +getFileName(AppData *data) { - GtkWidget* dialog = NULL; - const gchar *current; - gchar *selected = NULL; - - g_assert(data); - - ULOG_DEBUG("%s() - begin", G_STRFUNC); - - current = gtk_entry_get_text(GTK_ENTRY(data->mainViewData.fileNameEntry)); - if (NULL == current || strcmp(current, RECORDER_FILE_UNTITLED) == 0) - { - hildon_banner_show_information(GTK_WIDGET(data->mainView), GTK_STOCK_DIALOG_ERROR, _("Nothing to save")); - return; - } - - /* if saveFileName does not exist run saveas */ - if (NULL == data->saveFileName) - { - /* create dialog */ - dialog = GTK_WIDGET(hildon_file_chooser_dialog_new( - GTK_WINDOW(data->mainView), - GTK_FILE_CHOOSER_ACTION_SAVE)); - - /* show it */ - gtk_widget_show_all(dialog); - - if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) - { - selected = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); - } - - ULOG_DEBUG("%s() - dialog finished", G_STRFUNC); - - gtk_widget_destroy(dialog); - - if (NULL != selected) - { - ULOG_INFO("%s() - selected filename = '%s'", G_STRFUNC, - selected); - g_free(data->saveFileName); - data->saveFileName = g_strdup_printf("%s%s", selected, getExtension(data->file_format)); - g_free(selected); - selected = NULL; - } - else - { - return; - } - } - - /* save the file */ - if (doSave(gtk_entry_get_text(GTK_ENTRY(data->mainViewData.fileNameEntry)), data->saveFileName, data->file_format)) - { - gchar *basename = g_path_get_basename(data->saveFileName); - ULOG_INFO("%s() - file succesfully saved!", G_STRFUNC); - g_free(data->openFileName); - data->openFileName = g_strdup(data->saveFileName); - - gtk_entry_set_text(GTK_ENTRY(data->mainViewData.fileNameEntry), - data->saveFileName); - gtk_widget_set_sensitive(data->buttonSave, FALSE); - gtk_window_set_title(GTK_WINDOW(data->mainView), basename); - g_free(basename); - } - - ULOG_DEBUG("%s() - end", G_STRFUNC); + g_assert(data); + return gtk_label_get_text(GTK_LABEL(data->mainViewData.fileNameEntry)); + } -#endif static void cbSettings(GtkWidget* widget, AppData *data) { settings_edit( widget, data ); } +static void cbEmailing(GtkWidget* widget, AppData *data) +{ + + gboolean result; + GSList *list = NULL; + gchar *file = NULL; + + g_assert(NULL != data); + + if (g_file_test(getFileName(data), G_FILE_TEST_EXISTS)) + { + file = file2uri(getFileName(data)); + ULOG_INFO("Emailing: %s", file); + list = g_slist_append(list, file); + result = libmodest_dbus_client_compose_mail(data->osso, + NULL, /*to*/ + NULL, /*cc*/ + NULL, /*bcc*/ + NULL, /*body*/ + NULL, /*subj*/ + list); + if (!result) + hildon_banner_show_information(GTK_WIDGET(data->mainView), GTK_STOCK_DIALOG_ERROR, _("Emailing failed")); + + g_slist_free(list); + g_free(file); + } +} + static void cbSaveAs(GtkWidget* widget, AppData *data) { GtkWidget* dialog = NULL; @@ -1099,7 +1061,7 @@ static void cbSaveAs(GtkWidget* widget, AppData *data) ULOG_DEBUG("%s() - begin", G_STRFUNC); - current = gtk_entry_get_text(GTK_ENTRY(data->mainViewData.fileNameEntry)); + current = getFileName(data); if (NULL == current || strcmp(current, RECORDER_FILE_UNTITLED) == 0) { hildon_banner_show_information(GTK_WIDGET(data->mainView), GTK_STOCK_DIALOG_ERROR, _("Nothing to save")); @@ -1144,8 +1106,6 @@ static void cbSaveAs(GtkWidget* widget, AppData *data) basename = g_path_get_basename(data->saveFileName); ULOG_DEBUG("%s() - file '%s' succesfully saved!", G_STRFUNC, data->saveFileName); - gtk_window_set_title(GTK_WINDOW(data->mainView), basename); - /* Houston, we have a kludge: * for AU files we need to keep the old tmpfile for playback * for RAW/iLBC files, we can remove the tmpfile and point openFileName to the saved file @@ -1157,8 +1117,8 @@ static void cbSaveAs(GtkWidget* widget, AppData *data) data->openFileName = g_strdup(data->saveFileName); } - gtk_entry_set_text(GTK_ENTRY(data->mainViewData.fileNameEntry), - data->saveFileName); + gtk_label_set_text(GTK_LABEL(data->mainViewData.fileNameEntry), + basename); g_free(basename); data->saved = TRUE; @@ -1174,15 +1134,41 @@ static void cbSaveAs(GtkWidget* widget, AppData *data) ULOG_DEBUG("%s() - end", G_STRFUNC); } -static void cbRec(GtkWidget* widget, AppData *data) +static void cbRec(GtkWidget* widget, GdkEventButton *event, AppData *data) { g_assert(NULL != data); ULOG_DEBUG("%s() - begin", G_STRFUNC); + if (APPSTATE_RECORDING == getAppState(data)) + { + if (GST_IS_ELEMENT(data->recPipeline)) + { + gst_element_set_state(GST_ELEMENT(data->recPipeline), GST_STATE_PAUSED); + gtk_label_set_text(GTK_LABEL(data->mainViewData.stateEntry), + RECORDER_MSG_PAUSED); + hildon_banner_show_information(GTK_WIDGET(data->mainView), NULL, RECORDER_MSG_PAUSED); + setAppState(data, APPSTATE_PAUSED); + } + return; + } + + if (APPSTATE_PAUSED == getAppState(data)) + { + if (GST_IS_ELEMENT(data->recPipeline)) + { + gst_element_set_state(GST_ELEMENT(data->recPipeline), + GST_STATE_PLAYING); + setAppState(data, APPSTATE_RECORDING); + return; + } + } + if (APPSTATE_READY != getAppState(data)) { ULOG_WARN("%s() - state different than READY -> return", G_STRFUNC); + if (APPSTATE_RECORDING == getAppState(data)) + cbStop(widget, NULL,data); return; } @@ -1199,50 +1185,56 @@ static void cbRec(GtkWidget* widget, AppData *data) switch (data->filter) { case FORMAT_PCM: - data->saveFileName = g_strdup_printf("%s/%s", get_default_dir(), DEFAULT_TMP_FILE); - data->openFileName = g_strdup_printf("%s/%s", get_default_dir(), DEFAULT_TMP_FILE); + data->saveFileName = g_strdup_printf("%s/%s", DEFAULT_TMP_DIR, DEFAULT_TMP_FILE); + data->openFileName = g_strdup_printf("%s/%s", DEFAULT_TMP_DIR, DEFAULT_TMP_FILE); break; case FORMAT_PCMA: - data->saveFileName = g_strdup_printf("%s/%s", get_default_dir(), DEFAULT_TMP_PCMA_FILE); - data->openFileName = g_strdup_printf("%s/%s", get_default_dir(), DEFAULT_TMP_PCMA_FILE); + data->saveFileName = g_strdup_printf("%s/%s", DEFAULT_TMP_DIR, DEFAULT_TMP_PCMA_FILE); + data->openFileName = g_strdup_printf("%s/%s", DEFAULT_TMP_DIR, DEFAULT_TMP_PCMA_FILE); break; case FORMAT_PCMU: - data->saveFileName = g_strdup_printf("%s/%s", get_default_dir(), DEFAULT_TMP_PCMU_FILE); - data->openFileName = g_strdup_printf("%s/%s", get_default_dir(), DEFAULT_TMP_PCMU_FILE); + data->saveFileName = g_strdup_printf("%s/%s", DEFAULT_TMP_DIR, DEFAULT_TMP_PCMU_FILE); + data->openFileName = g_strdup_printf("%s/%s", DEFAULT_TMP_DIR, DEFAULT_TMP_PCMU_FILE); break; case FORMAT_WAV: - data->saveFileName = g_strdup_printf("%s/%s", get_default_dir(), DEFAULT_TMP_WAV_FILE); - data->openFileName = g_strdup_printf("%s/%s", get_default_dir(), DEFAULT_TMP_WAV_FILE); + data->saveFileName = g_strdup_printf("%s/%s", DEFAULT_TMP_DIR, DEFAULT_TMP_WAV_FILE); + data->openFileName = g_strdup_printf("%s/%s", DEFAULT_TMP_DIR, DEFAULT_TMP_WAV_FILE); break; case FORMAT_ILBC: default: - data->saveFileName = g_strdup_printf("%s/%s", get_default_dir(), DEFAULT_TMP_ILBC_FILE); - data->openFileName = g_strdup_printf("%s/%s", get_default_dir(), DEFAULT_TMP_ILBC_FILE); + data->saveFileName = g_strdup_printf("%s/%s", DEFAULT_TMP_DIR, DEFAULT_TMP_ILBC_FILE); + data->openFileName = g_strdup_printf("%s/%s", DEFAULT_TMP_DIR, DEFAULT_TMP_ILBC_FILE); break; } + g_mkdir(DEFAULT_TMP_DIR, 755); + ULOG_INFO("%s() - creating pipelines", G_STRFUNC); /* start recording */ /* create related pipelines */ if (createPipeline(data, PIPELINE_REC)) { ULOG_INFO("%s() - starting recording", G_STRFUNC); + gchar *basename; /* start recording */ + data->rectime = 0; gst_element_set_state(GST_ELEMENT(data->recPipeline), GST_STATE_PLAYING); /* update display */ - gtk_entry_set_text(GTK_ENTRY(data->mainViewData.fileNameEntry), - data->saveFileName); + basename = g_path_get_basename(data->saveFileName); + gtk_label_set_text(GTK_LABEL(data->mainViewData.fileNameEntry), + basename); + g_free(basename); setAppState(data, APPSTATE_RECORDING); gtk_widget_set_sensitive(data->buttonSaveAs, TRUE); - gtk_window_set_title(GTK_WINDOW(data->mainView), RECORDER_FILE_UNTITLED); data->file_format = data->filter; + setFormatString(data, data->file_format); } else { @@ -1250,11 +1242,13 @@ static void cbRec(GtkWidget* widget, AppData *data) hildon_banner_show_information(GTK_WIDGET(data->mainView), GTK_STOCK_DIALOG_ERROR, _("Could not create pipeline")); setAppState(data, APPSTATE_READY); } - + + gtk_widget_set_sensitive(data->buttonPlay, FALSE); + ULOG_DEBUG("%s() - end", G_STRFUNC); } -static void cbPlay(GtkWidget* widget, AppData *data) +static void cbPlay(GtkWidget* widget, GdkEventButton *event, AppData *data) { const gchar * file = NULL; @@ -1262,26 +1256,29 @@ static void cbPlay(GtkWidget* widget, AppData *data) ULOG_DEBUG("%s() - begin", G_STRFUNC); - file = gtk_entry_get_text(GTK_ENTRY(data->mainViewData.fileNameEntry)); + file = getFileName(data); if (NULL == data->openFileName || NULL == file || strcmp(file, RECORDER_FILE_UNTITLED) == 0) { ULOG_WARN("%s() - nothing to play", G_STRFUNC); return; } - openPlayPipeline(data); - if (APPSTATE_PLAYING == getAppState(data)) { if (GST_IS_ELEMENT(data->playPipeline)) { gst_element_set_state(GST_ELEMENT(data->playPipeline), GST_STATE_PAUSED); - setAppState(data, APPSTATE_READY); + setAppState(data, APPSTATE_PAUSED); } return; } - if (APPSTATE_READY != getAppState(data)) + if (APPSTATE_PAUSED != getAppState(data)) { + openPlayPipeline(data); + setAppState(data, APPSTATE_READY); + } + + if (APPSTATE_READY != getAppState(data) && APPSTATE_PAUSED != getAppState(data)) { ULOG_WARN("%s() - state different than PLAYING or READY -> return", G_STRFUNC); return; @@ -1289,18 +1286,6 @@ static void cbPlay(GtkWidget* widget, AppData *data) ULOG_INFO("filename %s", file); - /*openPlayPipeline( data );*/ - - /*if ( ! GST_IS_ELEMENT(data->playPipeline) ) - { - if (g_strrstr(data->openFileName, EXTENSION_RAW)) - { - ULOG_INFO("cbOpen() - file was raw, assuming audio/x-raw-int, 8kHz, 1 ch, 16-bit"); - destroyPipelines(data); - createPipeline(data, PIPELINE_PLAY); - } - }*/ - if (! GST_IS_ELEMENT(data->playPipeline)) { ULOG_WARN("%s() - playPipeline does not exist", G_STRFUNC); @@ -1314,10 +1299,12 @@ static void cbPlay(GtkWidget* widget, AppData *data) g_timeout_add(PLAY_UPDATE_INTERVAL, (GSourceFunc)cbCheckPosition, data); + gtk_widget_set_sensitive(data->buttonRec, FALSE); + ULOG_DEBUG("%s() - end", G_STRFUNC); } -static void cbStop(GtkWidget* widget, AppData *data) +static void cbStop(GtkWidget* widget, GdkEventButton *event, AppData *data) { g_assert(NULL != data); @@ -1325,20 +1312,12 @@ static void cbStop(GtkWidget* widget, AppData *data) /* check if we are playing/recording */ - /* - if (APPSTATE_PLAYING != getAppState(data) && - APPSTATE_RECORDING != getAppState(data)) - { - ULOG_WARN("cbStop() - state different than PLAYING or RECORDING " - "-> return"); - return; - } - */ - /* stop playing or recording */ gtk_tool_button_set_stock_id(GTK_TOOL_BUTTON(data->buttonPlay), GTK_STOCK_MEDIA_PLAY); gtk_widget_set_state(data->buttonPlay, GTK_STATE_NORMAL); gtk_widget_set_state(data->buttonRec, GTK_STATE_NORMAL); + gtk_widget_set_sensitive(data->buttonPlay, TRUE); + gtk_widget_set_sensitive(data->buttonRec, TRUE); /* destroy related pipeline */ switch(getAppState(data)) @@ -1350,6 +1329,7 @@ static void cbStop(GtkWidget* widget, AppData *data) gst_element_set_state(GST_ELEMENT(data->playPipeline), GST_STATE_PAUSED); /* flow through */ + case APPSTATE_PAUSED: case APPSTATE_READY: /* seek to zero, but not for PCM pipeline */ /* if (data->playPipelineType == PIPELINE_PLAY || seekToZero(data, GST_ELEMENT(data->playPipeline))) */ @@ -1358,8 +1338,9 @@ static void cbStop(GtkWidget* widget, AppData *data) gtk_adjustment_set_value( GTK_ADJUSTMENT(data->mainViewData.adjustment), 0); gtk_adjustment_value_changed(GTK_ADJUSTMENT(data->mainViewData.adjustment)); - gtk_entry_set_text(GTK_ENTRY(data->mainViewData.stateEntry), - RECORDER_MSG_STOPPED); + gtk_label_set_text(GTK_LABEL(data->mainViewData.ctime), "00:00"); + gtk_label_set_text(GTK_LABEL(data->mainViewData.stateEntry), + ""); } break; @@ -1393,83 +1374,6 @@ static void cbStop(GtkWidget* widget, AppData *data) /* ui construction functions */ -static GtkWidget* createToolBar(AppData *data) -{ - GtkToolbar* toolBar = NULL; - - GtkToolItem* new = NULL; - GtkToolItem* open = NULL; - GtkToolItem* save = NULL; - GtkToolItem* saveas = NULL; - GtkToolItem* sep = NULL; - GtkToolItem* play = NULL; - GtkToolItem* rec = NULL; - GtkToolItem* stop = NULL; - - /* create buttons */ - new = gtk_tool_button_new_from_stock(GTK_STOCK_NEW); - open = gtk_tool_button_new_from_stock(GTK_STOCK_OPEN); - save = gtk_tool_button_new_from_stock(GTK_STOCK_SAVE); - data->buttonSave = GTK_WIDGET(save); - saveas = gtk_tool_button_new_from_stock(GTK_STOCK_SAVE_AS); - data->buttonSaveAs = GTK_WIDGET(saveas); - gtk_widget_set_sensitive(data->buttonSave, FALSE); - gtk_widget_set_sensitive(data->buttonSaveAs, FALSE); - data->saved = TRUE; - - rec = gtk_tool_button_new_from_stock(GTK_STOCK_MEDIA_RECORD); - data->buttonRec = GTK_WIDGET(rec); - play = gtk_tool_button_new_from_stock(GTK_STOCK_MEDIA_PLAY); - data->buttonPlay = GTK_WIDGET(play); - stop = gtk_tool_button_new_from_stock(GTK_STOCK_MEDIA_STOP); - - /* create separator */ - sep = gtk_separator_tool_item_new(); - - /* create the toolbar itself */ - toolBar = GTK_TOOLBAR(gtk_toolbar_new()); - - /* add items to toolbar */ - gtk_toolbar_insert(toolBar, new, -1); - gtk_toolbar_insert(toolBar, open, -1); - /* - gtk_toolbar_insert(toolBar, save, -1); - */ - gtk_toolbar_insert(toolBar, saveas, -1); - gtk_toolbar_insert(toolBar, sep, -1); - gtk_toolbar_insert(toolBar, rec, -1); - gtk_toolbar_insert(toolBar, play, -1); - gtk_toolbar_insert(toolBar, stop, -1); - - /* connect signals */ - g_signal_connect(G_OBJECT(new), "clicked", - G_CALLBACK(cbNew), - data); - g_signal_connect(G_OBJECT(open), "clicked", - G_CALLBACK(cbOpen), - data); - /* - g_signal_connect(G_OBJECT(save), "clicked", - G_CALLBACK(cbSave), - data); - */ - g_signal_connect(G_OBJECT(saveas), "clicked", - G_CALLBACK(cbSaveAs), - data); - g_signal_connect(G_OBJECT(rec), "clicked", - G_CALLBACK(cbRec), - data); - g_signal_connect(G_OBJECT(play), "clicked", - G_CALLBACK(cbPlay), - data); - g_signal_connect(G_OBJECT(stop), "clicked", - G_CALLBACK(cbStop), - data); - - return GTK_WIDGET(toolBar); - -} - static void cbItemGroupChanged( gpointer data ) { AppData* app = (AppData* ) data; @@ -1511,126 +1415,109 @@ static void cbItemClose(GtkWidget *widget, gpointer data) /* Create the menu items needed for the main view */ static void createMenu( AppData *data ) { - /* Create needed variables */ - GSList *group = NULL; - GtkMenu *main_menu; - GtkWidget *menu_file; - GtkWidget *menu_others; - GtkWidget *item_file; - GtkWidget *item_file_open; - GtkWidget *item_file_save_as; - GtkWidget *item_others; - GtkWidget *item_pcma; - GtkWidget *item_pcmu; - GtkWidget *item_ilbc; - GtkWidget *item_pcm; - GtkWidget *item_settings; - /* - GtkWidget *item_radio_type1; - */ - GtkWidget *item_close; - GtkWidget *item_separator; - - /* Get the menu from view */ - main_menu = GTK_MENU(gtk_menu_new()); - hildon_window_set_menu(data->mainView, main_menu); - - /* Create new submenu for "Others" */ - menu_file = gtk_menu_new (); - menu_others = gtk_menu_new (); - - /* Create menu items */ - item_file = gtk_menu_item_new_with_label (_("File")); - item_file_open = gtk_menu_item_new_with_label(_("Open...")); - item_file_save_as = gtk_menu_item_new_with_label(_("Save as...")); - item_others = gtk_menu_item_new_with_label (_("Recording format")); - item_settings = gtk_menu_item_new_with_label (_("Settings")); - - item_pcma = gtk_radio_menu_item_new_with_label( - group, FORMAT_NAME_PCMA); - item_ilbc = gtk_radio_menu_item_new_with_label_from_widget( - GTK_RADIO_MENU_ITEM(item_pcma), FORMAT_NAME_ILBC); - item_pcmu = gtk_radio_menu_item_new_with_label_from_widget( - GTK_RADIO_MENU_ITEM(item_pcma), FORMAT_NAME_PCMU); - item_pcm = gtk_radio_menu_item_new_with_label_from_widget( - GTK_RADIO_MENU_ITEM(item_pcma), FORMAT_NAME_WAV); + HildonAppMenu *menu; + GtkWidget *button_new; + GtkWidget *button_open; + GtkWidget *button_save; + GtkWidget *button_email; + + menu = HILDON_APP_MENU( hildon_app_menu_new() ); + button_new = hildon_gtk_button_new(HILDON_SIZE_AUTO); + gtk_button_set_label( GTK_BUTTON(button_new), "New"); + button_open = hildon_gtk_button_new(HILDON_SIZE_AUTO); + gtk_button_set_label( GTK_BUTTON(button_open), "Open"); + button_save = hildon_gtk_button_new(HILDON_SIZE_AUTO); + gtk_button_set_label( GTK_BUTTON(button_save), "Save"); + button_email = hildon_gtk_button_new(HILDON_SIZE_AUTO); + gtk_button_set_label( GTK_BUTTON(button_email), "Send via email"); + + hildon_app_menu_append( menu, GTK_BUTTON(button_new)); + hildon_app_menu_append( menu, GTK_BUTTON(button_open)); + hildon_app_menu_append( menu, GTK_BUTTON(button_save)); + hildon_app_menu_append( menu, GTK_BUTTON(button_email)); + g_signal_connect(G_OBJECT(button_new), "clicked", + G_CALLBACK(cbNew), + data); + g_signal_connect(G_OBJECT(button_open), "clicked", + G_CALLBACK(cbOpen), + data); + g_signal_connect(G_OBJECT(button_save), "clicked", + G_CALLBACK(cbSaveAs), + data); + g_signal_connect( G_OBJECT( button_email ), "clicked", + GTK_SIGNAL_FUNC (cbEmailing), data); + gtk_widget_show_all( GTK_WIDGET(menu)); + + hildon_window_set_app_menu(HILDON_WINDOW(data->mainView), menu); + data->filter = get_default_filter(); - if (data->filter == FORMAT_ILBC) - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item_ilbc), TRUE); - else if (data->filter == FORMAT_WAV) - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item_pcm), TRUE); - else if (data->filter == FORMAT_PCMA) - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item_pcma), TRUE); - else - { - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item_ilbc), TRUE); - data->filter = FORMAT_ILBC; - } - - data->radio_pcma = item_pcma; - data->radio_ilbc = item_ilbc; - data->radio_pcm = item_pcm; - /* - data->radiotype = item_radio_type1; - */ - item_close = gtk_menu_item_new_with_label(_("Close")); - item_separator = gtk_separator_menu_item_new(); - - /* Add menu items to right menus */ - gtk_menu_append( main_menu, item_file ); - gtk_menu_append( menu_file, item_file_open ); - gtk_menu_append( menu_file, item_file_save_as ); - gtk_menu_append( main_menu, item_others ); - gtk_menu_append( menu_others, item_pcm ); - gtk_menu_append( menu_others, item_pcma ); - gtk_menu_append( menu_others, item_ilbc); - - gtk_menu_append( main_menu, item_settings ); - - gtk_menu_append( main_menu, item_close ); - - /* Add others submenu to the "Others" item */ - gtk_menu_item_set_submenu( - GTK_MENU_ITEM(item_file), menu_file ); - gtk_menu_item_set_submenu( - GTK_MENU_ITEM(item_others), menu_others ); - - /* Attach the callback functions to the activate signal */ - g_signal_connect( G_OBJECT( item_file_open), "activate", - GTK_SIGNAL_FUNC (cbOpen), data); - g_signal_connect( G_OBJECT( item_file_save_as), "activate", - GTK_SIGNAL_FUNC (cbSaveAs), data); - g_signal_connect( G_OBJECT( item_settings ), "activate", - GTK_SIGNAL_FUNC (cbSettings), data); - - g_signal_connect( G_OBJECT( item_close ), "activate", - GTK_SIGNAL_FUNC (cbItemClose), data); + setFormatString(data, data->filter); - g_signal_connect_swapped(G_OBJECT(item_pcma), "activate", G_CALLBACK(cbItemGroupChanged), data); - g_signal_connect_swapped(G_OBJECT(item_pcm), "activate", G_CALLBACK(cbItemGroupChanged), data); - - /* Make all menu widgets visible */ +} + +gboolean +cbScaleRelease(GtkWidget *widget, GdkEventButton *ev, gpointer data) +{ + AppData* app = (AppData* ) data; + + if (getAppState(app) == APPSTATE_RECORDING || NULL == app->playPipeline) + return FALSE; + + seekToTime(app->playPipeline, gtk_adjustment_get_value(app->mainViewData.adjustment)); + + return FALSE; - gtk_widget_show_all( GTK_WIDGET( main_menu ) ); } +gboolean +evKeypress(GtkWidget *widget, GdkEventKey *ev, AppData *appdata) +{ + + switch (ev->keyval) + { + case GDK_Return: + cbRec(widget, NULL, appdata); + return TRUE; + case GDK_Right: + cbPlay(widget, NULL, appdata); + return TRUE; + case GDK_Escape: + cbStop(widget, NULL, appdata); + return TRUE; + default: + break; + } + + return FALSE; +} + + gboolean maemo_recorder_ui_new(AppData *data) { HildonProgram *app = NULL; HildonWindow *window = NULL; GtkWidget *hbox = NULL; - GtkWidget *vbox = NULL; GtkWidget *label = NULL; - GtkWidget *entry1 = NULL; - GtkWidget *entry2 = NULL; - GtkWidget *entry3 = NULL; + GtkWidget *ctime = NULL; + GtkWidget *etime = NULL; + GtkWidget *filename = NULL; + GtkWidget *format = NULL; + GtkWidget *state = NULL; GtkWidget *toolBar = NULL; + GtkWidget *infohbox = NULL; GtkWidget *table = NULL; GtkWidget *scale = NULL; GtkObject *adjustment = NULL; + GtkWidget *rec = NULL; + GtkWidget *play = NULL; + GtkWidget *stop = NULL; + GtkWidget *recimage = NULL; + GtkWidget *playimage = NULL; + GtkWidget *stopimage = NULL; + g_assert(NULL != data); app = HILDON_PROGRAM(hildon_program_get_instance()); @@ -1643,55 +1530,21 @@ gboolean maemo_recorder_ui_new(AppData *data) /* content for main view */ - /* create vbox, divides control area and view area */ - vbox = gtk_vbox_new(FALSE, 0); - /* create hbox to divide control area */ hbox = gtk_hbox_new(FALSE, HILDON_MARGIN_DEFAULT); /* create toolbar */ - toolBar = createToolBar(data); /* create table for labels */ - table = gtk_table_new (4, 3, FALSE); - gtk_table_set_homogeneous(GTK_TABLE(table), FALSE); + table = gtk_table_new (6, 6, TRUE); + gtk_table_set_homogeneous(GTK_TABLE(table), TRUE); gtk_table_set_row_spacings (GTK_TABLE (table), 4); - gtk_table_set_col_spacings (GTK_TABLE (table), 0); - - label = gtk_label_new_with_mnemonic(_("Filename:")); - gtk_table_attach_defaults (GTK_TABLE (table), - label, - 0, 1, 0, 1); - - entry1 = gtk_entry_new (); - gtk_entry_set_has_frame(GTK_ENTRY(entry1), FALSE); - gtk_entry_set_text (GTK_ENTRY (entry1), _(RECORDER_FILE_UNTITLED)); - gtk_table_attach_defaults (GTK_TABLE (table), entry1, 1, 3, 0, 1); - gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry1); - - label = gtk_label_new_with_mnemonic (_("Length:")); - gtk_table_attach_defaults (GTK_TABLE (table), - label, - 0, 1, 1, 2); - - entry2 = gtk_entry_new (); - gtk_entry_set_has_frame(GTK_ENTRY(entry2), FALSE); - gtk_entry_set_text (GTK_ENTRY (entry2), "0:00.00"); - gtk_table_attach_defaults (GTK_TABLE (table), entry2, 1, 3, 1, 2); - gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry2); - - label = gtk_label_new_with_mnemonic (_("State:")); - gtk_table_attach_defaults (GTK_TABLE (table), - label, - 0, 1, 2, 3); - - entry3 = gtk_entry_new (); - gtk_entry_set_has_frame(GTK_ENTRY(entry3), FALSE); - gtk_entry_set_text (GTK_ENTRY (entry3), RECORDER_MSG_READY); - gtk_table_attach_defaults (GTK_TABLE (table), entry3, 1, 3, 2, 3); - gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry3); + gtk_table_set_col_spacings (GTK_TABLE (table), HILDON_MARGIN_TRIPLE); + filename = gtk_label_new(_(RECORDER_FILE_UNTITLED)); + format = gtk_label_new(RECORDER_FMT_STRING_NONE); + state = gtk_label_new(""); adjustment = gtk_adjustment_new (0.00, 0.00, 100.00, @@ -1699,37 +1552,73 @@ gboolean maemo_recorder_ui_new(AppData *data) 0.01, 0); + ctime = gtk_label_new("00:00"); + etime = gtk_label_new("00:00"); scale = gtk_hscale_new(GTK_ADJUSTMENT(adjustment)); + gtk_scale_set_draw_value(scale, FALSE); + gtk_box_pack_start(hbox, ctime, FALSE, FALSE, HILDON_MARGIN_DOUBLE); + gtk_box_pack_end(hbox, etime, FALSE, FALSE, HILDON_MARGIN_DOUBLE); + gtk_box_pack_end(hbox, scale, TRUE, TRUE, HILDON_MARGIN_DOUBLE); + gtk_box_set_homogeneous(hbox, FALSE); -/* gtk_table_attach_defaults (GTK_TABLE (table), - label, - 0, 3, 2, 3); -*/ + gtk_table_attach_defaults(table, filename, + 1, 4, 1, 2); + gtk_table_attach_defaults(table, format, + 1, 4, 2, 3); + gtk_table_attach_defaults(table, state, + 1, 4, 3, 4); + gtk_table_attach_defaults(table, hbox, + 0, 5, 5, 6); + + + recimage = gtk_image_new_from_file(REC_ICON); + rec = gtk_event_box_new(); + data->buttonRec = GTK_WIDGET(rec); + gtk_container_add(rec, recimage); + playimage = gtk_image_new_from_file(PLAY_ICON); + play = gtk_event_box_new(); + data->buttonPlay = GTK_WIDGET(play); + gtk_container_add(play, playimage); + stopimage = gtk_image_new_from_file(STOP_ICON); + stop = gtk_event_box_new(); + gtk_container_add(stop, stopimage); + + gtk_table_attach_defaults(table, rec, + 5, 6, 4, 6); + gtk_table_attach_defaults(table, play, + 5, 6, 2, 4); + gtk_table_attach_defaults(table, stop, + 5, 6, 0, 2); + + /* connect signals */ - g_signal_connect(G_OBJECT(adjustment), "value-changed", G_CALLBACK(cbUserSeek), data); - g_signal_connect(G_OBJECT(scale), "format-value", G_CALLBACK(cbFormatSeekbarValue), data); + g_signal_connect(G_OBJECT(scale), "button-release-event", G_CALLBACK(cbScaleRelease), data); g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(cbDestroy), data); + g_signal_connect(G_OBJECT(window), "key-press-event", + G_CALLBACK(evKeypress), data); - /* packing the view */ - gtk_container_add (GTK_CONTAINER(window), vbox); - gtk_box_pack_start (GTK_BOX(vbox), table, FALSE, TRUE, 0); - gtk_box_pack_start (GTK_BOX(vbox), scale, FALSE, FALSE, 0); -/* gtk_box_pack_start (GTK_BOX(vbox), hbox, TRUE, TRUE, 0); */ - - hildon_window_add_toolbar(window, GTK_TOOLBAR(toolBar)); + g_signal_connect(G_OBJECT(rec), "button-release-event", + G_CALLBACK(cbRec), + data); + g_signal_connect(G_OBJECT(play), "button-release-event", + G_CALLBACK(cbPlay), + data); + g_signal_connect(G_OBJECT(stop), "button-release-event", + G_CALLBACK(cbStop), + data); - /* initialise the ui */ - gtk_entry_set_editable(GTK_ENTRY(entry1), FALSE); - gtk_entry_set_editable(GTK_ENTRY(entry2), FALSE); - gtk_entry_set_editable(GTK_ENTRY(entry3), FALSE); + /* packing the view */ + gtk_container_add(GTK_CONTAINER(window), table); + /* store needed widgets */ data->app = app; data->mainView = window; - data->mainViewData.toolBar = GTK_WIDGET(toolBar); - data->mainViewData.fileNameEntry = GTK_WIDGET(entry1); - data->mainViewData.lengthEntry = GTK_WIDGET(entry2); - data->mainViewData.stateEntry = GTK_WIDGET(entry3); + data->mainViewData.fileNameEntry = GTK_WIDGET(filename); + data->mainViewData.formatEntry = GTK_WIDGET(format); + data->mainViewData.lengthEntry = GTK_WIDGET(etime); + data->mainViewData.ctime = GTK_WIDGET(ctime); + data->mainViewData.stateEntry = GTK_WIDGET(state); data->mainViewData.adjustment = GTK_OBJECT(adjustment); /* show the app */ @@ -1802,6 +1691,52 @@ static gboolean seekToZero(AppData *data, GstElement *pipeline) return TRUE; } +static void +setFormatString(AppData *data, AudioFormat afmt) +{ + gchar *str; + gchar *format; + + /* these are pretty much always the same */ + gint channels = 1; + gint rate = DEFAULT_RATE; /* 8000 */ + gint bits = 8; + + g_assert(data); + g_assert(GTK_IS_LABEL(data->mainViewData.formatEntry)); + + switch (afmt) + { + case FORMAT_PCMA: + format = FORMAT_NAME_PCMA; + break; + case FORMAT_PCMU: + format = FORMAT_NAME_PCMU; + break; + case FORMAT_ILBC: + format = FORMAT_NAME_ILBC; + rate = ILBC_RATE; + break; + /* TODO: we can play wavs with many sampling rates, 2 channels */ + /* we really should migrate to the better format spec */ + case FORMAT_WAV: + format = FORMAT_NAME_WAV; + bits = PCM_WIDTH; + break; + case FORMAT_PCM: + format = FORMAT_NAME_PCM; + bits = PCM_WIDTH; + break; + default: + gtk_label_set_text(GTK_LABEL(data->mainViewData.formatEntry), RECORDER_FMT_STRING_NONE); + return; + } + + str = g_strdup_printf("%s, %d %s, %d kHz, %d %s", format, channels, _("ch"), rate/1000, bits, _("bits")); + gtk_label_set_text(GTK_LABEL(data->mainViewData.formatEntry), str); + g_free(str); +} + static void setLength(AppData *data, gdouble secs) { guint mins = 0; @@ -1824,12 +1759,12 @@ static void setLength(AppData *data, gdouble secs) secs -= mins * 60.0; } - tmp = g_strdup_printf("%u:%05.2f", mins, secs); + tmp = g_strdup_printf("%02u:%02d", mins, (int)secs); /* ULOG_INFO("Setting length to %s", tmp); */ - gtk_entry_set_text(GTK_ENTRY(data->mainViewData.lengthEntry), + gtk_label_set_text(GTK_LABEL(data->mainViewData.lengthEntry), tmp); g_free(tmp); } @@ -1853,7 +1788,7 @@ static gdouble guessMediaLength(AppData *data) switch (data->file_format) { case FORMAT_ILBC: - bitrate = ILBC_BITRATE_20; + bitrate = ILBC_BITRATE_30; break; case FORMAT_PCMA: @@ -1864,6 +1799,7 @@ static gdouble guessMediaLength(AppData *data) default: return -1.0; } + if (bitrate == 0.0) return -1.0; @@ -1882,7 +1818,7 @@ static GstCaps *createCapsFilter(AudioFormat format) GST_TYPE_ILBC, "rate", G_TYPE_INT, ILBC_RATE, "channels", G_TYPE_INT, DEFAULT_CHANNELS, - "mode", G_TYPE_INT, 20, /* 20 ms frames */ + "mode", G_TYPE_INT, 30, /* 30 ms frames */ NULL); case FORMAT_PCMA: return gst_caps_new_simple( @@ -1919,15 +1855,7 @@ static gboolean cbStopPlayback(AppData *data) ULOG_INFO("Stopping playback"); g_assert(data != NULL); - - ret = gst_element_set_state(GST_ELEMENT(data->playPipeline), - GST_STATE_PAUSED); - if (seekToZero(data, GST_ELEMENT(data->playPipeline))) - { - gtk_adjustment_set_value( - GTK_ADJUSTMENT(data->mainViewData.adjustment), 0); - gtk_adjustment_value_changed(GTK_ADJUSTMENT(data->mainViewData.adjustment)); - } + destroyPipelines(data); setAppState(data, APPSTATE_READY); gtk_tool_button_set_stock_id(GTK_TOOL_BUTTON(data->buttonPlay), GTK_STOCK_MEDIA_PLAY); gtk_widget_set_state(data->buttonPlay, GTK_STATE_NORMAL); @@ -1937,13 +1865,12 @@ static gboolean cbStopPlayback(AppData *data) static void cbUserSeek(GtkAdjustment *adjustment, gpointer data) { - /*ULOG_INFO("cbUserSeek");*/ AppData *app; g_return_if_fail(data != NULL); app = (AppData *) data; - if (getAppState(app) != APPSTATE_READY || NULL == app->playPipeline) + if (getAppState(app) != APPSTATE_READY && getAppState(app) != APPSTATE_PAUSED || NULL == app->playPipeline) return; seekToTime(app->playPipeline, gtk_adjustment_get_value(adjustment)); @@ -1972,22 +1899,13 @@ static gboolean cbUpdateRecLength(AppData *data) gdouble secs; gchar *tmp; - if (gettimeofday(&tv, NULL) != 0) - return FALSE; + data->rectime += REC_UPDATE_INTERVAL/1000.0; - secs = tv.tv_sec - data->recStartTv.tv_sec; - secs += ((tv.tv_usec - data->recStartTv.tv_usec) / 1000000.0); + mins = data->rectime / 60; + secs = data->rectime - (mins * 60.0); + tmp = g_strdup_printf("%02u:%02d", mins, (int)secs); - if (secs >= 60.0) - { - mins = secs / 60; - secs -= mins * 60.0; - tmp = g_strdup_printf("%u:%05.2f", mins, secs); - } - else - tmp = g_strdup_printf("%0.2f", secs); - - gtk_entry_set_text(GTK_ENTRY(data->mainViewData.lengthEntry), + gtk_label_set_text(GTK_LABEL(data->mainViewData.lengthEntry), tmp); g_free(tmp); @@ -1998,3 +1916,4 @@ static gboolean cbUpdateRecLength(AppData *data) return FALSE; } +