11 G_DEFINE_TYPE(Audio, audio, GTK_TYPE_FRAME);
13 EB_Error_Code audio_save_wave(RESULT *res, gchar *file)
15 char binary_data[EB_SIZE_PAGE];
16 EB_Error_Code error_code;
17 EB_Position end_position;
22 end_position.page = res->pos.page + (res->size / EB_SIZE_PAGE);
23 end_position.offset = res->pos.offset + (res->size % EB_SIZE_PAGE);
24 if (EB_SIZE_PAGE <= end_position.offset)
26 end_position.offset -= EB_SIZE_PAGE;
29 error_code = eb_set_binary_wave(res->binfo->book, &res->pos, &end_position);
30 if (error_code != EB_SUCCESS)
32 LOG(LOG_CRITICAL, "Failed to set binary wave: %s", eb_error_message(error_code));
36 fp = fopen(file, "wb");
39 LOG(LOG_CRITICAL, "Failed to open file : %s", file);
40 return EB_ERR_BAD_FILE_NAME;
45 error_code = eb_read_binary(res->binfo->book, EB_SIZE_PAGE, binary_data, &read_len);
46 if(error_code != EB_SUCCESS || read_len == 0)
52 // If there are extra data (32 bytes) before fmt chunk,remove them.
53 if((strncmp("fmt ", &binary_data[44], 4) == 0) && (strncmp("fmt ", &binary_data[12], 4) != 0))
55 LOG(LOG_CRITICAL, "Warning: extra header found in WAVE data.");
56 write_len = fwrite(binary_data, 12, 1, fp);
57 write_len = fwrite(&binary_data[44], read_len - 44, 1, fp);
60 write_len = fwrite(binary_data, read_len, 1, fp);
65 void audio_save_as(GtkWidget *w, gpointer data)
67 static gchar *path = NULL;
68 path = app_browse_disk(_("Save Audio As"), mainwnd_get_wnd(), GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_SAVE_AS, path);
71 RESULT *res = (RESULT*)data;
72 if(audio_save_wave(res, path) != EB_SUCCESS)
73 LOG(LOG_WARNING, _("Failed to save audio"));
79 gboolean audio_context_menu(GtkWidget *w, GdkEventButton *event, gpointer user_data)
81 if(event->button != 3) return FALSE;
82 GtkWidget *menu = gtk_menu_new(), *item;
83 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_SAVE_AS, NULL);
84 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(audio_save_as), user_data);
85 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
86 gtk_widget_show_all(menu);
87 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time());
92 #ifdef ENABLE_GSTREAMER
94 gboolean audio_bus_cb(GstBus *bus, GstMessage *msg, gpointer data)
96 GstElement *pipeline = GST_ELEMENT(data);
97 switch (GST_MESSAGE_TYPE (msg))
101 gst_element_set_state(pipeline, GST_STATE_NULL);
102 gst_object_unref(GST_OBJECT (pipeline));
106 case GST_MESSAGE_ERROR:
111 gst_message_parse_error(msg, &error, &debug);
114 LOG(LOG_INFO, "%s\n", error->message);
126 static void audio_pad_added_cb(GstElement *dec, GstPad *pad, gpointer data)
128 GstElement *sink = (GstElement*)data;
129 GstPad *sinkpad = gst_element_get_pad(sink, "sink");
131 gst_pad_link(pad, sinkpad);
132 gst_object_unref(sinkpad);
135 void audio_play(GtkWidget *w, gpointer data)
137 GstElement *src, *dec, *sink, *pipeline = gst_pipeline_new ("pipeline");
138 GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE (pipeline));
139 RESULT *res = (RESULT*)data;
141 gst_bus_add_watch(bus, audio_bus_cb, (gpointer)pipeline);
142 gst_object_unref(bus);
144 src = g_object_new(GST_TYPE_SRC, NULL);
145 GST_SRC(src)->res = res;
146 dec = gst_element_factory_make("wavparse", "decoder");
147 sink = gst_element_factory_make("alsasink", "sink");
149 gst_bin_add_many(GST_BIN(pipeline), src, dec, sink, NULL);
150 gst_element_link(src, dec);
151 g_signal_connect(dec, "pad-added", G_CALLBACK(audio_pad_added_cb), sink);
153 gst_element_set_state(pipeline, GST_STATE_PLAYING);
158 static void audio_class_init(AudioClass *klass)
162 static void audio_init(Audio *self)
164 GtkWidget *btn, *img;
165 GtkWidget *hbox = gtk_hbox_new(FALSE, 0);
166 gtk_container_add(GTK_CONTAINER(self), hbox);
167 #ifdef ENABLE_GSTREAMER
168 btn = gtk_button_new();
169 img = gtk_image_new_from_stock(GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_SMALL_TOOLBAR);
170 gtk_button_set_image(GTK_BUTTON(btn), img);
171 g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(audio_play), render.link);
172 gtk_box_pack_start(GTK_BOX(hbox), btn, FALSE, TRUE, 0);
174 GtkWidget *label = gtk_label_new(_("Audio"));
175 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
177 btn = gtk_button_new();
178 img = gtk_image_new_from_stock(GTK_STOCK_SAVE_AS, GTK_ICON_SIZE_SMALL_TOOLBAR);
179 gtk_container_add(GTK_CONTAINER(btn), img);
180 //g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(audio_save_as), render.link);
181 gtk_box_pack_start(GTK_BOX(hbox), btn, FALSE, TRUE, 0);
184 void audio_render(Audio *self)
186 GtkTextIter iter1, iter2;
188 if(render_get_last_mark("wave", &iter1, &iter2))
190 gtk_text_buffer_delete(render.buf, &iter1, &iter2);
191 gtk_text_buffer_get_end_iter(render.buf, &iter1);
192 gtk_text_buffer_insert(render.buf, &iter1, "\n", -1);
193 gtk_text_buffer_get_end_iter(render.buf, &iter1);
194 GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(render.buf, &iter1);
195 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(render.view), GTK_WIDGET(self), anchor);
196 gtk_text_buffer_insert(render.buf, &iter1, "\n", -1);
197 g_object_set_data_full(G_OBJECT(self), "audio", render.link, result_free);
198 gtk_widget_show_all(GTK_WIDGET(self));
199 gtk_widget_realize(GTK_WIDGET(self));