~audio-recorder/audio-recorder/trunk

« back to all changes in this revision

Viewing changes to src/main.c

  • Committer: Osmo Antero
  • Date: 2011-09-18 09:13:24 UTC
  • Revision ID: osmoma@gmail.com-20110918091324-wosqw4bzzhhyqz6m
VersionĀ 0.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
#include "support.h"
23
23
#include "audio-sources.h"
24
24
#include "rec-window.h"
 
25
#include "dbus-service.h"
25
26
#include "audio-sources.h"
26
27
#include "media-profiles.h"
27
28
#include "timer.h"
41
42
static guint g_show_window = -1;
42
43
static guint g_show_tray_icon = -1;
43
44
static guint g_debug_levels = -1;
 
45
static gchar *g_command_arg = NULL;
 
46
 
44
47
static GOptionEntry option_entries[] = {
45
48
    // Translators: This is a command line option.
46
49
    { "show-window", 'w', 0, G_OPTION_ARG_INT, &g_show_window, N_("Show application window at startup (0=hide main window, 1=force display of main window)."), NULL},
51
54
    // Translators: This is a command line option.
52
55
    // Output audio level values in a terminal window. This makes it easier to set correct level (dB or %) value in the Timer.
53
56
    { "debug-signal", 'd', 0, G_OPTION_ARG_INT, &g_debug_levels, N_("List signal level values in a terminal window (0=do not list values, 1=list values)."), NULL},
 
57
 
 
58
    // Translators: This is a command line option. Notice: Do not translate the "identity|status|start|stop|pause|show|quit" words.
 
59
    // Control the recorder from command line with --command argument.
 
60
    // --command=identity returns the program name and version.
 
61
    // --command=status returns one of: "not running" | "on" | "off" | "paused".
 
62
    { "command", 'c', 0, G_OPTION_ARG_STRING, &g_command_arg, N_("Send a command to the recorder; identity|status|start|stop|pause|show|hide|quit."), NULL},
 
63
 
54
64
    { NULL },
55
65
};
56
66
 
57
67
static void *win_update_gui_ex(gpointer user_data);
58
68
static void *win_set_filename_ex(gpointer user_data);
59
69
static void *win_set_error_text_ex(gpointer user_data);
 
70
static void *win_show_window_ex(gpointer user_data);
60
71
static gboolean win_delete_cb(GtkWidget *widget, GdkEvent *event, gpointer data);
61
72
 
 
73
static void *send_client_request(gpointer data);
 
74
 
62
75
static void win_call_gui_func(GThreadFunc func, gpointer user_data) {
63
76
    // Create a thread to call GUI (GTK) related functions.
64
77
    // GUI functions are called from many places (inside/outside threads) and we have to set gdk_threads_enter() and gdk_threads_leave().
85
98
 
86
99
    rec_manager_get_state(&state, &pending);
87
100
 
 
101
    if (state == GST_STATE_PAUSED && pending == GST_STATE_NULL) {
 
102
        state = GST_STATE_NULL;
 
103
    }
 
104
 
 
105
    gchar *image_file = NULL;
88
106
    gchar *label = NULL;
89
 
    gchar *image_file = NULL;
90
107
    gboolean active = FALSE;
91
108
 
92
 
    if (state == GST_STATE_PAUSED && pending == GST_STATE_NULL) {
93
 
        state = GST_STATE_NULL;
94
 
    }
95
 
 
96
109
    switch (state) {
97
110
    case GST_STATE_PLAYING:
98
111
        // Recording is on
99
112
        image_file = (gchar*)get_image_path("audio-recorder-on-small.png");
 
113
 
100
114
        // Translators: This is a button label, also used in the menu.
101
115
        label = _("Stop recording");
102
116
        active = TRUE;
105
119
    case GST_STATE_PAUSED:
106
120
        // Paused
107
121
        image_file = (gchar*)get_image_path("audio-recorder-paused-small.png");
 
122
 
108
123
        // Translators: This is a button label, also used in the menu.
109
124
        label = _("Continue recording");
110
125
        active = TRUE;
114
129
    default:
115
130
        // Stopped/off
116
131
        image_file = (gchar*)get_image_path("audio-recorder-off-small.png");
 
132
 
117
133
        // Translators: This is a button label, also used in the menu.
118
134
        label = _("Start recording");
119
135
        active = FALSE;
122
138
    // Set label
123
139
    if (GTK_IS_BUTTON(g_win.recorder_button)) {
124
140
        gtk_button_set_label(GTK_BUTTON(g_win.recorder_button), label);
125
 
        // Set image
 
141
 
 
142
        // Set image (a small color dot on the button)
126
143
        GtkWidget *image = gtk_image_new_from_file(image_file);
127
144
        gtk_button_set_image(GTK_BUTTON(g_win.recorder_button), image);
128
145
 
129
 
        // TODO: Should we unref image?
130
 
 
 
146
        // TODO: Should we unref the image?
131
147
    }
 
148
 
132
149
    g_free(image_file);
133
150
 
134
151
    // Reset amplitude/level bar
376
393
}
377
394
 
378
395
void win_show_window(gboolean show) {
379
 
 
380
 
    // Close the about dialog if it's open
 
396
    // Show or hide window
 
397
    win_call_gui_func(win_show_window_ex, GINT_TO_POINTER(show));
 
398
}
 
399
 
 
400
static void *win_show_window_ex(gpointer user_data) {
 
401
    gboolean show = GPOINTER_TO_INT(user_data);
 
402
 
 
403
    // Important: We are calling GTK from a thread. Set lock.
 
404
    gdk_threads_enter();
 
405
 
 
406
    // Close about dialog if open
381
407
    about_destroy_dialog();
382
408
 
383
409
    // Show or hide the main window
384
 
    if (!GTK_IS_WINDOW(g_win.window)) return;
 
410
    if (!GTK_IS_WINDOW(g_win.window)) goto L_END;
385
411
 
386
412
    if (show) {
387
413
        // Show window. Also bring up if window is minimized/iconified.
389
415
        gtk_window_deiconify(GTK_WINDOW(g_win.window));
390
416
        gtk_window_present(GTK_WINDOW(g_win.window));
391
417
    } else {
 
418
        // Close settings dialog if open
 
419
        win_settings_destroy_dialog();
 
420
 
392
421
        // Hide window
393
422
        gtk_widget_hide(g_win.window);
394
423
    }
395
424
 
396
425
    // Update menu on the systray
397
426
    systray_set_menu_items2(show);
 
427
 
 
428
L_END:
 
429
    // Important: We are calling GTK from a thread. Free the lock.
 
430
    gdk_threads_leave();
 
431
 
 
432
    return 0;
398
433
}
399
434
 
400
435
void test_0_cb(GtkWidget *widget, gpointer data) {
558
593
    g_win.window = NULL;
559
594
}
560
595
 
 
596
void win_quit_application() {
 
597
    // Quit this application
 
598
    win_close_button_cb(NULL, (gpointer)TRUE);
 
599
}
 
600
 
 
601
 
561
602
gboolean win_close_button_press_cb(GtkWidget *widget, GdkEventButton *event, gpointer user_data) {
562
603
    // Right click on [Close] button?
563
604
    if (event->button == 3) {
575
616
}
576
617
 
577
618
gboolean win_delete_cb(GtkWidget *widget, GdkEvent *event, gpointer data) {
578
 
    // Called prior to exit.
 
619
    // Called prior exit.
579
620
 
580
621
    LOG_DEBUG("win_delete_cb() called.\n");
581
622
 
 
623
    dbus_service_module_exit();
 
624
 
582
625
    systray_module_exit();
583
626
 
584
627
    rec_manager_exit();
660
703
    // Show on all desktops
661
704
    gtk_window_stick(GTK_WINDOW(g_win.window));
662
705
 
 
706
    // Keep this window on top, above other windows
 
707
    gtk_window_set_keep_above(GTK_WINDOW(g_win.window), TRUE);
 
708
 
663
709
    gtk_window_set_default_icon_name("audio-recorder");
664
710
 
665
711
    gchar *prog_name = get_program_name();
1099
1145
    LOG_DEBUG("Value of --show-icon (-i)=%d\n", g_show_tray_icon);
1100
1146
    LOG_DEBUG("Value of --show-window (-w)=%d\n", g_show_window);
1101
1147
    LOG_DEBUG("Value of --debug-signal (-d)=%d\n", g_debug_levels);
 
1148
    LOG_DEBUG("Value of --command (-c)=%s\n", g_command_arg);
1102
1149
 
1103
1150
    // Initialize the i18n stuff
1104
 
#ifdef ENABLE_NLS
1105
1151
    bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
1106
1152
    bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
1107
1153
    textdomain(GETTEXT_PACKAGE);
1108
 
#endif
 
1154
 
1109
1155
    gtk_set_locale();
1110
1156
 
1111
1157
    // Initialize all modules
1114
1160
 
1115
1161
    g_thread_init(NULL);
1116
1162
    gdk_threads_init();
1117
 
    gdk_threads_enter();
1118
1163
 
1119
1164
    gst_init(&argc, &argv);
1120
1165
 
 
1166
    // Check if user wants to control the recorder (the running instance of the recorder) from the command line.
 
1167
    if (g_command_arg != NULL) {
 
1168
 
 
1169
        // $ audio-recorder --command <argument>
 
1170
 
 
1171
        // Check if we find existing instance of Audio-Recorder. Do not start this program twice.
 
1172
        gchar *identity = dbus_service_client_request("get_identity", NULL); // <-- Should return "Audio Recorder #.#"
 
1173
 
 
1174
        // Got an answer from existing instance?
 
1175
        if (identity != NULL) {
 
1176
            // Send client request (execute methode call over DBus)
 
1177
            send_client_request(g_command_arg);
 
1178
 
 
1179
            g_free(identity);
 
1180
            identity = NULL;
 
1181
 
 
1182
            // And kill this duplicate instance of audio-recorder
 
1183
            exit(0);
 
1184
        }
 
1185
 
 
1186
        g_free(identity);
 
1187
 
 
1188
        // Let this instance run
 
1189
        // ...
 
1190
    }
 
1191
 
 
1192
 
 
1193
    // Simply print program name + version and exit?
 
1194
    if (!g_strcmp0(g_command_arg, "identity")) {
 
1195
        send_client_request(g_command_arg);
 
1196
        // This will call exit(0)
 
1197
    }
 
1198
 
 
1199
    // Simply print recording status (not running | on | off | paused) and exit?
 
1200
    else if (!g_strcmp0(g_command_arg, "status")) {
 
1201
        send_client_request(g_command_arg);
 
1202
        // This will call exit(0)
 
1203
    }
 
1204
 
 
1205
    // Simply quit?
 
1206
    else if (!g_strcmp0(g_command_arg, "quit")) {
 
1207
        send_client_request(g_command_arg);
 
1208
        // This will call exit(0)
 
1209
    }
 
1210
 
 
1211
    // Initialize modules
1121
1212
    rec_manager_init();
1122
1213
 
1123
1214
    audio_sources_init();
1126
1217
 
1127
1218
    timer_module_init();
1128
1219
 
 
1220
    // Setup DBus server for this program
 
1221
    dbus_service_module_init();
 
1222
 
1129
1223
    systray_module_init();
1130
1224
 
1131
1225
    // Show button images (normally not shown in the GNOME)
1133
1227
    GtkSettings *settings = gtk_settings_get_default();
1134
1228
    g_object_set(settings, "gtk-button-images", TRUE, NULL);
1135
1229
 
1136
 
    // Create main window and all widgets
 
1230
    // Create main window and all its widgets
1137
1231
    win_create_window();
1138
1232
 
1139
1233
    // Determine how to display the window and tray icon
1181
1275
        show_window = TRUE;
1182
1276
    }
1183
1277
 
 
1278
 
 
1279
    // Let "--command show" and "--command hide" override the window visibility
 
1280
    if (g_strrstr(g_command_arg, "show")) {
 
1281
        show_window = TRUE;
 
1282
    } 
 
1283
    else if (g_strrstr(g_command_arg, "hide")) {
 
1284
        show_window = FALSE;
 
1285
    }
 
1286
 
 
1287
 
1184
1288
    if (show_window) {
1185
1289
        // Show
1186
1290
        win_show_window(TRUE);
1201
1305
    // Otherwise Media Players and Skype may show up before this app's main window. Skype may even block.
1202
1306
    win_set_device_id();
1203
1307
 
 
1308
    // Send client request (execute method call over DBus).
 
1309
    // We must call this from a thread. Otherwise DBus server (in dbus-service.c) and
 
1310
    // client request (also in dbus-service.c) will conflict & block.
 
1311
    g_thread_create(send_client_request, (gpointer)g_command_arg, FALSE, NULL);
 
1312
 
1204
1313
    // Main loop
 
1314
    gdk_threads_enter();
1205
1315
    gtk_main ();
1206
1316
    gdk_threads_leave();
1207
1317
 
1208
1318
    return 0;
1209
1319
}
1210
1320
 
 
1321
static void *send_client_request(gpointer data) {
 
1322
    // Send command via DBus to the existing instance of audio-recorder
 
1323
    if (!data) return 0;
 
1324
 
 
1325
    // $ audio-recorder --command identity // Print program name + version. Eg. "Audio Recorder 1.0"
 
1326
 
 
1327
    // $ audio-recorder --command start
 
1328
    // $ audio-recorder --command stop
 
1329
    // $ audio-recorder --command pause
 
1330
 
 
1331
    // $ audio-recorder --command status  // Print status; "not running" | "on" | "off" | "paused"
 
1332
 
 
1333
    // $ audio-recorder --command show
 
1334
    // $ audio-recorder --command quit
 
1335
 
 
1336
    // You can also combine
 
1337
    // $ audio-recorder --command start+show
 
1338
    // $ audio-recorder --command stop+hide
 
1339
    // $ audio-recorder --command stop+quit
 
1340
 
 
1341
    // To lower case
 
1342
    gchar *command = g_ascii_strdown((gchar*)data, -1);
 
1343
 
 
1344
    gboolean done = FALSE;
 
1345
    gchar *ret = NULL;
 
1346
 
 
1347
    if (!g_strcmp0(command, "identity")) {
 
1348
 
 
1349
        // Call get_identity(). This should return program name and version.
 
1350
        ret = dbus_service_client_request("get_identity", NULL/*no args*/);
 
1351
        if (!ret) {
 
1352
            // Eg. "Audio Recorder 2.x"
 
1353
            ret = about_program_name();
 
1354
        }
 
1355
        g_print("%s\n", ret);
 
1356
        g_free(ret);
 
1357
        // Exit
 
1358
        exit(0);
 
1359
    }
 
1360
 
 
1361
    else if (!g_strcmp0(command, "status")) {
 
1362
 
 
1363
        // Call get_state()
 
1364
        ret = dbus_service_client_request("get_state", NULL/*no args*/);
 
1365
        if (!ret) {
 
1366
            // Audio-recorder is not running
 
1367
            ret = g_strdup("not running");
 
1368
        }
 
1369
        g_print("%s\n", ret);
 
1370
        g_free(ret);
 
1371
        // Exit
 
1372
        exit(0);
 
1373
    }
 
1374
 
 
1375
    else if (!g_strcmp0(command, "quit")) {
 
1376
 
 
1377
        // Call set_state("quit"). Terminate application.
 
1378
        ret = dbus_service_client_request("set_state", "quit");
 
1379
        g_free(ret);
 
1380
        // Exit
 
1381
        exit(0);
 
1382
    }
 
1383
 
 
1384
    // -------------------------------------------------
 
1385
 
 
1386
    if (g_strrstr(command, "start")) {
 
1387
 
 
1388
        // Call set_state("start")
 
1389
        ret = dbus_service_client_request("set_state", "start");
 
1390
        if (g_strcmp0(ret, "OK")) {
 
1391
            LOG_ERROR("Cannot execute client/dbus request %s.\n", "set_state(\"start\")");
 
1392
        }
 
1393
        g_free(ret);
 
1394
        done = TRUE;
 
1395
    }
 
1396
 
 
1397
    if (g_strrstr(command, "stop")) {
 
1398
 
 
1399
        // Call set_state("stop")
 
1400
        ret = dbus_service_client_request("set_state", "stop");
 
1401
        if (g_strcmp0(ret, "OK")) {
 
1402
            LOG_ERROR("Cannot execute client/dbus request %s.\n", "set_state(\"stop\")");
 
1403
        }
 
1404
        g_free(ret);
 
1405
        done = TRUE;
 
1406
    }
 
1407
 
 
1408
    if (g_strrstr(command, "pause")) {
 
1409
 
 
1410
        // Call set_state("pause")
 
1411
        ret = dbus_service_client_request("set_state", "pause");
 
1412
        if (g_strcmp0(ret, "OK")) {
 
1413
            LOG_ERROR("Cannot execute client/dbus request %s.\n", "set_state(\"pause\")");
 
1414
        }
 
1415
        g_free(ret);
 
1416
        done = TRUE;
 
1417
    }
 
1418
 
 
1419
    if (g_strrstr(command, "show")) {
 
1420
 
 
1421
        // Call set_state("show")
 
1422
        ret = dbus_service_client_request("set_state", "show");
 
1423
        if (g_strcmp0(ret, "OK")) {
 
1424
            LOG_ERROR("Cannot execute client/dbus request %s.\n", "set_state(\"show\")");
 
1425
        }
 
1426
        g_free(ret);
 
1427
        done = TRUE;
 
1428
    }
 
1429
 
 
1430
    if (g_strrstr(command, "hide")) {
 
1431
 
 
1432
        // Call set_state("hide")
 
1433
        ret = dbus_service_client_request("set_state", "hide");
 
1434
        if (g_strcmp0(ret, "OK")) {
 
1435
            LOG_ERROR("Cannot execute client/dbus request %s.\n", "set_state(\"hide\")");
 
1436
        }
 
1437
        g_free(ret);
 
1438
        done = TRUE;
 
1439
    }
 
1440
 
 
1441
    if (g_strrstr(command, "identity")) {
 
1442
 
 
1443
        // Call set_state("start")
 
1444
        ret = dbus_service_client_request("get_identity", NULL/*no args*/);
 
1445
        if (!ret) {
 
1446
            LOG_ERROR("Cannot execute client/dbus request %s.\n", "get_identity()");
 
1447
        }
 
1448
        g_print("%s\n", ret);
 
1449
        g_free(ret);
 
1450
        done = TRUE;
 
1451
    }
 
1452
 
 
1453
    if (g_strrstr(command, "status")) {
 
1454
 
 
1455
        // Call get_state()
 
1456
        ret = dbus_service_client_request("get_state", NULL /*no args*/);
 
1457
        if (!ret) {
 
1458
            // Audio-recorder is not running
 
1459
            ret = g_strdup("not running");
 
1460
        }
 
1461
        // Print state; not running|on|off|paused
 
1462
        g_print("%s\n", ret);
 
1463
        g_free(ret);
 
1464
        done = TRUE;
 
1465
    }
 
1466
 
 
1467
    if (!done) {
 
1468
        LOG_ERROR("Invalid argument in --command=%s. See --help for more information.\n", command);
 
1469
    }
 
1470
 
 
1471
    g_free(command);
 
1472
 
 
1473
    // FALSE: Remove idle function
 
1474
    return 0;
 
1475
}
 
1476
 
 
1477