1 /*
2 * Sweep, a sound wave editor.
3 *
4 * Copyright (C) 2000 Conrad Parker
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
24
25 #include <stdio.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <glib.h>
29 #include <gdk/gdkkeysyms.h>
30 #include <gtk/gtk.h>
31
32 #include <sweep/sweep_i18n.h>
33 #include <sweep/sweep_types.h>
34 #include <sweep/sweep_sample.h>
35
36 #include "interface.h"
37
38 #include "../pixmaps/scrubby.xpm"
39 #include "../pixmaps/scrubby_system.xpm"
40
41 static gboolean up_and_running = FALSE;
42
43 static void
question_dialog_destroy_cb(GtkWidget * widget,gpointer data)44 question_dialog_destroy_cb (GtkWidget * widget, gpointer data)
45 {
46 GtkWidget * dialog;
47 sw_sample * sample;
48 gboolean quit_if_no_files = FALSE;
49
50 dialog = gtk_widget_get_toplevel (widget);
51
52 quit_if_no_files = (gboolean)
53 GPOINTER_TO_INT(g_object_get_data (G_OBJECT(widget), "quit_nofiles"));
54
55 sample = g_object_get_data (G_OBJECT(dialog), "default");
56 if (sample && sample_bank_contains (sample)) {
57 sample_set_edit_mode (sample, SWEEP_EDIT_MODE_READY);
58 }
59
60 if (quit_if_no_files || !up_and_running)
61 sample_bank_remove (NULL);
62 }
63
64 static void
question_dialog_answer_cb(GtkWidget * widget,gpointer data)65 question_dialog_answer_cb (GtkWidget * widget, gpointer data)
66 {
67 GtkWidget * dialog;
68 GCallback(*func) (GtkWidget* widget, gpointer data);
69
70 up_and_running = TRUE;
71
72 func = g_object_get_data (G_OBJECT(widget), "default");
73 dialog = gtk_widget_get_toplevel (widget);
74
75 if (func != NULL)
76 func (widget, data);
77
78 /* "destroy" will call destroy above */
79
80 gtk_widget_destroy (dialog);
81 }
82
83 static void
query_dialog_new(sw_sample * sample,char * title,char * question,gboolean show_cancel,char * ok_answer,char * no_answer,GCallback ok_callback,gpointer ok_callback_data,GCallback no_callback,gpointer no_callback_data,gpointer xpm_data,gboolean quit_if_no_files)84 query_dialog_new (sw_sample * sample, char * title, char * question,
85 gboolean show_cancel, char * ok_answer, char * no_answer,
86 GCallback ok_callback, gpointer ok_callback_data,
87 GCallback no_callback, gpointer no_callback_data,
88 gpointer xpm_data, gboolean quit_if_no_files)
89 {
90 gchar * new_title;
91
92 GtkWidget * window;
93 GtkWidget * button, * ok_button;
94 GtkWidget * vbox;
95 GtkWidget * hbox;
96 GtkWidget * label;
97 GtkWidget * pixmap;
98
99 window = gtk_dialog_new ();
100 sweep_set_window_icon (GTK_WINDOW(window));
101
102 new_title = g_strdup_printf ("%s: %s", "Sweep", title);
103 gtk_window_set_title (GTK_WINDOW(window), new_title);
104 g_free (new_title);
105
106 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_MOUSE);
107 gtk_container_set_border_width (GTK_CONTAINER(window), 8);
108
109 g_object_set_data (G_OBJECT(window), "default", sample);
110
111 g_signal_connect (G_OBJECT(window), "destroy",
112 G_CALLBACK(question_dialog_destroy_cb), window);
113
114 attach_window_close_accel(GTK_WINDOW(window));
115
116 g_object_set_data (G_OBJECT(window), "quit_nofiles",
117 GINT_TO_POINTER((gint)quit_if_no_files));
118
119 vbox = GTK_DIALOG(window)->vbox;
120
121 /* Question */
122
123 hbox = gtk_hbox_new (FALSE, 0);
124 gtk_box_pack_start (GTK_BOX(vbox), hbox, TRUE, FALSE, 0);
125 gtk_container_set_border_width (GTK_CONTAINER(hbox), 12);
126 gtk_widget_show (hbox);
127
128 if (xpm_data == NULL) xpm_data = scrubby_xpm;
129
130 pixmap = create_widget_from_xpm (window, xpm_data);
131 gtk_box_pack_start (GTK_BOX(hbox), pixmap, FALSE, FALSE, 12);
132 gtk_widget_show (pixmap);
133
134 label = gtk_label_new (question);
135 gtk_box_pack_start (GTK_BOX(hbox), label, TRUE, FALSE, 12);
136 gtk_widget_show (label);
137
138 /* New layout of buttons */
139
140 gtk_button_box_set_layout (GTK_BUTTON_BOX(GTK_DIALOG(window)->action_area), GTK_BUTTONBOX_SPREAD);
141
142 /* OK */
143
144 if (ok_answer == NULL) ok_answer = _("OK");
145 ok_button = gtk_button_new_with_label (ok_answer);
146 GTK_WIDGET_SET_FLAGS (GTK_WIDGET (ok_button), GTK_CAN_DEFAULT);
147 gtk_box_pack_start (GTK_BOX (GTK_DIALOG(window)->action_area),
148 ok_button, TRUE, TRUE, 0);
149 g_object_set_data (G_OBJECT(ok_button), "default", ok_callback);
150 gtk_widget_show (ok_button);
151 g_signal_connect (G_OBJECT(ok_button), "clicked",
152 G_CALLBACK (question_dialog_answer_cb),
153 ok_callback_data);
154
155 /* Cancel */
156
157 if (show_cancel) {
158 if (no_answer == NULL) no_answer = _("Cancel");
159 button = gtk_button_new_with_label (no_answer);
160 GTK_WIDGET_SET_FLAGS (GTK_WIDGET (button), GTK_CAN_DEFAULT);
161 gtk_box_pack_start (GTK_BOX (GTK_DIALOG(window)->action_area),
162 button, TRUE, TRUE, 0);
163 g_object_set_data (G_OBJECT(button), "default", no_callback);
164 gtk_widget_show (button);
165 g_signal_connect (G_OBJECT(button), "clicked",
166 G_CALLBACK (question_dialog_answer_cb),
167 no_callback_data);
168 }
169
170 gtk_widget_grab_default (ok_button);
171
172 gtk_widget_show (window);
173 }
174
175 void
question_dialog_new(sw_sample * sample,char * title,char * question,char * yes_answer,char * no_answer,GCallback yes_callback,gpointer yes_callback_data,GCallback no_callback,gpointer no_callback_data,sw_edit_mode edit_mode)176 question_dialog_new (sw_sample * sample, char * title, char * question,
177 char * yes_answer, char * no_answer,
178 GCallback yes_callback, gpointer yes_callback_data,
179 GCallback no_callback, gpointer no_callback_data,
180 sw_edit_mode edit_mode)
181 {
182 if (edit_mode != SWEEP_EDIT_MODE_READY)
183 sample_set_edit_mode (sample, edit_mode);
184
185 query_dialog_new (sample, title, question, TRUE, yes_answer, no_answer,
186 yes_callback, yes_callback_data,
187 no_callback, no_callback_data, NULL, FALSE);
188 }
189
190 /* Thread safe info dialogs */
191
192 typedef struct {
193 char * title;
194 char * message;
195 gpointer xpm_data;
196 } info_dialog_data;
197
198 static gint
do_info_dialog(gpointer data)199 do_info_dialog (gpointer data)
200 {
201 info_dialog_data * id = (info_dialog_data *)data;
202
203 query_dialog_new (NULL, id->title, id->message, FALSE,
204 _("OK"), NULL, NULL, NULL,
205 NULL, NULL, id->xpm_data, TRUE);
206
207 g_free (id->title);
208 g_free (id->message);
209
210 return FALSE;
211 }
212
213 void
info_dialog_new(char * title,gpointer xpm_data,const char * fmt,...)214 info_dialog_new (char * title, gpointer xpm_data, const char * fmt, ...)
215 {
216 info_dialog_data * id;
217 va_list ap;
218 #define BUF_LEN 512
219 char buf[BUF_LEN];
220
221 va_start (ap, fmt);
222 vsnprintf (buf, BUF_LEN, fmt, ap);
223 va_end (ap);
224
225 id = g_malloc (sizeof (info_dialog_data));
226 id->title = g_strdup (title);
227 id->message = g_strdup (buf);
228 id->xpm_data = xpm_data;
229
230 sweep_timeout_add ((guint32)0, (GtkFunction)do_info_dialog, id);
231 }
232
233 /* Thread safe GUI perror reporting */
234
235 typedef struct {
236 int thread_errno;
237 char * message;
238 } sweep_perror_data;
239
240 static gint
syserror_dialog_new(gpointer data)241 syserror_dialog_new (gpointer data)
242 {
243 sweep_perror_data * pd = (sweep_perror_data *)data;
244 gchar * sys_errstr = NULL;
245 char * new_message;
246
247 sys_errstr = (gchar *) g_strerror (pd->thread_errno);
248
249 if (sys_errstr != NULL) {
250 new_message = g_strdup_printf ("%s:\n\n%s", pd->message, sys_errstr);
251
252 query_dialog_new (NULL, sys_errstr, new_message, FALSE,
253 _("OK"), NULL, NULL, NULL,
254 NULL, NULL, scrubby_system_xpm, TRUE);
255 }
256
257 g_free (pd->message);
258 g_free (pd);
259
260 return FALSE;
261 }
262
263 void
sweep_perror(int thread_errno,const char * fmt,...)264 sweep_perror (int thread_errno, const char * fmt, ...)
265 {
266 sweep_perror_data * pd;
267 va_list ap;
268 #undef BUF_LEN
269 #define BUF_LEN 512
270 char buf[BUF_LEN];
271
272 va_start (ap, fmt);
273 vsnprintf (buf, BUF_LEN, fmt, ap);
274 va_end (ap);
275
276 pd = g_malloc (sizeof (sweep_perror_data));
277 pd->thread_errno = thread_errno;
278 pd->message = g_strdup (buf);
279
280 sweep_timeout_add ((guint32)0, (GtkFunction)syserror_dialog_new, pd);
281 }
282