1 /*
2 * TTTTTTTTTTTTTT EEEEEEEEEEEEEE OOOOOOOOOOOOOO
3 * TTTTTTTTTTTTTT EEEEEEEEEEEEEE OOOOOOOOOOOOOO
4 * TT EE OO OO
5 * TT EE OO OO
6 * TT EE OO OO
7 * TT EEEEEEEEEE OO OO
8 * TT EEEEEEEEEE OO OO
9 * TT EE OO OO
10 * TT EE OO OO
11 * TT EE OO OO
12 * TT EEEEEEEEEEEEEE OOOOOOOOOOOOOO
13 * TT EEEEEEEEEEEEEE OOOOOOOOOOOOOO
14 *
15 * L'�mulateur Thomson TO8
16 *
17 * Copyright (C) 1997-2017 Gilles F�tis, Eric Botcazou, Alexandre Pukall,
18 * J�r�mie Guillaume, Fran�ois Mouret
19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 */
34
35 /*
36 * Module : linux/ugui/ucass.c
37 * Version : 1.8.4
38 * Cr�� par : Eric Botcazou juillet 1999
39 * Modifi� par: Eric Botcazou 19/11/2006
40 * Gilles F�tis 27/07/2011
41 * Fran�ois Mouret 07/08/2011 24/03/2012 12/06/2012
42 * 04/11/2012 31/05/2015
43 *
44 * Gestion des cassettes.
45 */
46
47
48 #ifndef SCAN_DEPEND
49 #include <stdio.h>
50 #include <unistd.h>
51 #include <string.h>
52 #include <libgen.h>
53 #include <gtk/gtk.h>
54 #endif
55
56 #include "teo.h"
57 #include "std.h"
58 #include "errors.h"
59 #include "media/cass.h"
60 #include "linux/gui.h"
61
62 #define COUNTER_MAX 999
63
64 static GtkWidget *combo;
65 static gulong combo_id;
66 static GtkWidget *check_prot;
67 static gulong check_prot_id;
68 static GtkWidget *emptying_button;
69 static gulong emptying_button_id;
70 static GtkWidget *counter_box;
71 static int entry_max=0;
72 static GtkWidget *spinner_cass;
73 static GList *path_list = NULL;
74
75
76
block_all(void)77 static void block_all (void)
78 {
79 g_signal_handler_block (combo, combo_id);
80 g_signal_handler_block (check_prot, check_prot_id);
81 g_signal_handler_block (emptying_button, emptying_button_id);
82 }
83
84
85
unblock_all(void)86 static void unblock_all (void)
87 {
88 g_signal_handler_unblock (combo, combo_id);
89 g_signal_handler_unblock (check_prot, check_prot_id);
90 g_signal_handler_unblock (emptying_button, emptying_button_id);
91 }
92
93
94
95 /* update_params:
96 * Ajuste les param�tres de cassette.
97 */
update_params(void)98 static void update_params (void)
99 {
100 int combo_index;
101
102 if (combo_id != 0)
103 {
104 block_all ();
105
106 combo_index = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));
107
108 if (combo_index == 0)
109 {
110 gtk_widget_set_sensitive (emptying_button, FALSE);
111 gtk_widget_set_sensitive (check_prot, FALSE);
112 gtk_widget_set_sensitive (counter_box, FALSE);
113 }
114 else
115 {
116 gtk_widget_set_sensitive (emptying_button, TRUE);
117 gtk_widget_set_sensitive (check_prot, TRUE);
118 gtk_widget_set_sensitive (counter_box, TRUE);
119 }
120
121 unblock_all ();
122 }
123 }
124
125
126
127 /* set_counter_cass:
128 * Positionne le compteur de cassette.
129 */
set_counter_cass(void)130 static void set_counter_cass (void)
131 {
132 gtk_spin_button_set_value((GtkSpinButton *)spinner_cass, cass_GetCounter());
133 }
134
135
136
137 /* rewind_cass:
138 * Met le compteur de cassette � 0.
139 */
rewind_cass(void)140 static void rewind_cass (void)
141 {
142 cass_SetCounter(0);
143 set_counter_cass ();
144 }
145
146
147
148 /* eject_cass:
149 * Ejecte la cassette.
150 */
eject_cass(void)151 static void eject_cass (void)
152 {
153 rewind_cass ();
154 cass_Eject();
155 update_params ();
156 }
157
158
159
160 /* click_rewind_cass:
161 * Met le compteur de cassette � 0 (callback).
162 */
click_rewind_cass(GtkWidget * button,gpointer data)163 static void click_rewind_cass (GtkWidget *button, gpointer data)
164 {
165 rewind_cass ();
166 (void)button;
167 (void)data;
168 }
169
170
171
172 /* load_cass:
173 * Charge une cassette.
174 */
load_cass(gchar * filename)175 static int load_cass (gchar *filename)
176 {
177 int ret = cass_Load (filename);
178
179 rewind_cass();
180 switch (ret)
181 {
182 case TEO_ERROR :
183 ugui_Error (teo_error_msg, wControl);
184 break;
185
186 case TRUE :
187 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(check_prot), TRUE);
188 teo.cass.write_protect = TRUE;
189 break;
190
191 default : break;
192 }
193 return ret;
194 }
195
196
197
198 /* toggle_check_cass:
199 * Gestion de la protection (callback).
200 */
toggle_check_cass(GtkWidget * button,gpointer data)201 static void toggle_check_cass (GtkWidget *button, gpointer data)
202 {
203 if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)))
204 {
205 cass_SetProtection(TRUE);
206 teo.cass.write_protect = TRUE;
207 }
208 else
209 {
210 teo.cass.write_protect = FALSE;
211
212 if (cass_SetProtection(FALSE) == TRUE)
213 {
214 ugui_Error ((is_fr?"Ecriture impossible sur ce support."
215 :"Writing unavailable on this device."), wControl);
216 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button), TRUE);
217 teo.cass.write_protect = TRUE;
218 }
219 }
220 set_counter_cass ();
221 update_params ();
222 (void)data;
223 }
224
225
226
227 /* change_counter_cass:
228 * Change le compteur de la cassette (callback).
229 */
change_counter_cass(GtkWidget * widget,gpointer data)230 static void change_counter_cass (GtkWidget *widget, gpointer data)
231 {
232 cass_SetCounter(gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spinner_cass)));
233 (void)widget;
234 (void)data;
235 }
236
237
238
239 /* add_combo_entry
240 * Ajoute une entr�e dans le combobox si inexistante.
241 */
add_combo_entry(const char * path)242 static void add_combo_entry (const char *path)
243 {
244 GList *path_node = g_list_find_custom (path_list, (gconstpointer)path, (GCompareFunc)g_strcmp0);
245
246 if (path_node != NULL)
247 {
248 gtk_combo_box_set_active (GTK_COMBO_BOX(combo), g_list_position (path_list, path_node));
249 }
250 else
251 {
252 path_list = g_list_append (path_list, (gpointer)(g_strdup_printf (path,"%s")));
253 gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT(combo), NULL, (gchar *)basename((char *)path));
254 gtk_combo_box_set_active (GTK_COMBO_BOX(combo), entry_max);
255 entry_max++;
256 }
257 update_params ();
258 }
259
260
261
262 /* init_combo:
263 * Remplit un combo vide.
264 */
init_combo(void)265 static void init_combo (void)
266 {
267 add_combo_entry (is_fr?"(Aucun)":"(None)");
268 }
269
270
271
272 /* reset_combo:
273 * Vide le combobox (callback).
274 */
reset_combo(GtkButton * button,gpointer data)275 static void reset_combo (GtkButton *button, gpointer data)
276 {
277 block_all ();
278
279 ucass_Free ();
280 gtk_combo_box_text_remove_all (GTK_COMBO_BOX_TEXT(combo));
281 eject_cass ();
282 init_combo ();
283
284 unblock_all ();
285
286 update_params ();
287
288 (void)button;
289 (void)data;
290 }
291
292
293
294 /* combo_changed:
295 * Changement de s�lection du combobox (callback).
296 */
combo_changed(GtkComboBox * combo_box,gpointer data)297 static void combo_changed (GtkComboBox *combo_box, gpointer data)
298 {
299 int entry_selected = gtk_combo_box_get_active (combo_box);
300
301 if (entry_selected == 0)
302 {
303 eject_cass ();
304 }
305 else
306 {
307 (void)load_cass((char *)g_list_nth_data (path_list, (guint)entry_selected));
308 }
309 update_params ();
310
311 (void)data;
312 }
313
314
315
316 /* open_file:
317 * Charge une nouvelle cassette (callback).
318 */
open_file(GtkButton * button,gpointer data)319 static void open_file (GtkButton *button, gpointer data)
320 {
321 static int first=1;
322 GtkFileFilter *filter;
323 static GtkWidget *dialog;
324 gchar *folder_name;
325 gchar *file_name;
326
327 if (first) {
328 dialog = gtk_file_chooser_dialog_new (
329 is_fr?"Sélectionner une cassette":"Select a tape",
330 (GtkWindow *) wControl, GTK_FILE_CHOOSER_ACTION_OPEN,
331 is_fr?"_Annuler":"_Cancel", GTK_RESPONSE_CANCEL,
332 is_fr?"_Ouvrir":"_Open", GTK_RESPONSE_ACCEPT, NULL);
333 filter = gtk_file_filter_new ();
334 gtk_file_filter_set_name (filter, is_fr?"Fichiers cassette (.k7)":"Tape files (.k7)");
335 gtk_file_filter_add_pattern (filter, "*.k7");
336 gtk_file_filter_add_pattern (filter, "*.K7");
337 gtk_file_chooser_add_filter ((GtkFileChooser *)dialog, filter);
338
339 /* Attend que le dialog ait tout assimil� */
340 while (gtk_events_pending ())
341 gtk_main_iteration ();
342
343 first=0;
344 }
345
346 if (teo.cass.file != NULL)
347 {
348 folder_name = std_strdup_printf ("%s", teo.cass.file);
349 std_CleanPath (folder_name);
350 (void)gtk_file_chooser_set_current_folder((GtkFileChooser *)dialog, folder_name);
351 folder_name = std_free (folder_name);
352 }
353 else
354 if (teo.default_folder != NULL)
355 (void)gtk_file_chooser_set_current_folder((GtkFileChooser *)dialog, teo.default_folder);
356 else
357 if (access("./disks/", F_OK) == 0)
358 (void)gtk_file_chooser_set_current_folder((GtkFileChooser *)dialog, "./k7/");
359
360 if (gtk_dialog_run ((GtkDialog *)dialog) == GTK_RESPONSE_ACCEPT)
361 {
362 file_name = gtk_file_chooser_get_filename((GtkFileChooser *)dialog);
363 if (load_cass (file_name) >= 0)
364 {
365 block_all ();
366
367 add_combo_entry (teo.cass.file);
368 folder_name = gtk_file_chooser_get_current_folder ((GtkFileChooser *)dialog);
369 teo.default_folder = std_free(teo.default_folder);
370 if (folder_name != NULL)
371 teo.default_folder = std_strdup_printf ("%s",folder_name);
372 g_free (folder_name);
373
374 unblock_all ();
375 update_params ();
376 }
377 g_free (file_name);
378 }
379 gtk_widget_hide(dialog);
380 (void)button;
381 (void)data;
382 }
383
384
385 /* --------------------------- Partie publique ----------------------------- */
386
387
388 /* ucass_Free
389 * Lib�re la m�moire utilis�e par la liste des cassettes.
390 */
ucass_Free(void)391 void ucass_Free (void)
392 {
393 g_list_foreach (path_list, (GFunc)g_free, (gpointer) NULL);
394 g_list_free (path_list);
395 path_list=NULL;
396 entry_max = 0;
397 }
398
399
400
401 /* ucass_UpdateCounter:
402 * Positionne le compteur de cassette.
403 */
ucass_UpdateCounter(void)404 void ucass_UpdateCounter (void)
405 {
406 set_counter_cass ();
407 }
408
409
410
411 /* ucass_Init:
412 * Initialise la frame du notebook pour la cassette.
413 */
ucass_Init(GtkWidget * notebook)414 void ucass_Init (GtkWidget *notebook)
415 {
416 GtkWidget *vbox;
417 GtkWidget *hbox;
418 GtkWidget *widget;
419 GtkWidget *image;
420 GtkWidget *frame;
421 GtkAdjustment *adjustment;
422
423 /* frame de la cartouche */
424 frame=gtk_frame_new("");
425 gtk_frame_set_shadow_type( GTK_FRAME(frame), GTK_SHADOW_NONE);
426 gtk_frame_set_label_align( GTK_FRAME(frame), 0.985, 0.0);
427 widget=gtk_label_new((is_fr?"Cassette":"Tape"));
428 gtk_notebook_append_page( GTK_NOTEBOOK(notebook), frame, widget);
429
430 /* bo�te verticale associ�e � la frame */
431 vbox=gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
432 gtk_container_set_border_width( GTK_CONTAINER(vbox), 5);
433 gtk_container_add( GTK_CONTAINER(frame), vbox);
434
435 /* bo�te horizontale */
436 hbox=gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 2);
437 gtk_box_pack_start( GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
438
439 /* bouton de vidange */
440 emptying_button = gtk_button_new ();
441 image = gtk_image_new_from_icon_name ("edit-clear", GTK_ICON_SIZE_BUTTON);
442 gtk_button_set_image(GTK_BUTTON(emptying_button), image);
443 gtk_widget_set_tooltip_text (emptying_button,
444 is_fr?"Vide la liste des fichiers"
445 :"Empty the file list");
446 gtk_box_pack_start( GTK_BOX(hbox), emptying_button, FALSE, FALSE, 0);
447 emptying_button_id = g_signal_connect(G_OBJECT(emptying_button),
448 "clicked",
449 G_CALLBACK(reset_combo),
450 (gpointer) NULL);
451
452 /* combobox pour le rappel de cassette */
453 combo=gtk_combo_box_text_new();
454 gtk_box_pack_start( GTK_BOX(hbox), combo, TRUE, TRUE,0);
455 init_combo ();
456 if (teo.cass.file != NULL)
457 add_combo_entry (teo.cass.file);
458 combo_id = g_signal_connect (G_OBJECT(combo),
459 "changed",
460 G_CALLBACK(combo_changed),
461 (gpointer) NULL);
462
463 /* bouton protection de la cassette */
464 check_prot=gtk_check_button_new_with_label("prot.");
465 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_prot),
466 teo.cass.write_protect);
467 check_prot_id = g_signal_connect(G_OBJECT(check_prot),
468 "toggled",
469 G_CALLBACK(toggle_check_cass),
470 (gpointer)NULL);
471 gtk_box_pack_end( GTK_BOX(hbox), check_prot, FALSE, TRUE, 0);
472
473 /* bouton d'ouverture de fichier */
474 widget = gtk_button_new ();
475 image = gtk_image_new_from_icon_name ("document-open", GTK_ICON_SIZE_BUTTON);
476 gtk_button_set_image(GTK_BUTTON(widget), image);
477 gtk_widget_set_tooltip_text (widget, is_fr?"Ouvrir un fichier cassette"
478 :"Open a tape file");
479 gtk_box_pack_start( GTK_BOX(hbox), widget, FALSE, FALSE, 0);
480 (void)g_signal_connect(G_OBJECT(widget),
481 "clicked",
482 G_CALLBACK(open_file),
483 (gpointer) check_prot);
484
485 /* molette du compteur de cassette */
486 adjustment = gtk_adjustment_new (0, 0, COUNTER_MAX, 1, 10, 0);
487 spinner_cass = gtk_spin_button_new (adjustment, 0.5, 0);
488
489 /* seconde bo�te horizontale de la cassette */
490 counter_box=gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 2);
491 gtk_box_pack_start( GTK_BOX(vbox), counter_box, FALSE, FALSE, 0);
492
493 /* molette du compteur de cassette */
494 widget=gtk_label_new((is_fr?"Compteur:":"Counter:"));
495 gtk_box_pack_start (GTK_BOX (counter_box), widget, FALSE, FALSE, 0);
496
497 /* Connecter le signal directement au spin button ne marche pas. */
498 g_signal_connect(G_OBJECT(adjustment),
499 "value_changed",
500 G_CALLBACK(change_counter_cass),
501 (gpointer)NULL);
502 gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner_cass), FALSE);
503 gtk_box_pack_start (GTK_BOX (counter_box), spinner_cass, FALSE, FALSE, 0);
504
505 /* bouton rembobinage */
506 widget=gtk_button_new_with_label((is_fr?"Rembobiner la cassette":"Rewind tape"));
507 g_signal_connect(G_OBJECT(widget), "clicked",
508 G_CALLBACK(click_rewind_cass), (gpointer)NULL);
509 gtk_box_pack_start( GTK_BOX(counter_box), widget, TRUE, FALSE, 0);
510
511 update_params ();
512 }
513
514