~audio-recorder/audio-recorder/trunk

« back to all changes in this revision

Viewing changes to src/rec-manager.c

  • Committer: Osmo Antero
  • Date: 2012-09-29 18:12:44 UTC
  • Revision ID: osmoma@gmail.com-20120929181244-gmrxd5xww9pua60a
Support new systems; Ubuntu 12.10, Fedora 18. Improved timer and VAD-modules. Better gst-pipeline.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
*/
19
19
#include "rec-window.h"
20
20
#include "rec-manager.h"
 
21
#include "rec-manager-struct.h"
21
22
#include "log.h"
22
23
#include "dconf.h"
23
24
#include "utility.h"
28
29
// Command queue
29
30
static GAsyncQueue *g_cmd_queue = NULL;
30
31
 
31
 
// Set this to TRUE and the queue thread will stop and exit
32
 
static gboolean g_rec_manager_stop = FALSE;
33
 
 
34
32
// Last used/saved command
35
33
static RecorderCommand *g_last_rec_cmd = NULL;
36
34
 
37
 
static void rec_manager_start_command_thread();
 
35
// Message thread
 
36
static guint g_thread_id = 0;
 
37
 
38
38
static void rec_manager_free_command(RecorderCommand *cmd);
39
39
 
40
 
static void *rec_manager_command_thread(gpointer user_data);
41
 
 
42
 
// This is called from media players on the DBus
43
 
void dbus_player_data_function(MediaPlayerRec *media_player);
 
40
static gboolean rec_manager_command_thread(gpointer user_data);
44
41
 
45
42
void rec_manager_init() {
46
43
    LOG_DEBUG("Init rec-manager.c.\n");
49
46
    // Ref: http://www.gtk.org/api/2.6/glib/glib-Asynchronous-Queues.html
50
47
    g_cmd_queue = g_async_queue_new();
51
48
 
52
 
    g_rec_manager_stop = FALSE;
53
 
    rec_manager_start_command_thread();
 
49
    // Message thread within GTK's main loop
 
50
    // Ref: http://developer.gnome.org/glib/2.31/glib-The-Main-Event-Loop.html
 
51
    g_thread_id =  g_timeout_add_full(G_PRIORITY_DEFAULT, 200, rec_manager_command_thread, NULL, NULL);
54
52
 
55
53
    // Init recorder.c
56
54
    rec_module_init();
57
 
 
58
 
    // Set callback function so we receive messages from DBus/Media Players
59
 
    dbus_player_set_callback_func(dbus_player_data_function/*Function in this module*/);
60
55
}
61
56
 
62
57
void rec_manager_exit() {
65
60
    // Clean up recorder.c
66
61
    rec_module_exit();
67
62
 
68
 
    // Stop the command thread
69
 
    g_rec_manager_stop = TRUE;
70
 
    rec_manager_send_command_ex(RECORDING_QUIT_LOOP, NULL, NULL, NULL, 0, 0, 0);
71
 
 
72
 
    g_usleep(1000000/5);
 
63
    // Remove command thread
 
64
    g_source_remove(g_thread_id);
 
65
    g_thread_id = 0;
73
66
 
74
67
    // Unref message queue
75
 
    if (g_cmd_queue)
 
68
    if (g_cmd_queue) {
76
69
        g_async_queue_unref(g_cmd_queue);
 
70
    }
 
71
    g_cmd_queue = NULL;
77
72
 
78
 
    // Free the saved g_last_rec_cmd
 
73
    // Free g_last_rec_cmd
79
74
    rec_manager_free_command(g_last_rec_cmd);
80
75
    g_last_rec_cmd = NULL;
81
76
}
82
77
 
 
78
//external_data_function_t rec_get_external_data_function() {
 
79
    // Returen pointer to data function so other modules (media players, skype, etc.) can send messages to the queue.
 
80
//    return rec_manager_send_command;
 
81
//}
 
82
 
83
83
void rec_manager_print_command(RecorderCommand *cmd) {
84
84
    if (!cmd) return;
85
85
 
134
134
    }
135
135
}
136
136
 
137
 
void dbus_player_data_function(MediaPlayerRec *media_player) {
138
 
    // This is called from media players on the DBus (see dbus_player.c module).
139
 
    // Map the MediaPlayerRec data to this module.
140
 
 
141
 
    if (!media_player) return;
142
 
 
143
 
    dbus_player_debug_print(media_player);
144
 
 
145
 
    /*
146
 
    TODO: Check this.
147
 
    Removed by moma 17.04.2012
148
 
    
149
 
    // MediaPlayer is active?
150
 
    if (!media_player->active) {
151
 
        // No.
152
 
        // Stop recording and return
153
 
        rec_manager_stop_recording();
154
 
        return;
155
 
    }
156
 
    */
157
 
 
158
 
    // Create a message and send it to the queue.
159
 
 
160
 
    // Pointer to TrackInfo
161
 
    TrackInfo *track = &media_player->track;
162
 
 
163
 
    // MediaPlayer changed status.
164
 
    // Check its status.
165
 
    if (track->status == PLAYER_STATUS_PAUSED) {
166
 
 
167
 
        // Send RECORDING_PAUSE message to the queue
168
 
        rec_manager_send_command_ex(RECORDING_PAUSE, track->track/*track*/,
169
 
                                    track->artist/*artist*/,
170
 
                                    track->album/*album*/,
171
 
                                    track->current_secs/*track_pos*/,
172
 
                                    track->total_secs/*track_len*/,
173
 
                                    track->flags/*flags*/);
174
 
 
175
 
    } else if (track->status == PLAYER_STATUS_PLAYING) {
176
 
 
177
 
        // Send RECORDING_START message to the queue
178
 
        rec_manager_send_command_ex(RECORDING_START, track->track/*track*/,
179
 
                                    track->artist/*artist*/,
180
 
                                    track->album/*album*/,
181
 
                                    track->current_secs/*track_pos*/,
182
 
                                    track->total_secs/*track_len*/,
183
 
                                    track->flags/*flags*/);
184
 
 
185
 
    } else if (track->status == PLAYER_STATUS_NOTIFY_MSG) {
186
 
 
187
 
        // Send RECORDING_NOTIFY_MSG message to the queue
188
 
        rec_manager_send_command_ex(RECORDING_NOTIFY_MSG, track->track/*track*/,
189
 
                                    track->artist/*artist*/,
190
 
                                    track->album/*album*/,
191
 
                                    track->current_secs/*track_pos*/,
192
 
                                    track->total_secs/*track_len*/,
193
 
                                    track->flags/*flags*/);
194
 
 
195
 
    } else {
196
 
        // track.status == PLAYER_STATUS_CLOSED ||
197
 
        // track.status == PLAYER_STATUS_STOPPED
198
 
 
199
 
        // Send RECORDING_STOP message to the queue
200
 
        rec_manager_send_command_ex(RECORDING_STOP, track->track/*track*/,
201
 
                                    track->artist/*artist*/,
202
 
                                    track->album/*album*/,
203
 
                                    track->current_secs/*track_pos*/,
204
 
                                    track->total_secs/*track_len*/,
205
 
                                    track->flags/*flags*/);
206
 
    }
207
 
}
208
 
 
209
137
gint64 rec_manager_get_stream_time() {
210
138
    // Get and return current recording time (stream time) in seconds.
211
139
    return rec_get_stream_time();
229
157
        return "PAUSED";
230
158
 
231
159
    case GST_STATE_PLAYING:
232
 
        return "PLAYING";
 
160
        return "RECORDING ON";
233
161
 
234
162
    case GST_STATE_READY:
235
 
        return "READY";
 
163
        return "IN READY STATE";
236
164
 
237
165
    case GST_STATE_NULL:
238
 
        return "NULL";
 
166
        return "RECORDING OFF";
239
167
 
240
168
    default:
241
169
        return "UNKNOWN STATE";
331
259
}
332
260
 
333
261
void rec_manager_continue_recording() {
334
 
    // Send RECORDING_CONTINUE message to the queue (Continues paused recording. This does not restart if recording is off)
 
262
    // Send RECORDING_CONTINUE message to the queue (Continues paused recording. This does not start if recording is off)
335
263
    rec_manager_send_command_ex(RECORDING_CONTINUE, NULL/*track*/, NULL/*artist*/, NULL/*album*/, 0/*track_pos*/, 0/*track_len*/, 0/*flags*/);
336
264
}
337
265
 
383
311
    g_async_queue_push(g_cmd_queue, (gpointer)cmd);
384
312
}
385
313
 
386
 
static void rec_manager_start_command_thread() {
387
 
    // Create a work thread to handle all incoming messages/commands
388
 
    GError *error = NULL;
389
 
 
390
 
    GThread *gthread = g_thread_create(rec_manager_command_thread, NULL, FALSE, &error);
391
 
    if (!gthread || error) {
392
 
        LOG_ERROR("Cannot start command thread. This program has terminated. %s\n", (error ? error->message : ""));
393
 
        if (error)
394
 
            g_error_free(error);
395
 
 
396
 
        // This is a fatal error
397
 
        exit(0);
 
314
gboolean rec_manager_command_thread(gpointer user_data) {
 
315
    // Read next command from the queue
 
316
    RecorderCommand *cmd = (RecorderCommand*)g_async_queue_try_pop(g_cmd_queue);
 
317
    if (!cmd) {
 
318
        // TRUE: Continue calling this function
 
319
        return TRUE;
398
320
    }
399
 
}
400
 
 
401
 
void *rec_manager_command_thread(gpointer user_data) {
402
 
#define TIMEOUT_USECONDS (5*G_USEC_PER_SEC)
403
 
 
404
 
    while (!g_rec_manager_stop) {
405
 
 
406
 
        RecorderCommand *cmd = NULL;
407
 
 
408
 
        // Glib version is < 2.31.20?
409
 
        // Ref: http://developer.gnome.org/glib/2.30/glib-Version-Information.html
410
 
        //      http://ftp.gnome.org/pub/gnome/sources/glib/
411
 
        //
412
 
        // $ pkg-config --modversion glib-2.0
413
 
        //
414
 
#if (!GLIB_CHECK_VERSION(2, 31, 18))
415
 
        // Glib version is < 2.31.18.
416
 
        // We must use the older g_async_queue_timed_pop(...) function.
417
 
 
418
 
        // Get current time
419
 
        GTimeVal time;
420
 
        g_get_current_time(&time);
421
 
        g_time_val_add(&time, TIMEOUT_USECONDS/*in micro seconds*/);
422
 
 
423
 
        // Read next command from the queue
424
 
        cmd = (RecorderCommand*)g_async_queue_timed_pop(g_cmd_queue, &time);
425
 
#else
426
 
        // Glib version is >= 2.31.18.
427
 
        // We use the newer g_async_queue_timeout_pop(...) function.
428
 
 
429
 
        // Read next command from the queue
430
 
        cmd = (RecorderCommand*)g_async_queue_timeout_pop(g_cmd_queue, TIMEOUT_USECONDS/*in micro seconds*/);
431
 
#endif
432
 
 
433
 
        if (!cmd) continue;
434
 
 
435
 
        // Debug print
 
321
 
 
322
    // Debug print
436
323
#ifdef ACTIVE_DEBUGGING
437
 
        rec_manager_print_command(cmd);
 
324
    rec_manager_print_command(cmd);
438
325
#endif
439
326
 
440
 
        if (cmd->type == RECORDING_START) {
441
 
            // Save the values so gst-recorder.c can grab them
442
 
            conf_save_string_value("track/track-name", check_null(cmd->track));
443
 
            conf_save_int_value("track/track-pos", cmd->track_pos);
444
 
            conf_save_int_value("track/track-len", cmd->track_len);
445
 
            conf_save_string_value("track/artist-name", check_null(cmd->artist));
446
 
            conf_save_string_value("track/album-name", check_null(cmd->album));
447
 
        }
448
 
 
449
 
        // Verify the delete flag and filename
450
 
        gboolean del_flag = FALSE;
451
 
        if (cmd->flags == RECORDING_DELETE_FILE) {
452
 
            gchar *filename = NULL;
453
 
            conf_get_string_value("track/last-track-name", &filename);
454
 
 
455
 
            // Remove path and file extension
456
 
            gchar *path=NULL;
457
 
            gchar *base = NULL;
458
 
            gchar *ext = NULL;
459
 
            split_filename3(filename, &path, &base, &ext);
460
 
 
461
 
            // Filenames do match?
462
 
            del_flag = (filename && !g_strcmp0(base, cmd->track));
463
 
 
464
 
            g_free(path);
465
 
            g_free(base);
466
 
            g_free(ext);
467
 
            g_free(filename);
468
 
        }
469
 
 
470
 
        switch (cmd->type) {
471
 
        case RECORDING_STOP:
472
 
            rec_stop_recording(del_flag/*delete file?*/);
473
 
            break;
474
 
 
475
 
        case RECORDING_START:
476
 
            rec_start_recording();
477
 
            break;
478
 
 
479
 
        case RECORDING_PAUSE:
480
 
            rec_pause_recording();
481
 
            break;
482
 
 
483
 
        case RECORDING_CONTINUE:
484
 
            rec_continue_recording();
485
 
            break;
486
 
 
487
 
        case RECORDING_NOTIFY_MSG:
488
 
            win_set_error_text(cmd->track);
489
 
            break;
490
 
 
491
 
        case RECORDING_SHOW_WINDOW:
492
 
            win_show_window(TRUE);
493
 
            break;
494
 
 
495
 
        case RECORDING_HIDE_WINDOW:
496
 
            win_show_window(FALSE);
497
 
            break;
498
 
 
499
 
        case RECORDING_QUIT_LOOP:
500
 
            rec_stop_recording(FALSE);
501
 
            g_rec_manager_stop = TRUE;
502
 
            break;
503
 
 
504
 
        case RECORDING_QUIT_APP:
505
 
            rec_stop_recording(FALSE);
506
 
 
507
 
            // Quit application
508
 
            win_quit_application();
509
 
            break;
510
 
 
511
 
        } // switch ...
512
 
 
513
 
        // Free the lastly saved command
514
 
        rec_manager_free_command(g_last_rec_cmd);
515
 
 
516
 
        // Save this command
517
 
        g_last_rec_cmd = cmd;
518
 
 
519
 
    } // while ...
520
 
 
521
 
    LOG_DEBUG("rec_manager_command_thread: Command thread has terminated.\n");
522
 
    g_thread_exit(0);
523
 
    return 0;
 
327
    if (cmd->type == RECORDING_START) {
 
328
        // Save the values so gst-recorder.c can grab them
 
329
        conf_save_string_value("track/track-name", check_null(cmd->track));
 
330
        conf_save_int_value("track/track-pos", cmd->track_pos);
 
331
        conf_save_int_value("track/track-len", cmd->track_len);
 
332
        conf_save_string_value("track/artist-name", check_null(cmd->artist));
 
333
        conf_save_string_value("track/album-name", check_null(cmd->album));
 
334
    }
 
335
 
 
336
    // Verify the delete flag and filename
 
337
    gboolean del_flag = FALSE;
 
338
    if (cmd->flags == RECORDING_DELETE_FILE) {
 
339
        gchar *filename = NULL;
 
340
        conf_get_string_value("track/last-track-name", &filename);
 
341
 
 
342
        // Remove path and file extension
 
343
        gchar *path=NULL;
 
344
        gchar *base = NULL;
 
345
        gchar *ext = NULL;
 
346
        split_filename3(filename, &path, &base, &ext);
 
347
 
 
348
        // Filenames do match?
 
349
        del_flag = (filename && !g_strcmp0(base, cmd->track));
 
350
 
 
351
        g_free(path);
 
352
        g_free(base);
 
353
        g_free(ext);
 
354
        g_free(filename);
 
355
    }
 
356
 
 
357
    switch (cmd->type) {
 
358
    case RECORDING_STOP:
 
359
        rec_stop_recording(del_flag/*delete file?*/);
 
360
        break;
 
361
 
 
362
    case RECORDING_START:
 
363
        rec_start_recording();
 
364
        break;
 
365
 
 
366
    case RECORDING_PAUSE:
 
367
        rec_pause_recording();
 
368
        break;
 
369
 
 
370
    case RECORDING_CONTINUE:
 
371
        rec_continue_recording();
 
372
        break;
 
373
 
 
374
    case RECORDING_NOTIFY_MSG:
 
375
        win_set_error_text(cmd->track);
 
376
        break;
 
377
 
 
378
    case RECORDING_SHOW_WINDOW:
 
379
        win_show_window(TRUE);
 
380
        break;
 
381
 
 
382
    case RECORDING_HIDE_WINDOW:
 
383
        win_show_window(FALSE);
 
384
        break;
 
385
 
 
386
    case RECORDING_QUIT_LOOP:
 
387
        rec_stop_recording(FALSE);
 
388
        break;
 
389
 
 
390
    case RECORDING_QUIT_APP:
 
391
        rec_stop_recording(FALSE);
 
392
 
 
393
        // Quit application
 
394
        win_quit_application();
 
395
        break;
 
396
 
 
397
    } // switch ...
 
398
 
 
399
    // Free the lastly saved command
 
400
    rec_manager_free_command(g_last_rec_cmd);
 
401
 
 
402
    // Save this command
 
403
    g_last_rec_cmd = cmd;
 
404
 
 
405
    // TRUE: Continue calling this function
 
406
    return TRUE;
524
407
}
525
408
 
526
409