42
43
static gboolean rec_level_message_cb(GstBus *bus, GstMessage *message, void *user_data);
44
GstElement *rec_create_pipeline(gchar *audio_source, GList *dev_list, gchar *enc_pipeline,
45
gchar *output_filename, gboolean append_to_file, GError **error);
45
GstElement *rec_create_pipeline(PipelineParms *parms, GError **error);
47
47
void rec_set_state_to_null();
188
188
gboolean ret = FALSE;
189
gchar *filename = NULL;
191
// Audio source, eg "pulsesrc", "
192
gchar *audio_source = NULL;
195
GList *dev_list = NULL;
197
gchar *encoder_pipeline = NULL;
190
// Parms to construct a pipeline
191
PipelineParms *parms = g_malloc0(sizeof(PipelineParms));
199
193
gchar *track_name = NULL;
194
gchar *artist_name = NULL;
195
gchar *album_name = NULL;
200
196
gint track_pos = 0;
201
197
gint track_len = 0;
202
gchar *artist_name = NULL;
203
gchar *album_name = NULL;
205
199
// Get data from GConf registry.
229
223
str_trim(last_track_name);
231
225
// Append to file?
232
gboolean append_to_file = FALSE;
233
conf_get_boolean_value("append-to-file", &append_to_file);
226
conf_get_boolean_value("append-to-file", &parms->append);
235
if (append_to_file && g_file_test(last_track_name, G_FILE_TEST_IS_REGULAR)) {
228
if (parms->append && g_file_test(last_track_name, G_FILE_TEST_IS_REGULAR)) {
236
229
// Record to an existing filename
237
filename = g_strdup(last_track_name);
230
parms->filename = g_strdup(last_track_name);
239
232
// Did we get a track name (output filename) from a Media Player, Skype?
240
233
else if (str_length(track_name, 2048) > 0) {
241
234
// We have track, album and artist names. Create filename from these.
242
filename = rec_create_filename(track_name, artist_name, album_name);
235
parms->filename = rec_create_filename(track_name, artist_name, album_name);
245
238
// Simply generate a new, unique filename from date+time pattern
246
filename = rec_generate_unique_filename();
239
parms->filename = rec_generate_unique_filename();
249
242
// Purify the final filename, remove illegal characters. Edit in place.
250
purify_filename(filename, FALSE);
243
purify_filename(parms->filename, FALSE);
252
245
// Can we write to path/filename?
253
if (!is_file_writable(filename)) {
254
gchar *msg = g_strdup_printf(_("Cannot write to file \"%s\".\n"), filename);
246
if (!is_file_writable(parms->filename)) {
247
gchar *msg = g_strdup_printf(_("Cannot write to file \"%s\".\n"), parms->filename);
256
249
// Show error text
257
LOG_DEBUG("Cannot write to file \"%s\".\n", filename);
250
LOG_DEBUG("Cannot write to file \"%s\".\n", parms->filename);
259
252
rec_manager_set_error_text(msg);
265
258
// Save the last file name
266
conf_save_string_value("track/last-track-name", filename);
259
conf_save_string_value("track/last-track-name", parms->filename);
268
261
// Get the saved media profile id (aac, mp3, cdlossless, cdlossy, etc).
269
262
gchar *media_profile_id = rec_get_media_profile_id();
271
264
// Get partial pipline from GConf for this media_profile_id
272
encoder_pipeline = media_profiles_get_pipeline(media_profile_id);
265
parms->profile_str = media_profiles_get_pipeline(media_profile_id);
266
parms->file_ext = media_profiles_get_extension(media_profile_id);
273
267
g_free(media_profile_id);
277
273
gchar *device_id = NULL;
294
290
// Set/show current filename
295
rec_manager_set_filename_label(filename);
291
rec_manager_set_filename_label(parms->filename);
297
293
// Get audio source and device list
298
dev_list = audio_sources_get_device_NEW(&audio_source);
294
gchar *audio_source = NULL;
295
parms->dev_list = audio_sources_get_device_NEW(&audio_source);
296
parms->source = audio_source;
300
298
// Now build a GStreamer pipeline with these values
301
299
GError *error = NULL;
302
g_pipeline = rec_create_pipeline(audio_source, dev_list, encoder_pipeline, filename, append_to_file, &error);
300
g_pipeline = rec_create_pipeline(parms, &error);
568
559
if (!GST_IS_MESSAGE(msg)) return;
570
561
// We are only interested in the top-level pipeline.
571
if (msg->src != GST_OBJECT(g_pipeline)) return;
562
if (GST_MESSAGE_SRC(msg) != GST_OBJECT(g_pipeline)) return;
573
564
GstState old_state, new_state;
574
565
gst_message_parse_state_changed(msg, &old_state, &new_state, NULL);
577
567
GstState state, pending;
578
568
gst_element_get_state(g_pipeline, &state, &pending, 0);
579
LOG_DEBUG("Pipeline state changed from %s to: %s (stat=%s pending=%s).\n", gst_element_state_get_name(old_state), gst_element_state_get_name(new_state),
569
LOG_DEBUG("Pipeline state changed from %s to: %s (stat=%s pending=%s).\n",
570
gst_element_state_get_name(old_state), gst_element_state_get_name(new_state),
580
571
gst_element_state_get_name(state), gst_element_state_get_name(pending));
582
573
// Pipeline state changed from PAUSED to: READY (stat=READY pending=VOID_PENDING).
645
636
g_got_EOS_message = TRUE;
648
GstElement *rec_create_pipeline(gchar *audio_source, GList *dev_list, gchar *enc_pipeline, gchar *output_filename, gboolean append_to_file, GError **error) {
639
GstElement *rec_create_pipeline(PipelineParms *parms, GError **error) {
649
640
// Create a GStreamer pipeline for audio recording.
650
641
gchar *err_msg = NULL;
652
643
// Print debug info
653
644
LOG_DEBUG("----------------------------\n");
654
645
LOG_DEBUG("rec_create_pipeline, The parameters are:\n");
655
LOG_DEBUG("audio_source=%s\n", audio_source);
656
LOG_DEBUG("Device list is:\n");
646
LOG_DEBUG("audio source=%s\n", parms->source);
647
LOG_DEBUG("device list is:\n");
658
GList *n = g_list_first(dev_list);
649
GList *n = g_list_first(parms->dev_list);
660
651
gchar *device = (gchar*)n->data;
661
652
(void)device; // Avoid unused var message
664
655
n = g_list_next(n);
667
LOG_DEBUG("encoder_pipeline (from GConf)=%s\n",enc_pipeline);
668
LOG_DEBUG("filename=%s\n", output_filename);
669
LOG_DEBUG("append_to_file=%s\n", (append_to_file ? "TRUE" : "FALSE"));
658
LOG_DEBUG("profile from GConf=%s\n",parms->profile_str);
659
LOG_DEBUG("filename=%s\n", parms->filename);
660
LOG_DEBUG("append to file=%s\n", (parms->append ? "TRUE" : "FALSE"));
672
GstElement *pipeline = pipeline_create(audio_source, dev_list, enc_pipeline, "filesink", &err_msg);
662
// Create pipeline from the parms
663
GstElement *pipeline = pipeline_create(parms, &err_msg);
675
666
if (!GST_IS_PIPELINE(pipeline) || err_msg) {
679
// Get "output-sink" element
680
GstElement *filesink = gst_bin_get_by_name(GST_BIN(pipeline), "output-sink");
670
// Get "filesink" and set location (file name) and append mode
671
GstElement *filesink = gst_bin_get_by_name(GST_BIN(pipeline), "filesink");
682
673
if (!GST_IS_ELEMENT(filesink)) {
683
674
err_msg = g_strdup_printf(_("Cannot find audio element %s.\n"), "filesink");
687
// And set location (filename) and append mode
688
g_object_set(G_OBJECT(filesink), "location", output_filename, NULL);
689
g_object_set(G_OBJECT(filesink), "append", append_to_file, NULL);
678
g_object_set(G_OBJECT(filesink), "location", parms->filename, NULL);
679
g_object_set(G_OBJECT(filesink), "append", parms->append, NULL);
691
680
g_object_unref(filesink);
693
682
// Add a message handler
718
707
err_msg = g_strdup(_("Cannot start reading from the stream/pipeline.\n"));
721
LOG_DEBUG("Pipeline is OK. Starting recording to %s.\n", output_filename);
710
LOG_DEBUG("Pipeline is OK. Starting recording to %s.\n", parms->filename);
713
// gst_element_get_state(pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
724
716
// Are we finally ok?
758
750
// Valid pipeline?
759
751
if (!GST_IS_ELEMENT(g_pipeline)) return NULL;
761
// Get the "output-sink" element (by name)
762
GstElement *filesink = gst_bin_get_by_name(GST_BIN(g_pipeline), "output-sink");
753
// Get the "filesink" element (by name)
754
GstElement *filesink = gst_bin_get_by_name(GST_BIN(g_pipeline), "filesink");
765
757
if (!GST_IS_ELEMENT(filesink)) return NULL;
960
void rec_treshold_message(GstClockTime timestamp, gboolean above, gdouble threshold) {
961
// Listener module calls this function to notify the recorder about level change.
962
// The signal level is below/above the threshold.
964
g_print("Timestamp=%" GST_TIME_FORMAT " above=%s threshold=%3.3f\n",
965
GST_TIME_ARGS(timestamp), (above ? "TRUE" : "FALSE") , threshold);