1 /* view.c
2 * Functions to create a top level Denemo window
3 *
4 * for Denemo, a gtk+ frontend to GNU Lilypond
5 * (c) 2003-2005 Adam Tee (c) 2007, 2008 2009 Richard Shann
6 *
7 */
8
9 #include <string.h>
10 #include <math.h>
11 #include "core/view.h"
12
13 #include "command/lilydirectives.h"
14 #include "ui/dialogs.h"
15 #include "core/utils.h"
16 #include <stdlib.h>
17 #include <glib/gstdio.h>
18 #include <cairo.h>
19 #include <cairo-svg.h>
20 #include <librsvg/rsvg.h>
21 #include <sndfile.h>
22
23 #include "audio/playback.h"
24 #include "audio/pitchentry.h"
25 #include "audio/portaudiobackend.h"
26 #include "export/exportlilypond.h"
27 #include "export/print.h"
28 #include "printview/printview.h"
29 #include "printview/svgview.h"
30 #include "command/grace.h"
31 #include "core/kbd-custom.h"
32 #include "core/keyboard.h"
33 #include "export/exportmidi.h"
34 #include "audio/midi.h"
35 #ifdef _WITH_X11_
36 #include "export/screenshot.h"
37 #endif
38 #include "source/source.h"
39 #include "command/commandfuncs.h"
40 #include "display/calculatepositions.h"
41 #include "core/http.h"
42 #include "ui/texteditors.h"
43 #include "core/prefops.h"
44 #include "audio/audiointerface.h"
45 #include "source/sourceaudio.h"
46 #include "command/scorelayout.h"
47 #include "core/keymapio.h"
48 #include "command/measure.h"
49 #include "export/audiofile.h"
50 #include "export/guidedimportmidi.h"
51 #include "scripting/scheme-identifiers.h"
52 #include "scripting/scheme-callbacks.h"
53
54 static GtkWidget *playbutton;
55 static GtkWidget *midirecordbutton;
56 static GtkWidget *audiorecordbutton;
57 static GtkWidget *midi_in_status;
58 static GtkWidget *midiplayalongbutton;
59 static GtkWidget *midiconductbutton;
60 static GtkWidget *deletebutton;
61 static GtkWidget *exportbutton;
62 static GtkWidget *convertbutton;
63 static GtkSpinButton *leadin;
64 static GtkAdjustment *master_vol_adj;
65 static GtkAdjustment *audio_vol_adj;
66 static GtkAdjustment *master_tempo_adj;
67 #ifdef _HAVE_RUBBERBAND_
68 static GtkAdjustment *speed_adj;
69 #endif
70 static void pb_audiorecord (GtkWidget * button);
71 static void pb_exportaudio (GtkWidget * button);
72 static void toggle_scheme (void);
73
74 static DenemoProject* new_project(gboolean);
75 static void newtab ();
76
77 static void create_window (void);
78
79 static gint dnm_key_snooper (GtkWidget * grab_widget, GdkEventKey * event);
80 static void populate_opened_recent_menu (void);
81 static gchar *get_most_recent_file (void);
82 static void toggle_record_script (GtkAction * action, gpointer param);
83
84 typedef enum
85 {
86 ACCELS_LOADED = 0x0,
87 ACCELS_CHANGED = 0x1 << 0,
88 EXTRA_ACCELS_ACTIVE = 0x1 << 1,
89 ACCELS_MAY_HAVE_CHANGED = 0x1 << 2
90 } AccelStatus;
91
92 GtkWidget*
get_playalong_button()93 get_playalong_button(){
94 return midiplayalongbutton;
95 }
96
97 GtkWidget*
get_conduct_button()98 get_conduct_button(){
99 return midiconductbutton;
100 }
101
102 GtkWidget*
get_record_button()103 get_record_button(){
104 return midirecordbutton;
105 }
106
107 static void save_accels (void);
108
109 static gint scm_eval_status = 0;
110
111 static SCM
standard_handler(gchar * data SCM_UNUSED,SCM tag,SCM throw_args SCM_UNUSED)112 standard_handler (gchar * data SCM_UNUSED, SCM tag, SCM throw_args SCM_UNUSED)
113 {
114 g_warning ("\nA script error for file/script %s; the throw arguments are\n", data);
115 scm_display (throw_args, scm_current_output_port ());
116 scm_newline (scm_current_output_port ());
117 g_warning ("\nThe tag is\n");
118 scm_display (tag, scm_current_output_port ());
119 scm_newline (scm_current_output_port ());
120 scm_newline (scm_current_output_port ());
121 scm_eval_status = -1;
122 // g_warning ("Undo will be affected\n");
123 //stage_undo(Denemo.gui->movement, ACTION_SCRIPT_ERROR); We don't need this as control will return to activate_script() which will terminate the undo properly, with anything the script has done on the undo stack.
124 return SCM_BOOL_F;
125 }
126
127 static SCM
standard_preunwind_proc(void * data,SCM key,SCM parameters)128 standard_preunwind_proc (void *data,
129 SCM key,
130 SCM parameters)
131 {
132 // Capture the stack here:
133 *(SCM *)data = scm_make_stack (SCM_BOOL_T, SCM_EOL);
134 return *(SCM *)data;
135 }
136
137 gint
eval_file_with_catch(gchar * filename)138 eval_file_with_catch (gchar * filename)
139 {
140 // scm_c_primitive_load(filename);
141 SCM captured_stack = SCM_BOOL_F;
142 SCM name = scm_from_locale_string (filename);
143 scm_eval_status = 0;
144 scm_c_catch (SCM_BOOL_T,
145 (scm_t_catch_body) scm_primitive_load, (void *) name,
146 (scm_t_catch_handler) standard_handler, (void *) filename,
147 standard_preunwind_proc, &captured_stack);
148 if (captured_stack != SCM_BOOL_F)
149 {
150 #ifdef DEBUG
151 scm_display_backtrace(captured_stack, scm_current_error_port (), SCM_BOOL_F, SCM_BOOL_F);
152 #endif
153 }
154 return scm_eval_status;
155 }
156
157 gint
call_out_to_guile(const char * script)158 call_out_to_guile (const char *script)
159 {
160 scm_eval_status = 0;
161 scm_internal_catch (SCM_BOOL_T, (scm_t_catch_body) scm_c_eval_string, (void *) script, (scm_t_catch_handler) standard_handler, (void *) script);
162 return scm_eval_status;
163 }
164
165
166 //FIXME common up these!!!
167 void
define_scheme_variable(gchar * varname,gchar * value,gchar * tooltip)168 define_scheme_variable (gchar * varname, gchar * value, gchar * tooltip)
169 {
170
171 gchar *def = g_strdup_printf ("\"%s\"", value);
172 //g_debug("Defining %s\n", def);
173 scm_c_define (varname, scm_from_locale_string (def));
174 g_free (def);
175 }
176
177 void
define_scheme_literal_variable(gchar * varname,gchar * value,gchar * tooltip)178 define_scheme_literal_variable (gchar * varname, gchar * value, gchar * tooltip)
179 {
180 scm_c_define (varname, scm_from_locale_string (value));
181 }
182
183 void
define_scheme_int_variable(gchar * varname,gint value,gchar * tooltip)184 define_scheme_int_variable (gchar * varname, gint value, gchar * tooltip)
185 {
186 scm_c_define (varname, scm_from_int (value));
187 }
188
189 void
define_scheme_double_variable(gchar * varname,gdouble value,gchar * tooltip)190 define_scheme_double_variable (gchar * varname, gdouble value, gchar * tooltip)
191 {
192 scm_c_define (varname, scm_from_double (value));
193 }
194
195
196
197
198 void
define_scheme_bool_variable(gchar * varname,gint value,gchar * tooltip)199 define_scheme_bool_variable (gchar * varname, gint value, gchar * tooltip)
200 {
201 scm_c_define (varname, SCM_BOOL (value));
202 }
203
204
205 GError *
execute_script_file(gchar * filename)206 execute_script_file (gchar * filename)
207 {
208 GError *error = NULL;
209 gchar *script;
210 if (g_file_get_contents (filename, &script, NULL, &error))
211 {
212 call_out_to_guile (script); //FIXME setup error here if non null return
213 g_free (script);
214 }
215 return error;
216 }
217
218
219 void
execute_scheme(GtkAction * action,DenemoScriptParam * param)220 execute_scheme (GtkAction * action, DenemoScriptParam * param)
221 {
222 if (Denemo.ScriptRecording)
223 gtk_action_activate (gtk_action_group_get_action (Denemo.action_group, RecordScript_STRING));
224 //Denemo.ScriptRecording = FALSE;
225 executeScript ();
226 }
227
228
229
230
231
232 /***************** end of definitions to implement calling radio/check items from scheme *******************/
233
234 //returns newly allocated string. FIXME use proper scm_xxx calls not strings
235 gchar *
get_midi_control_command(guchar type,guchar value)236 get_midi_control_command (guchar type, guchar value)
237 {
238 gchar *command = g_strdup_printf ("(MIDI-shortcut::controller %d %d)", type, value);
239 SCM scm = scm_c_eval_string (command);
240 g_free (command);
241 if (scm_is_string (scm))
242 {
243 char *ctrl = scm_to_locale_string (scm);
244 command = g_strdup (ctrl); //FIXME
245 free (ctrl);
246 return command;
247 }
248 return NULL;
249 }
250
251 //returns newly allocated string. FIXME use proper scm_xxx calls not strings
252 gchar *
get_midi_pitch_bend_command(gint value)253 get_midi_pitch_bend_command (gint value)
254 {
255 gchar *command = g_strdup_printf ("(MIDI-shortcut::pitchbend %d)", value);
256 SCM scm = scm_c_eval_string (command);
257 g_free (command);
258 if (scm_is_string (scm))
259 {
260 char *pbend;
261 pbend = scm_to_locale_string (scm);
262 command = g_strdup (pbend); //FIXME
263 free (pbend);
264 return command;
265 }
266 return NULL;
267 }
268
269
270 static void
define_scheme_constants(void)271 define_scheme_constants (void)
272 {
273 gint major = 0, minor = 0, micro = 0;
274 sscanf (VERSION, "%d.%d.%d", &major, &minor, µ);
275 gchar *denemo_version = g_strdup_printf ("%d.%d.%d%s", major, minor, micro,
276 #ifdef G_OS_WIN32
277 "_Win"
278 #else
279 ""
280 #endif
281 );
282 gchar *filename = g_build_filename (get_system_data_dir (), COMMANDS_DIR, NULL);
283 gchar *actions_dir = g_strdup_printf ("%s%c", filename, G_DIR_SEPARATOR);
284 gchar *templates_dir = g_build_filename (get_system_data_dir (), "templates", NULL);
285 gchar *instruments_dir = g_build_filename (get_system_data_dir (), "templates", "instruments", NULL);
286 gchar *glyphs_dir = g_build_filename (get_system_data_dir (), COMMANDS_DIR, "bitmaps", NULL);
287 gchar *graphics_dir = g_build_filename (get_system_data_dir (), COMMANDS_DIR, "graphics", NULL);
288 glyphs_dir = g_strdup_printf ("%s%c", glyphs_dir, G_DIR_SEPARATOR);
289 graphics_dir = g_strdup_printf ("%s%c", graphics_dir, G_DIR_SEPARATOR);
290 if (filename)
291 g_free (filename);
292
293 filename = g_build_filename (get_user_data_dir (TRUE), COMMANDS_DIR, NULL);
294 gchar *local_actions_dir = g_strdup_printf ("%s%c", filename, G_DIR_SEPARATOR);
295 gchar *local_templates_dir = g_build_filename (get_user_data_dir (TRUE), "templates", NULL);
296 gchar *local_instruments_dir = g_build_filename (get_user_data_dir (TRUE), "templates", "instruments", NULL);
297 if (filename)
298 g_free (filename);
299
300 g_message ("Denemo version %s", denemo_version);
301
302 #define DEF_SCHEME_STR(which, what, tooltip)\
303 scm_c_define(which, scm_from_locale_string(what));
304
305 #define DEF_SCHEME_CONST(which, what)\
306 define_scheme_int_variable(which, what, "See documentation elsewhere");
307
308 DEF_SCHEME_CONST ("DENEMO_INPUTMIDI", INPUTMIDI);
309 DEF_SCHEME_CONST ("DENEMO_INPUTKEYBOARD", INPUTKEYBOARD);
310 DEF_SCHEME_CONST ("DENEMO_INPUTAUDIO", INPUTAUDIO);
311
312
313
314 DEF_SCHEME_CONST ("DENEMO_OVERRIDE_LILYPOND", DENEMO_OVERRIDE_LILYPOND);
315 DEF_SCHEME_CONST ("DENEMO_ALT_OVERRIDE", DENEMO_ALT_OVERRIDE);
316 DEF_SCHEME_CONST ("DENEMO_OVERRIDE_GRAPHIC", DENEMO_OVERRIDE_GRAPHIC);
317 DEF_SCHEME_CONST ("DENEMO_OVERRIDE_EDITOR", DENEMO_OVERRIDE_EDITOR);
318 DEF_SCHEME_CONST ("DENEMO_OVERRIDE_AFFIX", DENEMO_OVERRIDE_AFFIX);
319 DEF_SCHEME_CONST ("DENEMO_OVERRIDE_TAGEDIT", DENEMO_OVERRIDE_TAGEDIT);
320
321 DEF_SCHEME_CONST ("DENEMO_OVERRIDE_VOLUME", DENEMO_OVERRIDE_VOLUME);
322 DEF_SCHEME_CONST ("DENEMO_OVERRIDE_DURATION", DENEMO_OVERRIDE_DURATION);
323 DEF_SCHEME_CONST ("DENEMO_OVERRIDE_REPEAT", DENEMO_OVERRIDE_REPEAT);
324 DEF_SCHEME_CONST ("DENEMO_OVERRIDE_CHANNEL", DENEMO_OVERRIDE_CHANNEL);
325 DEF_SCHEME_CONST ("DENEMO_OVERRIDE_TEMPO", DENEMO_OVERRIDE_TEMPO);
326 DEF_SCHEME_CONST ("DENEMO_OVERRIDE_TRANSPOSITION", DENEMO_OVERRIDE_TRANSPOSITION);
327
328 DEF_SCHEME_CONST ("DENEMO_OVERRIDE_ONCE", DENEMO_OVERRIDE_ONCE);
329 DEF_SCHEME_CONST ("DENEMO_OVERRIDE_STEP", DENEMO_OVERRIDE_STEP);
330 DEF_SCHEME_CONST ("DENEMO_OVERRIDE_RAMP", DENEMO_OVERRIDE_RAMP);
331
332
333 DEF_SCHEME_CONST ("DENEMO_OVERRIDE_RELATIVE", DENEMO_OVERRIDE_RELATIVE);
334 DEF_SCHEME_CONST ("DENEMO_OVERRIDE_PERCENT", DENEMO_OVERRIDE_PERCENT);
335
336 DEF_SCHEME_CONST ("DENEMO_MIDI_MASK", DENEMO_MIDI_MASK);
337 DEF_SCHEME_CONST ("DENEMO_MIDI_INTERPRETATION_MASK", DENEMO_MIDI_INTERPRETATION_MASK);
338 DEF_SCHEME_CONST ("DENEMO_MIDI_ACTION_MASK", DENEMO_MIDI_ACTION_MASK);
339
340 DEF_SCHEME_CONST ("DENEMO_OVERRIDE_DYNAMIC", DENEMO_OVERRIDE_DYNAMIC);
341 DEF_SCHEME_CONST ("DENEMO_OVERRIDE_HIDDEN", DENEMO_OVERRIDE_HIDDEN);
342 DEF_SCHEME_CONST ("DENEMO_OVERRIDE_MARKUP", DENEMO_OVERRIDE_MARKUP);
343 DEF_SCHEME_CONST ("DENEMO_OVERRIDE_ABOVE", DENEMO_OVERRIDE_ABOVE);
344
345 DEF_SCHEME_CONST ("VERSION_MAJOR", major);
346 DEF_SCHEME_CONST ("VERSION_MINOR", minor);
347 DEF_SCHEME_CONST ("VERSION_MICRO", micro);
348
349 DEF_SCHEME_STR ("DENEMO_VERSION", denemo_version, "Holds the denemo version major.minor.micro");
350 DEF_SCHEME_STR ("DENEMO_ACTIONS_DIR", actions_dir, "Holds location of system-wide Denemo actions directory");
351 DEF_SCHEME_STR ("DENEMO_TEMPLATES_DIR", templates_dir, "Holds location of system-wide Denemo templates directory");
352 DEF_SCHEME_STR ("DENEMO_INSTRUMENTS_DIR", instruments_dir, "Holds location of system-wide Denemo instrument templates directory");
353 DEF_SCHEME_STR ("DENEMO_GLYPHS_DIR", glyphs_dir, "Holds location of system-wide Denemo glyphs directory");
354 DEF_SCHEME_STR ("DENEMO_GRAPHICS_DIR", graphics_dir, "Holds location of system-wide Denemo graphics directory");
355 DEF_SCHEME_STR ("DENEMO_LILYPOND_DIR", g_build_filename (actions_dir, "lilypond", NULL), "Holds location of Denemo's system-wide lilypond include files directory");
356 DEF_SCHEME_STR ("DENEMO_LOCAL_ACTIONS_DIR", local_actions_dir, "Holds location of Denemo actions directory beneath your home directory");
357 DEF_SCHEME_STR ("DENEMO_LOCAL_TEMPLATES_DIR", local_templates_dir, "Holds location of Denemo templates directory beneath your home directory");
358 DEF_SCHEME_STR ("DENEMO_LOCAL_INSTRUMENTS_DIR", local_instruments_dir, "Holds location of Denemo instrument templates directory beneath your home directory");
359 DEF_SCHEME_STR ("DENEMO_LOCAL_LILYPOND_DIR", g_build_filename (local_actions_dir, "lilypond", NULL), "Holds location of user lilypond include files directory");
360 DEF_SCHEME_STR ("DENEMO_HOME_DIR", g_get_home_dir (), "Holds location of user home directory");
361 {
362 gint i;
363 for (i = 0; i < G_N_ELEMENTS (DenemoObjTypeNames); i++)
364 DEF_SCHEME_CONST (DenemoObjTypeNames[i], i);
365 }
366 DEF_SCHEME_STR ("DenemoClickTrack", DENEMO_CLICK_TRACK_NAME, "Holds a name for identifying a click track as the staff name query=denemo_name");
367
368 #undef DEF_SCHEME_STR
369 #undef DEF_SCHEME_CONST
370 g_free (denemo_version);
371 g_free (actions_dir);
372 g_free (local_actions_dir);
373 }
374
375 /*
376 load denemo.scm from user's .denemo
377 */
378 static void
load_local_scheme_init(void)379 load_local_scheme_init (void)
380 {
381 gchar *filename = g_build_filename (get_user_data_dir (TRUE), COMMANDS_DIR, SCHEME_INIT, NULL);
382 if (g_file_test (filename, G_FILE_TEST_EXISTS))
383 eval_file_with_catch (filename); //scm_c_primitive_load(filename);
384 if (filename)
385 g_free (filename);
386 }
387
388 void
denemo_scheme_init(void)389 denemo_scheme_init (void)
390 {
391 gchar *initscheme = Denemo.scheme_file;
392 if(!Denemo.non_interactive)
393 Denemo.project->movement->undo_guard++;
394
395 if (initscheme)
396 {
397 if (g_file_test (initscheme, G_FILE_TEST_EXISTS))
398 eval_file_with_catch (initscheme); //scm_c_primitive_load(initscheme);
399 else
400 g_warning ("Cannot find your scheme initialization file %s", initscheme);
401 }
402
403 if (Denemo.prefs.profile->len)
404 {
405 gchar *name = g_strconcat (Denemo.prefs.profile->str, ".scm", NULL);
406 gchar *filename = g_build_filename (get_system_data_dir (), COMMANDS_DIR, name, NULL);
407 if (g_file_test (filename, G_FILE_TEST_EXISTS))
408 eval_file_with_catch (filename);
409 g_free (name);
410 g_free (filename);
411 score_status (Denemo.project, FALSE);
412 }
413
414 load_local_scheme_init ();
415 if(!Denemo.non_interactive)
416 Denemo.project->movement->undo_guard--;
417 }
418
419 /*
420 append scheme to user's denemo.scm
421 */
422 void
append_to_local_scheme_init(gchar * scheme)423 append_to_local_scheme_init (gchar * scheme)
424 {
425 gchar *filename = g_build_filename (get_user_data_dir (TRUE), COMMANDS_DIR, SCHEME_INIT, NULL);
426 FILE *fp = fopen (filename, "a+");
427 if (fp){
428 fprintf (fp, "%s", scheme);
429 fclose (fp);
430 }
431 g_free (filename);
432 }
433
434 /*
435 empty the user's user's denemo.scm
436 */
437 void
destroy_local_scheme_init(void)438 destroy_local_scheme_init (void)
439 {
440 gchar *filename = g_build_filename (get_user_data_dir (TRUE), COMMANDS_DIR, SCHEME_INIT, NULL);
441 FILE *fp = fopen (filename, "w");
442 if (fp)
443 fclose (fp);
444 }
445
446
447 /*
448 load denemo.scm from system,
449
450 */
451 static void
load_scheme_init(void)452 load_scheme_init (void)
453 {
454 //Denemo.project->movement->undo_guard++;
455 GList* dirs = NULL;
456 dirs = g_list_append(dirs, g_build_filename (PACKAGE_SOURCE_DIR, COMMANDS_DIR, NULL));
457 dirs = g_list_append(dirs, g_build_filename (get_system_data_dir (), COMMANDS_DIR, NULL));
458
459 gchar *filename = find_path_for_file(SCHEME_INIT, dirs);
460
461 g_debug ("System wide denemo.scm %s\n", filename);
462 if (g_file_test (filename, G_FILE_TEST_EXISTS))
463 eval_file_with_catch (filename); //scm_c_primitive_load(filename);
464 else
465 g_warning ("Cannot find Denemo's scheme initialization file denemo.scm");
466 g_free (filename);
467 //Denemo.project->movement->undo_guard--;
468 }
469
470 /* show the user's preferred view. Assumes all hidden on entry */
471 void
load_preferences(void)472 load_preferences (void)
473 {
474
475
476 Denemo.project->mode = Denemo.prefs.mode;
477 // if (Denemo.prefs.startmidiin)
478 // activate_action("/MainMenu/InputMenu/JackMidi");
479 // if(!have_midi())
480 // activate_action("/MainMenu/InputMenu/KeyboardOnly");
481
482 if (!Denemo.prefs.playback_controls)
483 activate_action ("/MainMenu/ViewMenu/" TogglePlaybackControls_STRING);
484 if (!Denemo.prefs.midi_in_controls)
485 activate_action ("/MainMenu/ViewMenu/" ToggleMidiInControls_STRING);
486
487 if (!Denemo.prefs.quickshortcuts)
488 activate_action ("/MainMenu/EditMenu/Preferences/Keybindings/" QuickEdits_STRING);
489
490 if (!Denemo.prefs.toolbar)
491 activate_action ("/MainMenu/ViewMenu/" ToggleToolbar_STRING);
492
493 //if (!Denemo.prefs.lyrics_pane)
494 //activate_action ("/MainMenu/ViewMenu/" ToggleLyricsView_STRING);
495 Denemo.prefs.lyrics_pane = TRUE; //ignore pref, does not work.
496 //gtk_toggle_action_set_active (gtk_ui_manager_get_action (Denemo.ui_manager, "/MainMenu/ViewMenu/ToggleLyricsView"), !Denemo.prefs.lyrics_pane);
497
498
499 if (!Denemo.prefs.rhythm_palette)
500 activate_action ("/MainMenu/ViewMenu/" ToggleRhythmToolbar_STRING);
501
502 if (!Denemo.prefs.manualtypeset)
503 activate_action ("/MainMenu/ViewMenu/" TogglePrintView_STRING);
504
505 if (!Denemo.prefs.object_palette)
506 activate_action ("/MainMenu/ViewMenu/" ToggleObjectMenu_STRING);
507
508
509
510 //these menu ones are visible on entry - FIXME is this the array of toolbars below, ending in TRUE?
511 if (!Denemo.prefs.playback_controls)
512 toggle_playback_controls (NULL, NULL);
513
514 if (!Denemo.prefs.midi_in_controls)
515 toggle_midi_in_controls (NULL, NULL);
516
517 if (!Denemo.prefs.toolbar)
518 toggle_toolbar (NULL, NULL);
519
520 if (Denemo.prefs.cursor_highlight)
521 {
522 Denemo.prefs.cursor_highlight = FALSE;
523 scheme_highlight_cursor (SCM_BOOL_T);
524 }
525 }
526
527 /*
528 * create and populate the keymap - a register of all the Denemo commands with their shortcuts
529 */
530 static void
init_keymap(void)531 init_keymap (void)
532 {
533 if (Denemo.map)
534 free_keymap (Denemo.map);
535 Denemo.map = allocate_keymap ();
536 #include "generated/register_commands.h"
537 }
538
539 static gboolean
load_files(gchar ** files)540 load_files(gchar** files)
541 {
542 gboolean ret = FALSE;
543 gint i = 0;
544
545 if(!files){
546 if(!Denemo.non_interactive)
547 newtab ();
548 else
549 Denemo.project = new_project (TRUE);
550 open_for_real (get_most_recent_file (), Denemo.project, FALSE, REPLACE_SCORE);
551 return TRUE;
552 }
553
554 for(i=0; files[i]; i++)
555 {
556 if(!Denemo.non_interactive)
557 newtab ();
558 else
559 Denemo.project = new_project (TRUE);
560 open_for_real (files[i], Denemo.project, FALSE, REPLACE_SCORE);
561 ret = TRUE;
562 }
563 return ret;
564 }
565
566 static void
autosave_recovery_check(void)567 autosave_recovery_check(void)
568 {
569 gchar *autosave_file;
570 if (!Denemo.project->autosavename)
571 return;
572 autosave_file = Denemo.project->autosavename->str;
573 if (g_file_test (autosave_file, G_FILE_TEST_EXISTS))
574 {
575
576 if ( choose_option (_("Denemo was terminated abnormally"), _("Open auto-saved file"), _("Delete auto-saved file")))
577 {
578 open_for_real (autosave_file, Denemo.project, TRUE, REPLACE_SCORE);
579 score_status (Denemo.project, TRUE);
580 }
581 g_remove (autosave_file);
582 }
583 }
584
585
586 /* Called from main for scheme initialization reasons.
587 calls back to finish command line processing
588 */
589 void*
inner_main(void * files)590 inner_main (void *files)
591 {
592 #if 0
593 //disabled pending appearance of pathconfig.h
594 /* initialize guile core */
595 {
596 SCM load_path;
597 char *user_path;
598
599 /* we assume a normal guile with %load-path always be present */
600 load_path = scm_c_lookup ("%load-path");
601
602 scm_variable_set_x (load_path, scm_cons (scm_from_locale_string (DENEMO_LOAD_PATH), scm_variable_ref (load_path)));
603
604 /* consider user-specified path extension */
605 user_path = getenv ("DENEMO_LOAD_PATH");
606 if (user_path)
607 {
608 scm_variable_set_x (load_path, scm_cons (scm_from_locale_string (user_path), scm_variable_ref (load_path)));
609 }
610 }
611 #endif
612
613 initprefs ();
614 init_lilypond_buffer();
615 initialize_print_status ();
616 //project Initializations
617 if (audio_initialize (&Denemo.prefs))
618 g_error ("Failed to initialize audio or MIDI backends");
619
620 if(!Denemo.non_interactive)
621 {
622 initialize_keystroke_help ();
623
624 create_window ();
625 installPalettes ();
626
627 if (Denemo.prefs.tooltip_timeout)
628 {
629 g_object_set (gtk_widget_get_settings (Denemo.window), "gtk-tooltip-timeout", Denemo.prefs.tooltip_timeout, NULL);
630 g_object_set (gtk_widget_get_settings (Denemo.window), "gtk-tooltip-browse-timeout", Denemo.prefs.tooltip_browse_timeout, NULL);
631 g_object_set (gtk_widget_get_settings (Denemo.window), "gtk-tooltip-browse-mode-timeout", Denemo.prefs.tooltip_browse_mode_timeout, NULL);
632 }
633
634
635 Denemo.prefs.mode = INPUTEDIT | INPUTRHYTHM | INPUTNORMAL; //FIXME must correspond with default in prefops.c
636
637 Denemo.accelerator_status = FALSE;
638 }
639
640 //Scheme initializations
641 {
642 const char prog[] =
643 "(catch #t (lambda () (setlocale LC_ALL \"\")) (lambda _(display \"Locale not supported by the C library. Falling back to default \\\"C\\\" locale.\\n\"(current-error-port))))";
644 scm_c_eval_string (prog);
645 //scm_setlocale( scm_variable_ref(scm_c_lookup("LC_ALL")), scm_from_locale_string("") );
646 create_scheme_identfiers ();
647
648 if (Denemo.prefs.autoupdate)
649 fetchcommands (NULL, NULL);
650
651 gint i;
652
653 //ensure (use-modules (ice-9 optargs)) is loaded first #:optional params
654 call_out_to_guile ("(use-modules (ice-9 optargs))");
655 init_keymap ();
656
657 define_scheme_constants ();
658
659 load_default_keymap_file ();
660
661 load_scheme_init ();
662
663 readHistory ();
664
665 gboolean file_loaded = load_files(files);
666
667 if (!file_loaded && !Denemo.scheme_commands)
668 {
669 gchar* code = g_strdup_printf("(d-InstrumentName \"%s\")", _("Unnamed"));
670 call_out_to_guile (code);
671 g_free(code);
672 denemo_scheme_init ();
673 }
674 }
675
676 //project related initializations
677 if(!Denemo.non_interactive)
678 {
679 populate_opened_recent_menu ();
680
681 load_preferences ();
682
683 gtk_key_snooper_install ((GtkKeySnoopFunc) dnm_key_snooper, NULL);
684 score_status (Denemo.project, FALSE);
685 if (Denemo.scheme_commands){
686 g_debug("Executing '%s'", Denemo.scheme_commands);
687 call_out_to_guile (Denemo.scheme_commands);
688 } else
689 autosave_recovery_check();
690
691
692
693 if (Denemo.prefs.fontname->len && Denemo.prefs.fontsize)
694 {
695 gchar *fontspec = g_strdup_printf ("%s %d", Denemo.prefs.fontname->str, Denemo.prefs.fontsize);
696 GtkSettings *settings = gtk_settings_get_default ();
697 gtk_settings_set_string_property (settings, "gtk-font-name", fontspec, "denemo");
698 g_free (fontspec);
699 }
700
701 gtk_main ();
702 } else
703
704 if (Denemo.scheme_commands){
705 g_debug("Executing '%s'", Denemo.scheme_commands);
706 call_out_to_guile (Denemo.scheme_commands);
707 }
708
709 return NULL;
710 }
711
712
713 static void
selection_received(GtkClipboard * clipboard,const gchar * text,DenemoScriptParam * param)714 selection_received (GtkClipboard * clipboard, const gchar * text, DenemoScriptParam * param)
715 {
716 if (!text)
717 {
718 warningdialog (_("No selection text available"));
719 param->status = FALSE;
720 return;
721 }
722 param->string = g_string_new (text);
723 param->status = TRUE;
724 gtk_main_quit ();
725 }
726
727 /* get the X selection into the param->string */
728
729 void
get_clipboard(GtkAction * action,DenemoScriptParam * param)730 get_clipboard (GtkAction * action, DenemoScriptParam * param)
731 {
732 GtkClipboard *clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
733 gtk_clipboard_request_text (clipboard, (GtkClipboardTextReceivedFunc) selection_received, param);
734 gtk_main ();
735 }
736
737
738
739 GString *
get_widget_path(GtkWidget * widget)740 get_widget_path (GtkWidget * widget)
741 {
742 const gchar *name;
743 GString *str = g_string_new ("/");
744 for (widget = gtk_widget_get_parent (widget); widget; widget = gtk_widget_get_parent (widget))
745 {
746 name = gtk_widget_get_name (widget);
747 g_string_prepend (str, name);
748 g_string_prepend_c (str, '/');
749 }
750 g_debug ("String is %s\n", str->str);
751 return str;
752 }
753
754 static gboolean
action_callbacks(DenemoProject * project)755 action_callbacks (DenemoProject * project)
756 {
757 GList *callbacks = project->callbacks;
758 if (callbacks == NULL)
759 return FALSE;
760 project->callbacks = NULL; //do this before calling the callbacks, so they cannot run twice
761 for (; callbacks; callbacks = g_list_delete_link (callbacks, callbacks))
762 {
763 call_out_to_guile (callbacks->data);
764 g_free (callbacks->data);
765 }
766 return TRUE;
767 }
768
769
770
771 /**
772 * Close the current musical score (Denemo.project) freeing all its movements (DenemoMovement), releasing its memory and removing it from the global list Denemo.projects
773 * Do not close the sequencer
774 */
775 static gboolean
close_project(void)776 close_project (void)
777 {
778 g_signal_handlers_block_by_func (G_OBJECT (Denemo.scorearea), G_CALLBACK (scorearea_draw_event), NULL); // turn of refresh of display before destroying the data
779 stop_midi_playback (NULL, NULL); // if you do not do this, there is a timer moving the score on which will hang
780 //FIXME why was this here??? activate_action("/MainMenu/InputMenu/KeyboardOnly");
781 #ifdef USE_EVINCE
782 if (Denemo.prefs.enable_thumbnails)
783 create_thumbnail (TRUE, NULL);
784 #endif
785 if (Denemo.autosaveid)
786 {
787 if (g_list_length (Denemo.projects) > 1)
788 g_debug ("Auto save being turned off");
789 g_source_remove (Denemo.autosaveid);
790 Denemo.autosaveid = 0;
791 }
792 if(Denemo.project->autosavename)
793 g_remove (Denemo.project->autosavename->str);
794 if (Denemo.textwindow && gtk_widget_get_visible (Denemo.textwindow))
795 {
796 activate_action ("/MainMenu/ViewMenu/" ToggleLilyText_STRING);
797 //FIXME there is a handler in exportlilypond.c for the delete signal. It would need to be disabled to get the memory freed.
798 }
799 free_movements (Denemo.project);
800
801 DenemoProject *oldproject = Denemo.project;
802 /*
803 * gtk_widget_destroy (Denemo.page); //note switch_page from g_signal_connect (G_OBJECT(Denemo.notebook), "switch_page", G_CALLBACK(switch_page), NULL);
804 * this widget destroy causes critical errors - the sequence of New, New Tab, (return to first tab), Close, New shows the effect.
805 */
806 gint index = g_list_index (Denemo.projects, oldproject);
807 gtk_notebook_remove_page (GTK_NOTEBOOK (Denemo.notebook), index);
808 g_message ("Closing project %d", index);
809 Denemo.projects = g_list_remove (Denemo.projects, oldproject); //FIXME ?? or in the destroy callback??
810 g_free (oldproject);
811 if (Denemo.projects)
812 {
813 if (index > g_list_length (Denemo.projects) - 1)
814 index = g_list_length (Denemo.projects) - 1;
815 if (index < 0)
816 index = 0;
817
818 Denemo.project = g_list_nth_data (Denemo.projects, index);
819 g_message ("Selecting score (tab) %d\n", index);
820 gtk_notebook_set_current_page (GTK_NOTEBOOK (Denemo.notebook), index);
821 }
822 else
823 Denemo.project = NULL;
824 g_signal_handlers_unblock_by_func (G_OBJECT (Denemo.scorearea), G_CALLBACK (scorearea_draw_event), NULL);
825 return TRUE;
826 }
827
828 /* remove all the movements (ie the DenemoMovement) leaving it with project->movement NULL */
829 void
free_movements(DenemoProject * project)830 free_movements (DenemoProject * project)
831 {gint success;
832 if(!is_playing())
833 success = delete_imported_midi(); g_print("Success %d\n", success);
834 GList *g;
835 free_scoreblocks (project);
836 for (g = project->movements; g; g = g->next)
837 {
838 project->movement = g->data;
839 project->movement->undo_guard = 1; //no undo as that is per movement
840 //close_source_audio ();//???
841 // if(!delete_imported_midi ()) not if still playing!!!
842 // delete_imported_midi();
843 free_score (project);
844 }
845 project->movement = NULL;
846 delete_directives (&project->lilycontrol.directives);
847 delete_directives (&project->scoreheader.directives);
848 delete_directives (&project->paper.directives);
849 g_list_free (project->movements);
850 project->movements = NULL;
851
852
853 /* any other free/initializations */
854 project->lilycontrol.papersize = g_string_new ("a4"); //A4 default
855 project->lilycontrol.staffsize = g_string_new ("18");
856 project->lilycontrol.lilyversion = g_string_new ("");
857 project->lilycontrol.orientation = TRUE; //portrait
858 }
859
860 /**
861 * Wrapper function to close application when the quit
862 * menu item has been used
863 *
864 *
865 */
866 void
closewrapper(GtkAction * action,DenemoScriptParam * param)867 closewrapper (GtkAction * action, DenemoScriptParam* param)
868 {
869 if(!Denemo.non_interactive){
870 GList *display;
871 gint unsaved = 0;
872 for (display = Denemo.projects; display != NULL; display = g_list_next (display))
873 {
874 DenemoProject *project = (DenemoProject *)display->data;
875 if (project->notsaved)
876 unsaved++;
877 }
878 if (unsaved>1)
879 { GString *options = g_string_new ("");
880 g_string_append_printf(options,"%s%c%s", _("Ask me about each"),'\0', _("Close all without saving"));
881 gchar *title = g_strdup_printf (_("You have %d score(s) unsaved"), unsaved);
882 gchar * response = get_option (title, options->str, options->len);
883 if (response != options->str)
884 {
885 for (display = Denemo.projects; display != NULL; display = g_list_next (display))
886 {
887 DenemoProject *project = (DenemoProject *)display->data;
888 project->notsaved = FALSE;
889 }
890 }
891 }
892
893 for (display = Denemo.projects; display != NULL; display = Denemo.projects)
894 {
895 Denemo.project = (DenemoProject *) display->data;
896 if (close_gui_with_check (NULL, NULL) == FALSE)
897 break;
898 }
899 }
900 }
901
902 /**
903 * callback from deleting window belonging to project:
904 * close window if check for unsaved data succeeds.
905 *
906 */
907
908 static gboolean
delete_callback(GtkWidget * widget,GdkEvent * event)909 delete_callback (GtkWidget * widget, GdkEvent * event)
910 {
911 close_gui_with_check (NULL, NULL);
912 return TRUE;
913 }
914
915 /**
916 * callback to fetch up-to-date system commands from internet, denemo.org hardwired at present
917 */
918 void
fetchcommands(GtkAction * action,DenemoScriptParam * param)919 fetchcommands (GtkAction * action, DenemoScriptParam* param)
920 {
921 static gchar *location = NULL;
922 location = g_build_filename (get_user_data_dir (TRUE), "download", COMMANDS_DIR, NULL);
923 gboolean err = g_mkdir_with_parents (location, 0770);
924 if (err)
925 {
926 gchar *message = g_strdup_printf (_("Could not make folder %s for the downloaded commands"), location);
927 warningdialog (message);
928 g_free (message);
929 return;
930 }
931
932 g_debug ("location is %s\n", location);
933 GError *error = NULL;
934 gchar *arguments[] = {
935 "wget",
936 "-N",
937 "-r",
938 "-np", //only below the menus directory
939 "-nH", //cut prefix
940 "--cut-dirs=1", //cut download part of path
941 DENEMO_DEFAULT_ANON_FTP,
942 NULL
943 };
944
945 g_spawn_async (location, /* dir */
946 arguments, NULL, /* env */
947 G_SPAWN_SEARCH_PATH, /* search in path for executable */
948 NULL, /* child setup func */
949 NULL, /* user data */
950 NULL, &error);
951 //FIXME create a callback to tell the user the result...
952 }
953
954
955 /**
956 * callback to load system extra commands
957 * if user has a local (possibly updated) set in ~/.denemo/downloads then that directory is used.
958 */
959 void
morecommands(GtkAction * action,DenemoScriptParam * param)960 morecommands (GtkAction * action, DenemoScriptParam* param)
961 {
962 static gchar *location = NULL;
963 location = g_build_filename (get_user_data_dir (TRUE), "download", COMMANDS_DIR, "menus", NULL);
964 if (!g_file_test (location, G_FILE_TEST_EXISTS))
965 {
966 g_free (location);
967 location = NULL;
968 }
969 if (location == NULL)
970 location = g_build_filename (get_system_data_dir (), COMMANDS_DIR, "menus", NULL);
971 load_keymap_dialog_location (location);
972 //#define WARNING_NEW_MENUS "Note: if you load a command that creates a new menu\nSome of the new commands may not work until you have exited\nand re-started denemo"
973 //warningdialog(WARNING_NEW_MENUS);
974 if (Denemo.last_merged_command && g_str_has_prefix (Denemo.last_merged_command, get_system_data_dir ()))
975 {
976 g_free (location);
977 location = g_strdup (Denemo.last_merged_command); //FIXME
978 }
979 }
980
981 /**
982 * callback to load local extra commands
983 *
984 */
985 void
mycommands(GtkAction * action,DenemoScriptParam * param)986 mycommands (GtkAction * action, DenemoScriptParam* param)
987 {
988 static gchar *location = NULL;
989 if (location == NULL)
990 location = g_build_filename (get_user_data_dir (TRUE), COMMANDS_DIR, "menus", NULL);
991
992 if (Denemo.last_merged_command && g_str_has_prefix (Denemo.last_merged_command, get_user_data_dir (TRUE)))
993 {
994 g_free (location);
995 location = g_path_get_dirname (Denemo.last_merged_command);
996 }
997 load_keymap_dialog_location (location);
998 // warningdialog(WARNING_NEW_MENUS);
999 //g_debug("The last was %s %s %s\n", Denemo.last_merged_command, location, get_user_data_dir(FALSE));
1000 }
1001
1002
1003
1004 /**
1005 * Open in New Window callback
1006 * Creates new view then opens file in the view
1007 */
1008 void
openinnew(GtkAction * action,DenemoScriptParam * param)1009 openinnew (GtkAction * action, DenemoScriptParam * param)
1010 {
1011 newtab ();
1012 file_open_with_check (NULL, param);
1013 if (param && (param->status == FALSE))
1014 close_project ();
1015 set_title_bar (Denemo.project);
1016 }
1017
1018
1019 /**
1020 * Close callback
1021 * if user confirms close the current project
1022 * if it is the last close the application.
1023 * return FALSE if project was not closed, else TRUE
1024 */
1025 gboolean
close_gui_with_check(GtkAction * action,DenemoScriptParam * param)1026 close_gui_with_check (GtkAction * action, DenemoScriptParam* param)
1027 {
1028 DenemoProject *project = Denemo.project;
1029 Denemo.prefs.mode = Denemo.project->mode;
1030 if (action_callbacks (Denemo.project))
1031 return FALSE; //Denemo.project may have been closed, depends on script callbacks;
1032 if (Denemo.accelerator_status)
1033 {
1034 if (confirm (_("You have made changes to the commands you have"), _("Do you want to save the changes?")))
1035 save_accels ();
1036 }
1037 //do not ask for confirm if scripted FIXME
1038 if ((!project->notsaved) || (project->notsaved && confirmbox (project)))
1039 close_project ();
1040 else
1041 return FALSE;
1042
1043 if (action) //called as Close not Quit
1044 {
1045 if (Denemo.projects == NULL)
1046 newtab ();
1047 return TRUE;
1048 }
1049 if (Denemo.projects == NULL)
1050 {
1051
1052 storeWindowState ();
1053 writeHistory ();
1054 writeXMLPrefs (&Denemo.prefs);
1055 writePalettes ();
1056 project = Denemo.project;
1057 if(project)
1058 {
1059
1060 /* It would be nice to delete the print directory to avoid filling up /tmp, however this fails on Unix at least for an unknown reason.
1061 gint result = g_remove (locateprintdir ());
1062 g_print("Removed %s %s\n", locateprintdir(), result==0?"successfully":"not gone");
1063 */
1064 #ifdef G_OS_WIN32
1065 CoUninitialize ();
1066 g_message ("Windows - Exiting without shutting down audio");
1067 if (project->input_source == INPUTMIDI)
1068 {
1069 if (confirm (_("MIDI Controller Active?"), _("Please turn off your MIDI keyboard\nif you have not already done so")))
1070 _exit (0); //audio shutdown can hang
1071 }
1072 else
1073 _exit (0);
1074
1075 #endif
1076 }
1077
1078 g_print ("Exiting directly - may leave notes sounding on audio!");
1079 _exit (0);
1080 audio_shutdown ();
1081
1082
1083 exit (0); //do not use gtk_main_quit, as there may be inner loops active.
1084 }
1085 return TRUE;
1086 }
1087
1088
1089 static void
singleton_callback(GtkToolButton * toolbutton,RhythmPattern * r)1090 singleton_callback (GtkToolButton * toolbutton, RhythmPattern * r)
1091 {
1092 DenemoProject *project = Denemo.project;
1093 #define CURRP ((RhythmPattern *)project->currhythm->data)
1094 if (project->currhythm && CURRP)
1095 unhighlight_rhythm (CURRP);
1096 project->currhythm = NULL;
1097
1098 project->rstep = r->rsteps;
1099 project->cstep = NULL;
1100
1101 #define g (project->rstep)
1102 #define MODE (project->mode)
1103 unhighlight_rhythm (project->prevailing_rhythm);
1104 project->prevailing_rhythm = r;
1105 highlight_rhythm (r);
1106 if ((MODE & (INPUTEDIT | INPUTRHYTHM)))
1107 {
1108 gint save = MODE;
1109 MODE = INPUTINSERT | INPUTNORMAL;
1110 ((GSourceFunc) (((RhythmElement *) g->data)->functions->data)) (project);
1111 displayhelper (project);
1112 MODE = save;
1113 }
1114 #undef CURRP
1115 #undef g
1116 #undef MODE
1117 }
1118
1119 /*UNUSED
1120 static void
1121 pb_first (GtkWidget * button)
1122 {
1123 call_out_to_guile ("(DenemoFirst)");
1124 }
1125 */
1126
1127 static void
pb_go_back(GtkWidget * button)1128 pb_go_back (GtkWidget * button)
1129 {
1130 call_out_to_guile ("(DenemoGoBack)");
1131 }
1132
1133 static void
pb_previous(GtkWidget * button)1134 pb_previous (GtkWidget * button)
1135 {
1136 call_out_to_guile ("(DenemoPrevious)");
1137 }
1138
1139 /*UNUSED
1140 static void
1141 pb_rewind (GtkWidget * button)
1142 {
1143 call_out_to_guile ("(DenemoRewind)");
1144 }
1145 */
1146 static void
pb_stop(GtkWidget * button)1147 pb_stop (GtkWidget * button)
1148 {
1149 call_out_to_guile ("(DenemoStop)");
1150 }
1151
1152 static void
pb_play(GtkWidget * button)1153 pb_play (GtkWidget * button)
1154 {
1155 call_out_to_guile ("(DenemoPlay)");
1156 }
1157
1158 /*UNUSED
1159 static void
1160 pb_pause (GtkWidget * button)
1161 {
1162 call_out_to_guile ("(DenemoPause)");
1163 }
1164 */
1165 /*UNUSED
1166 static void
1167 pb_forward (GtkWidget * button)
1168 {
1169 call_out_to_guile ("(DenemoForward)");
1170 }
1171 */
1172 static void
pb_next(GtkWidget * button)1173 pb_next (GtkWidget * button)
1174 {
1175 call_out_to_guile ("(DenemoNext)");
1176 }
1177
1178 static void
pb_go_forward(GtkWidget * button)1179 pb_go_forward (GtkWidget * button)
1180 {
1181 call_out_to_guile ("(DenemoGoForward)");
1182 }
1183
1184 /*UNUSED
1185 static void
1186 pb_last (GtkWidget * button)
1187 {
1188 call_out_to_guile ("(DenemoLast)");
1189 }
1190 */
1191 static void
pb_start_to_cursor(GtkWidget * button)1192 pb_start_to_cursor (GtkWidget * button)
1193 {
1194 call_out_to_guile ("(DenemoSetPlaybackStart)");
1195 //gtk_widget_draw(Denemo.scorearea, NULL);
1196 draw_score_area();
1197 draw_score (NULL);
1198 }
1199
1200 static void
pb_end_to_cursor(GtkWidget * button)1201 pb_end_to_cursor (GtkWidget * button)
1202 {
1203 call_out_to_guile ("(DenemoSetPlaybackEnd)");
1204 //gtk_widget_draw(Denemo.scorearea, NULL);
1205 draw_score_area();
1206 draw_score (NULL);
1207 }
1208
1209 static void
pb_loop(GtkWidget * button)1210 pb_loop (GtkWidget * button)
1211 {
1212 call_out_to_guile ("(DenemoLoop)");
1213 }
1214
1215 static void
pb_tempo(GtkAdjustment * adjustment)1216 pb_tempo (GtkAdjustment * adjustment)
1217 {
1218 gdouble tempo;
1219 gdouble bpm = gtk_adjustment_get_value (adjustment);
1220 tempo = (Denemo.project->movement->tempo > 0) ? bpm / Denemo.project->movement->tempo : 1.0;
1221 scm_c_define ("DenemoTempo::Value", scm_from_double (tempo));
1222 call_out_to_guile ("(DenemoTempo)");
1223 Denemo.project->movement->smfsync = G_MAXINT;
1224 }
1225 static void
pb_mute_staffs()1226 pb_mute_staffs ()
1227 {
1228 call_out_to_guile ("(d-MuteStaffs)");
1229 }
1230 void
update_tempo_widget(gdouble value)1231 update_tempo_widget (gdouble value)
1232 {
1233 gdouble bpm = gtk_adjustment_get_value (master_tempo_adj);//g_debug("bpm %f and correction %f\n", bpm, value);
1234 bpm += value;
1235 gtk_adjustment_set_value (master_tempo_adj, bpm);
1236 gtk_adjustment_changed (master_tempo_adj);
1237 Denemo.project->movement->smfsync = G_MAXINT;
1238 }
1239
1240 #ifdef _HAVE_RUBBERBAND_
1241 static void
set_speed(GtkAdjustment * adjustment)1242 set_speed (GtkAdjustment * adjustment)
1243 {
1244 gdouble speed = gtk_adjustment_get_value (adjustment);
1245 set_playback_speed(speed);
1246 }
1247 #endif
1248
1249 static void
pb_volume(GtkAdjustment * adjustment)1250 pb_volume (GtkAdjustment * adjustment)
1251 {
1252 gdouble volume = gtk_adjustment_get_value (adjustment);
1253 scm_c_define ("DenemoVolume::Value", scm_from_double (volume));
1254 call_out_to_guile ("(DenemoVolume)");
1255 }
1256
1257 static void
audio_volume_cut(GtkAdjustment * adjustment)1258 audio_volume_cut (GtkAdjustment * adjustment)
1259 {
1260 if (Denemo.project->movement->recording)
1261 {
1262 Denemo.project->movement->recording->volume = gtk_adjustment_get_value (adjustment);
1263 }
1264 }
1265
1266 static void
audio_volume_boost(GtkAdjustment * adjustment)1267 audio_volume_boost (GtkAdjustment * adjustment)
1268 {
1269 if (Denemo.project->movement->recording)
1270 {
1271 Denemo.project->movement->recording->volume = gtk_adjustment_get_value (adjustment);
1272 }
1273 }
1274
1275 static void
leadin_changed(GtkSpinButton * spin)1276 leadin_changed (GtkSpinButton * spin)
1277 {
1278 if (Denemo.project->movement->recording)
1279 {
1280 set_lead_in (gtk_spin_button_get_value (spin));
1281 //g_debug("%d for %f\n", Denemo.project->movement->recording->leadin, gtk_spin_button_get_value(spin));
1282 }
1283 }
1284
1285 void
update_leadin_widget(gdouble secs)1286 update_leadin_widget (gdouble secs)
1287 {
1288 gtk_spin_button_set_value (leadin, secs);
1289 }
1290
1291 static void
pb_play_range(GtkWidget * button)1292 pb_play_range (GtkWidget * button)
1293 {
1294 if(Denemo.project->movement->markstaffnum)
1295 call_out_to_guile ("(DenemoSetPlaybackIntervalToSelection)(d-Play)");
1296 else
1297 call_out_to_guile ("(d-DenemoPlayCursorToEnd)");
1298 }
1299
1300 static void
pb_range(GtkWidget * button)1301 pb_range (GtkWidget * button)
1302 {
1303 PlaybackRangeDialog ();
1304 }
1305
1306 static void
pb_panic(GtkWidget * button)1307 pb_panic (GtkWidget * button)
1308 {
1309 playback_panic ();
1310 Denemo.project->movement->start_time = 0.0;
1311 Denemo.project->movement->end_time = -1.0; //ie unset
1312 set_start_and_end_objects_for_draw ();
1313 reset_temperament ();
1314 draw_score_area();
1315 }
1316
1317 static void
track_delete(smf_track_t * track)1318 track_delete (smf_track_t * track)
1319 {
1320 if (track == NULL || track->user_pointer)
1321 return;
1322 if (track->smf == NULL)
1323 {
1324 smf_t *smf = smf_new ();
1325 smf_add_track (smf, track);
1326 smf_delete (smf);
1327 }
1328 else
1329 smf_track_delete (track);
1330 }
1331
1332 void
set_midi_in_status(void)1333 set_midi_in_status (void)
1334 {
1335 if (midi_in_status)
1336 {
1337 gchar *text = NULL;
1338 if ((Denemo.project->midi_destination & MIDIRECORD) && (Denemo.project->midi_destination & MIDIPLAYALONG))
1339 text = g_strconcat ("<span foreground=\"blue\">", _("Recording + Play Along"), "</span>", NULL);
1340 else if (Denemo.project->midi_destination & MIDIRECORD)
1341 text = g_strconcat ("<span foreground=\"red\">", _("Recording"), "</span>", NULL);
1342 else if (Denemo.project->midi_destination & MIDIPLAYALONG)
1343 text = g_strconcat ("<span foreground=\"red\">", _("Play Along"), "</span>", NULL);
1344 else if ((Denemo.keyboard_state & ~GDK_LOCK_MASK) == (GDK_CONTROL_MASK))
1345 text = g_strconcat ("<span foreground=\"#808000\" size=\"larger\">", _("Checking Pitches"), "</span>", NULL);
1346 else if ((Denemo.keyboard_state == (GDK_SHIFT_MASK)) || (Denemo.keyboard_state == (GDK_LOCK_MASK)))
1347 text = g_strconcat ("<span foreground=\"#008080\" size=\"larger\">", _("Listening to Pitches"), "</span>", NULL);
1348 else if ((Denemo.keyboard_state & CHORD_MASK))
1349 text = g_strconcat ("<span foreground=\"#000000\">", _("Editing a Chord"), "</span>", NULL);
1350 else if ((Denemo.keyboard_state & ADDING_MASK))
1351 text = g_strconcat ("<span foreground=\"#000000\">", _("Starting a Chord"), "</span>", NULL);
1352 else
1353 text = g_strconcat ("<span foreground=\"#000000\">", _("Appending/Editing Pitches"), "</span>", NULL);
1354 gtk_label_set_markup (GTK_LABEL (midi_in_status), text);
1355 g_free(text);
1356 }
1357 }
1358
midi_in_adjust(gint value)1359 void midi_in_adjust (gint value) {
1360 Denemo.keyboard_state = value;
1361 Denemo.keyboard_state_locked = value;//lock if set to listening or checking
1362 set_midi_in_status ();
1363 switch_back_to_main_window ();
1364 }
1365
1366
midi_in_menu(void)1367 static void midi_in_menu (void) {
1368 GtkWidget *menu = gtk_menu_new ();
1369 GtkWidget *item = gtk_menu_item_new_with_label (_("Checking Pitches"));
1370 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1371 g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (midi_in_adjust), GINT_TO_POINTER(GDK_CONTROL_MASK));
1372
1373 item = gtk_menu_item_new_with_label (_("Listening to Pitches"));
1374 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1375 g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (midi_in_adjust), GINT_TO_POINTER(GDK_SHIFT_MASK));
1376
1377 item = gtk_menu_item_new_with_label (_("Appending/Editing Pitches"));
1378 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1379 g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (midi_in_adjust), 0);
1380 gtk_widget_show_all (menu);
1381 gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time ());
1382 }
1383
1384 void
pb_conduct(GtkWidget * button)1385 pb_conduct (GtkWidget * button)
1386 {
1387 Denemo.project->midi_destination ^= MIDICONDUCT;
1388 if (Denemo.project->midi_destination & MIDICONDUCT)
1389 gtk_button_set_label (GTK_BUTTON (button), _("Mouse Conductor ON"));
1390 else
1391 gtk_button_set_label (GTK_BUTTON (button), _("Mouse Conductor OFF"));
1392 }
1393
1394
1395
1396 void
pb_playalong(GtkWidget * button)1397 pb_playalong (GtkWidget * button)
1398 {
1399 Denemo.project->midi_destination ^= MIDIPLAYALONG;
1400 if (Denemo.project->midi_destination & MIDIPLAYALONG)
1401 gtk_button_set_label (GTK_BUTTON (button), _("Switch to Normal Playback"));
1402 else
1403 gtk_button_set_label (GTK_BUTTON (button), _("Switch to Play Along Playback"));
1404 set_midi_in_status ();
1405 }
1406
show_midi_record_control(void)1407 gboolean show_midi_record_control(void) {
1408 gtk_widget_show (deletebutton);
1409 gtk_widget_show (convertbutton);
1410 set_midi_in_status ();
1411 return FALSE;// stop timer callback
1412 }
1413 gboolean
pb_record(gchar * callback)1414 pb_record (gchar *callback)
1415 {
1416 if(is_playing())
1417 {
1418 warningdialog(_("Stop playing first"));
1419 return FALSE;
1420 }
1421 if (Denemo.project->movement->recording && (Denemo.project->movement->recording->type==DENEMO_RECORDING_AUDIO))
1422 {
1423 warningdialog(_("Cannot mix audio and MIDI recordings"));
1424 return FALSE;
1425 }
1426
1427 if (Denemo.project->movement->recorded_midi_track && midi_is_from_file())
1428 {
1429 warningdialog(_("Cannot mix MIDI recordings with imported MIDI - delete imported MIDI first"));
1430 return FALSE;
1431 }
1432
1433 if (Denemo.project->movement->recorded_midi_track && !confirm (_("MIDI Recording"), _("Delete last recording?")))
1434 {
1435 return FALSE;
1436 }
1437
1438 delete_imported_midi ();
1439 call_out_to_guile ("(DenemoSetPlaybackStart)");
1440
1441
1442
1443 new_midi_recording();
1444
1445
1446
1447 Denemo.project->midi_destination |= MIDIRECORD;
1448 track_delete (Denemo.project->movement->recorded_midi_track);
1449 Denemo.project->movement->recorded_midi_track = smf_track_new ();
1450 gtk_widget_hide (deletebutton);
1451 gtk_widget_hide (convertbutton);
1452
1453 set_midi_in_status ();
1454 gchar *script = callback?g_strdup_printf("(d-Play \"%s\")", callback): g_strdup("(d-Play)");
1455 call_out_to_guile (script);
1456 g_free(script);
1457 {//this note off event prevents the first MIDI note from sounding a few seconds into the recording
1458 //why such a spurious note is heard is unknown, it does not get put into the event queues (immediate or standard)
1459 gchar buf[] = {0x80, 0x0, 0x0};
1460 handle_midi_event (buf);
1461
1462 }
1463 return TRUE;
1464 }
1465
1466 static void
pb_audiorecord(GtkWidget * button)1467 pb_audiorecord (GtkWidget * button)
1468 {
1469 gtk_button_set_image (GTK_BUTTON (audiorecordbutton),
1470 gtk_image_new_from_stock (GTK_STOCK_MEDIA_RECORD, GTK_ICON_SIZE_BUTTON));//highlighting may have turned it off
1471 if (Denemo.prefs.maxrecordingtime)
1472 {
1473 Denemo.project->audio_recording = !Denemo.project->audio_recording;
1474 if(!Denemo.project->audio_recording) gtk_widget_show(exportbutton);
1475 }
1476 else
1477 {
1478 warningdialog (_("The preference set for recording time is 0 - nothing can be recorded.\nSee Edit → Change Preferences Audio/Midi Tab"));
1479 }
1480 }
1481 static void
pb_exportaudio(GtkWidget * button)1482 pb_exportaudio (GtkWidget * button)
1483 {
1484 if(!Denemo.project->audio_recording)
1485 Denemo.project->audio_recording = FALSE;
1486 export_recorded_audio ();
1487 }
1488
highlight_audio_record(void)1489 void highlight_audio_record(void) {
1490 static gboolean on;
1491 on = !on;
1492 gtk_button_set_image (GTK_BUTTON (audiorecordbutton),
1493 gtk_image_new_from_stock (on?GTK_STOCK_MEDIA_RECORD:GTK_STOCK_MEDIA_STOP, GTK_ICON_SIZE_BUTTON));
1494 }
1495
delete_recording(void)1496 void delete_recording (void) {
1497 //FIXME a better name for the mutex which originally was just for midi data, but will work for audio data too.
1498 if (Denemo.project->movement && Denemo.project->movement->recording)
1499 {
1500 DenemoRecording *temp = Denemo.project->movement->recording;
1501 g_static_mutex_lock (&smfmutex);
1502 Denemo.project->movement->recording = NULL;
1503 g_static_mutex_unlock (&smfmutex);
1504 if (temp->sndfile)
1505 sf_close (temp->sndfile);
1506 g_free (temp->filename);
1507 g_list_free_full(temp->notes, g_free);
1508 g_free (temp);
1509 Denemo.project->movement->recording = NULL;
1510 Denemo.project->movement->marked_onset = NULL;
1511 }
1512 }
1513 static void
pb_midi_delete(GtkWidget * button)1514 pb_midi_delete (GtkWidget * button)
1515 {
1516 DenemoRecording *recording = Denemo.project->movement->recording;
1517 if(recording)
1518 {
1519 if(recording->type!=DENEMO_RECORDING_MIDI)
1520 {
1521 g_warning("Cannot delete Audio yet");
1522 return;//see sourceaudio.c:222 for deleting audio
1523 }
1524 track_delete (Denemo.project->movement->recorded_midi_track);
1525 Denemo.project->movement->recorded_midi_track = NULL;
1526
1527 delete_recording ();
1528 }
1529 gtk_widget_hide (convertbutton);
1530 gtk_widget_hide (button);
1531 gtk_widget_queue_draw(Denemo.scorearea);
1532 }
1533
1534 static void
pb_midi_convert(GtkWidget * button)1535 pb_midi_convert (GtkWidget * button)
1536 {
1537
1538 call_out_to_guile ("(DenemoConvert)");
1539
1540 g_info ("Finished midi convert");
1541 }
1542 #define CURRP ((RhythmPattern *)project->currhythm->data)
1543 #define LABEL_WIDGET_OF_TOOLBUTTON(a) (gtk_tool_button_get_label_widget((a)))
1544
set_rhythm_label(RhythmPattern * r,gchar * text)1545 void set_rhythm_label (RhythmPattern * r, gchar *text)
1546 {
1547 DenemoProject *project = Denemo.project;
1548 GtkWidget *label = LABEL_WIDGET_OF_TOOLBUTTON (CURRP->button);
1549 gchar *labelstr;
1550 if (r->nickname && r->nickname->len)
1551 labelstr = g_strconcat (text,"\n",r->nickname->str, NULL);
1552 else
1553 labelstr = g_strdup (text);
1554 //g_debug("markup is %s\n", ((RhythmElement*)g->data)->icon);
1555 gtk_label_set_markup (GTK_LABEL (label), labelstr);
1556 g_free (labelstr);
1557 }
1558
1559 /**
1560 * Rhythm callback select rhythm
1561 * inserts the rhythm if pitchless
1562 */
1563 void
select_rhythm_pattern(RhythmPattern * r)1564 select_rhythm_pattern (RhythmPattern * r)
1565 {
1566 DenemoProject *project = Denemo.project;
1567
1568
1569 if (project->currhythm && (CURRP != r))
1570 { //Change the highlighting
1571 if (CURRP)
1572 unhighlight_rhythm (CURRP);
1573 else if (project->rstep)
1574 unhighlight_rhythm (((RhythmElement *) project->rstep->data)->rhythm_pattern);
1575 }
1576
1577 project->currhythm = g_list_find (project->rhythms, r);
1578 if (project->currhythm != NULL)
1579 {
1580 project->rstep = r->rsteps;
1581 project->cstep = r->clipboard->data;
1582
1583 gchar *text = ((RhythmElement *) project->rstep->data)->highlightlabel;
1584 if (text)
1585 {
1586 set_rhythm_label (r, text);
1587 }
1588 highlight_rhythm (CURRP);
1589 }
1590 #undef CURRP
1591 }
1592 #undef LABEL_WIDGET_OF_TOOLBUTTON
insert_and_select_snippet(RhythmPattern * r)1593 static void insert_and_select_snippet (RhythmPattern * r)
1594 {
1595 select_rhythm_pattern (r);
1596 if ((Denemo.project->mode & INPUTEDIT))
1597 {
1598 insert_clipboard (r->clipboard);
1599 }
1600 }
insert_snippet(RhythmPattern * r)1601 static void insert_snippet (RhythmPattern * r)
1602 {
1603
1604 if ((Denemo.project->mode & INPUTEDIT))
1605 {
1606 insert_clipboard (r->clipboard);
1607 }
1608 }
1609
1610 static void rename_snippet (RhythmPattern *r);
1611
1612 static void
activate_rhythm_pattern(GtkToolButton * toolbutton,RhythmPattern * r)1613 activate_rhythm_pattern (GtkToolButton * toolbutton, RhythmPattern * r)
1614 {
1615 GtkWidget *menu = gtk_menu_new ();
1616 GtkWidget *item = gtk_menu_item_new_with_label (_("Select and Reset Snippet"));
1617 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1618 g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (select_rhythm_pattern),r);
1619
1620 item = gtk_menu_item_new_with_label (_("Insert Snippet at Cursor"));
1621 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1622 g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (insert_snippet), r);
1623 item = gtk_menu_item_new_with_label (_("Re-label Snippet"));
1624 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1625 g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (rename_snippet), r);
1626
1627 item = gtk_menu_item_new_with_label (_("Insert and Select"));
1628 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1629 g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (insert_and_select_snippet), r);
1630
1631 item = gtk_menu_item_new_with_label (_("Delete Snippet"));
1632 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1633 g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (delete_rhythm_pattern), r);
1634 gtk_widget_show_all (menu);
1635 gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time ());
1636 }
1637
insert_nth_rhythm(gint n)1638 gboolean insert_nth_rhythm (gint n) {
1639
1640 gint nr = g_list_length (Denemo.project->rhythms);
1641 if (n>=0 && n<nr)
1642 {
1643 insert_clipboard (((RhythmPattern*)(g_list_nth (Denemo.project->rhythms, n))->data)->clipboard);
1644 return TRUE;
1645 }
1646 return FALSE;
1647 }
null_action()1648 static void null_action () {}
1649
1650 /* duration_code(gpointer function)
1651 * return an ascii code to indicate what duration (if any) function gives.
1652 * '0x0' means not a duration
1653 * chars 012345678 are the standard note durations
1654 *
1655 */
1656 gchar
duration_code(gpointer fn)1657 duration_code (gpointer fn)
1658 {
1659 return fn == (gpointer) insert_chord_0key ? '0' : fn == (gpointer) insert_chord_1key ? '1' : fn == (gpointer) insert_chord_2key ? '2' : fn == (gpointer) insert_chord_3key ? '3' : fn == (gpointer) insert_chord_4key ? '4' : fn == (gpointer) insert_chord_5key ? '5' : fn == (gpointer) insert_chord_6key ? '6' : fn == (gpointer) insert_chord_7key ? '7' : fn == (gpointer) insert_chord_8key ? '8' : 0;
1660 }
1661
1662 /* modifier_code(gpointer function)
1663 * return an ascii code to indicate what modifier (if any) function gives.
1664 * '0x0' means not a valid modifier for a rhythmic duration
1665 * char '.' means a dotted note, '(' and ')' mean start and end slur
1666 * r to z are rests
1667 * others to be defined
1668 *
1669 */
1670 gchar
modifier_code(gpointer fn)1671 modifier_code (gpointer fn)
1672 {
1673 return fn == (gpointer) triplet_start ? '~' :
1674 fn == (gpointer) tuplet_end ? '|' :
1675 fn == (gpointer) add_dot_key ? '.' :
1676 fn == (gpointer) toggle_begin_slur ? '(' :
1677 fn == (gpointer) toggle_end_slur ? ')' :
1678 fn == (gpointer) insert_rest_0key ? 'r' :
1679 fn == (gpointer) insert_rest_1key ? 's' :
1680 fn == (gpointer) insert_rest_2key ? 't' :
1681 fn == (gpointer) insert_rest_3key ? 'u' :
1682 fn == (gpointer) insert_rest_4key ? 'v' :
1683 fn == (gpointer) insert_rest_5key ? 'w' :
1684 fn == (gpointer) insert_rest_6key ? 'x' :
1685 fn == (gpointer) insert_rest_7key ? 'y' :
1686 fn == (gpointer) insert_rest_8key ? 'z' :
1687 fn == (gpointer) null_action ? 'S' :
1688 0;
1689 }
1690
1691 gboolean
code_is_a_duration(gchar code)1692 code_is_a_duration (gchar code)
1693 {
1694 return code == 0 || (code >= 'r' && code <= 'z');
1695 }
1696
1697
1698
1699 /* add_to_rhythm appends to a rhythm pattern the callback function fn
1700 fn is a callback function
1701 returns TRUE if something was added
1702 */
1703 gboolean
append_rhythm(RhythmPattern * r,gpointer fn)1704 append_rhythm (RhythmPattern * r, gpointer fn)
1705 {
1706 RhythmElement *relement;
1707
1708 int keyval = duration_code (fn);
1709 if (keyval)
1710 {
1711
1712 relement = (RhythmElement *) g_malloc0 (sizeof (RhythmElement));
1713
1714 relement->functions = g_list_append (NULL, fn);
1715
1716 r->rsteps = g_list_append (r->rsteps, relement);
1717 relement->rhythm_pattern = r;
1718 return TRUE;
1719 }
1720 keyval = modifier_code (fn);
1721 if (keyval)
1722 {
1723 if (r->rsteps)
1724 {
1725 relement = (RhythmElement *) (g_list_last (r->rsteps)->data);
1726 }
1727 else
1728 {
1729 relement = (RhythmElement *) g_malloc0 (sizeof (RhythmElement));
1730 }
1731 relement->functions = g_list_append (relement->functions, (gpointer) fn);
1732 if (r->rsteps == NULL)
1733 {
1734 r->rsteps = g_list_append (r->rsteps, relement);
1735 }
1736 relement->rhythm_pattern = r;
1737 return TRUE;
1738 }
1739 return FALSE;
1740 }
1741
1742
1743 static void
remove_breaks(GList * clip)1744 remove_breaks (GList * clip)
1745 {
1746 for (; clip; clip = clip->next)
1747 {
1748 GList *g = clip->data;
1749 for (; g; g = g->next)
1750 {
1751 //g_debug("have %x type %d\n", g->data, ((DenemoObject*)g->data)->type);
1752 if ((((DenemoObject *) g->data)->type == MEASUREBREAK) || (((DenemoObject *) g->data)->type == STAFFBREAK))
1753 g = clip->data = g_list_delete_link (clip->data, g); //we search from the start again, as g has been freed
1754 }
1755 }
1756 }
1757
1758 static void
attach_clipboard(RhythmPattern * r)1759 attach_clipboard (RhythmPattern * r)
1760 {
1761 DenemoProject *project = Denemo.project;
1762 DenemoMovement *si;
1763 if (project->movement) si = project->movement;
1764 if (si->markstaffnum)
1765 {
1766 push_clipboard ();
1767 copytobuffer (si);
1768 push_clipboard ();
1769 r->clipboard = pop_off_clipboard ();
1770 remove_breaks (r->clipboard);
1771 pop_clipboard ();
1772 }
1773 }
1774
1775
1776 gint
insert_pattern_in_toolbar(RhythmPattern * r,gboolean highlight)1777 insert_pattern_in_toolbar (RhythmPattern * r, gboolean highlight)
1778 {
1779 if(Denemo.non_interactive)
1780 return -1;
1781 DenemoProject *project = Denemo.project;
1782 if (r->clipboard == NULL)
1783 {
1784 g_warning ("No clipboard for this pattern, cannot add");
1785 return -1;
1786 }
1787 GtkWidget *toolbar = gtk_ui_manager_get_widget (Denemo.ui_manager, "/RhythmToolBar");
1788 gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (r->button), -1);
1789 gtk_widget_show_all (GTK_WIDGET (r->button));
1790
1791 project->rhythms = g_list_append (project->rhythms, r);
1792 if (highlight)
1793 {
1794 project->rstep = r->rsteps;
1795 project->cstep = r->clipboard->data;
1796 if (project->currhythm)
1797 unhighlight_rhythm ((RhythmPattern *) project->currhythm->data);
1798 project->currhythm = g_list_last (project->rhythms);
1799 highlight_rhythm ((RhythmPattern *) project->currhythm->data);
1800 }
1801 g_signal_connect (G_OBJECT (r->button), "clicked", G_CALLBACK (activate_rhythm_pattern), (gpointer) r);
1802 return g_list_length (project->rhythms); //the index of the newly added snippet
1803 }
1804
1805 void
install_button_for_pattern(RhythmPattern * r,gchar * thelabel)1806 install_button_for_pattern (RhythmPattern * r, gchar * thelabel)
1807 {
1808 GtkToolButton *button;
1809 GtkWidget *label;
1810 button = (GtkToolButton *) gtk_tool_button_new (NULL, NULL);
1811 label = gtk_label_new (thelabel);
1812 gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
1813 gtk_tool_button_set_label_widget (button, label);
1814 r->button = button;
1815 }
shorten_string(gchar * str)1816 static GString *shorten_string (gchar *str) {
1817 GString *ret = g_string_new("");
1818 for(;*str;str++)
1819 {
1820 switch (*str) {
1821 case '\n':
1822 case '\t':
1823 case ' ':
1824 continue;
1825 default:
1826 g_string_append_c (ret, *str);
1827
1828 }
1829 if(ret->len > 8) break;
1830 }
1831 return ret;
1832 }
1833
1834 /*
1835 * curobj is a list of DenemoObject,
1836 * creates a RhythmPattern
1837 * and the ASCII pattern that is used by the caller to generate a label on the snippet button and a set of highlighted labels for each step of the rhythm pattern.
1838 * accumulates the lilypond field of the rhythm pattern from the lilypond fields of the objects
1839 */
create_rhythm_and_pattern(GList * curobj,RhythmPattern * r,GString * pattern)1840 static void create_rhythm_and_pattern (GList *curobj, RhythmPattern* r, GString *pattern) {
1841 if(r->lilypond==NULL)
1842 r->lilypond = g_string_new("");
1843 for (; curobj; curobj = curobj->next)
1844 {
1845 gpointer fn;
1846 DenemoObject *obj = (DenemoObject *) curobj->data;
1847 switch (obj->type)
1848 {
1849 case TUPCLOSE:
1850 fn = (gpointer) tuplet_end;
1851 g_string_append_c (pattern, '|');
1852 append_rhythm (r, fn);
1853 break;
1854 case TUPOPEN:
1855 switch (((tupopen *) obj->object)->denominator)
1856 {
1857 case 3:
1858 fn = (gpointer) triplet_start;
1859 g_string_append_c (pattern, '~');
1860 break;
1861 default: // need to create start_xxxtuplet() functions to go with triplet_start(), then they can go here.
1862 fn = NULL;
1863 }
1864 append_rhythm (r, fn);
1865 break;
1866 case CHORD:
1867 {
1868 chord *ch = (chord *) obj->object;
1869
1870 if (ch->notes)
1871 {
1872 switch (ch->baseduration)
1873 {
1874 case 0:
1875 fn = insert_chord_0key;
1876 break;
1877 case 1:
1878 fn = insert_chord_1key;
1879 break;
1880 case 2:
1881 fn = insert_chord_2key;
1882 break;
1883 case 3:
1884 fn = insert_chord_3key;
1885 break;
1886 case 4:
1887 fn = insert_chord_4key;
1888 break;
1889 case 5:
1890 fn = insert_chord_5key;
1891 break;
1892 case 6:
1893 fn = insert_chord_6key;
1894 break;
1895 case 7:
1896 fn = insert_chord_7key;
1897 break;
1898 case 8:
1899 fn = insert_chord_8key;
1900 break;
1901 default:
1902 g_warning ("Handling unknown type of chord as whole note");
1903 fn = insert_chord_0key;
1904 break;
1905 }
1906 g_string_append_c (pattern, duration_code (fn));
1907 append_rhythm (r, fn);
1908 }
1909 else
1910 { /* a rest */
1911 switch (ch->baseduration)
1912 {
1913 case 0:
1914 fn = insert_rest_0key;
1915 break;
1916 case 1:
1917 fn = insert_rest_1key;
1918 break;
1919 case 2:
1920 fn = insert_rest_2key;
1921 break;
1922 case 3:
1923 fn = insert_rest_3key;
1924 break;
1925 case 4:
1926 fn = insert_rest_4key;
1927 break;
1928 case 5:
1929 fn = insert_rest_5key;
1930 break;
1931 case 6:
1932 fn = insert_rest_6key;
1933 break;
1934 case 7:
1935 fn = insert_rest_7key;
1936 break;
1937 case 8:
1938 fn = insert_rest_8key;
1939 break;
1940 default:
1941 g_warning ("Handling unknown type of rest as whole note rest");
1942 fn = insert_rest_0key;
1943 break;
1944 }
1945 g_string_append_c (pattern, modifier_code (fn));
1946 append_rhythm (r, fn);
1947 } /* end of rests */
1948 gint i;
1949 for (i = ch->numdots; i; i--)
1950 {
1951 fn = add_dot_key;
1952 g_string_append_c (pattern, modifier_code (fn));
1953 append_rhythm (r, fn);
1954 }
1955 if (ch->slur_begin_p)
1956 {
1957 fn = (gpointer) toggle_begin_slur;
1958 g_string_append_c (pattern, '(');
1959 append_rhythm (r, fn);
1960 }
1961 if (ch->slur_end_p)
1962 {
1963 fn = (gpointer) toggle_end_slur;
1964 g_string_append_c (pattern, ')');
1965 append_rhythm (r, fn);
1966 }
1967 //FIXME other built-ins here - cresc endcresc ...
1968 }
1969 break;
1970 case LILYDIRECTIVE:
1971 {
1972 DenemoDirective *direc = (DenemoDirective *)obj->object;
1973 fn = (gpointer) null_action;
1974 if((curobj->prev==NULL)&&(curobj->next==NULL) && (r->nickname==NULL))
1975 {
1976 if(direc->display)
1977 r->nickname = shorten_string (direc->display->str);
1978 else
1979 if(direc->graphic_name)
1980 r->nickname = shorten_string (direc->graphic_name->str);
1981 else
1982 if(direc->postfix)
1983 r->nickname = shorten_string (direc->prefix->str);
1984 else
1985 r->nickname = g_string_new ("S");
1986 }
1987 g_string_append_c (pattern, 'S');
1988 append_rhythm (r, fn);
1989 }
1990 break;
1991 default:
1992 {
1993 fn = null_action;
1994 g_string_append_c (pattern, 'S');
1995 append_rhythm (r, fn);
1996 }
1997 //g_warning("ignoring %d", obj->type);
1998 break;
1999 } /* end of switch obj type */
2000 //g_debug("Number of rhythms %d\n", g_list_length(r->rsteps));
2001 if (obj->lilypond)
2002 g_string_append (r->lilypond, obj->lilypond);
2003 } /* End object loop */
2004 }
2005 //create values for highlightlabel field of the r->steps from the pattern
fill_in_steps(RhythmPattern * r,GString * pattern)2006 void fill_in_steps (RhythmPattern* r, GString *pattern) {
2007 /* fill the r->rsteps with highlightlabels for each step */
2008 GList *g;
2009 RhythmElement *el;
2010 gint i;
2011 for (g = r->rsteps, i = 0; g; g = g->next, i++)
2012 {
2013 el = (RhythmElement *) g->data;
2014 if (i == 0 && (*(pattern->str) < '0' || *(pattern->str) > '8') && g->next)
2015 g = g->next; // pattern does not start with a note (0 to 8), so we skip to the second element, unless there are no notes
2016 while (*(pattern->str + i) && (*(pattern->str + i) < '0' || *(pattern->str + i) > '8'))
2017 i++;
2018 if (*(pattern->str + i))
2019 {
2020 *(pattern->str + i) += HIGHLIGHT_OFFSET;
2021 el->highlightlabel = music_font (pattern->str);
2022 *(pattern->str + i) -= HIGHLIGHT_OFFSET;
2023 }
2024 //g_debug("el->highlightlabel = %s step %d pattern->str %s\n", el->highlightlabel, i, pattern->str);
2025 }
2026 }
2027
2028
rename_rhythm(RhythmPattern * r,gchar * name)2029 static void rename_rhythm (RhythmPattern *r, gchar *name)
2030 {
2031 GtkWidget *label = gtk_tool_button_get_label_widget (r->button);
2032 if (r->nickname == NULL)
2033 r->nickname = g_string_new (r->name);
2034 if(name==NULL)
2035 name = string_dialog_entry (Denemo.project, _("Rename Music Snippet"), _("Give new label for snippet"), r->nickname->str);
2036 if(name && *name)
2037 {
2038 g_string_assign (r->nickname, name);
2039 gtk_label_set_markup (GTK_LABEL (label), r->nickname->str);
2040 }
2041 }
2042
rename_snippet(RhythmPattern * r)2043 static void rename_snippet (RhythmPattern *r)
2044 {
2045 rename_rhythm (r, NULL);
2046 }
2047 //create a rhythm pattern (aka snippet) from r->clipboard or the selection
2048 //put the rhythm pattern in the Denemo.project and on the snippets toolbar
2049 //highlight the created rhythm if from the selection
create_rhythm(RhythmPattern * r,gboolean from_selection)2050 void create_rhythm (RhythmPattern *r, gboolean from_selection) {
2051 GString *pattern = g_string_new("");
2052 install_button_for_pattern (r, NULL);
2053 if (from_selection)
2054 attach_clipboard (r);
2055
2056 if (r->clipboard)
2057 create_rhythm_and_pattern ( (GList *)((GList *)r->clipboard)->data, r, pattern);
2058 gchar *labelstr;
2059 labelstr = music_font (pattern->str);
2060 GtkWidget *label = gtk_tool_button_get_label_widget (r->button);
2061 gtk_label_set_markup (GTK_LABEL (label), labelstr);
2062 g_free (labelstr);
2063 fill_in_steps (r, pattern);
2064 if (r->rsteps)
2065 {
2066 /* make the list circular */
2067 r->rsteps->prev = g_list_last (r->rsteps);
2068 g_list_last (r->rsteps)->next = r->rsteps;
2069 }
2070 insert_pattern_in_toolbar (r, from_selection);
2071 if(r->nickname)
2072 rename_rhythm (r, r->nickname->str);
2073 if(!from_selection)
2074 unhighlight_rhythm (r);
2075 g_string_free (pattern, TRUE);
2076 }
2077
2078
2079 /* create_rhythm_cb
2080 - create a rhythm pattern from the current selection
2081 - clipboard field is pointed to the selected objects
2082 - a button is created in "/RhythmToolbar"
2083 - and the pattern is added to project->rhythms
2084 - with the first step of it put in project->rstep
2085 - the rhythm becomes the prevailing_rhythm, setting cstep
2086
2087 */
2088 void
create_rhythm_cb(GtkAction * action,DenemoScriptParam * param)2089 create_rhythm_cb (GtkAction * action, DenemoScriptParam* param)
2090 {
2091 DenemoProject *project = Denemo.project;
2092
2093 DenemoMovement *si = project->movement;
2094 RhythmPattern *r;
2095
2096 if (!si->markstaffnum) /* Indicator that there's a selection. */
2097 {
2098 warningdialog (_("No selection to create a music snippet from\nSee Edit → Select menu for selecting music to snip"));
2099 return;
2100 }
2101
2102 r = (RhythmPattern *) g_malloc0 (sizeof (RhythmPattern));
2103
2104
2105 if (project->lilysync != project->changecount)
2106 refresh_lily_cb (NULL, Denemo.project);/* ensure lilypond syntax attached to objects in selection */
2107 create_rhythm (r, TRUE);
2108
2109 }
2110 // create a rhythm pattern for a standard duration note or rest action is the insert_chord or rest for the appropriate duration.
2111 static void
create_singleton_rhythm(gpointer insert_fn)2112 create_singleton_rhythm (gpointer insert_fn)
2113 {
2114 DenemoProject *project = Denemo.project;
2115 gboolean already_done = FALSE; // a singleton which has already been installed globally, that is a new tab is being opened.
2116 gboolean default_rhythm = FALSE;
2117 DenemoMovement *si = project->movement;
2118 RhythmPattern *r = (RhythmPattern *) g_malloc0 (sizeof (RhythmPattern));
2119 GString *pattern = g_string_new("");
2120 if (insert_fn == (gpointer) insert_chord_0key)
2121 pattern = g_string_assign (pattern, "0");
2122 if (insert_fn == (gpointer) insert_chord_1key)
2123 pattern = g_string_assign (pattern, "1");
2124 if (insert_fn == (gpointer) insert_chord_2key)
2125 pattern = g_string_assign (pattern, "2"), default_rhythm = TRUE;
2126 if (insert_fn == (gpointer) insert_chord_3key)
2127 pattern = g_string_assign (pattern, "3");
2128 if (insert_fn == (gpointer) insert_chord_4key)
2129 pattern = g_string_assign (pattern, "4");
2130 if (insert_fn == (gpointer) insert_chord_5key)
2131 pattern = g_string_assign (pattern, "5");
2132 if (insert_fn == (gpointer) insert_chord_6key)
2133 pattern = g_string_assign (pattern, "6");
2134 if (insert_fn == (gpointer) insert_chord_7key)
2135 pattern = g_string_assign (pattern, "7");
2136 if (insert_fn == (gpointer) insert_chord_8key)
2137 pattern = g_string_assign (pattern, "8");
2138
2139 if (insert_fn == (gpointer) insert_rest_0key)
2140 pattern = g_string_assign (pattern, "r");
2141 if (insert_fn == (gpointer) insert_rest_1key)
2142 pattern = g_string_assign (pattern, "s");
2143 if (insert_fn == (gpointer) insert_rest_2key)
2144 pattern = g_string_assign (pattern, "t");
2145 if (insert_fn == (gpointer) insert_rest_3key)
2146 pattern = g_string_assign (pattern, "u");
2147 if (insert_fn == (gpointer) insert_rest_4key)
2148 pattern = g_string_assign (pattern, "v");
2149 if (insert_fn == (gpointer) insert_rest_5key)
2150 pattern = g_string_assign (pattern, "w");
2151 if (insert_fn == (gpointer) insert_rest_6key)
2152 pattern = g_string_assign (pattern, "x");
2153 if (insert_fn == (gpointer) insert_rest_7key)
2154 pattern = g_string_assign (pattern, "y");
2155 if (insert_fn == (gpointer) insert_rest_8key)
2156 pattern = g_string_assign (pattern, "z");
2157 if (pattern->len<=0)
2158 {
2159 g_critical ("Bad call to create_singleton_rhythm");
2160 g_string_free (pattern, TRUE);
2161 return;
2162 }
2163 /* if we already have it globally we don't need it again
2164 note we never delete the singleton rhythms */
2165 if (Denemo.singleton_rhythms[(unsigned int) *pattern->str])
2166 {
2167 g_free (r);
2168 r = Denemo.singleton_rhythms[(unsigned int) *pattern->str];
2169 already_done = TRUE;
2170 }
2171 else
2172 {
2173 Denemo.singleton_rhythms[(unsigned int) *pattern->str] = r;
2174 already_done = FALSE;
2175 }
2176
2177 if (!already_done)
2178 {
2179 gchar *labelstr;
2180 append_rhythm (r, insert_fn);
2181 labelstr = music_font (pattern->str);
2182 g_free (labelstr);
2183
2184 /* make the list circular */
2185 r->rsteps->prev = g_list_last (r->rsteps);
2186 g_list_last (r->rsteps)->next = r->rsteps;
2187 }
2188 if (default_rhythm)
2189 {
2190 project->prevailing_rhythm = r;
2191 project->rstep = r->rsteps;
2192 project->cstep = NULL;
2193 highlight_rhythm (r);
2194 }
2195 g_string_free (pattern, TRUE);
2196 }
2197
2198
2199 static void
save_accels(void)2200 save_accels (void)
2201 {
2202 save_default_keymap_file ();
2203 Denemo.accelerator_status = FALSE;
2204 }
2205
2206
2207 static void show_type (GtkWidget * widget, gchar * message);
2208
2209
2210 static void
configure_keyboard_idx(GtkWidget * w,gint idx)2211 configure_keyboard_idx (GtkWidget * w, gint idx)
2212 {
2213 configure_keyboard_dialog_init_idx (NULL, idx);
2214 }
2215
2216 //static void toggleRecording (GtkWidget*w, gboolean *record) {
2217 //g_debug("Recording was %d\n", *record);
2218 // *record = !*record;
2219 //}
2220
2221 static void
toggle_record_script(GtkAction * action,gpointer param)2222 toggle_record_script (GtkAction * action, gpointer param)
2223 {
2224 if(!gtk_widget_get_visible (gtk_widget_get_toplevel(Denemo.script_view)))
2225 toggle_scheme();
2226 Denemo.ScriptRecording = !Denemo.ScriptRecording;
2227 }
2228
2229 static void
appendSchemeText_cb(GtkWidget * widget,gchar * text)2230 appendSchemeText_cb (GtkWidget * widget, gchar * text)
2231 {
2232 gboolean sensitive = gtk_widget_get_visible (gtk_widget_get_toplevel (Denemo.script_view));
2233 appendSchemeText (text);
2234 if(!sensitive) activate_action ("/MainMenu/ViewMenu/ToggleScript");
2235 }
2236
2237
2238
2239 static void
load_command_from_location(GtkWidget * w,gchar * filepath)2240 load_command_from_location (GtkWidget * w, gchar * filepath)
2241 {
2242 gchar *location = g_strdup_printf ("%s%c", filepath, G_DIR_SEPARATOR);
2243 g_info ("Calling the file loader with %s", location);
2244 load_keymap_dialog_location (location);
2245 g_free (location);
2246 }
2247
2248
2249 static void attach_right_click_callback (GtkWidget * widget, GtkAction * action);
2250
2251 /* the callback for menu items that are scripts. The script is attached to the action,
2252 tagged as "scheme".
2253 The script may be empty, in which case it is fetched from actions/menus...
2254
2255 This call also ensures that the right-click callback is attached to all the proxies of the action, as there are problems trying to do this earlier, and it defines a scheme variable to give the name of the script being executed.
2256 */
2257 gboolean
activate_script(GtkAction * action,DenemoScriptParam * param)2258 activate_script (GtkAction * action, DenemoScriptParam * param)
2259 {
2260 DenemoProject *project = Denemo.project;
2261 gchar *name = (gchar *) gtk_action_get_name (action);
2262 gint idx = lookup_command_from_name (Denemo.map, name);
2263 gboolean ret = FALSE;
2264 // the proxy list is NULL until the menu item is first called...
2265 //BUT if you first activate it with right button ....
2266 if (GTK_IS_ACTION (action))
2267 {
2268 if (!g_object_get_data (G_OBJECT (action), "signal_attached"))
2269 {
2270 GSList *h = gtk_action_get_proxies (action);
2271 for (; h; h = h->next)
2272 {
2273 attach_right_click_callback (h->data, action);
2274 show_type (h->data, "type is ");
2275 }
2276 }
2277
2278 //FIXME use define_scheme_variable for this
2279 //define a global variable in Scheme (CurrentScript) to give the name of the currently executing script
2280 const gchar *name = gtk_action_get_name (action);
2281 gchar *current_script = g_strdup_printf ("(define CurrentScript \"%s\")\n", name);
2282
2283 /*note that scripts must copy their name from CurrentScript into local storage before calling other scripts if they
2284 need it */
2285 gchar *paramvar = NULL;
2286 if (param && param->string)
2287 {
2288 paramvar = g_strdup_printf ("%s::params", name);
2289 scm_c_define (paramvar, scm_from_locale_string (param->string->str));
2290 }
2291
2292 scm_c_eval_string (current_script);
2293 g_free (current_script);
2294
2295 gchar *text = get_scheme_from_idx (idx);
2296 if (!is_action_name_builtin((gchar*) gtk_action_get_name(action)))
2297 {
2298 if (text)
2299 {
2300 stage_undo (project->movement, ACTION_STAGE_END); //undo is a queue so this is the end :)
2301 ret = (gboolean) ! call_out_to_guile (text);
2302 stage_undo (project->movement, ACTION_STAGE_START);
2303 }
2304 else
2305 {
2306 g_warning ("Could not get script for %s", gtk_action_get_name (action));
2307 ret = FALSE;
2308 }
2309 }
2310 if (paramvar)
2311 scm_c_define (paramvar, SCM_BOOL_F);
2312 g_free (paramvar);
2313 }
2314 else
2315 warningdialog (_("Have no way of getting the script, sorry"));
2316 return ret;
2317 }
2318
2319
2320
2321
2322 /*pop up the help for passed command as info dialog
2323 */
2324 void
popup_help_for_action(GtkAction * action)2325 popup_help_for_action (GtkAction * action)
2326 {
2327 const gchar *name = gtk_action_get_name (action);
2328 gint idx = lookup_command_from_name (Denemo.map, name);
2329 gchar *tooltip = idx >= 0 ? (gchar *) lookup_tooltip_from_idx (Denemo.map, idx) : "A menu for ...";
2330
2331 tooltip = g_strdup_printf (_("Command: %s\n\nInformation:\n%s"), name, tooltip);
2332 infodialog (tooltip);
2333 g_free (tooltip);
2334 }
2335
2336 /* replace dangerous characters in command names */
2337 static void
subst_illegals(gchar * myname)2338 subst_illegals (gchar * myname)
2339 {
2340 gchar *c; // avoid whitespace etc
2341 for (c = myname; *c; c++)
2342 if (*c == ' ' || *c == '\t' || *c == '\n' || *c == '/' || *c == '\\')
2343 *c = '-';
2344 }
2345
2346
2347
2348
2349
2350 static void
placeOnButtonBar(GtkWidget * widget,GtkAction * action)2351 placeOnButtonBar (GtkWidget * widget, GtkAction * action)
2352 {
2353 gchar *name = (gchar *) gtk_action_get_name (action);
2354 gint idx = lookup_command_from_name (Denemo.map, name);
2355 if (idx > 0)
2356 {
2357 gchar *label = (gchar *) lookup_label_from_idx (Denemo.map, idx);
2358
2359 gchar *scheme = g_strdup_printf ("\n;To remove the %s button delete from here\n(CreateButton \"Button%s\" \"%s\")\n(d-SetDirectiveTagActionScript \"Button%s\" \"(" DENEMO_SCHEME_PREFIX "%s)\")\n;;End of delete %s button", name, name, g_strescape (label, NULL), name, name, name);
2360 //g_debug("the scheme is \n%s\n", scheme);
2361 if (!call_out_to_guile (scheme))
2362 append_to_local_scheme_init (scheme);
2363 else
2364 warningdialog (_("Could not create button"));
2365 g_free (scheme);
2366 }
2367 }
2368
2369 static void
placeInPalette(GtkWidget * widget,GtkAction * action)2370 placeInPalette (GtkWidget * widget, GtkAction * action)
2371 {
2372 gchar *name = (gchar *) gtk_action_get_name (action);
2373 gint idx = lookup_command_from_name (Denemo.map, name);
2374 if (idx > 0)
2375 place_action_in_palette (idx, name);
2376 }
2377
2378 /* gets a name label and tooltip from the user, then creates a menuitem in the menu
2379 given by the path myposition whose callback is the activate on the current scheme script.
2380 */
2381
2382 static void
insertScript(GtkWidget * widget,gchar * insertion_point)2383 insertScript (GtkWidget * widget, gchar * insertion_point)
2384 {
2385 DenemoProject *project = Denemo.project;
2386 gchar *myname, *mylabel, *myscheme, *mytooltip, *submenu;
2387 gchar *myposition = g_path_get_dirname (insertion_point);
2388 gchar *after = g_path_get_basename (insertion_point);
2389 gint idx = lookup_command_from_name (Denemo.map, after);
2390 myname = string_dialog_entry (project, "Create a new menu item", "Give item name (avoid clashes): ", "MyName");
2391 //FIXME check for name clashes
2392
2393 if (myname == NULL)
2394 return;
2395 subst_illegals (myname);
2396 mylabel = string_dialog_entry (project, _("Create a new menu item"), _("Give menu label: "), _("My Label"));
2397 if (mylabel == NULL)
2398 return;
2399
2400 mytooltip = string_dialog_entry (project, _("Create a new menu item"), _("Give explanation of what it does: "), _("Prints my special effect"));
2401 if (mytooltip == NULL)
2402 return;
2403 if (confirm (_("Create a new menu item"), _("Do you want the new menu item in a submenu?")))
2404 {
2405 submenu = string_dialog_entry (project, _("Create a new menu item"), _("Give a label for the Sub-Menu"), _("Sub Menu Label"));
2406 if (submenu)
2407 {
2408 subst_illegals (submenu);
2409 myposition = g_strdup_printf ("%s/%s", myposition, submenu); //FIXME G_DIR_SEPARATOR in myposition???
2410 }
2411 }
2412
2413 myscheme = get_script_view_text ();
2414
2415 gchar *xml_filename = g_strconcat (myname, XML_EXT, NULL);
2416 gchar *scm_filename = g_strconcat (myname, SCM_EXT, NULL);
2417 g_info ("The filename built is %s from %s", xml_filename, myposition);
2418 gchar *xml_path = g_build_filename (get_user_data_dir (TRUE), COMMANDS_DIR, "menus", myposition, xml_filename, NULL);
2419 gchar *scm_path = g_build_filename (get_user_data_dir (TRUE), COMMANDS_DIR, "menus", myposition, scm_filename, NULL);
2420 g_free (xml_filename);
2421 if ((!g_file_test (xml_path, G_FILE_TEST_EXISTS)) || (g_file_test (xml_path, G_FILE_TEST_EXISTS) && confirm (_("Duplicate Name"), _("A command of this name is already available in your custom menus; Overwrite?"))))
2422 {
2423 gchar *dirpath = g_path_get_dirname (xml_path);
2424 g_mkdir_with_parents (dirpath, 0770);
2425 g_free (dirpath);
2426 //g_file_set_contents(xml_path, text, -1, NULL);
2427 save_command_metadata (xml_path, myname, mylabel, mytooltip, idx < 0 ? NULL : after);
2428 save_command_data(scm_path, myscheme);
2429 load_xml_keymap (xml_path);
2430
2431 if (confirm (_("New Command Added"), _("Do you want to save this with your default commands?")))
2432 save_accels ();
2433 }
2434 else
2435 warningdialog (_("Operation cancelled"));
2436 g_free (myposition);
2437 return;
2438 }
2439
2440
2441
2442 void
append_scheme_call(gchar * func)2443 append_scheme_call (gchar * func)
2444 {
2445 if (strcmp (func, "ExecuteScheme"))
2446 {
2447 GtkTextIter enditer;
2448 GtkTextBuffer *buffer = gtk_text_view_get_buffer ((GtkTextView *) (Denemo.script_view));
2449 //gtk_text_buffer_set_text(buffer,"",-1);
2450 gtk_text_buffer_get_end_iter (buffer, &enditer);
2451 gchar *text = g_strdup_printf ("(d-%s)\n", func); //prefix dnm_!!!!!!!
2452 gtk_text_buffer_insert (buffer, &enditer, text, -1);
2453 //g_debug("Added %s\n", text);
2454 g_free (text);
2455 if (Denemo.prefs.immediateplayback)
2456 play_note (DEFAULT_BACKEND, 0, 9, 58, 300, 127 * Denemo.project->movement->master_volume);
2457 }
2458 }
2459
2460
2461
2462
2463 /* get init.scm for the current path into the scheme text editor.
2464 */
2465 static void
get_initialization_script(GtkWidget * widget,gchar * directory)2466 get_initialization_script (GtkWidget * widget, gchar * directory)
2467 {
2468 GError *error = NULL;
2469 gchar *script;
2470 g_debug ("Loading %s/init.scm into Denemo.script_view", directory);
2471
2472 GList* dirs = NULL;
2473 dirs = g_list_append(dirs, g_build_filename (get_user_data_dir (TRUE), COMMANDS_DIR, "menus", directory, NULL));
2474 dirs = g_list_append(dirs, g_build_filename (get_user_data_dir (TRUE), "download", COMMANDS_DIR, "menus", directory, NULL));
2475 dirs = g_list_append(dirs, g_build_filename (get_system_data_dir (), COMMANDS_DIR, "menus", directory, NULL));
2476 gchar* filename = find_path_for_file (INIT_SCM, dirs);
2477
2478 if(!filename){
2479 g_warning("Could not find scm initialization file");
2480 return;
2481 }
2482
2483 if (g_file_get_contents (filename, &script, NULL, &error))
2484 appendSchemeText (script);
2485 else
2486 g_warning ("Could not get contents of %s", filename);
2487 g_free (script);
2488 g_free (filename);
2489 }
2490
2491 /* write scheme script from Denemo.script_view into file init.scm in the user's local menupath.
2492 */
2493 static void
put_initialization_script(GtkWidget * widget,gchar * directory)2494 put_initialization_script (GtkWidget * widget, gchar * directory)
2495 {
2496 gchar *filename = g_build_filename (get_user_data_dir (TRUE), COMMANDS_DIR, "menus", directory, INIT_SCM, NULL);
2497 if ((!g_file_test (filename, G_FILE_TEST_EXISTS)) || confirm (_("There is already an initialization script here"), _("Do you want to replace it?")))
2498 {
2499 gchar *scheme = get_script_view_text ();
2500 if (scheme && *scheme)
2501 {
2502 FILE *fp = fopen (filename, "w");
2503 if (fp)
2504 {
2505 fprintf (fp, "%s", scheme);
2506 fclose (fp);
2507 if (confirm (_("Wrote init.scm"), _("Shall I execute it now?")))
2508 call_out_to_guile (scheme);
2509 }
2510 else
2511 {
2512 warningdialog (_("Could not create init.scm;\n" "you must create your scripted menu item in the menu\n" "before you create the initialization script for it, sorry."));
2513 }
2514 g_free (scheme);
2515 }
2516 }
2517 }
2518
2519 /* upload scripts for command/tag name.
2520 Parameters: name the name of a command or a tag
2521 script the scheme script that the command runs, or an editscript for directives with tag name
2522 init_script the scheme script that is run before the command runs, not used for tags
2523 command the xml description of that command, or "" for tags
2524 for tags:
2525 command is "" for an editscript and name is the tag for directives that the script edits
2526 for commands:
2527 command is the command set file for merging the command as a new menu item
2528 the script is given in scheme and any initialization script for the menu is given in init_script
2529 */
2530 static void
upload_scripts(gchar * name,gchar * script,gchar * init_script,gchar * command,gchar * menupath,gchar * label,gchar * tooltip,gchar * after)2531 upload_scripts (gchar * name, gchar * script, gchar * init_script, gchar * command, gchar * menupath, gchar * label, gchar * tooltip, gchar * after)
2532 {
2533 SCM func_symbol;
2534 SCM func;
2535 func_symbol = scm_c_lookup ("d-UploadRoutine");
2536 func = scm_variable_ref (func_symbol);
2537 #define ARG(s) s?scm_from_locale_string(s):scm_from_locale_string("")
2538 SCM list = scm_list_n (ARG (command), ARG (name), ARG (script), ARG (init_script), ARG (menupath), ARG (label), ARG (tooltip), ARG (after), SCM_UNDEFINED);
2539 scm_call_1 (func, list);
2540 #undef ARG
2541 }
2542
2543
2544
2545 /* save the action (which must be a script),
2546 setting the script text to the script currently in the script_view
2547 The save is to the user's menu hierarchy on disk
2548 */
2549 static void
saveMenuItem(GtkWidget * widget,GtkAction * action)2550 saveMenuItem (GtkWidget * widget, GtkAction * action)
2551 {
2552 gchar *name = (gchar *) gtk_action_get_name (action);
2553 gint idx = lookup_command_from_name (Denemo.map, name);
2554
2555 command_row* row = NULL;
2556 keymap_get_command_row (Denemo.map, &row, idx);
2557
2558 gchar *tooltip = (gchar *) lookup_tooltip_from_idx (Denemo.map, idx);
2559 gchar *label = (gchar *) lookup_label_from_idx (Denemo.map, idx);
2560
2561 gchar *xml_filename = g_strconcat (name, XML_EXT, NULL);
2562 gchar *xml_path = g_build_filename (get_user_data_dir (TRUE), COMMANDS_DIR, "menus", row->menupath, xml_filename, NULL);
2563 g_free (xml_filename);
2564
2565 gchar *scm_filename = g_strconcat (name, SCM_EXT, NULL);
2566 gchar *scm_path = g_build_filename (get_user_data_dir (TRUE), COMMANDS_DIR, "menus", row->menupath, scm_filename, NULL);
2567 g_free (scm_filename);
2568
2569 gchar *scheme = get_script_view_text ();
2570 if (scheme && *scheme && confirm (_("Save Script"), g_strconcat (_("Over-write previous version of the script for "), name, _(" ?"), NULL)))
2571 {
2572 gchar *dirpath = g_path_get_dirname (xml_path);
2573 g_mkdir_with_parents (dirpath, 0770);
2574 g_free (dirpath);
2575 save_command_metadata (xml_filename, name, label, tooltip, row->after);
2576 save_command_data(scm_path, scheme);
2577 row->scheme = NULL;
2578 }
2579 else
2580 warningdialog (_("No script saved"));
2581 }
2582
2583
2584 /* upload the action,
2585 from the user's menu hierarchy on disk, along with initialization script and menu item xml etc
2586 */
2587 #ifdef UPLOAD_TO_DENEMO_DOT_ORG
2588 static void
uploadMenuItem(GtkWidget * widget,GtkAction * action)2589 uploadMenuItem (GtkWidget * widget, GtkAction * action)
2590 {
2591 gchar *name = (gchar *) gtk_action_get_name (action);
2592 gint idx = lookup_command_from_name (Denemo.map, name);
2593
2594 command_row* row = NULL;
2595 keymap_get_command_row (the_keymap, &row, idx);
2596 gchar *tooltip = (gchar *) lookup_tooltip_from_idx (Denemo.map, idx);
2597 gchar *label = (gchar *) lookup_label_from_idx (Denemo.map, idx);
2598
2599 gchar *filename = g_build_filename (get_user_data_dir (TRUE), COMMANDS_DIR, "menus", row->menupath, name,
2600 NULL);
2601 gchar *script = get_scheme_from_idx (idx);
2602 gchar *xml;
2603 GError *error = NULL;
2604 g_file_get_contents (filename, &xml, NULL, &error);
2605 filename = g_build_filename (get_user_data_dir (TRUE), COMMANDS_DIR, "menus", row->menupath, INIT_SCM, NULL);
2606 gchar *init_script;
2607 g_file_get_contents (filename, &init_script, NULL, &error);
2608
2609 if (xml == NULL)
2610 xml = "";
2611 if (init_script == NULL)
2612 init_script = "";
2613 if (script == NULL)
2614 script = "";
2615
2616
2617 upload_scripts (name, script, init_script, xml, row->menupath, label, tooltip, row->after);
2618
2619 }
2620 #endif
2621
2622 /* upload editscript for tag */
2623 void
upload_edit_script(gchar * tag,gchar * script)2624 upload_edit_script (gchar * tag, gchar * script)
2625 {
2626 upload_scripts (tag, script, "", "", "", "", "", "");
2627 }
2628
2629
2630 static const gchar *
locatebitmapsdir(void)2631 locatebitmapsdir (void)
2632 {
2633 static gchar *bitmapsdir = NULL;
2634 gboolean err;
2635 if (!bitmapsdir)
2636 {
2637 bitmapsdir = g_build_filename (get_user_data_dir (TRUE), COMMANDS_DIR, "bitmaps", NULL);
2638 }
2639 err = g_mkdir_with_parents (bitmapsdir, 0770);
2640 if (err)
2641 {
2642 warningdialog (_("Could not create .denemo/actions/bitmaps for your graphics for customized commands"));
2643 g_free (bitmapsdir);
2644 bitmapsdir = g_strdup (""); //FIXME
2645 }
2646 return bitmapsdir;
2647 }
2648 static const gchar *
locategraphicsdir(void)2649 locategraphicsdir (void)
2650 {
2651 static gchar *bitmapsdir = NULL;
2652 gboolean err;
2653 if (!bitmapsdir)
2654 {
2655 bitmapsdir = g_build_filename (get_user_data_dir (TRUE), COMMANDS_DIR, "graphics", NULL);
2656 }
2657 err = g_mkdir_with_parents (bitmapsdir, 0770);
2658 if (err)
2659 {
2660 warningdialog (_("Could not create .denemo-xxx/actions/graphics for your graphics for customized commands"));
2661 g_free (bitmapsdir);
2662 bitmapsdir = g_strdup (""); //FIXME
2663 }
2664 return bitmapsdir;
2665 }
2666 static const gchar *
locatedownloadbitmapsdir(void)2667 locatedownloadbitmapsdir (void)
2668 {
2669 static gchar *bitmapsdir = NULL;
2670 if (!bitmapsdir)
2671 {
2672 bitmapsdir = g_build_filename (get_user_data_dir (TRUE), "download", COMMANDS_DIR, "bitmaps", NULL);
2673 }
2674 return bitmapsdir;
2675 }
2676
2677 /* if a graphic file for name exists (local or downloaded or systemwide) create an icon for it called label
2678 and return label, else return NULL
2679 */
2680 gchar *
get_icon_for_name(gchar * name,gchar * label)2681 get_icon_for_name (gchar * name, gchar * label)
2682 {
2683 return NULL; //this function is disabled until we figure out why the icons are no longer being shown.
2684 #ifdef PROBLEM_SHOWING_ICONS_FIXED
2685 gchar *pngname = g_strconcat (name, ".png", NULL);
2686 gchar *filename = g_build_filename (locatebitmapsdir (), pngname,
2687 NULL);
2688 if (!g_file_test (filename, G_FILE_TEST_EXISTS))
2689 {
2690 g_free (filename);
2691 filename = g_build_filename (locatedownloadbitmapsdir (), pngname, NULL);
2692 if (!g_file_test (filename, G_FILE_TEST_EXISTS))
2693 {
2694 g_free (filename);
2695 filename = g_build_filename (get_system_data_dir (), COMMANDS_DIR, "bitmaps", pngname, NULL);
2696 if (!g_file_test (filename, G_FILE_TEST_EXISTS))
2697 {
2698
2699 g_free (filename);
2700 filename = g_build_filename (get_system_data_dir (), COMMANDS_DIR, "graphics", pngname, NULL);
2701 if (!g_file_test (filename, G_FILE_TEST_EXISTS))
2702 {
2703 g_free (filename);
2704 g_free (pngname);
2705 return NULL;
2706 }
2707 }
2708 }
2709 }
2710 GError *error = NULL;
2711 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (filename, &error);
2712 g_free (filename);
2713 g_free (pngname);
2714 if (error)
2715 {
2716 warningdialog (error->message);
2717 return NULL;
2718 }
2719 static GtkIconFactory *icon_factory;
2720 if (!icon_factory)
2721 {
2722 icon_factory = gtk_icon_factory_new ();
2723 gtk_icon_factory_add_default (icon_factory);
2724 }
2725 GtkIconSet *icon_set = gtk_icon_set_new_from_pixbuf (pixbuf);
2726 g_object_unref (pixbuf);
2727 gtk_icon_factory_add (icon_factory, label, icon_set);
2728 return label;
2729 #endif
2730 }
2731
2732
2733
2734 gchar *
create_xbm_data_from_pixbuf(GdkPixbuf * pixbuf,int lox,int loy,int hix,int hiy)2735 create_xbm_data_from_pixbuf (GdkPixbuf * pixbuf, int lox, int loy, int hix, int hiy)
2736 {
2737 int width, height, rowstride, n_channels;
2738 guchar *pixels;
2739
2740 n_channels = gdk_pixbuf_get_n_channels (pixbuf);
2741
2742 #ifdef DEBUG
2743 //g_assert (gdk_pixbuf_get_colorspace (pixbuf) == GDK_COLORSPACE_RGB);
2744 //g_assert (gdk_pixbuf_get_bits_per_sample (pixbuf) == 8);
2745 //g_assert (gdk_pixbuf_get_has_alpha (pixbuf));
2746 //g_assert (n_channels == 4);
2747 #endif
2748 width = hix - lox;
2749 height = hiy - loy;
2750 rowstride = gdk_pixbuf_get_rowstride (pixbuf);
2751 pixels = gdk_pixbuf_get_pixels (pixbuf);
2752 int x, y, i;
2753
2754 char *chars = g_malloc0 (sizeof (char) * width * height); //about 8 times too big!
2755 char *this = chars;
2756 for (i = 0, y = loy; y < hiy; y++)
2757 {
2758 for (x = lox; x < hix; x++, i++)
2759 {
2760 this = chars + (i / 8);
2761 gint set = ((pixels + y * rowstride + x * n_channels)[3] > 0);
2762 #ifdef G_OS_WIN32
2763 set = (set ? 0 : 1); //bizarrely the bitmaps come out inverted on windows
2764 #endif
2765
2766 *this += set << i % 8;
2767 }
2768 i = ((i + 7) / 8) * 8;
2769 }
2770 return chars;
2771 }
2772
2773 static GHashTable *bitmaps;
2774 static void
bitmap_table_insert(gchar * name,DenemoGraphic * xbm)2775 bitmap_table_insert (gchar * name, DenemoGraphic * xbm)
2776 {
2777 if (!bitmaps)
2778 bitmaps = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); //FIXME is this right for GdkBitmap data?
2779 g_hash_table_insert (bitmaps, g_strdup (name), xbm); //FIXME
2780 }
2781
2782 static DenemoGraphic *
create_bitmap_from_data(gchar * data,gint width,gint height)2783 create_bitmap_from_data (gchar * data, gint width, gint height)
2784 {
2785 #if 0
2786 /* static GdkColor white, black;gboolean init = FALSE; */
2787 /* if(!init) { */
2788 /* gdk_color_parse ("white", &white); */
2789 /* gdk_colormap_alloc_color (gdk_colormap_get_system (), &white, TRUE, TRUE); */
2790 /* gdk_color_parse ("black", &black); */
2791 /* gdk_colormap_alloc_color (gdk_colormap_get_system (), &black, TRUE, TRUE); */
2792 /* } */
2793 // return gdk_pixmap_create_from_data(NULL,data, width, height, 1, &white, &black);
2794 //return gdk_bitmap_create_from_data(NULL,data, width, height);
2795 cairo_surface_t *surface = cairo_image_surface_create_for_data (data, CAIRO_FORMAT_A1, width, height,
2796 cairo_format_stride_for_width (CAIRO_FORMAT_A1, width));
2797 cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
2798 cairo_pattern_reference (pattern);
2799 return pattern;
2800 #else
2801 return NULL;
2802 #endif
2803 }
2804
2805 static gboolean
loadGraphicFromFormat(gchar * basename,gchar * name,DenemoGraphic ** xbm)2806 loadGraphicFromFormat (gchar * basename, gchar * name, DenemoGraphic ** xbm)
2807 {
2808 RsvgDimensionData thesize;
2809 gchar *filename = g_strconcat (name, ".png", NULL);
2810 thesize.width = 40;
2811 thesize.height = 40;
2812 cairo_surface_t *surface = cairo_image_surface_create_from_png (filename);
2813 if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS)
2814 {
2815 g_free (filename);
2816 filename = g_strconcat (name, ".svg", NULL);
2817 if (g_file_test (filename, G_FILE_TEST_EXISTS))
2818 {
2819 #ifdef CAIRO_HAS_SVG_SURFACE
2820 GError *error = NULL;
2821 RsvgHandle *handle = rsvg_handle_new_from_file (filename, &error);
2822 if (handle == NULL)
2823 {
2824 if (error)
2825 g_warning ("Could not open %s error %s", basename, error->message);
2826 else
2827 g_warning ("Opening %s, Bug in librsvg:rsvg handle null but no error message", basename);
2828 return FALSE;
2829 }
2830
2831 rsvg_handle_get_dimensions (handle, &thesize);
2832 surface = cairo_svg_surface_create_for_stream (NULL, NULL, (double) (thesize.width), (double) (thesize.height));
2833 cairo_t *cr = cairo_create (surface);
2834 rsvg_handle_render_cairo (handle, cr);
2835 rsvg_handle_close (handle, NULL);
2836 g_object_unref (handle);
2837 cairo_destroy (cr);
2838 #else
2839 g_warning ("Cairo svg backend not available");
2840 return FALSE;
2841 #endif
2842 }
2843 }
2844 else
2845 {
2846 FILE *fp = fopen (filename, "rb");
2847 if (fp)
2848 {
2849 fseek (fp, 16, SEEK_SET);
2850 fread (&thesize.width, 4, 1, fp);
2851 fread (&thesize.height, 4, 1, fp);
2852 thesize.width = GINT_FROM_BE (thesize.width);
2853 thesize.height = GINT_FROM_BE (thesize.height);
2854 fclose (fp);
2855 }
2856 }
2857 g_free (filename);
2858 if (cairo_surface_status (surface) == CAIRO_STATUS_SUCCESS)
2859 {
2860 cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
2861 cairo_pattern_reference (pattern);
2862
2863 DenemoGraphic *graphic = g_malloc (sizeof (DenemoGraphic));
2864 graphic->type = DENEMO_PATTERN;
2865 graphic->width = thesize.width;
2866 graphic->height = thesize.height;
2867 //g_debug("size %d x %d", thesize.width, thesize.height);
2868
2869 graphic->graphic = pattern;
2870 bitmap_table_insert (basename, graphic);
2871 *xbm = graphic;
2872 return TRUE;
2873 }
2874 else
2875 return FALSE;
2876 }
2877
2878
2879 gboolean
loadGraphicItem(gchar * name,DenemoGraphic ** xbm)2880 loadGraphicItem (gchar * name, DenemoGraphic ** xbm)
2881 {
2882
2883 if (!name || !*name)
2884 return FALSE;
2885 #define NEWLINE "\n"
2886 if (*name == *NEWLINE)
2887 {
2888 //if name starts '\n' treat it as lines holding char font size weight (e.g. bold) slant (e.g. italic)
2889 //so let user specify a hex value and convert to utf8 here len = g_unichar_to_utf8( uc, utf_string );
2890 //e.g "\n0x20" would be glyph 0x20 from the feta26 font, size 35 not bold or italic (as in drawfetachar_cr())
2891 //while "\n0x40 0x40\nSans\n16\n1\n1" would be a "AA" string in sans font at 16pt bold and italic
2892 gchar **spec = g_strsplit (name + 1, NEWLINE, 5);
2893 gint i;
2894 DenemoGraphic *graphic = g_malloc (sizeof (DenemoGraphic));
2895 DenemoGlyph *glyph = (DenemoGlyph *) g_malloc (sizeof (DenemoGlyph));
2896 graphic->type = DENEMO_FONT;
2897 graphic->graphic = glyph;
2898 glyph->fontname = "feta26";
2899 glyph->size = 35.0;
2900 for (i = 0; i < 5 && spec[i]; i++)
2901 {
2902 switch (i)
2903 {
2904 case 0:
2905 {
2906 // get a set of hex values (unicodes?) and create a utf8 string
2907 //should involve strtol(spec[0], &next, 0);
2908 //and perhaps g_unichar_to_utf8(*spec[0], NULL);
2909 // and glyph->utf = g_malloc(len);
2910 //if not hex digits, then treat as utf8 string
2911 glyph->utf = g_strdup (spec[0]);
2912 break;
2913 }
2914 case 1:
2915 glyph->fontname = g_strdup (spec[1]);
2916 break;
2917 case 2:
2918 glyph->size = g_ascii_strtod (spec[2], NULL);
2919 break;
2920 case 3:
2921 glyph->weight = atoi (spec[3]);
2922 break;
2923 case 4:
2924 glyph->slant = atoi (spec[4]);
2925 break;
2926 }
2927 }
2928 g_strfreev (spec);
2929 *xbm = graphic;
2930 return TRUE;
2931 }
2932 if (bitmaps && (*xbm = (DenemoGraphic *) g_hash_table_lookup (bitmaps, name)))
2933 {
2934 return TRUE;
2935 }
2936
2937 GList* files = NULL;
2938 files = g_list_append(files, g_strconcat (name, ".png", NULL));
2939 files = g_list_append(files, g_strconcat (name, ".svg", NULL));
2940
2941 GList* dirs = NULL;
2942 dirs = g_list_append(dirs, g_build_filename (locategraphicsdir (), NULL));
2943 dirs = g_list_append(dirs, g_build_filename (locatebitmapsdir (), NULL));
2944 dirs = g_list_append(dirs, g_build_filename (locatedownloadbitmapsdir (), NULL));
2945 dirs = g_list_append(dirs, g_build_filename (PACKAGE_SOURCE_DIR, COMMANDS_DIR, "bitmaps", NULL));
2946 dirs = g_list_append(dirs, g_build_filename (get_system_data_dir (), COMMANDS_DIR, "bitmaps", NULL));
2947 dirs = g_list_append(dirs, g_build_filename (get_system_data_dir (), COMMANDS_DIR, "graphics", NULL));
2948
2949 gboolean success = TRUE;
2950 gchar *dir = find_dir_for_files (files, dirs);
2951 if(!dir){
2952 g_warning ("Could not find graphic item %s", name);
2953 success = FALSE;
2954 }
2955
2956 else{
2957 gchar* basename = g_build_filename(dir, name, NULL);
2958 success = loadGraphicFromFormat (name, basename, xbm);
2959 g_free(basename);
2960
2961 if(!success)
2962 g_warning ("Could not load graphic item %s from %s", name, dir);
2963 }
2964
2965 g_free(dir);
2966
2967 return success;
2968 }
2969
2970 /* save the current graphic
2971 */
2972 static void
saveGraphicItem(GtkWidget * widget,GtkAction * action)2973 saveGraphicItem (GtkWidget * widget, GtkAction * action)
2974 {
2975 gchar *name = (gchar *) gtk_action_get_name (action);
2976 gchar *pngname = g_strconcat (name, ".png", NULL);
2977 gchar *filename = g_build_filename (locatebitmapsdir (), pngname,
2978 NULL);
2979 //FIXME allow fileselector here to change the name
2980 gchar *msg = g_strdup_printf (_("Saving a graphic for use in the %s script"), name);
2981 if (!g_file_test (filename, G_FILE_TEST_EXISTS) || confirm (msg, _("Replace current graphic?")))
2982 {
2983 guint width = Denemo.project->xbm_width;
2984 guint height = Denemo.project->xbm_height;
2985 create_bitmap_from_data (Denemo.project->xbm, width, height);
2986 }
2987
2988 g_free (pngname);
2989 g_free (msg);
2990 g_free (filename);
2991 }
2992
2993 /* return a directory path for a system menu ending in menupath, or NULL if none exists
2994 checking user's download then the installed menus
2995 user must free the returned string*/
2996 static gchar *
get_system_menupath(gchar * menupath)2997 get_system_menupath (gchar * menupath)
2998 {
2999 gchar *filepath = g_build_filename (get_user_data_dir (TRUE), "download", COMMANDS_DIR, "menus", menupath, NULL);
3000 //g_debug("No file %s\n", filepath);
3001 if (0 != g_access (filepath, 4))
3002 {
3003 g_free (filepath);
3004 filepath = g_build_filename (get_system_data_dir (), COMMANDS_DIR, "menus", menupath, NULL);
3005 }
3006 return filepath;
3007 }
3008
3009
3010 /*
3011 menu_click:
3012 intercepter for the callback when clicking on menu items for the set of Actions the Denemo offers.
3013 Left click runs default action, after recording the item in a scheme script if recording.
3014 Right click offers pop-up menu for setting shortcuts etc
3015
3016 */
3017 static gboolean
menu_click(GtkWidget * widget,GdkEventButton * event,GtkAction * action)3018 menu_click (GtkWidget * widget, GdkEventButton * event, GtkAction * action)
3019 {
3020 keymap *the_keymap = Denemo.map;
3021 const gchar *func_name = gtk_action_get_name (action);
3022 //g_debug("widget name %s action name %s accel path %s\n", gtk_widget_get_name(widget), func_name, gtk_action_get_accel_path (action));
3023
3024 // GSList *h = gtk_action_get_proxies (action);
3025 //g_debug("In menu click action is %p h is %p\n",action, h);
3026
3027
3028
3029 gint idx = lookup_command_from_name (the_keymap, func_name);
3030 command_row* row = NULL;
3031 keymap_get_command_row (the_keymap, &row, idx);
3032 //g_debug("event button %d, idx %d for %s recording = %d scm = %d\n", event->button, idx, func_name, Denemo.ScriptRecording,g_object_get_data(G_OBJECT(action), "scm") );
3033 if (event->button != 3) //Not right click
3034 if (Denemo.ScriptRecording)
3035 if (idx_has_callback (the_keymap, idx))
3036 {
3037 append_scheme_call ((gchar *) func_name);
3038 }
3039
3040 if (event->button != 3)
3041 return FALSE;
3042
3043 gboolean sensitive = gtk_widget_get_visible (gtk_widget_get_toplevel (Denemo.script_view));//some buttons should be insensitive if the Scheme window is not visible
3044 GtkWidget *menu = gtk_menu_new ();
3045 gchar *labeltext = g_strdup_printf ("Help for %s", func_name);
3046 GtkWidget *item = gtk_menu_item_new_with_label (labeltext);
3047
3048 g_free (labeltext);
3049 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3050 g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (popup_help_for_action), (gpointer) action);
3051
3052 /* Place button in palette */
3053 if (idx != -1)
3054 {
3055 item = gtk_menu_item_new_with_label (_("Place Command in a Palette"));
3056 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3057 g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (placeInPalette), action);
3058 }
3059
3060 /* "drag" menu item onto button bar */
3061
3062 //item = gtk_menu_item_new_with_label (_("Place Command on the Title Bar"));
3063 //gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3064 //g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (placeOnButtonBar), action);
3065
3066
3067 if (idx != -1)
3068 {
3069 //item = gtk_menu_item_new_with_label (_("Create Mouse Shortcut"));
3070 //gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3071 //g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (createMouseShortcut), action);
3072 item = gtk_menu_item_new_with_label (_("Open Command Center\non this command"));
3073 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3074 g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (configure_keyboard_idx), GINT_TO_POINTER (idx));
3075 item = gtk_menu_item_new_with_label (_("Save Command Set"));
3076 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3077 g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (save_default_keymap_file), action);
3078
3079
3080 item = gtk_separator_menu_item_new ();
3081 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3082 } //idx!=-1
3083
3084 // applies if it is a built-in command: FIXME not set for the popup menus though
3085 gchar *myposition = g_object_get_data (G_OBJECT (widget), "menupath");
3086 //g_debug("position from built in is %s\n", myposition);
3087 if (row && !myposition)
3088 //menu item runs a script
3089 myposition = row->menupath;
3090
3091 //g_debug("position is %s\n", myposition);
3092 if (myposition == NULL)
3093 {
3094 // g_warning("Cannot find the position of this menu item %s in the menu system", func_name);
3095 return TRUE;
3096 }
3097 static gchar *filepath; // static so that we can free it next time we are here.
3098 if (filepath)
3099 g_free (filepath);
3100 filepath = get_system_menupath (myposition);
3101 if (0 == g_access (filepath, 4))
3102 {
3103 //g_debug("We can look for a menu item in the path %s\n", filepath);
3104 item = gtk_menu_item_new_with_label ("More Commands");
3105 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3106 g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (load_command_from_location), (gpointer) filepath);
3107 }
3108
3109 if (!is_action_name_builtin((gchar*)func_name))
3110 {
3111 gchar *scheme = get_scheme_from_idx (idx);
3112 if (!scheme)
3113 g_warning ("Could not get script for %s", gtk_action_get_name (action));
3114 else
3115 {
3116 item = gtk_menu_item_new_with_label (_("Get Script into Scheme Window"));
3117 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3118 g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (appendSchemeText_cb), scheme);
3119 }
3120 {
3121
3122 item = gtk_menu_item_new_with_label (_("Save Script from Scheme Window"));
3123 gtk_widget_set_sensitive (item, sensitive);
3124 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3125 g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (saveMenuItem), action);
3126 }
3127 if (Denemo.project->xbm)
3128 {
3129 //item = gtk_menu_item_new_with_label (_("Save Graphic"));
3130 // GtkSettings* settings = gtk_settings_get_default();
3131 // gtk_settings_set_long_property (settings,"gtk-menu-images",(glong)TRUE, "XProperty");
3132 //item = gtk_image_menu_item_new_from_stock("Save Graphic", gtk_accel_group_new());
3133 item = gtk_image_menu_item_new_from_stock (_("Save Graphic") /*_("_OK") */ , NULL);
3134
3135 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3136 g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (saveGraphicItem), action);
3137 }
3138 #ifdef UPLOAD_TO_DENEMO_DOT_ORG
3139 item = gtk_menu_item_new_with_label (_("Upload this Script to denemo.org"));
3140 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3141 g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (uploadMenuItem), action);
3142 #endif
3143 }
3144
3145 item = gtk_menu_item_new_with_label (_("Save Script as New Menu Item"));
3146 gtk_widget_set_sensitive (item, sensitive);
3147 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3148 static gchar *insertion_point;
3149 if (insertion_point)
3150 g_free (insertion_point);
3151 insertion_point = g_build_filename (myposition, func_name, NULL);
3152 //g_debug("using %p %s for %d %s %s\n", insertion_point, insertion_point, idx, myposition, func_name);
3153 g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (insertScript), insertion_point);
3154
3155 /* options for getting/putting init.scm */
3156 item = gtk_menu_item_new_with_label (_("Get Initialization Script for this Menu"));
3157 gtk_widget_set_sensitive (item, sensitive);
3158
3159 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3160 g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (get_initialization_script), myposition);
3161
3162 item = gtk_menu_item_new_with_label (_("Put Script as Initialization Script for this Menu"));
3163 gtk_widget_set_sensitive (item, sensitive);
3164
3165 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3166 g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (put_initialization_script), myposition);
3167
3168 gtk_widget_show_all (menu);
3169 gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time ());
3170 return TRUE;
3171 }
3172
3173
3174
3175 static void
color_rhythm_button(RhythmPattern * r,const gchar * color)3176 color_rhythm_button (RhythmPattern * r, const gchar * color)
3177 {
3178 if ((r == NULL) || (r->button == NULL))
3179 return;
3180 GdkColor thecolor;
3181 gdk_color_parse (color, &thecolor);
3182 gtk_widget_modify_fg (gtk_tool_button_get_label_widget (GTK_TOOL_BUTTON (r->button)), GTK_STATE_NORMAL, &thecolor);
3183 //bg does not work, and setting the label in a GtkEvent box gave a problem on some build - R.Rankin patched for this and so we have to use fg
3184 }
3185
3186 void
highlight_rhythm(RhythmPattern * r)3187 highlight_rhythm (RhythmPattern * r)
3188 {
3189 //g_debug("highlight\n");
3190 color_rhythm_button (r, "black");
3191 }
3192
3193 void
unhighlight_rhythm(RhythmPattern * r)3194 unhighlight_rhythm (RhythmPattern * r)
3195 {
3196 //g_debug("Unhighlight\n");
3197 color_rhythm_button (r, "gray");
3198 }
3199
3200
3201 /*
3202
3203
3204
3205 */
3206 void
highlight_rest(DenemoProject * project,gint dur)3207 highlight_rest (DenemoProject * project, gint dur)
3208 {
3209 if (project->currhythm)
3210 {
3211 unhighlight_rhythm ((RhythmPattern *) project->currhythm->data);
3212 }
3213 gint nb_sr = 'r' + dur;
3214 if(nb_sr < 0 || nb_sr > NB_SINGLETON_RHYTHMS){
3215 g_critical("Singleton rhythm index out of range");
3216 return;
3217 }
3218 if(!Denemo.singleton_rhythms[nb_sr]){
3219 g_debug("Unvalid singleton rhythm %i", nb_sr);
3220 return;
3221 }
3222 project->currhythm = NULL;
3223 project->cstep = NULL;
3224 project->rstep = Denemo.singleton_rhythms[nb_sr]->rsteps;
3225 unhighlight_rhythm (project->prevailing_rhythm);
3226 project->prevailing_rhythm = Denemo.singleton_rhythms[nb_sr];
3227 highlight_rhythm (project->prevailing_rhythm);
3228
3229 }
3230
3231 void
highlight_duration(DenemoProject * project,gint dur)3232 highlight_duration (DenemoProject * project, gint dur)
3233 {
3234 if (project->currhythm)
3235 {
3236 unhighlight_rhythm ((RhythmPattern *) project->currhythm->data);
3237 }
3238 gint nb_sr = '0' + dur;
3239 if(nb_sr < 0 || nb_sr > NB_SINGLETON_RHYTHMS){
3240 g_critical("Singleton rhythm index out of range");
3241 return;
3242 }
3243 if(!Denemo.singleton_rhythms[nb_sr]){
3244 g_debug("Unvalid singleton rhythm %i", nb_sr);
3245 return;
3246 }
3247 project->currhythm = NULL;
3248 project->cstep = NULL;
3249 project->rstep = Denemo.singleton_rhythms[nb_sr]->rsteps;
3250 unhighlight_rhythm (project->prevailing_rhythm);
3251 project->prevailing_rhythm = Denemo.singleton_rhythms[nb_sr];
3252 highlight_rhythm (project->prevailing_rhythm);
3253 write_status (project);
3254 }
3255
3256
3257
delete_rhythm_pattern(RhythmPattern * r)3258 void delete_rhythm_pattern (RhythmPattern *r)
3259 {
3260 DenemoProject *project = Denemo.project;
3261 free_clipboard (r->clipboard);
3262 r->clipboard = NULL;
3263 if (r->name)
3264 {
3265 gchar *command = g_strdup_printf ("(define Snippet::%s 0)", r->name);
3266 call_out_to_guile (command);
3267 g_free (command);
3268 }
3269
3270 gtk_widget_destroy (GTK_WIDGET (r->button));
3271 /* list is circular, so before we free it we have to break it */
3272 r->rsteps->prev->next = NULL;
3273 r->rsteps->prev = NULL;
3274 GList *g;
3275 for (g = r->rsteps; g; g = g->next)
3276 g_free (g->data);
3277 g_list_free (r->rsteps);
3278 g_free (r);
3279 //g_debug("length %d\n", g_list_length(project->rhythms));
3280 project->rhythms = g_list_remove (project->rhythms, r);//project->currhythm->data);
3281 //g_debug("length %d %p\n", g_list_length(project->rhythms), project->rhythms);
3282 project->currhythm = g_list_last (project->rhythms);
3283
3284 if (project->currhythm == NULL)
3285 {
3286 create_singleton_rhythm ((gpointer) insert_chord_2key);//to re-set the default rhythm which is 1/4 note
3287 }
3288 else
3289 {
3290 highlight_rhythm (project->currhythm->data);
3291 project->rstep = ((RhythmPattern *) project->currhythm->data)->rsteps;
3292 project->cstep = ((RhythmPattern *) project->currhythm->data)->clipboard->data;
3293 }
3294 update_scheme_snippet_ids ();
3295 }
3296
3297
3298
3299
3300 /*
3301 * delete a rhythmic pattern and its button
3302 *
3303 */
3304 void
delete_rhythm_cb(GtkAction * action,DenemoScriptParam * param)3305 delete_rhythm_cb (GtkAction * action, DenemoScriptParam* param)
3306
3307 {
3308 DenemoProject *project = Denemo.project;
3309 if ((project->mode & (INPUTEDIT)) == 0)
3310 return;
3311 if (project->currhythm == NULL)
3312 return;
3313 RhythmPattern *r = (RhythmPattern *) project->currhythm->data;
3314 delete_rhythm_pattern (r);
3315 }
3316
3317
3318 /*
3319 * workaround for glib<2.10
3320 */
3321 /* UNUSED
3322 static void
3323 attach_action_to_widget (GtkWidget * widget, GtkAction * action, DenemoProject * project)
3324 {
3325 g_object_set_data (G_OBJECT (widget), "action", action);
3326 }
3327 */
3328 /* attaches a button-press-event signal to the widget with the action as data
3329 for use in the callback */
3330 static void
attach_right_click_callback(GtkWidget * widget,GtkAction * action)3331 attach_right_click_callback (GtkWidget * widget, GtkAction * action)
3332 {
3333
3334
3335
3336 gtk_widget_add_events (widget, (GDK_BUTTON_PRESS_MASK)); //will not work because label are NO_WINDOW
3337 g_signal_connect (G_OBJECT (widget), "button-release-event", G_CALLBACK (menu_click), action);
3338
3339 //g_debug("menu click set on %s GTK_WIDGET_FLAGS %x\n", gtk_action_get_name(action), GTK_WIDGET_FLAGS(widget));
3340 //show_type(widget, "Type is ");
3341
3342 g_object_set_data (G_OBJECT (action), "signal_attached", action); //Non NULL to indicate the signal is attached
3343 }
3344
3345
3346 /* UNUSED
3347 static void
3348 dummy (void)
3349 {
3350 call_out_to_guile ("(d-Insert2)");
3351 call_out_to_guile ("(d-Insert2)");
3352 call_out_to_guile ("(d-Insert2)");
3353 call_out_to_guile ("(d-Insert2)");
3354 call_out_to_guile ("(d-Insert2)");
3355 return;
3356 }
3357 */
3358 /**
3359 * Menu entries with no shortcut keys, tooltips, and callback functions
3360 */
3361 GtkActionEntry menu_entries[] = {
3362 #include "generated/entries.h"
3363 {"Browse", NULL, N_("Browse"), NULL, N_("Opens a dialog for a new file"), G_CALLBACK (file_open_with_check)}
3364
3365 };
3366
3367
3368
3369
3370 GtkAction *
activate_action(gchar * path)3371 activate_action (gchar * path)
3372 {
3373 GtkAction *a;
3374 a = gtk_ui_manager_get_action (Denemo.ui_manager, path);
3375 if (a)
3376 gtk_action_activate (a);
3377 else
3378 g_warning ("No command at %s - should this be in denemoui.xml?", path);
3379 return a;
3380 }
3381
3382 /**
3383 * callback changing the input source (keyboard only/audio/midi)
3384 *
3385 */
3386
3387 static void
change_input_type(GtkRadioAction * action,GtkRadioAction * current)3388 change_input_type (GtkRadioAction * action, GtkRadioAction * current)
3389 {
3390 DenemoProject *project = Denemo.project;
3391
3392 gint val = gtk_radio_action_get_current_value (current);
3393 gboolean fail = FALSE;
3394 if (project->notsaved)
3395 {
3396 warningdialog (_("You have unsaved work. Hardware problems may cause the program to exit during this task.\nPlease save first."));
3397 gtk_radio_action_set_current_value (current, project->input_source);
3398 return;
3399 }
3400 switch (val)
3401 {
3402 case INPUTKEYBOARD:
3403 if (project->input_source == INPUTAUDIO)
3404 {
3405 //g_debug("Stopping audio\n");
3406 stop_pitch_input ();
3407 }
3408 if (project->input_source == INPUTMIDI)
3409 {
3410 //g_debug("Stopping midi\n");
3411 stop_pitch_input ();
3412 }
3413 project->input_source = INPUTKEYBOARD;
3414 Denemo.project->last_source = INPUTKEYBOARD;
3415 g_debug ("Input keyboard %d", Denemo.project->last_source);
3416 break;
3417 case INPUTAUDIO:
3418 //g_debug("Starting audio\n");
3419 if (project->input_source == INPUTMIDI)
3420 {
3421 //g_debug("Stopping midi\n");
3422 stop_pitch_input ();
3423 }
3424 project->input_source = INPUTAUDIO;
3425 if (setup_pitch_input ())
3426 {
3427 fail = TRUE;
3428 warningdialog (_("Could not start Audio input"));
3429 gtk_radio_action_set_current_value (current, INPUTKEYBOARD);
3430 }
3431 else
3432 start_pitch_input ();
3433 break;
3434 case INPUTMIDI:
3435 midi_stop ();
3436 audio_shutdown ();
3437 (void)audio_initialize (&Denemo.prefs);
3438 if(have_midi())
3439 project->input_source = INPUTMIDI;
3440 else
3441 fail = TRUE;
3442 break;
3443 default:
3444 g_warning ("Bad Value");
3445 break;
3446 }
3447 if (fail)
3448 {
3449 project->input_source = INPUTKEYBOARD;
3450 gtk_radio_action_set_current_value (current, INPUTKEYBOARD);
3451 }
3452 else
3453 write_input_status ();
3454 }
3455
3456 /* callback: if not Insert mode set Insert mode else set Edit mode */
3457 void
toggle_edit_mode(GtkAction * action,DenemoScriptParam * param)3458 toggle_edit_mode (GtkAction * action, DenemoScriptParam* param)
3459 {
3460 DenemoProject *project = Denemo.project;
3461 static gint mode = INPUTINSERT;
3462 if (project->mode & INPUTEDIT)
3463 {
3464 switch (mode & ~MODE_MASK)
3465 {
3466 case INPUTINSERT:
3467 activate_action ("/MainMenu/ModeMenu/InsertMode");
3468 break;
3469 case INPUTCLASSIC:
3470 activate_action ("/MainMenu/ModeMenu/ClassicMode");
3471 break;
3472 case 0:
3473 activate_action ("/MainMenu/ModeMenu/Modeless");
3474 break;
3475 default:
3476 ;
3477 }
3478 }
3479 else
3480 {
3481 mode = project->mode; // remember mode for switching back
3482 activate_action ("/MainMenu/ModeMenu/EditMode");
3483 }
3484 }
3485
3486 /* callback: if rest entry make note entry and vv */
3487 void
toggle_rest_mode(GtkAction * action,DenemoScriptParam * param)3488 toggle_rest_mode (GtkAction * action, DenemoScriptParam* param)
3489 {
3490 DenemoProject *project = Denemo.project;
3491 static gint mode = INPUTNORMAL;
3492 if (project->mode & INPUTREST)
3493 {
3494 switch (mode & ~ENTRY_TYPE_MASK)
3495 {
3496 case INPUTNORMAL:
3497 activate_action ("/MainMenu/ModeMenu/Note");
3498 break;
3499 case INPUTBLANK:
3500 activate_action ("/MainMenu/ModeMenu/Blank");
3501 break;
3502 default:
3503 ;
3504 }
3505 }
3506 else
3507 {
3508 mode = project->mode; // remember mode for switching back
3509 activate_action ("/MainMenu/ModeMenu/Rest");
3510 }
3511 }
3512
3513
3514 /* callback: if rhythm entry make note entry and vv */
3515 void
toggle_rhythm_mode(GtkAction * action,DenemoScriptParam * param)3516 toggle_rhythm_mode (GtkAction * action, DenemoScriptParam* param)
3517 {
3518 DenemoProject *project = Denemo.project;
3519 #if 1
3520 //g_debug("Was mode %x\n", project->mode);
3521 if (project->mode & INPUTRHYTHM)
3522 project->mode &= ~INPUTRHYTHM;
3523 else
3524 {
3525 project->mode |= INPUTRHYTHM;
3526 activate_action ("/MainMenu/ModeMenu/EditMode");
3527 }
3528 //g_debug("Now mode %x\n", project->mode);
3529 #else
3530 static gint mode = INPUTNORMAL;
3531 if (project->mode & INPUTRHYTHM)
3532 {
3533 switch (mode & ~ENTRY_TYPE_MASK)
3534 {
3535 case INPUTNORMAL:
3536 activate_action ("/MainMenu/ModeMenu/Note");
3537 break;
3538 default:
3539 ;
3540 }
3541 }
3542 else
3543 {
3544 mode = project->mode; // remember mode for switching back, breaks with multi project FIXME
3545 activate_action ("/MainMenu/ModeMenu/Rhythm");
3546 }
3547 #endif
3548 }
3549
3550 /**
3551 * Function to toggle the visibility of the LilyPond text window. It refreshes
3552 * the text if needed
3553 */
3554 static void
toggle_lilytext(GtkAction * action,gpointer param)3555 toggle_lilytext (GtkAction * action, gpointer param)
3556 {
3557 DenemoProject *project = Denemo.project;
3558 //if(!project->textview)
3559 refresh_lily_cb (action, project);
3560 if (!gtk_widget_get_visible (Denemo.textwindow))
3561 gtk_widget_show /*_all*/ (Denemo.textwindow);
3562 else
3563 gtk_widget_hide (Denemo.textwindow);
3564 //g_debug("toggling lily window");
3565 }
3566
3567
3568 /**
3569 * Function to toggle the visibility of the Scheme text window.
3570 */
3571 static void
toggle_scheme(void)3572 toggle_scheme (void)
3573 {
3574 GtkWidget *textwindow = gtk_widget_get_toplevel (Denemo.script_view);
3575 if (!gtk_widget_get_visible (textwindow))
3576 gtk_widget_show_all (textwindow);
3577 else
3578 gtk_widget_hide (textwindow);
3579 //g_debug("toggling scheme window");
3580 }
3581
3582
3583
3584
3585 /**
3586 * Function to toggle whether rhythm toolbar is visible
3587 * (no longer switches keymap to Rhythm.keymaprc when toolbar is on back to standard when off.)
3588 *
3589 */
3590 static void
toggle_rhythm_toolbar(GtkAction * action,gpointer param)3591 toggle_rhythm_toolbar (GtkAction * action, gpointer param)
3592 {
3593 GtkWidget *widget;
3594 widget = gtk_ui_manager_get_widget (Denemo.ui_manager, "/RhythmToolBar");
3595 //g_debug("Callback for %s\n", g_type_name(G_TYPE_FROM_INSTANCE(widget)));
3596 if ((!action) || gtk_widget_get_visible (widget))
3597 {
3598
3599 gtk_widget_hide (widget);
3600 }
3601 else
3602 {
3603
3604 gtk_widget_show (widget);
3605 /* make sure we are in Insert and Note for rhythm toolbar */
3606 // activate_action( "/MainMenu/ModeMenu/Note");
3607 //activate_action( "/MainMenu/ModeMenu/InsertMode");
3608 }
3609 if (Denemo.prefs.persistence && (Denemo.project->view == DENEMO_MENU_VIEW))
3610 Denemo.prefs.rhythm_palette = gtk_widget_get_visible (widget);
3611 }
3612
3613 /**
3614 * Function to toggle whether main toolbar is visible
3615 *
3616 *
3617 */
3618 void
toggle_toolbar(GtkAction * action,gpointer param)3619 toggle_toolbar (GtkAction * action, gpointer param)
3620 {
3621 GtkWidget *widget;
3622 widget = gtk_ui_manager_get_widget (Denemo.ui_manager, "/ToolBar");
3623 if ((!action) || gtk_widget_get_visible (widget))
3624 gtk_widget_hide (widget);
3625 else
3626 gtk_widget_show (widget);
3627 if (Denemo.prefs.persistence && (Denemo.project->view == DENEMO_MENU_VIEW))
3628 Denemo.prefs.toolbar = gtk_widget_get_visible (widget);
3629 }
3630
3631 /**
3632 * Function to toggle whether playback toolbar is visible
3633 *
3634 *
3635 */
3636 void
toggle_playback_controls(GtkAction * action,gpointer param)3637 toggle_playback_controls (GtkAction * action, gpointer param)
3638 {
3639 GtkWidget *widget;
3640 widget = Denemo.playback_control;
3641 if ((!action) || gtk_widget_get_visible (widget))
3642 gtk_widget_hide (widget);
3643 else
3644 gtk_widget_show (widget);
3645 if (Denemo.prefs.persistence && (Denemo.project->view == DENEMO_MENU_VIEW))
3646 Denemo.prefs.playback_controls = gtk_widget_get_visible (widget);
3647 }
3648
3649 /**
3650 * Function to toggle whether playback toolbar is visible
3651 *
3652 *
3653 */
3654 void
toggle_midi_in_controls(GtkAction * action,gpointer param)3655 toggle_midi_in_controls (GtkAction * action, gpointer param)
3656 {
3657 GtkWidget *widget;
3658 widget = Denemo.midi_in_control;
3659 if ((!action) || gtk_widget_get_visible (widget))
3660 gtk_widget_hide (widget);
3661 else
3662 gtk_widget_show (widget);
3663 if (Denemo.prefs.persistence && (Denemo.project->view == DENEMO_MENU_VIEW))
3664 Denemo.prefs.midi_in_controls = gtk_widget_get_visible (widget);
3665 }
3666
3667
3668 /**
3669 * Function to toggle whether keyboard bindings can be set by pressing key over menu item
3670 *
3671 *
3672 */
3673 static void
toggle_quick_edits(GtkAction * action,gpointer param)3674 toggle_quick_edits (GtkAction * action, gpointer param)
3675 {
3676 Denemo.prefs.quickshortcuts = !Denemo.prefs.quickshortcuts;
3677 }
3678
3679
3680 /*UNUSED
3681 static void
3682 toggle_main_menu (GtkAction * action, gpointer param)
3683 {
3684 GtkWidget *widget;
3685 widget = gtk_ui_manager_get_widget (Denemo.ui_manager, "/MainMenu");
3686 if ((!action) || gtk_widget_get_visible (widget))
3687 gtk_widget_hide (widget);
3688 else
3689 gtk_widget_show (widget);
3690 }
3691 */
3692 /**
3693 * Function to toggle whether action menubar is visible
3694 *
3695 *
3696 */
3697 /* UNUSED
3698 static void
3699 toggle_action_menu (GtkAction * action, gpointer param)
3700 {
3701 GtkWidget *widget;
3702 widget = gtk_ui_manager_get_widget (Denemo.ui_manager, "/ActionMenu");
3703 if (!widget)
3704 return; // internal error - out of step with menu_entries...
3705 if ((!action) || gtk_widget_get_visible (widget))
3706 {
3707
3708 gtk_widget_hide (widget);
3709 }
3710 else
3711 {
3712 gtk_widget_show (widget);
3713 }
3714 }*/
3715
3716 /**
3717 * Function to toggle visibility of print preview pane of current project
3718 *
3719 *
3720 */
3721 static void
toggle_print_view(GtkAction * action,gpointer param)3722 toggle_print_view (GtkAction * action, gpointer param)
3723 {
3724 if(Denemo.non_interactive)
3725 return;
3726 #ifndef USE_EVINCE
3727 g_debug("This feature requires denemo to be built with evince");
3728 #else
3729 GtkWidget *w = gtk_widget_get_toplevel (Denemo.printarea);
3730 if ((!action) || gtk_widget_get_visible (w))
3731 gtk_widget_hide (w);
3732 else
3733 {
3734 // gtk_widget_show (w);
3735 //if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (Denemo.printarea), "printviewupdate")) < Denemo.project->changecount)
3736 // refresh_print_view (TRUE);
3737 implement_show_print_view (TRUE);
3738 }
3739 #endif
3740 }
3741 /**
3742 * Function to toggle visibility of playback view pane of current project
3743 *
3744 *
3745 */
3746 static void
toggle_playback_view(GtkAction * action,gpointer param)3747 toggle_playback_view (GtkAction * action, gpointer param)
3748 {
3749 if(Denemo.non_interactive)
3750 return;
3751 GtkWidget *w = gtk_widget_get_toplevel (Denemo.playbackview);
3752 if (gtk_widget_get_visible (w))
3753 gtk_widget_hide (w);
3754 else
3755 {
3756 gtk_widget_show (w);
3757 GtkImageType type = gtk_image_get_storage_type (GTK_IMAGE(Denemo.playbackview));
3758 if (type == GTK_IMAGE_EMPTY)
3759 call_out_to_guile ("(d-PlaybackView #f)");
3760
3761 }
3762 }
3763 /**
3764 * Function to toggle visibility of score layout window of current project
3765 *
3766 *
3767 */
3768 static void
toggle_score_layout(GtkAction * action,gpointer param)3769 toggle_score_layout (GtkAction * action, gpointer param)
3770 {
3771 #ifndef USE_EVINCE
3772 g_debug("This feature requires denemo to be built with evince");
3773 #else
3774 DenemoProject *project = Denemo.project;
3775 GtkWidget *w = project->score_layout;
3776 GList *g = gtk_container_get_children (GTK_CONTAINER (w));
3777 if (g == NULL)
3778 {
3779 create_default_scoreblock ();
3780 }
3781 if ((!action) || gtk_widget_get_visible (w))
3782 gtk_widget_hide (w);
3783 else
3784 {
3785 gtk_widget_show (w);
3786 }
3787 #endif
3788 }
3789
3790
3791 /**
3792 * Function to toggle visibility of command manager window
3793 *
3794 *
3795 */
3796 static void
toggle_command_manager(GtkAction * action,gpointer param)3797 toggle_command_manager (GtkAction * action, gpointer param)
3798 {
3799 if(Denemo.command_manager==NULL)
3800 {
3801 configure_keyboard_dialog (action, NULL);
3802 }
3803 else
3804 {
3805 GtkWidget *w = Denemo.command_manager;
3806 if ((!action) || gtk_widget_get_visible (w))
3807 gtk_widget_hide (w);
3808 else
3809 gtk_widget_show (w);
3810 }
3811 }
3812
3813 /**
3814 * Function to toggle visibility of lyrics view pane of current movement
3815 *
3816 *
3817 */
3818 void
toggle_lyrics_view(GtkAction * action,gpointer param)3819 toggle_lyrics_view (GtkAction * action, gpointer param)
3820 {
3821 #ifndef USE_EVINCE
3822 g_debug("This feature requires denemo to be built with evince");
3823 #else
3824 GtkWidget *widget = Denemo.project->movement->lyricsbox;
3825 static gint last_height = 100;
3826 if (!widget)
3827 g_warning ("No lyrics");
3828 else
3829 {
3830 if ((!action) || gtk_widget_get_visible (widget))
3831 {
3832 GtkWidget *parent = gtk_widget_get_parent(gtk_widget_get_parent(widget));
3833 gint height = get_widget_height (parent);
3834 last_height = get_widget_height (widget);
3835 gtk_paned_set_position (GTK_PANED(parent), height);
3836 gtk_widget_hide (widget);
3837 }
3838 else
3839 {
3840 gtk_widget_show (widget);
3841 GtkWidget *parent = gtk_widget_get_parent(gtk_widget_get_parent(widget));
3842 gint height = get_widget_height (parent);
3843 if((height>last_height))
3844 gtk_paned_set_position (GTK_PANED(parent), height - last_height);
3845 }
3846 if (Denemo.prefs.persistence && (Denemo.project->view == DENEMO_MENU_VIEW))
3847 Denemo.prefs.lyrics_pane = gtk_widget_get_visible (widget);
3848 }
3849 #endif
3850 }
3851
3852
show_lilypond_errors(void)3853 void show_lilypond_errors (void)
3854 {
3855 GtkWidget *widget = gtk_widget_get_parent (Denemo.console);
3856
3857 if (!gtk_widget_get_visible (widget))
3858 activate_action ("/MainMenu/ViewMenu/" ToggleConsoleView_STRING);
3859 }
3860 /**
3861 * Function to toggle visibility of print preview pane of current project
3862 *
3863 *
3864 */
3865 static void
toggle_score_view(GtkAction * action,gpointer param)3866 toggle_score_view (GtkAction * action, gpointer param)
3867 {
3868 #ifndef USE_EVINCE
3869 g_debug("This feature requires denemo to be built with evince");
3870 #else
3871 GtkWidget *w = gtk_widget_get_parent (gtk_widget_get_parent (Denemo.scorearea));
3872 if ((!action) || gtk_widget_get_visible (w))
3873 gtk_widget_hide (w);
3874 else
3875 {
3876 gtk_widget_show (w);
3877 gtk_widget_grab_focus (Denemo.scorearea);
3878 }
3879 #endif
3880 }
3881
3882 /**
3883 * Function to toggle visibility of titles etc of current project
3884 *
3885 *
3886 */
3887 static void
toggle_scoretitles(GtkAction * action,gpointer param)3888 toggle_scoretitles (GtkAction * action, gpointer param)
3889 {
3890 #ifndef USE_EVINCE
3891 g_debug("This feature requires denemo to be built with evince");
3892 #else
3893 GtkWidget *widget = Denemo.project->buttonboxes;
3894 if ((!action) || gtk_widget_get_visible (widget))
3895 gtk_widget_hide (widget);
3896 else
3897 gtk_widget_show (widget);
3898 if (Denemo.prefs.persistence && (Denemo.project->view == DENEMO_MENU_VIEW))
3899 Denemo.prefs.visible_directive_buttons = gtk_widget_get_visible (widget);
3900 #endif
3901 }
3902
3903 /**
3904 * Function to toggle whether object menubar is visible
3905 *
3906 *
3907 */
3908 static void
toggle_object_menu(GtkAction * action,gpointer param)3909 toggle_object_menu (GtkAction * action, gpointer param)
3910 {
3911 #ifndef USE_EVINCE
3912 g_debug("This feature requires denemo to be built with evince");
3913 #else
3914 GtkWidget *widget;
3915 widget = gtk_ui_manager_get_widget (Denemo.ui_manager, "/ObjectMenu");
3916 if (!widget)
3917 return; // internal error - out of step with menu_entries...
3918 if ((!action) || gtk_widget_get_visible (widget))
3919 {
3920
3921 gtk_widget_hide (widget);
3922 }
3923 else
3924 {
3925 gtk_widget_show (widget);
3926 }
3927 #endif
3928 }
3929
3930
3931
3932 /**
3933 * Toggle entries for the menus
3934 */
3935 GtkToggleActionEntry toggle_menu_entries[] = {
3936 {ToggleToolbar_STRING, NULL, N_("Tools"), NULL, N_("Show/hide a toolbar for general operations on music files"),
3937 G_CALLBACK (toggle_toolbar), TRUE}
3938 ,
3939 {TogglePlaybackControls_STRING, NULL, N_("Playback Control"), NULL, N_("Show/hide playback controls"),
3940 G_CALLBACK (toggle_playback_controls), TRUE}
3941 ,
3942 {ToggleMidiInControls_STRING, NULL, N_("Midi In Control"), NULL, N_("Show/hide Midi Input controls"),
3943 G_CALLBACK (toggle_midi_in_controls), TRUE}
3944 ,
3945 {ToggleRhythmToolbar_STRING, NULL, N_("Snippets"), NULL, N_("Show/hide a toolbar which allows\nyou to store and enter snippets of music and to enter notes using rhythm pattern of a snippet"),
3946 G_CALLBACK (toggle_rhythm_toolbar), TRUE}
3947 ,
3948 {ToggleObjectMenu_STRING, NULL, N_("Object Menu"), NULL, N_("Show/hide a menu which is arranged by objects\nThe actions available for note objects change with the mode"),
3949 G_CALLBACK (toggle_object_menu), TRUE}
3950 ,
3951 {ToggleLilyText_STRING, NULL, N_("LilyPond"), NULL, N_("Show/hide the LilyPond music typesetting language window"),
3952 G_CALLBACK (toggle_lilytext), FALSE}
3953 ,
3954 {ToggleScript_STRING, NULL, N_("Scheme Script"), NULL, N_("Show scheme script window"),
3955 G_CALLBACK (toggle_scheme), FALSE}
3956 ,
3957
3958 {TogglePrintView_STRING, NULL, N_("Typeset Music"), NULL, NULL,
3959 G_CALLBACK (toggle_print_view), FALSE}
3960 ,
3961
3962 {TogglePlaybackView_STRING, NULL, N_("Playback"), NULL, NULL,
3963 G_CALLBACK (toggle_playback_view), FALSE}
3964 ,
3965
3966 {ToggleScoreLayout_STRING, NULL, N_("Score Layout"), NULL, NULL,
3967 G_CALLBACK (toggle_score_layout), FALSE}
3968 ,
3969 {ToggleCommandManager_STRING, NULL, N_("Command Center"), NULL, NULL,
3970 G_CALLBACK (toggle_command_manager), FALSE}
3971 ,
3972
3973 {ToggleLyricsView_STRING, NULL, N_("Lyrics"), NULL, NULL,
3974 G_CALLBACK (toggle_lyrics_view), TRUE}
3975 ,
3976
3977
3978 {ToggleScoreView_STRING, NULL, N_("Score"), NULL, NULL,
3979 G_CALLBACK (toggle_score_view), TRUE}
3980 ,
3981
3982 {ToggleScoreTitles_STRING, NULL, N_("Titles, Buttons etc"), NULL, NULL,
3983 G_CALLBACK (toggle_scoretitles), FALSE}
3984 ,
3985
3986
3987 {QuickEdits_STRING, NULL, N_("Allow Quick Shortcut Edits"), NULL, "Enable editing keybindings by pressing a key while hovering over the menu item",
3988 G_CALLBACK (toggle_quick_edits), TRUE}
3989 ,
3990 {RecordScript_STRING, NULL, N_("Record Scheme Script"), NULL, "Start recording commands into the Scheme script text window",
3991 G_CALLBACK (toggle_record_script), FALSE}
3992 ,
3993
3994 {RHYTHM_E_STRING, NULL, N_("Audible Feedback\nInsert Duration/Edit Note"), NULL, N_("Gives feedback as you enter durations. N.B. durations are entered in Edit mode"),
3995 G_CALLBACK (toggle_rhythm_mode), FALSE}
3996 ,
3997 {ReadOnly_STRING, NULL, N_("Read Only"), NULL, "Make score read only\nNot working",
3998 G_CALLBACK (default_mode), FALSE}
3999 };
4000
4001
4002
4003 static GtkRadioActionEntry input_menu_entries[] = {
4004 {"KeyboardOnly", NULL, N_("No External Input"), NULL, N_("Entry of notes via computer keyboard only\nIgnores connected MIDI or microphone devices."),
4005 INPUTKEYBOARD}
4006 ,
4007 {"Microphone", NULL, N_("Audio Input"), NULL, N_("Enable pitch entry from microphone"), INPUTAUDIO
4008 /* G_CALLBACK (toggle_pitch_recognition), FALSE */ }
4009 ,
4010 {"JackMidi", NULL, N_("Midi Input"), NULL, N_("Input from a MIDI source. Set up the source first using Edit → Change Preferences → Audio/Midi\nUse View → MIDI In Control to control what the input does.\n"), INPUTMIDI /*G_CALLBACK (jackmidi) */ }
4011 };
4012
4013 struct cbdata
4014 {
4015 DenemoProject *project;
4016 gchar *filename;
4017 };
4018
4019 /**
4020 * Add history entry to the History menu, create a menu item for it
4021 */
4022 void
addhistorymenuitem(gchar * filename)4023 addhistorymenuitem (gchar * filename)
4024 {
4025 if (!g_file_test (filename, G_FILE_TEST_EXISTS))
4026 return;
4027 GtkWidget *item = gtk_ui_manager_get_widget (Denemo.ui_manager,
4028 "/MainMenu/FileMenu/OpenMenu/OpenRecent/Browse");
4029 GtkWidget *menu = gtk_widget_get_parent (GTK_WIDGET (item));
4030
4031 item = gtk_menu_item_new_with_label (filename);
4032 gtk_menu_shell_insert (GTK_MENU_SHELL (menu), item, 0);
4033 g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (openrecent), g_strdup (filename)); //FIXME
4034 gtk_widget_show (item);
4035 }
4036
4037 /**
4038 * Top-Level function to populate the History menu
4039 * with elements read from the denemohistory file
4040 */
4041 static void
populate_opened_recent_menu(void)4042 populate_opened_recent_menu (void)
4043 {
4044 g_queue_foreach (Denemo.prefs.history, (GFunc) addhistorymenuitem, NULL);
4045 }
4046
4047 static gchar *
get_most_recent_file(void)4048 get_most_recent_file (void)
4049 {
4050 if (Denemo.prefs.history)
4051 {
4052 gchar *filename = (gchar *) g_queue_peek_tail (Denemo.prefs.history);
4053 if (filename && g_file_test (filename, G_FILE_TEST_EXISTS))
4054 return filename;
4055 }
4056 return NULL;
4057 }
4058
4059 static void
show_type(GtkWidget * widget,gchar * message)4060 show_type (GtkWidget * widget, gchar * message)
4061 {
4062 g_message ("%s%s", message, widget ? g_type_name (G_TYPE_FROM_INSTANCE (widget)) : "NULL widget");
4063 }
4064
4065
4066
4067
4068 /**
4069 * Key snooper function. This function intercepts all key events before they are
4070 * passed to other functions for further processing. We use do quick shortcut edits.
4071 */
4072 static gint
dnm_key_snooper(GtkWidget * grab_widget,GdkEventKey * event)4073 dnm_key_snooper (GtkWidget * grab_widget, GdkEventKey * event)
4074 {
4075 //no special processing for key release events
4076 if (event->type == GDK_KEY_RELEASE)
4077 return FALSE;
4078 //if the grab_widget is a menu, the event could be a quick edit
4079 if (Denemo.prefs.quickshortcuts && GTK_IS_MENU (grab_widget))
4080 {
4081 return keymap_accel_quick_edit_snooper (grab_widget, event);
4082 }
4083 //else we let the event be processed by other functions
4084 return FALSE;
4085 }
4086
visible_rhythm_buttons(GList * rhythms,gboolean on)4087 static void visible_rhythm_buttons (GList *rhythms, gboolean on)
4088 {
4089 GList *g;
4090 for (g=rhythms;g;g=g->next)
4091 on?gtk_widget_show (GTK_WIDGET(((RhythmPattern*)(g->data))->button)):
4092 gtk_widget_hide (GTK_WIDGET(((RhythmPattern*)(g->data))->button));
4093
4094 }
4095
4096 static void
switch_page(GtkNotebook * notebook,GtkWidget * page,guint pagenum)4097 switch_page (GtkNotebook * notebook, GtkWidget * page, guint pagenum)
4098 {
4099 //g_debug("switching pagenum %d\n",pagenum);
4100 DenemoProject *project = Denemo.project;
4101 if (project == NULL)
4102 return;
4103 GList *g = g_list_nth (Denemo.projects, pagenum);
4104 if (g == NULL)
4105 {
4106 g_warning ("Got a switch page, but there is no such page in Denemo.projects");
4107 return;
4108 }
4109 DenemoProject *newproject = g->data;
4110 if (project == newproject)
4111 return; //on arrival Denemo.project is already set to the new project when you are doing new window
4112 /* turn off the LilyPond window if it is on
4113 it would be nice to keep a record of whether it was open for re-opening
4114 on return to this tab FIXME */
4115
4116 if (Denemo.textwindow && gtk_widget_get_visible (Denemo.textwindow))
4117 activate_action ("/MainMenu/ViewMenu/" ToggleLilyText_STRING);
4118
4119 if (gtk_widget_get_visible (Denemo.project->score_layout))
4120 activate_action ("/MainMenu/ViewMenu/" ToggleScoreLayout_STRING);
4121
4122 unhighlight_rhythm (Denemo.project->prevailing_rhythm);
4123
4124 visible_rhythm_buttons (Denemo.project->rhythms, FALSE);
4125
4126 Denemo.project = project = (DenemoProject *) (g->data);
4127 //g_debug("switch page\n");
4128
4129 //FIXME if Denemo.project->movement->recording then show Denemo.audio_vol_control
4130 if (Denemo.prefs.visible_directive_buttons)
4131 {
4132 gtk_widget_hide (Denemo.project->buttonboxes);
4133 activate_action ("/MainMenu/ViewMenu/" ToggleScoreTitles_STRING);
4134 }
4135
4136
4137 visible_rhythm_buttons (Denemo.project->rhythms, TRUE);
4138
4139
4140 set_title_bar (Denemo.project);
4141 highlight_rhythm (Denemo.project->prevailing_rhythm);
4142 draw_score_area();
4143 draw_score (NULL);
4144 }
4145
4146
4147
4148
4149 static gboolean
thecallback(GtkWidget * widget,GdkEventButton * event,GtkAction * action)4150 thecallback (GtkWidget * widget, GdkEventButton * event, GtkAction * action)
4151 {
4152 if (event->button == 1 && !(event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)))
4153 return FALSE;
4154 g_debug ("going for %d for %d\n", event->button, event->state);
4155 event->button = 3;
4156 return menu_click (widget, event, action);
4157 }
4158
4159 /* proxy_connected
4160 callback to set callback for right click on menu items and
4161 set the shortcut label
4162
4163 */
4164 static void
proxy_connected(GtkUIManager * uimanager,GtkAction * action,GtkWidget * proxy)4165 proxy_connected (GtkUIManager * uimanager, GtkAction * action, GtkWidget * proxy)
4166 {
4167 int command_idx;
4168 command_row* row;
4169 attach_right_click_callback (proxy, action);
4170 const gchar *tooltip = gtk_action_get_tooltip (action);
4171 const gchar *additional_text;
4172 if (tooltip && g_str_has_prefix (tooltip, _("Menu:")))
4173 additional_text = _("Click here then hover over the menu items to find out what they will do");
4174 else
4175 additional_text = _("Left click to execute the command, press a key to assign a keyboard shortcut to the command,\nRight click to get a menu from which you can\nCreate a button for this command, or a two-key keyboard shortcut or more options still");
4176 gchar *tip = g_strconcat (tooltip, "\n------------------------------------------------------------------\n", additional_text, NULL);
4177 // unfortunately submenus seem not to be attached yet ... if((GTK_IS_IMAGE_MENU_ITEM(proxy)) && gtk_menu_item_get_submenu(proxy)) tip = g_strdup("test");
4178 // Denemo.map is not yet created either :(
4179 denemo_widget_set_tooltip_text (proxy, tip);
4180 g_free (tip);
4181 if (GTK_IS_IMAGE_MENU_ITEM (proxy))
4182 {
4183 #ifdef FAST_MACHINE
4184 g_signal_connect_after (action, "activate", G_CALLBACK (switch_back_to_main_window), NULL); /*ensure keyboard focus returns to drawing area */
4185 #endif
4186 // ????????????? should I put an icon named for the action->label into an icon factory here (we could just have one, static, and use gtk_icon_factory_add_default??????????
4187 if (!g_object_get_data (G_OBJECT (action), "connected"))
4188 g_signal_connect (G_OBJECT (proxy), "button-press-event", G_CALLBACK (thecallback), action);
4189 g_object_set_data (G_OBJECT (action), "connected", (gpointer) 1); //Unfortunately GtkImageMenuItems that pop up a menu do not wait for a button press - the focus switches to the popped up memory on entry. So we don't see this signal for them
4190 }
4191 #if 0 //(GTK_MINOR_VERSION <10)
4192 attach_action_to_widget (proxy, action, Denemo.project);
4193 #endif
4194 if (Denemo.map == NULL)
4195 return;
4196 command_idx = lookup_command_from_name (Denemo.map, gtk_action_get_name (action));
4197
4198 if (command_idx > -1){
4199 keymap_get_command_row (Denemo.map, &row, command_idx);
4200 update_accel_labels (Denemo.map, command_idx);
4201
4202 if (row->hidden)
4203 set_visibility_for_action (action, FALSE);
4204 }
4205 }
4206
4207
4208
4209
4210
4211 static GtkWidget *
create_playbutton(GtkWidget * box,gchar * thelabel,gpointer callback,gchar * image,gchar * tooltip)4212 create_playbutton (GtkWidget * box, gchar * thelabel, gpointer callback, gchar * image, gchar * tooltip)
4213 {
4214 GtkWidget *button;
4215 if (thelabel)
4216 button = gtk_button_new_with_label (thelabel);
4217 else
4218 button = gtk_button_new ();
4219 gtk_widget_set_can_focus (button, FALSE);
4220 if (image)
4221 {
4222 gtk_button_set_image (GTK_BUTTON (button), gtk_image_new_from_stock (image, GTK_ICON_SIZE_BUTTON));
4223 }
4224 g_signal_connect (button, "clicked", G_CALLBACK (callback), NULL);
4225 gtk_box_pack_start (GTK_BOX (box), button, FALSE, TRUE, 0);
4226 gtk_widget_set_tooltip_text (button, tooltip);
4227 return button;
4228 }
4229
4230
4231 void
set_playbutton(gboolean pause)4232 set_playbutton (gboolean pause)
4233 {
4234 if (pause)
4235 {
4236 gtk_button_set_image (GTK_BUTTON (playbutton), gtk_image_new_from_stock (GTK_STOCK_MEDIA_PAUSE, GTK_ICON_SIZE_BUTTON));
4237 }
4238 else
4239 {
4240 gtk_button_set_image (GTK_BUTTON (playbutton), gtk_image_new_from_stock (GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_BUTTON));
4241 }
4242 }
4243
4244 //Set the master volume of the passed score and change the slider to suit
4245 void
set_master_volume(DenemoMovement * si,gdouble volume)4246 set_master_volume (DenemoMovement * si, gdouble volume)
4247 {
4248 si->master_volume = volume;
4249 if (master_vol_adj)
4250 {
4251 gtk_adjustment_set_value (master_vol_adj, volume);
4252 gtk_adjustment_changed (master_vol_adj);
4253 }
4254 }
4255
4256 //Set the master tempo of the passed score and change the slider to suit
4257 void
set_master_tempo(DenemoMovement * si,gdouble tempo)4258 set_master_tempo (DenemoMovement * si, gdouble tempo)
4259 {
4260 if(si->master_tempo>0.0)
4261 {
4262 Denemo.project->movement->end_time /= si->master_tempo;
4263 Denemo.project->movement->start_time /= si->master_tempo;
4264 }
4265 si->master_tempo = tempo;
4266 Denemo.project->movement->end_time *= si->master_tempo;
4267 Denemo.project->movement->start_time *= si->master_tempo;
4268 if (master_tempo_adj)
4269 {
4270 gtk_adjustment_set_value (master_tempo_adj, tempo * si->tempo);
4271 gtk_adjustment_changed (master_tempo_adj);
4272 }
4273 }
4274
toggle_dynamic_compression(gboolean * compression)4275 static void toggle_dynamic_compression (gboolean *compression)
4276 {
4277 *compression = 100 * (!*compression);
4278 Denemo.project->movement->smfsync = G_MAXINT;
4279 }
4280
4281 /* create_window() creates the toplevel window and all the menus - it only
4282 called once per invocation of Denemo */
4283 static void
create_window(void)4284 create_window (void)
4285 {
4286
4287 GtkWidget *outer_main_vbox, *main_hbox, *main_vbox, *menubar, *toolbar, *hbox;
4288 GtkUIManager *ui_manager;
4289 GError *error;
4290 gchar *denemoui_path = NULL;
4291 gchar* data_file = NULL;
4292
4293 Denemo.window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4294 gtk_window_set_title (GTK_WINDOW (Denemo.window), _("Denemo Main Window"));
4295 // it accesses Denemo.window
4296 loadWindowState ();
4297 #ifdef G_OS_WIN32
4298 g_message ("Denemo icon not used");
4299 //not installed on windows ... data_file = g_build_filename (get_system_data_dir (), "icons","denemo.png", NULL);
4300 #else
4301 GList* icon_dirs = NULL;
4302 icon_dirs = g_list_append(icon_dirs, g_build_filename(PACKAGE_SOURCE_DIR, PIXMAPS_DIR, NULL));
4303 icon_dirs = g_list_append(icon_dirs, g_strconcat (get_system_data_dir (), "/../pixmaps", NULL)); //FIXME installed in wrong place?
4304
4305 data_file = find_path_for_file("denemo.png", icon_dirs);
4306 if(data_file)
4307 gtk_window_set_default_icon_from_file (data_file, NULL);
4308 #endif
4309
4310 g_signal_connect (G_OBJECT (Denemo.window), "delete_event", G_CALLBACK (delete_callback), NULL);
4311 g_free (data_file);
4312
4313 gtk_window_set_resizable (GTK_WINDOW (Denemo.window), TRUE);
4314
4315 Denemo.color = 0xFFFFFF; //white background RGB values
4316
4317 //FIXME this is where score_layout should be created.
4318 //score_layout should belong the Denemo.xxx not Denemo.project->xxx (so as to be like the others)
4319 #ifdef USE_EVINCE
4320 install_printpreview (NULL);
4321 #endif
4322 install_svgview (NULL);
4323
4324 outer_main_vbox = gtk_vbox_new (FALSE, 1);
4325 gtk_container_set_border_width (GTK_CONTAINER (outer_main_vbox), 1);
4326 gtk_container_add (GTK_CONTAINER (Denemo.window), outer_main_vbox);
4327 gtk_widget_show (outer_main_vbox);
4328
4329 Denemo.action_group = gtk_action_group_new ("MenuActions");
4330 gtk_action_group_set_translation_domain (Denemo.action_group, NULL);
4331 /* This also sets current Denemo.project as the callback data for all the functions in the
4332 * menubar, which is not needed since we have only one set of actions for all
4333 the projects. We will always act on Denemo.project anyway.*/
4334 gtk_action_group_add_actions (Denemo.action_group, menu_entries, G_N_ELEMENTS (menu_entries), Denemo.project);
4335 gtk_action_group_add_toggle_actions (Denemo.action_group, toggle_menu_entries, G_N_ELEMENTS (toggle_menu_entries), Denemo.project);
4336
4337
4338
4339
4340 gtk_action_group_add_radio_actions (Denemo.action_group, input_menu_entries, G_N_ELEMENTS (input_menu_entries), have_midi ()? INPUTMIDI : INPUTKEYBOARD /* initial value */ ,
4341 G_CALLBACK (change_input_type), NULL);
4342
4343
4344
4345
4346 ui_manager = gtk_ui_manager_new ();
4347 Denemo.ui_manager = ui_manager;
4348 gtk_ui_manager_set_add_tearoffs (Denemo.ui_manager, TRUE);
4349 gtk_ui_manager_insert_action_group (ui_manager, Denemo.action_group, 0);
4350
4351 g_signal_connect (G_OBJECT (Denemo.ui_manager), "connect-proxy", G_CALLBACK (proxy_connected), NULL);
4352
4353
4354 //We do not use accel_group anymore TODO delete the next 2 lines
4355 //accel_group = gtk_ui_manager_get_accel_group (ui_manager);
4356 //gtk_window_add_accel_group (GTK_WINDOW (Denemo.window), accel_group);
4357
4358 GList* dirs = NULL;
4359 dirs = g_list_append(dirs, g_build_filename(PACKAGE_SOURCE_DIR, UI_DIR, NULL));
4360 dirs = g_list_append(dirs, g_build_filename(get_system_data_dir (), UI_DIR, NULL));
4361
4362 denemoui_path = find_path_for_file("denemoui.xml", dirs);
4363
4364 if (!denemoui_path)
4365 {
4366 g_error ("denemoui.xml could not be found, exiting");
4367 exit (EXIT_FAILURE);
4368 }
4369
4370 error = NULL;
4371 if (!gtk_ui_manager_add_ui_from_file (ui_manager, denemoui_path, &error))
4372 {
4373 g_error ("Could not load %s: %s", denemoui_path, error->message);
4374 g_error_free (error);
4375 exit (EXIT_FAILURE);
4376 }
4377
4378
4379 {
4380 //pops up with menu items for the directives attached to the current note
4381 GtkWidget *menu = gtk_ui_manager_get_widget (Denemo.ui_manager, "/NoteEditPopupDirectives");
4382 g_signal_connect (menu, "deactivate", G_CALLBACK (unpopulate_menu), NULL);
4383 }
4384
4385 //menubar = gtk_item_factory_get_widget (item_factory, "<main>");
4386 Denemo.menubar = gtk_ui_manager_get_widget (ui_manager, "/MainMenu"); // this triggers Lily... missing action
4387 if (Denemo.prefs.newbie)
4388 gtk_widget_set_tooltip_text (Denemo.menubar, _("This is the Main Menu bar, where menus for the mostly non-musical aspects (saving, printing, setting up input sources etc) are placed. See the Object Menu bar for the commands that edit music"));
4389 gtk_box_pack_start (GTK_BOX (outer_main_vbox), Denemo.menubar, FALSE, TRUE, 0);
4390 gtk_widget_show (Denemo.menubar);
4391
4392 if (Denemo.prefs.newbie)
4393 gtk_widget_set_tooltip_text (gtk_ui_manager_get_widget (ui_manager, "/ObjectMenu"), _("This is the Object Menu bar, where menus for the commands that edit music live. They are arranged in a hierarchy Score, Movement, Staff (which contains Voices) and then the things that go on a staff, notes, clefs etc. Directives covers everything else that you can put in amongst the notes to change the behavior from that point in the music."));
4394
4395 gtk_widget_set_tooltip_markup (gtk_ui_manager_get_widget (ui_manager, "/RhythmToolBar"),
4396 _
4397 ("You can populate this bar with buttons holding a snippet of music. The highlighted snippet is the <i>prevailing duration</i>, that is the next note entered will follow the rhythmic pattern of this snippet.\nYou can enter the whole snippet by clicking on it, or using the command under ObjectMenu → Notes/Rests → Append/InsertDuration → Insert Snippet. You can also select the <i>prevailing snippet</i> using ObjectMenu → Notes/Rests → Select Duration → Next Snippet.\nYou can hide this bar (to make more room on the screen) using the View menu. You can make it your preference to hide it using MainMenu → Edit → Change Preferences → Display Note/Rest entry toolbar"));
4398
4399 toolbar = gtk_ui_manager_get_widget (ui_manager, "/ToolBar");
4400 // The user should be able to decide toolbar style.
4401 // But without gnome, there is no (ui) to set this option.
4402 if (Denemo.prefs.newbie)
4403 gtk_widget_set_tooltip_text (toolbar, _("This tool bar contains a few conventional commands. You can hide it (to make more room on the screen) using the View menu. You can make it your preference to hide it using MainMenu → Edit → Change Preferences → Display general toolbar"));
4404 gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_BOTH_HORIZ);
4405 gtk_box_pack_start (GTK_BOX (outer_main_vbox), toolbar, FALSE, TRUE, 0);
4406 gtk_widget_set_can_focus (toolbar, FALSE);
4407 //GTK_WIDGET_UNSET_FLAGS(toolbar, GTK_CAN_FOCUS);
4408
4409
4410 {
4411 Denemo.playback_control = gtk_vbox_new (FALSE, 1);
4412 gtk_widget_set_tooltip_text (Denemo.playback_control,
4413 _
4414 ("Controls for playback. The arrows on either side of the PLAY and STOP buttons move the playback start"
4415 " and playback end markers. Loop plays in a loop - you can edit while it plays. You can also record the output and save it as .ogg or .wav file. The temperament used for playing back can be set here."));
4416 gtk_box_pack_start (GTK_BOX (outer_main_vbox), Denemo.playback_control, FALSE, TRUE, 0);
4417 GtkFrame *frame = (GtkFrame *) gtk_frame_new (_("Playback Control"));
4418 gtk_frame_set_shadow_type ((GtkFrame *) frame, GTK_SHADOW_IN);
4419 gtk_container_add (GTK_CONTAINER (Denemo.playback_control), GTK_WIDGET (frame));
4420
4421 GtkWidget *inner1 = gtk_vbox_new (FALSE, 1);
4422 gtk_container_add (GTK_CONTAINER (frame), inner1);
4423
4424
4425 GtkWidget *inner = gtk_hbox_new (FALSE, 1);
4426 gtk_box_pack_start (GTK_BOX (inner1), inner, FALSE, TRUE, 0);
4427
4428 //gtk_box_pack_start (GTK_BOX (outer_main_vbox), inner, FALSE, TRUE, 0);
4429 gtk_widget_set_can_focus (inner, FALSE);
4430 GtkWidget *label;
4431
4432
4433 //create_playbutton(inner, NULL, pb_first, GTK_STOCK_GOTO_FIRST);
4434
4435
4436
4437 //create_playbutton(inner,NULL, pb_rewind, GTK_STOCK_MEDIA_REWIND);
4438
4439 create_playbutton (inner, NULL, pb_go_back, GTK_STOCK_GO_BACK, _("Moves the playback start point (which shows as a green bar) earlier in time\nThe red and green bars do not get drawn until you have started play, or at least created the time base."));
4440
4441 create_playbutton (inner, NULL, pb_start_to_cursor, GTK_STOCK_GO_DOWN, _("Sets the playback start point (green bar) to the note at the cursor.\nThe red and green bars do not get drawn until you have started play, or at least created the time base."));
4442 create_playbutton (inner, NULL, pb_next, GTK_STOCK_GO_FORWARD, _("Moves the playback start point (which shows as a green bar) later in time\nThe red and green bars do not get drawn until you have started play, or at least created the time base."));
4443 create_playbutton (inner, NULL, pb_stop, GTK_STOCK_MEDIA_STOP, _("Stops the playback. On pressing play after this playback will start where the green bar is, not where you stopped. Use the Play/Pause button for that."));
4444 playbutton = create_playbutton (inner, NULL, pb_play, GTK_STOCK_MEDIA_PLAY, _("Starts playing back from the playback start (green bar) until the playback end (red bar).\nWhen playing it pauses the play, and continues when pressed again."));
4445 audiorecordbutton = create_playbutton (inner, NULL, pb_audiorecord, GTK_STOCK_MEDIA_RECORD, _("Starts/Stops recording the audio output from Denemo.\nRecords live performance and/or playback,\nsave to disk to avoid overwriting previous recordings."));
4446 exportbutton = create_playbutton (inner, NULL, pb_exportaudio, GTK_STOCK_SAVE, _("Exports the audio recorded to disk"));
4447
4448 create_playbutton (inner, NULL, pb_previous, GTK_STOCK_GO_BACK, _("Moves the playback end point (which shows as a red bar) earlier in time\nThe red and green bars do not get drawn until you have started play, or at least created the time base."));
4449 create_playbutton (inner, NULL, pb_end_to_cursor, GTK_STOCK_GO_UP, _("Sets the playback end point (red bar) to the note at the cursor.\nThe red and green bars do not get drawn until you have started play, or at least created the time base."));
4450
4451 create_playbutton (inner, NULL, pb_go_forward, GTK_STOCK_GO_FORWARD, _("Moves the playback end point (which shows as a red bar) later in time\nThe red and green bars do not get drawn until you have started play, or at least created the time base."));
4452
4453 //create_playbutton(inner,NULL, pb_forward, GTK_STOCK_MEDIA_FORWARD);
4454
4455 create_playbutton (inner, _("Loop"), pb_loop, NULL, _("The music between the red and green bars is played in a loop.\nYou can edit the music while it is playing\n(so that you can continuously listen as you try alternatives)."));
4456
4457 // midiconductbutton = create_playbutton (inner, _("Conductor"), pb_conduct, NULL, _("With the mouse conductor once you press play the playback progresses as you move the mouse around\nWith this you can speed up and slow down the playback to listen in detail to a certain passage\n"));
4458
4459 create_playbutton (inner,
4460 #ifdef _HAVE_JACK_
4461 _("Panic")
4462 #else
4463 _("Reset")
4464 #endif
4465 , pb_panic, NULL, _("Resets the synthesizer, on JACK it sends a JACK panic."));
4466
4467
4468 create_playbutton (inner, _("Play Selection"), pb_play_range, NULL, _("Plays the current selection or from the cursor to the end if no selection present."));
4469 create_playbutton (inner, _("Playback Range"), pb_range, NULL, _("Pops up a dialog to get timings for start and end of playback."));
4470 GtkWidget *temperament_control = get_temperament_combo ();
4471 if (!gtk_widget_get_parent (temperament_control))
4472 //gtk_container_add (GTK_CONTAINER (inner), temperament_control);
4473 gtk_box_pack_start (GTK_BOX (inner), temperament_control, FALSE, FALSE, 0);
4474 {
4475 GtkWidget *hbox;
4476 hbox = gtk_hbox_new (FALSE, 1);
4477 gtk_box_pack_start (GTK_BOX (inner1), hbox, TRUE, TRUE, 0);
4478 // Tempo
4479 label = gtk_label_new (_("Tempo:"));
4480 gtk_widget_set_tooltip_text (label, _("Set the (initial) tempo of the movement"));
4481 gtk_widget_set_can_focus (label, FALSE);
4482 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
4483 master_tempo_adj = (GtkAdjustment *) gtk_adjustment_new (120.0, 0.0, 600.0, 1.0, 1.0, 0.0);
4484 GtkWidget *hscale = gtk_hscale_new (GTK_ADJUSTMENT (master_tempo_adj));
4485 gtk_scale_set_digits (GTK_SCALE (hscale), 0);
4486 //GTK_WIDGET_UNSET_FLAGS(hscale, GTK_CAN_FOCUS);
4487 gtk_widget_set_can_focus (hscale, FALSE);
4488
4489 g_signal_connect (G_OBJECT (master_tempo_adj), "value_changed", G_CALLBACK (pb_tempo), NULL);
4490 gtk_box_pack_start (GTK_BOX (hbox), hscale, TRUE, TRUE, 0);
4491
4492 create_playbutton(hbox, _("Mute Staffs"), pb_mute_staffs, NULL, _("Select which staffs should be muted during playback."));
4493
4494 // Volume
4495 label = gtk_label_new (_("Volume"));
4496 //GTK_WIDGET_UNSET_FLAGS(label, GTK_CAN_FOCUS);
4497 gtk_widget_set_tooltip_text (label, _("Set the (initial) volume of the movement"));
4498
4499 gtk_widget_set_can_focus (label, FALSE);
4500 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
4501
4502 master_vol_adj = (GtkAdjustment *) gtk_adjustment_new (1.0, 0.0, 1.0, 1.0, 1.0, 0.0);
4503
4504 hscale = gtk_hscale_new (GTK_ADJUSTMENT (master_vol_adj));
4505 gtk_scale_set_digits (GTK_SCALE (hscale), 2);
4506 gtk_widget_set_can_focus (hscale, FALSE);
4507 //GTK_WIDGET_UNSET_FLAGS(hscale, GTK_CAN_FOCUS);
4508 g_signal_connect (G_OBJECT (master_vol_adj), "value_changed", G_CALLBACK (pb_volume), NULL);
4509 gtk_box_pack_start (GTK_BOX (hbox), hscale, TRUE, TRUE, 0);
4510
4511 GtkWidget *always_full_volume = gtk_check_button_new_with_label (_("Always Full Volume"));
4512 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (always_full_volume), Denemo.prefs.dynamic_compression);
4513 g_signal_connect_swapped (G_OBJECT (always_full_volume), "toggled", G_CALLBACK (toggle_dynamic_compression), &Denemo.prefs.dynamic_compression);
4514 gtk_box_pack_start (GTK_BOX (hbox), always_full_volume, FALSE, FALSE, 10);
4515
4516
4517 // Audio Volume
4518 Denemo.audio_vol_control = gtk_hbox_new (FALSE, 1);
4519 label = gtk_label_new (_("Audio Volume Cut"));
4520 gtk_widget_set_tooltip_text (label, _("Reduce the volume of the source audio relative to the volume of the score"));
4521
4522 gtk_widget_set_can_focus (label, FALSE);
4523 gtk_box_pack_start (GTK_BOX (Denemo.audio_vol_control), label, FALSE, TRUE, 0);
4524
4525 audio_vol_adj = (GtkAdjustment *) gtk_adjustment_new (1.0, 0.0, 1.0, 0.1, 0.2, 0.0);
4526
4527 hscale = gtk_hscale_new (GTK_ADJUSTMENT (audio_vol_adj));
4528 gtk_scale_set_digits (GTK_SCALE (hscale), 2);
4529 gtk_widget_set_can_focus (hscale, FALSE);
4530 //GTK_WIDGET_UNSET_FLAGS(hscale, GTK_CAN_FOCUS);
4531 g_signal_connect (G_OBJECT (audio_vol_adj), "value_changed", G_CALLBACK (audio_volume_cut), NULL);
4532 gtk_box_pack_start (GTK_BOX (Denemo.audio_vol_control), hscale, TRUE, TRUE, 0);
4533
4534 label = gtk_label_new (_("Audio Volume Boost"));
4535 gtk_widget_set_tooltip_text (label, _("Boost the volume of the source audio relative to the volume of the score"));
4536 gtk_widget_set_can_focus (label, FALSE);
4537 gtk_box_pack_start (GTK_BOX (Denemo.audio_vol_control), label, FALSE, TRUE, 0);
4538
4539 audio_vol_adj = (GtkAdjustment *) gtk_adjustment_new (1.0, 1.0, 10.0, 0.5, 2.0, 0.0);
4540
4541 hscale = gtk_hscale_new (GTK_ADJUSTMENT (audio_vol_adj));
4542 gtk_scale_set_digits (GTK_SCALE (hscale), 2);
4543 gtk_widget_set_can_focus (hscale, FALSE);
4544 //GTK_WIDGET_UNSET_FLAGS(hscale, GTK_CAN_FOCUS);
4545 g_signal_connect (G_OBJECT (audio_vol_adj), "value_changed", G_CALLBACK (audio_volume_boost), NULL);
4546 gtk_box_pack_start (GTK_BOX (Denemo.audio_vol_control), hscale, TRUE, TRUE, 0);
4547 label = gtk_label_new (_("Audio Lead In "));
4548 gtk_widget_set_can_focus (label, FALSE);
4549 gtk_box_pack_start (GTK_BOX (Denemo.audio_vol_control), label, FALSE, TRUE, 0);
4550 leadin = (GtkSpinButton *) gtk_spin_button_new_with_range (-2.0, 2.0, 0.01);
4551 gtk_widget_set_tooltip_text (GTK_WIDGET (label), _("Set the number of seconds to clip from the audio, or if negative number of seconds silence before audio plays.\nThis is useful when the audio track does not begin on a barline."));
4552 g_signal_connect (G_OBJECT (leadin), "value_changed", G_CALLBACK (leadin_changed), NULL);
4553 gtk_box_pack_start (GTK_BOX (Denemo.audio_vol_control), GTK_WIDGET (leadin), FALSE, TRUE, 0);
4554 //label = gtk_label_new (_(" secs."));
4555 //gtk_widget_set_can_focus (label, FALSE);
4556 //gtk_box_pack_start (GTK_BOX (Denemo.audio_vol_control), label, FALSE, TRUE, 0);
4557
4558 gtk_box_pack_start (GTK_BOX (hbox), Denemo.audio_vol_control, TRUE, TRUE, 0);
4559
4560 #ifdef _HAVE_RUBBERBAND_
4561 /* Speed */
4562 label = gtk_label_new (_("Slowdown:"));
4563 gtk_widget_set_can_focus (label, FALSE);
4564 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
4565 speed_adj = (GtkAdjustment *) gtk_adjustment_new (1.0, 1.0, 4.0, 0.01, 0.1, 0.0);
4566
4567
4568
4569 hscale = gtk_hscale_new (GTK_ADJUSTMENT (speed_adj));
4570 //gtk_scale_set_digits (GTK_SCALE (hscale), 0);
4571 gtk_widget_set_can_focus (hscale, FALSE);
4572 gtk_widget_set_tooltip_text (label, _("Slow down the audio output maintaining the pitch"));
4573 g_signal_connect (G_OBJECT (speed_adj), "value_changed", G_CALLBACK (set_speed), NULL);
4574 gtk_box_pack_start (GTK_BOX (hbox), hscale, TRUE, TRUE, 0);
4575 #endif
4576
4577
4578 }
4579
4580
4581 Denemo.midi_in_control = gtk_vbox_new (FALSE, 1);
4582 gtk_widget_set_tooltip_text (Denemo.midi_in_control,
4583 _
4584 ("Controls for managing input from a MIDI controller (e.g. keyboard) attached to the computer. You may need to select your MIDI device first using MainMenu → Edit → Change Preferences → MIDI looking for MIDI in devices (turn your device on first). When you have a MIDI controller durations are inserted without any pitch (they appear in brown) playing on the controller puts the pitches onto the durations. The Shift and Control and ALT keys can also be used for listening without entering notes, checking pitches entered and entering chords. The foot pedal can also be used for chords. Release the ALT key and re-press to start a new chord - timing is unimportant, play the chord fast or slow."));
4585 gtk_box_pack_start (GTK_BOX (outer_main_vbox), Denemo.midi_in_control, FALSE, TRUE, 0);
4586 frame = (GtkFrame *) gtk_frame_new (_("Midi In Control"));
4587 gtk_frame_set_shadow_type ((GtkFrame *) frame, GTK_SHADOW_IN);
4588 gtk_container_add (GTK_CONTAINER (Denemo.midi_in_control), GTK_WIDGET (frame));
4589
4590 inner1 = gtk_vbox_new (FALSE, 1);
4591 gtk_container_add (GTK_CONTAINER (frame), inner1);
4592 //inner = gtk_hbox_new(FALSE, 1);
4593 //gtk_box_pack_start (GTK_BOX (inner1), inner, FALSE, TRUE, 0);
4594
4595 GtkWidget *enharmonic_control = get_enharmonic_frame ();
4596 if (!gtk_widget_get_parent (enharmonic_control))
4597 gtk_container_add (GTK_CONTAINER (inner1), enharmonic_control);
4598
4599 {
4600 GtkWidget *hbox;
4601 hbox = gtk_hbox_new (FALSE, 1);
4602 gtk_box_pack_start (GTK_BOX (inner1), hbox, TRUE, TRUE, 0);
4603 GtkWidget *midi_in_button = gtk_button_new ();
4604 g_signal_connect (G_OBJECT(midi_in_button), "clicked", midi_in_menu, NULL);
4605 midi_in_status = gtk_label_new (_("Appending/Editing Pitches"));
4606 gtk_container_add(GTK_CONTAINER(midi_in_button), midi_in_status);
4607 gtk_widget_set_tooltip_text (midi_in_status, _("This tells you what will happen to a MIDI in event from your controller. Click here or use the Control Shift or ALT keys, or caps lock to affect what will happen. Moving the cursor into the display will revert to editing notes."));
4608 gtk_label_set_use_markup (GTK_LABEL (midi_in_status), TRUE);
4609 gtk_box_pack_start (GTK_BOX (hbox), midi_in_button, FALSE, TRUE, 0);
4610
4611 midiplayalongbutton =
4612 create_playbutton (hbox, _("Switch to Play Along Playback"), pb_playalong, NULL, _("When in playalong mode, on clicking Play, the music plays until it reaches the Denemo cursor\nFrom then on you must play the notes at the cursor to progress the playback.\nSo if you set the cursor on the first note of the part you want to play, then once you have pressed play you can play along with Denemo, with Denemo filling in the other parts and waiting if you play a wrong note."));
4613
4614 deletebutton = create_playbutton (hbox, "Delete", pb_midi_delete, NULL, _("Delete the MIDI recording you have made."));
4615
4616 convertbutton = create_playbutton (hbox, "Convert", pb_midi_convert, NULL, _("Convert the MIDI recording you have made to notation."));
4617 midirecordbutton = create_playbutton (hbox, NULL, pb_record, GTK_STOCK_MEDIA_RECORD, _("Starts playing and simultaneously records from MIDI in.\nOnce a recording is made it is played back with the score when you press Play.\nIt can be deleted with the Delete button or converted to notation with the Convert button.\nA MIDI recording is not saved with the Denemo score."));
4618
4619 gtk_widget_show_all (Denemo.midi_in_control);
4620 gtk_widget_show_all (Denemo.playback_control);
4621 gtk_widget_hide (deletebutton);
4622 gtk_widget_hide (convertbutton);
4623 gtk_widget_hide (exportbutton);
4624 gtk_widget_hide (Denemo.audio_vol_control);
4625 }
4626 }
4627
4628
4629 toolbar = gtk_ui_manager_get_widget (ui_manager, "/RhythmToolBar");
4630 gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_TEXT);
4631 gtk_box_pack_start (GTK_BOX (outer_main_vbox), toolbar, FALSE, TRUE, 0);
4632
4633 menubar = gtk_ui_manager_get_widget (ui_manager, "/ObjectMenu");
4634 if (menubar)
4635 {
4636 gtk_box_pack_start (GTK_BOX (outer_main_vbox), menubar, FALSE, TRUE, 0);
4637 }
4638
4639 main_hbox = gtk_hbox_new (FALSE, 1);
4640 gtk_widget_show (main_hbox);
4641 gtk_box_pack_start (GTK_BOX (outer_main_vbox), main_hbox, TRUE, TRUE, 0);
4642 Denemo.hpalettes = gtk_hbox_new (FALSE, 1);
4643 gtk_widget_show(Denemo.hpalettes);
4644 gtk_box_pack_start (GTK_BOX (main_hbox), Denemo.hpalettes, FALSE, FALSE, 0);
4645 main_vbox = gtk_vbox_new (FALSE, 1);
4646 gtk_widget_show (main_vbox);
4647 gtk_box_pack_start (GTK_BOX (main_hbox), main_vbox, TRUE, TRUE, 0);
4648
4649 Denemo.vpalettes = gtk_vbox_new (FALSE, 1);
4650 gtk_widget_show(Denemo.vpalettes);
4651 gtk_box_pack_start (GTK_BOX (main_vbox), Denemo.vpalettes, FALSE, FALSE, 0);
4652
4653 Denemo.notebook = gtk_notebook_new ();
4654 gtk_notebook_set_show_tabs (GTK_NOTEBOOK (Denemo.notebook), FALSE); //only show when more than one
4655 //gtk_notebook_popup_enable (Denemo.notebook);?? doesn't work...
4656 gtk_widget_show (Denemo.notebook);
4657 gtk_box_pack_start (GTK_BOX (main_vbox), Denemo.notebook, FALSE, FALSE, 0);
4658
4659 {
4660 Denemo.scorearea = gtk_drawing_area_new ();
4661 if (Denemo.prefs.newbie)
4662 gtk_widget_set_tooltip_text (Denemo.scorearea, _("This is the Denemo Display for the music you have entered."
4663 " See the print view window for the typeset appearance. "
4664 " The blue lozenge is the Denemo Cursor - it turns red when when the bar is full or green if you are inserting in a bar. "
4665 "Overfull/Underfull bars are colored red/blue,"
4666 " use the Upbeat (Anacrusis, Pickup) command if that is intentional."
4667 "\nYou can switch to a menu-less view or a page-view using the Esc key."
4668 " For the paged view you drag the red bar up the page to set how many systems you want showing."
4669 "For the paged view you will probably want a smaller zoom - use Control+scroll-wheel on your mouse to zoom the display."
4670 "\nMany commands operate on the object at the Denemo cursor. "
4671 "Right-click on an object to get a short menu of actions or set the mouse input mode.\n"
4672 "Shift-Right-click for more objects to insert."));
4673 #if GTK_MAJOR_VERSION == 2
4674 GtkWidget *outer_pane = gtk_vpaned_new ();
4675 #else
4676 GtkWidget *outer_pane = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
4677 #endif
4678 GtkWidget *scorearea_topbox = gtk_vbox_new (FALSE, 1);
4679 //gtk_container_add (GTK_CONTAINER (main_vbox), scorearea_topbox);
4680 gtk_box_pack_start (GTK_BOX (main_vbox), outer_pane, TRUE, TRUE, 0);
4681 gtk_paned_pack1 (GTK_PANED (outer_pane), scorearea_topbox, TRUE, FALSE);
4682 GtkWidget *score_and_scroll_hbox = gtk_hbox_new (FALSE, 1);
4683 //gtk_container_add (GTK_CONTAINER (scorearea_topbox), score_and_scroll_hbox);
4684 gtk_box_pack_start (GTK_BOX (scorearea_topbox), score_and_scroll_hbox, TRUE, TRUE, 0);
4685 gtk_widget_show (score_and_scroll_hbox);
4686
4687 gtk_box_pack_start (GTK_BOX (score_and_scroll_hbox), Denemo.scorearea, TRUE, TRUE, 0); // with this, the scorearea_draw_event is called
4688 gtk_widget_show (Denemo.scorearea);
4689 #if GTK_MAJOR_VERSION != 2
4690 g_signal_connect (G_OBJECT (Denemo.scorearea), "draw", G_CALLBACK (scorearea_draw_event), NULL);
4691 #else
4692 g_signal_connect (G_OBJECT (Denemo.scorearea), "expose_event", G_CALLBACK (scorearea_draw_event), NULL);
4693 #endif
4694 g_signal_connect (G_OBJECT (Denemo.scorearea), "configure_event", G_CALLBACK (scorearea_configure_event), NULL);
4695 g_signal_connect (G_OBJECT (Denemo.scorearea), "button_release_event", G_CALLBACK (scorearea_button_release), NULL);
4696 g_signal_connect (G_OBJECT (Denemo.scorearea), "motion_notify_event", G_CALLBACK (scorearea_motion_notify), NULL);
4697 g_signal_connect (G_OBJECT (Denemo.scorearea), "leave-notify-event", G_CALLBACK (scorearea_leave_event), NULL);
4698 g_signal_connect (G_OBJECT (Denemo.scorearea), "enter-notify-event", G_CALLBACK (scorearea_enter_event), NULL);
4699 g_signal_connect (G_OBJECT (Denemo.scorearea), "scroll_event", G_CALLBACK (scorearea_scroll_event), NULL);
4700 //g_signal_handlers_block_by_func(Denemo.scorearea, G_CALLBACK (ascorearea_motion_notify), NULL);
4701 g_signal_connect (G_OBJECT (Denemo.scorearea), "button_press_event", G_CALLBACK (scorearea_button_press), NULL);
4702 g_signal_connect (G_OBJECT (Denemo.scorearea), "key_press_event", G_CALLBACK (scorearea_keypress_event), NULL);
4703 g_signal_connect (G_OBJECT (Denemo.scorearea), "key_release_event", G_CALLBACK (scorearea_keyrelease_event), NULL);
4704
4705
4706 #if GTK_MAJOR_VERSION==2
4707 gtk_widget_add_events /*gtk_widget_set_events */ (Denemo.scorearea, (GDK_EXPOSURE_MASK |
4708 GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_ENTER_NOTIFY_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK));
4709 #else
4710 gtk_widget_add_events /*gtk_widget_set_events */ (Denemo.scorearea, (GDK_EXPOSURE_MASK | GDK_SCROLL_MASK |
4711 GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_ENTER_NOTIFY_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK));
4712 #endif
4713 Denemo.vadjustment = (GtkAdjustment *) gtk_adjustment_new (1.0, 1.0, 2.0, 1.0, 4.0, 1.0);
4714 g_signal_connect (G_OBJECT (Denemo.vadjustment), "value_changed", G_CALLBACK (vertical_scroll), NULL);
4715 Denemo.vscrollbar = gtk_vscrollbar_new (GTK_ADJUSTMENT (Denemo.vadjustment));
4716 gtk_box_pack_start (GTK_BOX (score_and_scroll_hbox), Denemo.vscrollbar, FALSE, TRUE, 0);
4717 gtk_widget_show (Denemo.vscrollbar);
4718
4719 Denemo.hadjustment = (GtkAdjustment *) gtk_adjustment_new (1.0, 1.0, 2.0, 1.0, 4.0, 1.0);
4720
4721 g_signal_connect (G_OBJECT (Denemo.hadjustment), "value_changed", G_CALLBACK (horizontal_scroll), NULL);
4722 Denemo.hscrollbar = gtk_hscrollbar_new (GTK_ADJUSTMENT (Denemo.hadjustment));
4723 gtk_box_pack_start (GTK_BOX (scorearea_topbox), Denemo.hscrollbar, FALSE, TRUE, 0);
4724 gtk_widget_show_all (outer_pane);
4725 }
4726
4727
4728 create_lilywindow ();
4729
4730 // This section creates an hbox and places it in the main vbox. Inside this hbox are placed a status bar and a label.
4731 // The status bar is not properly used within Denemo, and could just as well be a label too.
4732 Denemo.statuslabel = gtk_label_new ("");
4733 gtk_widget_set_tooltip_text (Denemo.statuslabel, _("This bar shows:\nPending ♯ or ♭ sign (if the next note entered will be sharpened or flattened)\nThe movement number\nDescription of the object at the Denemo cursor\nPosition and status (appending or inserting) of the cursor.\nIf the Playback Controls are visible then the timing of the object at the cursor is shown.\nIf MIDI in controls are visible the current enharmonic range is shown.\nWhen the first key of a two-key shortcut is pressed the possible continuations are shown here."));
4734 #if GTK_MAJOR_VERSION == 2
4735 hbox = gtk_hpaned_new ();
4736 #else
4737 hbox = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
4738 #endif
4739 gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);
4740 gtk_paned_add1 (GTK_PANED (hbox), Denemo.statuslabel);
4741 gtk_widget_show (Denemo.statuslabel);
4742 //Denemo.status_context_id = gtk_statusbar_get_context_id (GTK_STATUSBAR (Denemo.statusbar), "Denemo");
4743 //gtk_statusbar_push (GTK_STATUSBAR (Denemo.statusbar), Denemo.status_context_id, "Denemo");
4744 Denemo.input_label = gtk_label_new (_("No MIDI filter"));
4745 gtk_widget_set_tooltip_text (Denemo.input_label, _("This area shows which MIDI filters are active. It can also be used by commands to pass information to the user"));
4746 gtk_widget_show (Denemo.input_label);
4747 Denemo.input_filters = g_string_new ("");
4748 gtk_paned_add2 (GTK_PANED (hbox), Denemo.input_label);
4749 gtk_paned_set_position (GTK_PANED (hbox), 600);
4750 gtk_widget_show (hbox);
4751 // End of status bar stuff - note this is not working on Windows correctly.
4752
4753
4754 create_scheme_window ();
4755 gtk_widget_hide(gtk_ui_manager_get_widget (Denemo.ui_manager, "/MainMenu/HiddenMenu"));
4756 if (!Denemo.non_interactive)
4757 gtk_widget_show (Denemo.window);
4758 // Now that the window is shown, initialize the gcs
4759 // gcs_init (Denemo.window->window);
4760
4761 parse_paths (denemoui_path, Denemo.project);
4762 g_free (denemoui_path);
4763
4764 //set all the labels to use markup so that we can use the music font. Be aware this means you cannot use labels involving "&" "<" and ">" and so on without escaping them
4765 // FIXME labels in toolitems are not correct until you do NewWindow.
4766 // Really we should change the default for the class. */
4767 use_markup (Denemo.window);
4768 //g_debug("Turning on the modes\n");
4769
4770
4771
4772
4773
4774 g_signal_connect (G_OBJECT (Denemo.notebook), "switch_page", G_CALLBACK (switch_page), NULL);
4775
4776 } /* create window */
4777
4778
4779 void
newview(GtkAction * action,DenemoScriptParam * param)4780 newview (GtkAction * action, DenemoScriptParam * param)
4781 {
4782 newtab ();
4783 Denemo.project->movement->undo_guard = 1; //do not collect undo for initialization of score
4784 load_scheme_init ();
4785 Denemo.project->movement->undo_guard = Denemo.prefs.disable_undo;
4786 }
4787
4788 void
new_score_cb(GtkAction * action,DenemoScriptParam * param)4789 new_score_cb (GtkAction * action, DenemoScriptParam * param)
4790 {
4791 DenemoScriptParam dummy;
4792 dummy.string = NULL;
4793 if (param == NULL)
4794 param = &dummy;
4795 file_newwrapper (action, param);
4796 if (param->status)
4797 {
4798 //call_out_to_guile ("(d-InstrumentName (_ \"Unnamed\"))");
4799 // call_out_to_guile ("(d-ScoreTitle (_ \"Click Title\"))");
4800 denemo_scheme_init ();
4801 }
4802 }
4803
4804 static DenemoProject*
new_project(gboolean new_movement)4805 new_project(gboolean new_movement)
4806 {
4807 static gint id = 1;
4808 DenemoProject *project = (DenemoProject *) g_malloc0 (sizeof (DenemoProject));
4809 //uniquely identifies this musical score editor for duration of program.
4810 project->id = id++;
4811 project->mode = Denemo.prefs.mode;
4812 project->pending_midi = g_queue_new ();
4813 Denemo.projects = g_list_append (Denemo.projects, project);
4814 Denemo.project = NULL;
4815 project->lilycontrol.papersize = g_string_new ("a4"); //A4 default
4816 project->lilycontrol.staffsize = g_string_new ("18");
4817 project->lilycontrol.lilyversion = g_string_new ("");
4818 project->lilycontrol.orientation = TRUE; //portrait
4819 project->total_edit_time = 0;
4820 reset_editing_timer ();
4821 if(new_movement){
4822 Denemo.project = project;
4823 point_to_new_movement (project);
4824 project->movements = g_list_append (NULL, project->movement);
4825 }
4826
4827 return project;
4828 }
4829
4830 gint
hide_printarea_on_delete(void)4831 hide_printarea_on_delete (void)
4832 {
4833 activate_action ("/MainMenu/ViewMenu/" TogglePrintView_STRING);
4834 return TRUE;
4835 }
4836
4837 static gint
hide_score_layout_on_delete(void)4838 hide_score_layout_on_delete (void)
4839 {
4840 activate_action ("/MainMenu/ViewMenu/" ToggleScoreLayout_STRING);
4841 return TRUE;
4842 }
4843
4844 static void toggle_rhythm_toolbar (GtkAction * action, gpointer param);
4845 static void toggle_entry_toolbar (GtkAction * action, gpointer param);
4846 static void toggle_object_menu (GtkAction * action, gpointer param);
4847
4848 /* UNUSED
4849 static void toggle_main_menu (GtkAction * action, gpointer param);
4850 */
4851 static void toggle_print_view (GtkAction * action, gpointer param);
4852 static void toggle_score_layout (GtkAction * action, gpointer param);
4853 static void toggle_command_manager (GtkAction * action, gpointer param);
4854 static void toggle_scoretitles (GtkAction * action, gpointer param);
4855
4856 static void
toggle_page_view(void)4857 toggle_page_view (void)
4858 {
4859
4860 static gdouble zoom = 1.0;
4861 static gdouble system_height = 0.25;
4862 DenemoMovement *si = Denemo.project->movement;
4863 if (si->page_width == 0)
4864 {
4865 si->page_width = gdk_screen_get_width (gtk_window_get_screen (GTK_WINDOW (Denemo.window)));
4866 si->page_height = gdk_screen_get_height (gtk_window_get_screen (GTK_WINDOW (Denemo.window)));
4867 if (si->page_height / (double) si->page_width < 1.4)
4868 si->page_width = si->page_height / 1.4;
4869 si->page_zoom = 0.5;
4870 si->page_system_height = 0.25;
4871 }
4872 if (Denemo.project->view == DENEMO_PAGE_VIEW)
4873 {
4874 gtk_window_get_size (GTK_WINDOW (Denemo.window), &si->page_width, &si->page_height);
4875 si->page_zoom = si->zoom;
4876 si->page_system_height = si->system_height;
4877 si->zoom = zoom;
4878 si->system_height = system_height;
4879 Denemo.project->view = DENEMO_LINE_VIEW;
4880 gtk_window_resize (GTK_WINDOW (Denemo.window), si->stored_width, si->stored_height);
4881 }
4882 else
4883 {
4884 gtk_window_get_size (GTK_WINDOW (Denemo.window), &si->stored_width, &si->stored_height);
4885 zoom = si->zoom;
4886 system_height = si->system_height;
4887 si->zoom = si->page_zoom;
4888 si->system_height = si->page_system_height;
4889 Denemo.project->view = DENEMO_PAGE_VIEW;
4890 gtk_window_resize (GTK_WINDOW (Denemo.window), si->page_width, si->page_height);
4891 }
4892 }
4893
4894 /* Hide/show everything except the drawing area */
4895 void
toggle_to_drawing_area(gboolean show)4896 toggle_to_drawing_area (gboolean show)
4897 {
4898 if(Denemo.non_interactive)
4899 return;
4900 #define current_view Denemo.project->view
4901 gint height; // height of menus that are hidden
4902 gint win_width, win_height;
4903 height = 0;
4904
4905 if (current_view == DENEMO_LINE_VIEW)
4906 {
4907 toggle_page_view ();
4908 return;
4909 }
4910 if (current_view == DENEMO_PAGE_VIEW)
4911 {
4912 toggle_page_view ();
4913 win_width = Denemo.project->movement->stored_width;
4914 win_height = Denemo.project->movement->stored_height;
4915 }
4916 else
4917 gtk_window_get_size (GTK_WINDOW (Denemo.window), &win_width, &win_height);
4918 //g_debug("window width is %d\n", win_width);
4919 // NOTE lyrics are per movement
4920 GtkWidget *widget;
4921 gboolean hide = !show;
4922 if (((current_view == DENEMO_PAGE_VIEW) && hide) || (show && (!current_view)))
4923 return;
4924
4925 hide ? (gtk_widget_hide(Denemo.vpalettes),gtk_widget_hide(Denemo.hpalettes)):
4926 (gtk_widget_show(Denemo.vpalettes),gtk_widget_show(Denemo.hpalettes));
4927 current_view = hide ? DENEMO_LINE_VIEW : DENEMO_MENU_VIEW;
4928 #define ACCUM height += get_widget_height(widget)
4929
4930
4931 #define TOG(name, item, menu)\
4932 widget = gtk_ui_manager_get_widget (Denemo.ui_manager, name);\
4933 static gboolean item=TRUE;\
4934 if(hide)\
4935 item = gtk_widget_get_visible (widget);\
4936 if((hide && item) || (show && item))\
4937 ACCUM, activate_action(menu);
4938
4939 #define TOG2(name, item)\
4940 widget = gtk_ui_manager_get_widget (Denemo.ui_manager, name);\
4941 static gboolean item=TRUE;\
4942 if(hide)\
4943 item = gtk_widget_get_visible (widget);\
4944 if(hide && item)\
4945 ACCUM, gtk_widget_hide(widget);\
4946 if(!hide && item)\
4947 ACCUM, gtk_widget_show(widget);
4948
4949 #define TOG3(name, item, menu)\
4950 widget = name;\
4951 static gboolean item=TRUE;\
4952 if(hide) \
4953 item = gtk_widget_get_visible (widget);\
4954 if((hide && item) || (show && item))\
4955 ACCUM, activate_action(menu);
4956
4957 TOG ("/ToolBar", toolbar, "/MainMenu/ViewMenu/" ToggleToolbar_STRING);
4958 //TOG("/RhythmToolBar", rtoolbar, "/MainMenu/ViewMenu/"ToggleRhythmToolbar_STRING);
4959 TOG ("/ObjectMenu", objectmenu, "/MainMenu/ViewMenu/" ToggleObjectMenu_STRING);
4960
4961 TOG2 ("/MainMenu", mainmenu);
4962
4963 //TOG3(gtk_widget_get_parent(gtk_widget_get_parent(Denemo.printarea)), print_view, "/MainMenu/ViewMenu/"TogglePrintView_STRING);
4964 TOG3 (Denemo.project->buttonboxes, scoretitles, "/MainMenu/ViewMenu/" ToggleScoreTitles_STRING);
4965 TOG3 (Denemo.playback_control, playback_control, "/MainMenu/ViewMenu/" TogglePlaybackControls_STRING);
4966 TOG3 (Denemo.midi_in_control, midi_in_control, "/MainMenu/ViewMenu/" ToggleMidiInControls_STRING);
4967
4968 gtk_window_resize (GTK_WINDOW (Denemo.window), win_width, win_height + (current_view ? -height : height));
4969 #undef current_view
4970 }
4971
4972 void
ToggleReduceToDrawingArea(GtkAction * action,DenemoScriptParam * param)4973 ToggleReduceToDrawingArea (GtkAction * action, DenemoScriptParam * param)
4974 {
4975 GtkWidget *widget = gtk_ui_manager_get_widget (Denemo.ui_manager, "/MainMenu");
4976 gboolean visibile = gtk_widget_get_visible (widget);
4977 if (Denemo.project->view == DENEMO_MENU_VIEW && !visibile)
4978 {
4979 g_warning ("Out of step");
4980 Denemo.project->view = DENEMO_LINE_VIEW;
4981 }
4982 toggle_to_drawing_area (!gtk_widget_get_visible (widget));
4983 }
4984
4985 /**
4986 * Creates a new DenemoProject structure represented by a tab in a notebook: the DenemoProject can, at anyone time, control one musical score possibly of several movements. It can, from time to time have different musical scores loaded into it. So it is to be thought of as a Music Score Editor.
4987 * This DenemoProject* project is appended to the global list Denemo.projects.
4988 * A single movement (DenemoMovement) is instantiated in the project.
4989 *
4990 */
4991 static void
newtab(void)4992 newtab (void)
4993 {
4994 if (Denemo.project && gtk_widget_get_visible (Denemo.project->score_layout))
4995 activate_action ("/MainMenu/ViewMenu/" ToggleScoreLayout_STRING);
4996 if (Denemo.project && gtk_widget_get_visible (Denemo.textwindow))
4997 activate_action ("/MainMenu/ViewMenu/" ToggleLilyText_STRING);
4998 if (Denemo.project)
4999 visible_rhythm_buttons (Denemo.project->rhythms, FALSE);
5000 DenemoProject* project = new_project(FALSE);
5001 project->score_layout = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5002 gtk_window_set_title (GTK_WINDOW (project->score_layout), "Score Layout");
5003 gtk_window_set_default_size (GTK_WINDOW (project->score_layout), 1000, 600);
5004 g_signal_connect (G_OBJECT (project->score_layout), "delete-event", G_CALLBACK (hide_score_layout_on_delete), NULL);
5005 /* Initialize the project */
5006
5007 //create the tab for this project
5008 GtkWidget *top_vbox = gtk_vbox_new (FALSE, 1);
5009 project->buttonboxes = gtk_vbox_new (FALSE, 1);
5010 gtk_box_pack_start (GTK_BOX (top_vbox), project->buttonboxes, FALSE, TRUE, 0);
5011 project->buttonbox = gtk_hbox_new (FALSE, 1);
5012 gtk_widget_set_tooltip_text (project->buttonbox, _("A button bar that can be populated by titles and other user generated buttons.\nGenerally by clicking the button you can edit the title or value or execute the action of the button"));
5013 gtk_box_pack_start (GTK_BOX (project->buttonboxes), project->buttonbox, FALSE, TRUE, 0);
5014
5015 gtk_widget_set_can_focus (project->buttonboxes, FALSE);
5016 gtk_widget_set_can_focus (project->buttonbox, FALSE);
5017
5018 GtkWidget *main_vbox = gtk_vbox_new (FALSE, 1);
5019 gtk_box_pack_start (GTK_BOX (top_vbox), main_vbox, TRUE, TRUE, 0);
5020 gint pagenum =
5021 gtk_notebook_insert_page_menu (GTK_NOTEBOOK (Denemo.notebook), top_vbox, NULL, NULL, -1); //puts top_vbox inside Denemo.notebook
5022
5023 gtk_notebook_popup_enable (GTK_NOTEBOOK (Denemo.notebook));
5024
5025 Denemo.page = gtk_notebook_get_nth_page (GTK_NOTEBOOK (Denemo.notebook), pagenum); //note Denemo.page is suspect, it is set to the last page created and it is never unset even when that page is deleted - it is only used by the selection paste routine.
5026 gtk_notebook_set_current_page (GTK_NOTEBOOK (Denemo.notebook), pagenum);
5027
5028 Denemo.project = project;
5029 set_title_bar (project);
5030 if (pagenum)
5031 gtk_notebook_set_show_tabs (GTK_NOTEBOOK (Denemo.notebook), TRUE);
5032 set_title_bar (project);
5033 gtk_widget_show (top_vbox);
5034 gtk_widget_show (main_vbox);
5035
5036 //gtk_grab_remove(toolbar); ?????????
5037
5038 #if 0
5039 GtkWidget *hbox = gtk_hbox_new (FALSE, 1);
5040 gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);
5041 gtk_widget_show (hbox);
5042 #endif
5043
5044
5045 //FIXME populate_opened_recent_menu (project);
5046
5047 /* create the first movement now because showing the window causes it to try to draw the scorearea
5048 which it cannot do before there is a score. FIXME use signal blocking to control this - see importxml.c */
5049 point_to_new_movement (project);
5050 project->movements = g_list_append (NULL, project->movement);
5051
5052 //install_lyrics_preview (project->movement, top_vbox);
5053 gtk_widget_set_can_focus (Denemo.scorearea, TRUE);
5054 gtk_widget_show (Denemo.page);
5055 gtk_widget_grab_focus (Denemo.scorearea);
5056
5057
5058 create_singleton_rhythm ((gpointer) insert_chord_0key);
5059 create_singleton_rhythm ((gpointer) insert_chord_1key);
5060 create_singleton_rhythm ((gpointer) insert_chord_2key);
5061 create_singleton_rhythm ((gpointer) insert_chord_3key);
5062 create_singleton_rhythm ((gpointer) insert_chord_4key);
5063 create_singleton_rhythm ((gpointer) insert_chord_5key);
5064 create_singleton_rhythm ((gpointer) insert_chord_6key);
5065 create_singleton_rhythm ((gpointer) insert_chord_7key);
5066 create_singleton_rhythm ((gpointer) insert_chord_8key);
5067
5068
5069 create_singleton_rhythm ((gpointer) insert_rest_0key);
5070 create_singleton_rhythm ((gpointer) insert_rest_1key);
5071 create_singleton_rhythm ((gpointer) insert_rest_2key);
5072 create_singleton_rhythm ((gpointer) insert_rest_3key);
5073 create_singleton_rhythm ((gpointer) insert_rest_4key);
5074 create_singleton_rhythm ((gpointer) insert_rest_5key);
5075 create_singleton_rhythm ((gpointer) insert_rest_6key);
5076 create_singleton_rhythm ((gpointer) insert_rest_7key);
5077 create_singleton_rhythm ((gpointer) insert_rest_8key);
5078
5079 //Denemo.project->mode = Denemo.prefs.mode;
5080
5081 // this stops the keyboard input from getting to scorearea_keypress_event if done after attaching the signal, why?
5082 gtk_notebook_set_current_page (GTK_NOTEBOOK (Denemo.notebook), pagenum); //if this is not done Gdk-CRITICAL **: gdk_draw_drawable: assertion `GDK_IS_DRAWABLE (drawable)' failed message results. Presumably because we have failed to block the (expose_event) drawing while we set up the new page. FIXME.
5083
5084 gtk_widget_set_can_focus (Denemo.scorearea, TRUE);
5085 //GTK_WIDGET_SET_FLAGS(Denemo.scorearea, GTK_CAN_FOCUS);
5086 gtk_widget_grab_focus (GTK_WIDGET (Denemo.scorearea));
5087
5088 if (Denemo.prefs.autosave)
5089 {
5090 if (Denemo.autosaveid)
5091 {
5092 g_debug ("No autosave on new tab.");
5093 }
5094 else
5095 {
5096 Denemo.autosaveid = g_timeout_add_seconds (Denemo.prefs.autosave_timeout, (GSourceFunc) auto_save_document_timeout, Denemo.project);
5097 }
5098 }
5099
5100
5101 if (Denemo.prefs.visible_directive_buttons)
5102 {
5103 gtk_widget_hide (Denemo.project->buttonboxes);
5104 activate_action ("/MainMenu/ViewMenu/" ToggleScoreTitles_STRING);
5105 }
5106 if (have_midi () && Denemo.prefs.startmidiin)
5107 project->input_source = INPUTMIDI;
5108 panic_all (); //g_print ("Reset synth as part of newtab()\n");
5109 } /* end of newtab creating a new DenemoProject holding one musical score */
5110
5111