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, &micro);
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/RestsAppend/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