1 /* gtkui.c - GTK+ GUI implementation
2 *
3 * Copyright 2010 Petteri Hintsanen <petterih@iki.fi>
4 *
5 * This file is part of abx.
6 *
7 * abx is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * abx is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 * License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with abx. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "gtkui.h"
22 #include "test.h"
23 #include <stdlib.h>
24
25 int current_trial; /* Current test trial, or -1 if there
26 * is no test in progress. */
27 Metadata metadata_a; /* Metadata for sample A. */
28 Metadata metadata_b; /* Metadata for sample B. */
29 gchar *basename_a; /* Basename for file A. */
30 gchar *basename_b; /* Basename for file B. */
31
32 static gint ntrials = 10;
33 static gint outdev = -1;
34
35
36 /*
37 * Parse command line options.
38 */
39 static void
parse_options(int * argc,char ** argv[])40 parse_options(int *argc, char **argv[])
41 {
42 GError *error = NULL;
43 GOptionContext *context;
44
45 GOptionEntry entries[] = {
46 { "num-trials", 'i', 0, G_OPTION_ARG_INT, &ntrials,
47 "Do N trials.", "N" },
48 { "audio-device", 'd', 0, G_OPTION_ARG_INT, &outdev,
49 "Use PortAudio audio device ID", "ID" },
50 { NULL }
51 };
52
53 context = g_option_context_new("[SAMPLE-A SAMPLE-B]");
54 g_option_context_set_summary
55 (context, "Test for audible differences in fidelity between "
56 "two audio samples\nwith ABX test.");
57 g_option_context_set_description
58 (context, "Report bugs to <petterih@iki.fi>.");
59 g_option_context_add_main_entries(context, entries, NULL);
60 g_option_context_add_group(context, gtk_get_option_group(TRUE));
61 if (!g_option_context_parse(context, argc, argv, &error))
62 {
63 g_error("option parsing failed: %s\n", error->message);
64 }
65
66 /* ntrials must be positive */
67 if (ntrials < 0) ntrials = 0;
68 }
69
70 /*
71 * Initialize GTK+, init a new test with command-line arguments (if
72 * needed), and pass control for GTK+.
73 */
74 void
ui_main(int argc,char * argv[])75 ui_main(int argc, char *argv[])
76 {
77 parse_options(&argc, &argv);
78 gtk_init(&argc, &argv);
79
80 if (argc >= 3) {
81 switch (init_test(argv[1], argv[2], ntrials, outdev)) {
82 case 0:
83 /* test init successful */
84 show_main_window();
85 reset_test();
86 break;
87 case 1:
88 error_dialog(main_window,
89 "An error occurred while setting up playback "
90 "for the first sample.");
91 return;
92 case 2:
93 error_dialog(main_window,
94 "An error occurred while setting up playback "
95 "for the second sample.");
96 return;
97 case 3:
98 error_dialog
99 (main_window, "The given samples have "
100 "different durations. Both samples must have "
101 "exactly the same duration.");
102 return;
103 case 4:
104 error_dialog
105 (main_window, "Invalid number of trials given in "
106 "the command line.");
107 return;
108 }
109 } else {
110 /* no current test available */
111 current_trial = -1;
112 show_main_window();
113 }
114
115 gtk_main();
116 }
117
118 /*
119 * Display a simple error dialog with the given parent window and
120 * error message.
121 */
122 void
error_dialog(GtkWidget * parent_win,char * msg)123 error_dialog(GtkWidget *parent_win, char *msg)
124 {
125 GtkWidget *errdialog;
126 errdialog = gtk_message_dialog_new
127 (GTK_WINDOW(parent_win), GTK_DIALOG_DESTROY_WITH_PARENT,
128 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s", msg);
129 gtk_window_set_title(GTK_WINDOW(errdialog), "Error");
130 gtk_dialog_run(GTK_DIALOG(errdialog));
131 gtk_widget_destroy(errdialog);
132 }
133
134 /*
135 * Reset test parameters (current trial and metadata). Close and
136 * destroy possibly open windows, and update the main window. This
137 * function is usually called after a new test has been successfully
138 * initialized.
139 */
140 void
reset_test(void)141 reset_test(void)
142 {
143 if (basename_a) g_free(basename_a);
144 if (basename_b) g_free(basename_b);
145 current_trial = 0;
146 get_metadatas(&metadata_a, &metadata_b);
147 basename_a = g_path_get_basename(metadata_a.filename);
148 basename_b = g_path_get_basename(metadata_b.filename);
149 hide_decide_dialog();
150 hide_result_window();
151 update_main_window();
152 }
153