1 /* file.c
2 * License: this file may be used under the FSF GPL version 3 or later
3 * Denemo File IO
4 *
5 * for Denemo, a gtk+ frontend to GNU Lilypond
6 * (c) Adam Tee, Matthew Hiller 2000-2005
7 * (c) University of Leeds 2000-2005
8 * (c) Richard Shann 2010
9 */
10
11 #include "display/calculatepositions.h"
12 #include "command/commandfuncs.h"
13 #include "command/contexts.h"
14 #include <denemo/denemo.h>
15 #include "ui/dialogs.h"
16 #include "export/exportabc.h"
17 #include "export/exportlilypond.h"
18 #include "export/file.h"
19 #include "export/guidedimportmidi.h"
20 #include "ui/moveviewport.h"
21 #include "command/staff.h"
22 #include "command/score.h"
23 #include "core/cache.h"
24 #include "core/utils.h"
25 #include "core/exportxml.h"
26 #include "export/exportmidi.h"
27 #include "core/importxml.h"
28 #include "export/importmusicxml.h"
29 #include "importmidi.h"
30
31 #include "core/prefops.h"
32 #include "core/binreloc.h"
33 #include "core/view.h"
34 #include "command/lilydirectives.h"
35 #include "ui/texteditors.h"
36 #include "export/print.h"
37 #include <stdio.h>
38 #include <string.h>
39 #include <sys/stat.h> /* check existance and type of files */
40 #include <dirent.h> /* filter and sort filenames */
41 #include "source/source.h"
42 #include "source/sourceaudio.h"
43 #include "source/proof.h"
44 #include "audio/pitchentry.h"
45 #include "audio/audiointerface.h"
46
47 static gint file_open (DenemoProject * gui, DenemoSaveType template, ImportType type, gchar * filename);
48 static gint file_import_lilypond (DenemoProject * gui, DenemoSaveType template, ImportType type, gchar * filename);
49 static gint file_import_midi (DenemoProject * gui, DenemoSaveType template, ImportType type, gchar * filename);
50 static gint file_import_musicxml (DenemoProject * gui, DenemoSaveType template, ImportType type, gchar * filename);
51 static gboolean replace_existing_file_dialog (const gchar * filename, gint format_id);
52
53 typedef enum
54 {
55 DENEMO_FORMAT = 0,
56 DNM_FORMAT,
57 MUDELA_FORMAT,
58 PDF_FORMAT,
59 PNG_FORMAT,
60 ABC_FORMAT,
61 MIDI_FORMAT,
62 CSOUND_FORMAT,
63 MUSICXML_FORMAT
64 }
65 FileFormatNames;
66
67 struct FileFormatData
68 {
69 gchar *filename_mask;
70 gchar *description;
71 gchar *filename_extension;
72 gboolean async; /* TRUE if uses async */
73 };
74
75 /* WARNING this array has to match the FileFormatNames enum above which is used to index it!!!!!!!!!" */
76 static struct FileFormatData supported_file_formats[] = {
77 {"*.denemo", N_("Denemo XML format (*.denemo)"), ".denemo", 0},
78 {"*.dnm", N_("Denemo XML format (*.dnm)"), ".dnm", 0},
79 {"*.ly", N_("Lilypond (*.ly)"), ".ly", 0},
80 {"*.pdf", N_("PDF (*.pdf)"), ".pdf", 1},
81 {"*.png", N_("PNG Image format (*.png)"), ".png", 1},
82 {"*.abc", N_("ABC (*.abc)"), ".abc", 0},
83 {"*.mid", N_("Midi (*.mid, *.midi)"), ".mid", 0},
84 {"*.sco", N_("CSound Score File (*.sco)"), ".sco", 0},
85 {"*.mxml", N_("MusicXML file (*.mxml, *.xml)"), ".mxml", 0}
86 };
87
88 static GList*
supported_file_extensions(gchar * format)89 supported_file_extensions(gchar* format){
90 GList* exts = NULL;
91
92 if(g_strcmp0 ("denemo", format) == 0){
93 exts = g_list_append(exts, "*.denemo");
94 exts = g_list_append(exts, "*.DENEMO");
95 }
96
97 if(g_strcmp0 ("lilypond", format) == 0){
98 exts = g_list_append(exts, "*.ly");
99 exts = g_list_append(exts, "*.LY");
100 }
101
102 if(g_strcmp0 ("midi", format) == 0){
103 exts = g_list_append(exts, "*.midi");
104 exts = g_list_append(exts, "*.mid");
105 exts = g_list_append(exts, "*.MIDI");
106 exts = g_list_append(exts, "*.MID");
107 }
108
109 if(g_strcmp0 ("musicxml", format) == 0){
110 exts = g_list_append(exts, "*.mxml");
111 exts = g_list_append(exts, "*.MXML");
112 exts = g_list_append(exts, "*.xml");
113 }
114
115 if(g_strcmp0 ("pdf", format) == 0){
116 exts = g_list_append(exts, "*.pdf");
117 exts = g_list_append(exts, "*.PDF");
118 }
119 if(g_strcmp0 ("evince", format) == 0){
120 exts = g_list_append(exts, "*.pdf");
121 exts = g_list_append(exts, "*.PDF");
122 }
123 if(g_strcmp0 ("proof", format) == 0){
124 exts = g_list_append(exts, "*.pdf");
125 exts = g_list_append(exts, "*.PDF");
126 }
127 return exts;
128 }
129
130 /* Some macros just to shorten lines */
131 #define FORMAT_MASK(i) supported_file_formats[i].filename_mask
132 #define FORMAT_DESCRIPTION(i) supported_file_formats[i].description
133 #define FORMAT_EXTENSION(i) supported_file_formats[i].filename_extension
134 #define FORMAT_ASYNC(i) supported_file_formats[i].async
135
136 struct FileDialogData
137 {
138 DenemoSaveType template;
139 gint format_id;
140 };
141
142 /* directory last used for saving */
143 static gchar *file_selection_path = NULL;
144 static gchar *system_template_path = NULL;
145 static gchar *system_example_path = NULL;
146 static gchar *local_template_path = NULL;
147 static gchar *default_template_path = NULL;
148
149
150 /**
151 * Display a message box asking the user whether to save unsaved changes
152 * or close without saving
153 */
154 static gboolean
confirm_save(DenemoProject * gui,gchar * primary,gchar * secondary)155 confirm_save (DenemoProject * gui, gchar * primary, gchar * secondary)
156 {
157 if (Denemo.non_interactive)
158 return TRUE;
159 GtkWidget *dialog;
160 gboolean r = FALSE;
161
162 dialog = gtk_message_dialog_new (GTK_WINDOW (Denemo.window), (GtkDialogFlags) (GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT), GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, "%s", primary);
163 (void) gtk_dialog_add_button ((GtkDialog *) dialog, _("Close without Saving"), GTK_RESPONSE_NO);
164
165 (void) gtk_dialog_add_button ((GtkDialog *) dialog, _("_Cancel"), GTK_RESPONSE_CANCEL);
166
167 (void) gtk_dialog_add_button ((GtkDialog *) dialog, _("Save _As"), GTK_RESPONSE_YES);
168
169 gtk_dialog_set_default_response ((GtkDialog *) dialog, GTK_RESPONSE_YES);
170
171 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", secondary);
172 gtk_widget_show_all (dialog);
173 gint response = gtk_dialog_run (GTK_DIALOG (dialog));
174
175 if (response == GTK_RESPONSE_YES)
176 {
177 gtk_widget_destroy (dialog);
178 file_saveas (SAVE_NORMAL);
179 if (gui->notsaved)
180 r = FALSE;
181 else
182 r = TRUE;
183 }
184 else if (response == GTK_RESPONSE_NO)
185 {
186 gtk_widget_destroy (dialog);
187 r = TRUE;
188 }
189 else
190 {
191 gtk_widget_destroy (dialog);
192 r = FALSE;
193 }
194 return r;
195 }
196
197 /**
198 * Display a message box asking the user to confirm that unsaved
199 * changes will be lost
200 * @return TRUE if the OK button clicked or Enter pressed
201 */
202 gboolean
confirmbox(DenemoProject * gui)203 confirmbox (DenemoProject * gui)
204 {
205 gboolean ret;
206 gchar *primary = g_strdup_printf (_("The score %s has unsaved changes"), gui->filename->len ? gui->filename->str : _("(Untitled)"));
207 ret = confirm_save (gui, primary, _("Save changes?"));
208 g_free (primary);
209 return ret;
210 }
211
212 /**
213 * Custom function to compare the elements of the History queue
214 * it simply wraps up stcmp
215 *
216 * @param a pointer to a queue elements
217 * @param b pointer to the comparison value
218 * @return gint 0 if match -1 or 1 otherwise
219 */
220 static gint
history_compare(gconstpointer a,gconstpointer b)221 history_compare (gconstpointer a, gconstpointer b)
222 {
223 return (strcmp ((gchar *) a, (gchar *) b));
224 }
225
226
227 /**
228 * Callback for the history menu
229 * opens the selected file
230 */
231 void
openrecent(G_GNUC_UNUSED GtkWidget * widget,gchar * filename)232 openrecent (G_GNUC_UNUSED GtkWidget * widget, gchar * filename)
233 {
234 DenemoProject *gui = Denemo.project;
235 if (!gui->notsaved || (gui->notsaved && confirmbox (gui)))
236 {
237 // deletescore(NULL, gui);
238 if (open_for_real (filename, gui, FALSE, FALSE))
239 {
240 gchar *warning = g_strdup_printf (_("Load of recently used file %s failed"), filename);
241 warningdialog (warning);
242 g_free (warning);
243 }
244 }
245 }
246
247 /**
248 * Decorate the window with the tile
249 */
250 static void
set_gui_tabname(DenemoProject * gui,gchar * filename)251 set_gui_tabname (DenemoProject * gui, gchar * filename)
252 {
253 if(gui->tabname==NULL)
254 gui->tabname = g_string_new (filename);
255 else
256 g_string_assign (gui->tabname, filename);
257 if(!Denemo.non_interactive)
258 set_title_bar (gui);
259 }
260
261 /**
262 * Sets the filename for storing the passed in gui.
263 * and adds it to the history
264 */
265 static void
set_project_filename(DenemoProject * gui,gchar * filename)266 set_project_filename (DenemoProject * gui, gchar * filename)
267 {
268 GList *link = NULL;
269 g_string_assign (gui->filename, filename);
270 set_gui_tabname (gui, filename);
271
272 if ((link = g_queue_find_custom (Denemo.prefs.history, gui->filename->str, &history_compare)))
273 g_queue_remove (Denemo.prefs.history, link->data);
274
275 g_debug ("max history now %d\n", Denemo.prefs.maxhistory);
276 if (g_queue_get_length (Denemo.prefs.history) > Denemo.prefs.maxhistory)
277 {
278 gpointer data = g_queue_pop_head (Denemo.prefs.history);
279 g_debug ("Losing one history");
280 if (data)
281 g_free (data);
282 }
283 if(!Denemo.non_interactive){
284 if (link) /* not a new one */
285 addhistorymenuitem (filename);
286 }
287 g_queue_push_tail (Denemo.prefs.history, g_strdup (gui->filename->str));
288 }
289
290 static gchar *
strip_path_and_extension(gchar * filename)291 strip_path_and_extension (gchar * filename)
292 {
293 gchar *basename;
294 basename = g_path_get_basename (filename);
295 (void) strtok (basename, ".");
296 return basename;
297 }
298
299 static void
update_file_selection_path(gchar * file)300 update_file_selection_path (gchar * file)
301 {
302 if (file_selection_path)
303 g_free (file_selection_path);
304 file_selection_path = g_path_get_dirname (file);
305 }
306
307 gint
lyinput(gchar * filename)308 lyinput (gchar * filename)
309 {
310 gchar *path = g_path_get_dirname (filename);
311 gchar *base = g_path_get_basename (filename);
312 #ifdef G_OS_WIN32
313 gchar *call = g_strescape (path, "");
314 call = g_strdup_printf ("%s%s%s%s%s", "(debug-set! stack 200000) (lyimport::load-file \"", call, "\\\\\" \"", base, "\")");
315 g_debug ("Calling %s\n", call);
316 #else
317 gchar *call = g_strdup_printf ("%s%s%c%s%s%s", "(lyimport::load-file \"", path, G_DIR_SEPARATOR, "\" \"", base, "\")");
318 #endif
319
320
321 call_out_to_guile (call);
322 g_free (path);
323 g_free (base);
324 g_free (call);
325 return 0;
326 }
327
328 static gboolean
exists(gchar * filename,const gchar * extension)329 exists(gchar* filename, const gchar* extension)
330 {
331 return (strcmp (filename + strlen (filename) - strlen(extension), extension) == 0);
332 }
333
delete_all_rhythms(void)334 static void delete_all_rhythms (void)
335 {
336 DenemoProject *project = Denemo.project;
337 GList *g;
338 for (g = project->rhythms;g;g=project->rhythms)
339 {
340 delete_rhythm_pattern (g->data);
341 }
342 }
enquire_rhythms(void)343 static void enquire_rhythms (void) {
344 if (Denemo.project->rhythms && choose_option (_("Music Snippets Can be Kept"), _("Drop Music Snippets"), _("Keep Music Snippets")))
345 delete_all_rhythms ();
346 }
347 /**
348 * The function that actually determines the file type and calls the
349 * function that opens the file. (So many layers of indirection...)
350 *filename must be full path
351 * @return 0 for success non zero for failure
352 */
353 gint
open_for_real(gchar * filename,DenemoProject * gui,DenemoSaveType template,ImportType type)354 open_for_real (gchar * filename, DenemoProject * gui, DenemoSaveType template, ImportType type)
355 {
356 if(!Denemo.non_interactive)
357 g_signal_handlers_block_by_func (G_OBJECT (Denemo.scorearea), G_CALLBACK (scorearea_draw_event), NULL);
358 gint result;
359 gboolean xml = FALSE;
360 result = 1; //FAILURE
361 if (type == REPLACE_SCORE)
362 {
363 if(Denemo.non_interactive)
364 delete_all_rhythms ();
365 else
366 enquire_rhythms ();
367 }
368 if (g_file_test (filename, G_FILE_TEST_EXISTS))
369 {
370 if (exists (filename, ".denemo") || exists (filename, ".dnm"))
371 xml = TRUE, result = importXML (filename, gui, type);
372 else if (exists (filename, ".ly"))
373 result = lyinput (filename);
374 else if (exists (filename, ".mxml") || exists (filename, ".xml"))
375 result = mxmlinput (filename);
376 else if (exists (filename, ".mid") || exists (filename, ".midi"))
377 result = (type==GUIDED_IMPORT)?guidedImportMidi (filename):importMidi (filename);
378 else if (exists (filename, ".pdf") || exists (filename, ".PDF"))
379 {
380 #ifndef USE_EVINCE
381 g_debug("This feature requires denemo to be built with evince");
382 #else
383 // a .pdf file for transcribing from, does not affect the current score.
384 g_signal_handlers_unblock_by_func (G_OBJECT (Denemo.scorearea), G_CALLBACK (scorearea_draw_event), NULL);
385 return type==PROOFREAD? (!open_proofread_file(filename)) : !open_source (filename, 0, 0, 0);
386 #endif
387 }
388 g_message("Opening file %s", filename);
389 }
390 //printf("\nResult == %d type == %d template == %d xml == %d\n",result,type,template,(int)xml);
391 if (result == 0)
392 {
393 if (!template)
394 { // not a template
395 update_file_selection_path (filename);
396 if (type == REPLACE_SCORE)
397 {
398 if (xml){
399 set_project_filename (gui, filename);
400 }
401 else
402 {
403 gchar *sname = strip_path_and_extension (filename);
404 set_gui_tabname (gui, sname);
405 g_free (sname);
406 }
407 }
408 if (type == ADD_STAFFS || type == ADD_MOVEMENTS)
409 score_status (gui, TRUE);
410 }
411 else
412 {
413 g_string_assign (gui->filename, "");
414 set_gui_tabname (gui, "");
415 }
416 //if (Denemo.printarea)
417 // g_object_set_data (G_OBJECT (Denemo.printarea), "printviewupdate", (gpointer) G_MAXUINT);
418 if (!xml)
419 updatescoreinfo (gui);
420 else
421 {
422 if ((gui->script) && !(type == ADD_STAFFS || type == ADD_MOVEMENTS))
423 {
424 gui->has_script = TRUE;
425 cache_all ();
426 executeScript ();
427 }
428 }
429 set_rightmeasurenum (gui->movement);
430 select_lyrics ();
431
432 if(!Denemo.non_interactive){
433 set_bottom_staff (gui);
434 update_hscrollbar (gui);
435 update_vscrollbar (gui);
436 draw_score_area();
437 g_signal_emit_by_name (G_OBJECT (Denemo.hadjustment), "changed");
438 g_signal_emit_by_name (G_OBJECT (Denemo.vadjustment), "changed");
439 force_lily_refresh (gui);
440 }
441 }
442 else /*file load failed - gui may not be valid */
443 {
444 if(!Denemo.non_interactive)
445 deletescore (NULL, gui);
446 }
447 if(!Denemo.non_interactive){
448 g_signal_handlers_unblock_by_func (G_OBJECT (Denemo.scorearea), G_CALLBACK (scorearea_draw_event), NULL);
449 gui->movement->undo_guard = 1;
450 }
451 denemo_scheme_init (); //to re-instate any user defined directives for whole score
452 if(!Denemo.non_interactive){
453 if (!(type == ADD_STAFFS || type == ADD_MOVEMENTS))
454 score_status (gui, FALSE);
455 rewind_audio ();
456 panic_all ();// g_print ("Reset synth in file open\n");
457 gui->movement->undo_guard = Denemo.prefs.disable_undo; //user pref to (dis)allow undo information to be collected
458 }
459
460 return result;
461 }
462
463 /*
464 If the filename format already has the correct extension use
465 it. otherwise add the file name extension
466 */
467 static gchar *
create_filename(const gchar * file_name,gint format_id)468 create_filename (const gchar * file_name, gint format_id)
469 {
470 if (g_pattern_match_simple (FORMAT_MASK (format_id), file_name))
471 return (g_strdup (file_name));
472 else
473 return (g_strconcat (file_name, FORMAT_EXTENSION (format_id), NULL));
474 }
475
476 /*
477 This is used to strip the extension (if it exists) off of ASYNC file types.
478 */
479 static gchar *
strip_filename_ext(const gchar * file_name,gint format_id)480 strip_filename_ext (const gchar * file_name, gint format_id)
481 {
482 gchar *ext = strrchr (file_name, '.');
483 if (ext == NULL)
484 return g_strdup (file_name);
485 gint i;
486 GString *file_name_stripped = g_string_new ("");
487 gint filename_size = strlen (file_name);
488 gint ext_size = strlen (FORMAT_EXTENSION (format_id));
489 if (strlen (ext) != ext_size)
490 return g_strdup (file_name);
491 gint stripped_filename_size = filename_size - ext_size;
492 for (i = 0; i < stripped_filename_size; i++)
493 {
494 g_string_append_c (file_name_stripped, file_name[i]);
495 }
496 printf ("\nTruncated filename == %s\n", file_name_stripped->str);
497 return g_string_free (file_name_stripped, FALSE);
498 }
499
500 /* Save gui in the file in format format_id to the file filename (or gui->filename
501 if filename is NULL)
502 If there is a scheme script, offers to save that with the file.
503 */
504 static gint
save_in_format(gint format_id,DenemoProject * gui,gchar * filename)505 save_in_format (gint format_id, DenemoProject * gui, gchar * filename)
506 {
507 gint ret = 0;
508 gchar *file = filename ? filename : gui->filename->str;
509 switch (format_id)
510 {
511 case DENEMO_FORMAT:
512 case DNM_FORMAT:
513 {
514 /* HERE examine Denemo.Script and
515 * if present ask it it should be
516 * saved with the file, if not
517 * delete the script.
518 */
519
520 if (!Denemo.non_interactive && (!gui->has_script) && getNumCharsSchemeText ())
521 if (!confirm (_("You have a Script defined"), _("Use this script every time this file is opened?")))
522 {
523 deleteSchemeText ();
524 }
525 ret = exportXML (file, gui);
526 break;
527 };
528 case MUDELA_FORMAT:
529 {
530 gui->movement->markstaffnum = 0;
531 exportlilypond (file, gui, TRUE);
532 break;
533 };
534 case PDF_FORMAT:
535 {
536 gui->movement->markstaffnum = 0;
537 export_pdf (file, gui);
538 break;
539 };
540 case PNG_FORMAT:
541 {
542 gui->movement->markstaffnum = 0;
543 export_png (file, (GChildWatchFunc) printpng_finished, gui);
544 break;
545 };
546 case ABC_FORMAT:
547 {
548 exportabc (file, gui, 0, 0);
549 break;
550 };
551 case MIDI_FORMAT:
552 {
553 exportmidi (file, gui->movement);
554 break;
555 };
556 default:
557 break;
558 };
559 return ret;
560 }
561
562 /**
563 * File save called by fileselsave callback
564 * param file_name is full path to file possibly with extension
565 */
566 static gint
filesel_save(DenemoProject * gui,const gchar * file_name,gint format_id,DenemoSaveType template)567 filesel_save (DenemoProject * gui, const gchar * file_name, gint format_id, DenemoSaveType template)
568 {
569 gint ret = 0;
570 //g_assert (gui != NULL);
571 //g_assert (file_name != NULL);
572 //g_assert (format_id >= 0 && format_id < (int) G_N_ELEMENTS (supported_file_formats));
573
574 // Append file extension if needed
575 gchar *file = NULL;
576 gchar *basename = NULL;
577 file = create_filename (file_name, format_id);
578 if (!template && format_id == DENEMO_FORMAT)
579 {
580 update_file_selection_path (file);
581 if(!Denemo.non_interactive)
582 set_project_filename (gui, file);
583 }
584 basename = g_path_get_basename (file);
585 if (basename[0] != '.') // avoids empty filename
586 {
587 if (FORMAT_ASYNC (format_id))
588 ret = save_in_format (format_id, gui, strip_filename_ext (file_name, format_id)); //FIXME strip_filename is not freed
589 else
590 ret = save_in_format (format_id, gui, file);
591
592 /*export parts as lilypond files */
593 if (Denemo.prefs.saveparts)
594 export_lilypond_parts (file, gui);
595 if(!Denemo.non_interactive)
596 gui->movement->readonly = FALSE;
597 }
598 g_free (basename);
599 g_free (file);
600 return ret;
601 }
602
603 /* set local_template_path up */
604 static void
init_local_path(void)605 init_local_path (void)
606 {
607 local_template_path = g_build_filename (get_user_data_dir (TRUE), "templates", NULL);
608 gboolean err = g_mkdir_with_parents (local_template_path, 0770);
609 if (err)
610 {
611 warningdialog (_("Could not create .denemo/templates for you personal templates"));
612 g_free (local_template_path);
613 local_template_path = NULL;
614 }
615 }
616
617 typedef enum
618 {
619 LOCAL,
620 SYSTEM,
621 EXAMPLE
622 } TemplateType;
623
624 /*
625 * Sets the file_selection_path to the templates directory and
626 * calls file_open to create the file selection dialog
627 * LOCAL whether to use the local templates or systemwide templates or examples
628 * does nothing if unable to access templates
629 * filename is NULL for interactive use, otherwise file base name
630 */
631 static gint
template_open(DenemoProject * gui,TemplateType local,gchar * filename)632 template_open (DenemoProject * gui, TemplateType local, gchar * filename)
633 {
634 gboolean ret = FALSE;
635 if (local == LOCAL)
636 {
637 if (local_template_path == NULL)
638 {
639 init_local_path ();
640 }
641 default_template_path = local_template_path;
642 }
643 else if (local == EXAMPLE)
644 {
645 if (system_example_path == NULL)
646 {
647 system_example_path = g_build_filename (get_system_data_dir (), "..", "examples", "denemo", NULL);
648 GDir *denemo_path = g_dir_open (system_example_path, 0, NULL);
649 if (denemo_path == NULL)
650 {
651 warningdialog (_("No examples directory in installation"));
652 system_example_path = NULL;
653 }
654 }
655 default_template_path = system_example_path;
656 }
657 else
658 {
659 if (system_template_path == NULL)
660 {
661 system_template_path = g_build_filename (get_system_data_dir (), "templates", NULL);
662 GDir *denemo_path = g_dir_open (system_template_path, 0, NULL);
663 if (denemo_path == NULL)
664 {
665 warningdialog (_("No templates directory in installation"));
666 system_template_path = NULL;
667 }
668 }
669 default_template_path = system_template_path;
670 }
671 if (default_template_path)
672 {
673 gchar *filepath = g_build_filename (default_template_path, filename, NULL);
674 ret = file_open (gui, TRUE, REPLACE_SCORE, filepath);
675 g_free (filepath);
676 gui->filename = g_string_new ("");
677 gui->tabname = g_string_new ("");
678 }
679 return ret;
680 }
681
682 static void
open_with_check(TemplateType dir,GtkAction * action,DenemoScriptParam * param)683 open_with_check(TemplateType dir, GtkAction * action, DenemoScriptParam * param){
684 GET_1PARAM(action, param, filename);
685 if (Denemo.project->notsaved){
686 if (filename==NULL && confirmbox (Denemo.project)){
687 param->status = !template_open (Denemo.project, dir, filename);
688 }
689 }
690 else{
691 param->status = !template_open (Denemo.project, dir, filename);
692 }
693 }
694
695 /*
696 * Open system template file callback function
697 */
698 void
system_template_open_with_check(GtkAction * action,DenemoScriptParam * param)699 system_template_open_with_check (GtkAction * action, DenemoScriptParam * param)
700 {
701 open_with_check (SYSTEM, action, param);
702 }
703
704 /*
705 * Open system template file callback function
706 */
707 void
system_example_open_with_check(GtkAction * action,DenemoScriptParam * param)708 system_example_open_with_check (GtkAction * action, DenemoScriptParam * param)
709 {
710 open_with_check (EXAMPLE, action, param);
711 }
712
713 /*
714 * Open local template file callback function
715 */
716 void
local_template_open_with_check(GtkAction * action,DenemoScriptParam * param)717 local_template_open_with_check (GtkAction * action, DenemoScriptParam * param)
718 {
719 open_with_check (LOCAL, action, param);
720 }
721
722 /**
723 * Wrapper function for opening a file, d-Open
724 * if no param checks to see if current score has changed and prompts user to save
725 * otherwise opens the file
726 */
727 void
file_open_with_check(GtkAction * action,DenemoScriptParam * param)728 file_open_with_check (GtkAction * action, DenemoScriptParam * param)
729 {
730 GET_1PARAM (action, param, filename);
731 if (query)
732 {
733 param->status = (Denemo.project->filename != NULL) && Denemo.project->filename->len;
734 if (param->status)
735 g_string_assign (param->string, Denemo.project->filename->str);
736 return;
737 }
738 DenemoProject *gui = Denemo.project;
739 if (!gui->notsaved || (gui->notsaved && (confirmbox (gui))))
740 {
741 param->status = !file_open (gui, FALSE, REPLACE_SCORE, filename);
742 }
743 }
744
745 void
file_import_lilypond_with_check(GtkAction * action,DenemoScriptParam * param)746 file_import_lilypond_with_check (GtkAction * action, DenemoScriptParam * param)
747 {
748 GET_1PARAM(action, param, filename);
749 param->status = !file_import_lilypond (Denemo.project, FALSE, REPLACE_SCORE, filename);
750 }
751
752 void
file_import_midi_with_check(GtkAction * action,DenemoScriptParam * param)753 file_import_midi_with_check (GtkAction * action, DenemoScriptParam * param)
754 {
755 GET_2PARAMS(action, param, filename, guided);
756 if(guided)
757 file_import_midi (Denemo.project, FALSE, GUIDED_IMPORT, filename);
758 else
759 file_import_midi (Denemo.project, FALSE, REPLACE_SCORE, filename);
760 }
761
762 void
file_import_musicxml_with_check(GtkAction * action,DenemoScriptParam * param)763 file_import_musicxml_with_check (GtkAction * action, DenemoScriptParam * param)
764 {
765 GET_1PARAM(action, param, filename);
766 param->status = !file_import_musicxml (Denemo.project, FALSE, REPLACE_SCORE, filename);
767 }
768
769 #define ADD(insertion_strategy)\
770 GET_1PARAM(action, param, filename);\
771 (void)signal_structural_change(Denemo.project);\
772 param->status = !file_open(Denemo.project, FALSE, insertion_strategy, filename);\
773 score_status(Denemo.project, TRUE);\
774
775 /**
776 * Wrapper function for opening a file to add movements to the current score
777 *
778 */
779 void
file_add_movements(GtkAction * action,DenemoScriptParam * param)780 file_add_movements (GtkAction * action, DenemoScriptParam * param)
781 {
782 ADD (ADD_MOVEMENTS)}
783
784 /**
785 * Wrapper function for opening a file to add staffs to the current movement
786 *
787 */
788 void
file_add_staffs(GtkAction * action,DenemoScriptParam * param)789 file_add_staffs (GtkAction * action, DenemoScriptParam * param)
790 {
791 ADD (ADD_STAFFS)}
792
793 static void
set_current_folder(GtkWidget * file_selection,DenemoSaveType template)794 set_current_folder (GtkWidget * file_selection, DenemoSaveType template)
795 {
796 gchar *path, *fallback;
797 if (template == SAVE_TEMPLATE)
798 {
799 fallback = path = default_template_path;
800 }
801 else
802 {
803 fallback = path = file_selection_path;
804 GDir *denemo_path = g_dir_open (Denemo.prefs.denemopath->str, 0, NULL);
805 if (denemo_path != NULL)
806 {
807 g_dir_close (denemo_path);
808 fallback = Denemo.prefs.denemopath->str;
809 }
810 }
811 if (path != NULL)
812 {
813 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (file_selection), path);
814 }
815 else
816 {
817 if (fallback != NULL)
818 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (file_selection), fallback);
819 }
820 }
821
822 gchar *
file_dialog(gchar * message,gboolean type,gchar * location)823 file_dialog (gchar * message, gboolean type, gchar * location)
824 {
825 GtkWidget *file_selection;
826 gchar *filename;
827 file_selection = gtk_file_chooser_dialog_new (message, GTK_WINDOW (Denemo.window), type ? GTK_FILE_CHOOSER_ACTION_OPEN : GTK_FILE_CHOOSER_ACTION_SAVE, _("_Cancel"), GTK_RESPONSE_REJECT, type ? _("_Open") : _("_Save"), GTK_RESPONSE_ACCEPT, NULL);
828
829 if (location)
830 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (file_selection), location);
831 gtk_dialog_set_default_response (GTK_DIALOG (file_selection), GTK_RESPONSE_ACCEPT);
832 gtk_widget_show_all (file_selection);
833 if (gtk_dialog_run (GTK_DIALOG (file_selection)) == GTK_RESPONSE_ACCEPT)
834 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (file_selection));
835 else
836 filename = NULL;
837 gtk_widget_destroy (file_selection);
838 return filename;
839 }
840
841 static void
update_preview_cb(GtkFileChooser * file_chooser,gpointer data)842 update_preview_cb (GtkFileChooser * file_chooser, gpointer data)
843 {
844 #ifndef USE_EVINCE
845 g_debug("This feature requires denemo to be built with evince");
846 #else
847 GtkWidget *preview = NULL;
848 gchar *thumb_filename = NULL;
849 gchar *selection_filename = NULL;
850 GdkPixbuf *pixbuf = NULL;
851 gboolean have_preview = FALSE;
852
853 preview = GTK_WIDGET (data);
854 selection_filename = gtk_file_chooser_get_preview_filename (file_chooser);
855 thumb_filename = large_thumbnail_name (selection_filename);
856 pixbuf = gdk_pixbuf_new_from_file_at_size (thumb_filename, 512, 512, NULL);
857 have_preview = (pixbuf != NULL);
858 g_debug ("\n# %s for %s thumbnail = %s\n", have_preview ? "We have a thumbnail generated" : "We have not yet generated a thumbnail", selection_filename, thumb_filename);
859 g_free (selection_filename);
860 g_free (thumb_filename);
861
862 gtk_image_set_from_pixbuf (GTK_IMAGE (preview), pixbuf);
863 if (pixbuf)
864 g_object_unref (pixbuf);
865
866 gtk_file_chooser_set_preview_widget_active (file_chooser, have_preview);
867 #endif
868 }
869
870 static gboolean
file_open_dialog(gchar * message,gchar * format,FileFormatNames save_type,DenemoSaveType template,ImportType type,gchar * filename)871 file_open_dialog(gchar* message, gchar* format, FileFormatNames save_type, DenemoSaveType template, ImportType type, gchar* filename){
872 gboolean ret = -1;
873 if(filename && (!g_file_test(filename, G_FILE_TEST_EXISTS)) && (!g_path_is_absolute (filename)) && file_selection_path)
874 filename = g_build_filename (file_selection_path, filename, NULL);//memory leak
875
876 if(filename && !g_file_test(filename, G_FILE_TEST_IS_DIR))
877 return (open_for_real(filename, Denemo.project, template, type));
878
879 GtkWidget *file_selection;
880 GtkFileFilter *filter;
881 gint i;
882
883
884 file_selection = gtk_file_chooser_dialog_new (_(message),
885 GTK_WINDOW (Denemo.window),
886 GTK_FILE_CHOOSER_ACTION_OPEN,
887 _("_Cancel"),
888 GTK_RESPONSE_REJECT,
889 _("_Open"),
890 GTK_RESPONSE_ACCEPT, NULL);
891 /* Open in passed in directory or the last visited directory, if any, or a default depending on template. */
892 if (filename && g_file_test(filename, G_FILE_TEST_IS_DIR))
893 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (file_selection), filename);
894 else
895 set_current_folder(file_selection, template);
896
897 filter = gtk_file_filter_new ();
898 gtk_file_filter_set_name (filter, FORMAT_DESCRIPTION(save_type));
899
900 GList* exts = supported_file_extensions (format);
901 GList* cur = NULL;
902 for (cur = exts; cur; cur = cur->next)
903 gtk_file_filter_add_pattern (filter, cur->data);
904 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (file_selection), filter);
905 gtk_dialog_set_default_response (GTK_DIALOG (file_selection),
906 GTK_RESPONSE_ACCEPT);
907 gtk_widget_show_all (file_selection);
908 GtkWidget *preview;
909 preview = gtk_image_new();
910 gtk_file_chooser_set_preview_widget(GTK_FILE_CHOOSER (file_selection), preview);
911 g_signal_connect (GTK_FILE_CHOOSER(file_selection), "update-preview",
912 G_CALLBACK (update_preview_cb), preview);
913 gtk_widget_show_all (preview);
914 if (gtk_dialog_run (GTK_DIALOG (file_selection)) == GTK_RESPONSE_ACCEPT)
915 {
916 gchar *name = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (file_selection));
917 if((ret=open_for_real (name, Denemo.project, template, type))) {
918 gchar *warning = g_strdup_printf(_("Load of file %s failed"), name);
919 warningdialog(warning);
920 g_free(warning);
921 }
922 g_free (name);
923 }
924 gtk_widget_destroy (file_selection);
925
926
927 return ret;
928 }
929
930 /**
931 * File open dialog - opened where appropriate
932 * return 0 on success non-zero on failure.
933 * filename must be full path or NULL for dialog
934 */
935 static gint
file_open(DenemoProject * gui,DenemoSaveType template,ImportType type,gchar * filename)936 file_open (DenemoProject * gui, DenemoSaveType template, ImportType type, gchar * filename)
937 {
938 return file_open_dialog ("Open", "denemo", DENEMO_FORMAT, template, type, filename);
939 }
940
941 gint
open_source_file(void)942 open_source_file (void)
943 {
944 return file_open_dialog ("Open", "evince", PDF_FORMAT, 0, SOURCE_PDF, NULL);
945 }
946 gint
open_proof_file(void)947 open_proof_file (void)
948 {
949 return file_open_dialog ("Open", "proof", PDF_FORMAT, 0, PROOFREAD, NULL);
950 }
951
952 /**
953 * Lilypond Import dialog - opened where appropriate
954 * return 0 on success non-zero on failure.
955 * filename must be full path or NULL for dialog
956 */
957 static gint
file_import_lilypond(DenemoProject * gui,DenemoSaveType template,ImportType type,gchar * filename)958 file_import_lilypond (DenemoProject * gui, DenemoSaveType template, ImportType type, gchar * filename)
959 {
960 return file_open_dialog ("Import Lilypond", "lilypond", MUDELA_FORMAT, template, type, filename);
961 }
962
963 /**
964 * Midi Import dialog - opened where appropriate
965 * return 0 on success non-zero on failure.
966 * filename must be full path or NULL for dialog
967 */
968 static gint
file_import_midi(DenemoProject * gui,DenemoSaveType template,ImportType type,gchar * filename)969 file_import_midi (DenemoProject * gui, DenemoSaveType template, ImportType type, gchar * filename)
970 {
971 return file_open_dialog ("Import Midi", "midi", MIDI_FORMAT, template, type, filename);
972 }
973
974 /**
975 * MusicXML Import dialog - opened where appropriate
976 * return 0 on success non-zero on failure.
977 * filename must be full path or NULL for dialog
978 */
979 static gint
file_import_musicxml(DenemoProject * gui,DenemoSaveType template,ImportType type,gchar * filename)980 file_import_musicxml (DenemoProject * gui, DenemoSaveType template, ImportType type, gchar * filename)
981 {
982 return file_open_dialog ("Import MusicXML", "musicxml", MUSICXML_FORMAT, template, type, filename);
983 }
984
985 /**
986 * Wrapper function to save the current file if not already
987 * saved.
988 */
989 void
file_saveaswrapper(GtkAction * action,DenemoScriptParam * param)990 file_saveaswrapper (GtkAction * action, DenemoScriptParam * param)
991 {
992 GET_1PARAM (action, param, filename);
993 DenemoProject *gui = Denemo.project;
994 if (filename == NULL)
995 {
996 file_saveas (FALSE);
997 }
998 else
999 {
1000 gint status = filesel_save (gui, filename, DENEMO_FORMAT, FALSE);
1001
1002 if(!Denemo.non_interactive){
1003 if (status == 0)
1004 score_status (gui, FALSE);
1005 force_lily_refresh (gui);
1006 }
1007 }
1008 }
1009
1010 /**
1011 * Wrapper function to save the current file as template
1012 */
1013 void
template_save(G_GNUC_UNUSED GtkAction * action,G_GNUC_UNUSED DenemoScriptParam * param)1014 template_save (G_GNUC_UNUSED GtkAction * action, G_GNUC_UNUSED DenemoScriptParam * param)
1015 {
1016 init_local_path ();
1017 default_template_path = local_template_path;
1018 file_saveas (SAVE_TEMPLATE);
1019 }
1020
1021
1022 /**
1023 * Wrapper function to save the current file as a copy
1024 */
1025 void
file_copy_save(G_GNUC_UNUSED GtkAction * action,G_GNUC_UNUSED DenemoScriptParam * param)1026 file_copy_save (G_GNUC_UNUSED GtkAction * action, G_GNUC_UNUSED DenemoScriptParam * param)
1027 {
1028 init_local_path ();
1029 file_saveas (SAVE_COPY);
1030 }
1031
1032 /**
1033 * Wrapper function for saving an existing file
1034 *
1035 */
1036 void
file_savewrapper(GtkAction * action,DenemoScriptParam * param)1037 file_savewrapper (GtkAction * action, DenemoScriptParam * param)
1038 {
1039 DenemoProject *gui = Denemo.project;
1040 GET_1PARAM (action, param, filename);
1041 if (filename) {
1042 exportXML (filename, gui);
1043 return;
1044 }
1045 if (file_save (NULL, gui))
1046 {
1047 if (action && Denemo.project->filename && Denemo.project->filename->len)
1048 {
1049 warningdialog (_("File save failed"));
1050 score_status (gui, TRUE);
1051 }
1052 else
1053 {
1054 if (param)
1055 param->status = FALSE;
1056 }
1057 }
1058 }
1059
1060 /**
1061 * if gui->filename exists saves gui to the filename based on its extension
1062 * otherwise call saveas routine
1063 */
1064 gint
file_save(GtkWidget * widget,DenemoProject * gui)1065 file_save (GtkWidget * widget, DenemoProject * gui)
1066 {
1067 gint ret;
1068 DenemoMovement *si = gui->movement;
1069 g_debug ("READONLY %d\n", si->readonly);
1070 if ((gui->filename->len == 0) /* || (si->readonly == TRUE) */ )
1071 /* No filename's been given or is opened from template */
1072 file_saveas (FALSE);
1073 else
1074 ret = save_in_format (DENEMO_FORMAT, gui, NULL);
1075
1076 /*Save parts as lilypond files */
1077 if (Denemo.prefs.saveparts)
1078 export_lilypond_parts (gui->filename->str, gui);
1079
1080 score_status (gui, FALSE);
1081 return ret;
1082 }
1083
1084 static void
file_dialog_response(GtkWidget * dialog,gint response_id,struct FileDialogData * data)1085 file_dialog_response (GtkWidget * dialog, gint response_id, struct FileDialogData *data)
1086 {
1087 DenemoProject *gui = Denemo.project;
1088 if (response_id == GTK_RESPONSE_ACCEPT)
1089 {
1090 gchar *file_name = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
1091 if (replace_existing_file_dialog (file_name, data->format_id))
1092 {
1093 gint status = filesel_save (gui, file_name, data->format_id, data->template);
1094 if (status == 0)
1095 score_status (gui, FALSE);
1096 force_lily_refresh (gui); //FIXME why is this here???
1097 }
1098 g_free (file_name);
1099 }
1100 gtk_widget_destroy (dialog);
1101 g_free (data);
1102 }
1103
1104
1105 #define FILE_SAVE_DIALOG(description, template)\
1106 GtkWidget *file_selection;\
1107 GtkFileFilter *filter;\
1108 file_selection = gtk_file_chooser_dialog_new (description,\
1109 GTK_WINDOW (Denemo.window),\
1110 GTK_FILE_CHOOSER_ACTION_SAVE,\
1111 _("_Cancel"),\
1112 GTK_RESPONSE_REJECT,\
1113 _("_Save"),\
1114 GTK_RESPONSE_ACCEPT, NULL);\
1115 /*set default folder for saving */\
1116 set_current_folder(file_selection, template?SAVE_TEMPLATE:SAVE_NORMAL);\
1117 \
1118 /* assign title */ \
1119 gchar *title = get_scoretitle();\
1120 if (title)\
1121 { \
1122 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (file_selection), title);\
1123 } \
1124 \
1125 filter = gtk_file_filter_new ();\
1126 gtk_file_filter_set_name (filter, FORMAT_DESCRIPTION(format_id));\
1127 gtk_file_filter_add_pattern (filter, FORMAT_MASK(format_id));\
1128 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (file_selection), filter);\
1129 gtk_dialog_set_default_response (GTK_DIALOG (file_selection),\
1130 GTK_RESPONSE_ACCEPT);\
1131 gtk_widget_show_all (file_selection);\
1132 struct FileDialogData *data = (struct FileDialogData *) g_malloc (sizeof (struct FileDialogData));\
1133 data->template=template;\
1134 data->format_id=format_id;\
1135 g_signal_connect(file_selection, "response", G_CALLBACK(file_dialog_response), data);
1136
1137 /**
1138 * Create file saveas dialog to enable user to export the current file to
1139 *
1140 *
1141 */
1142 static void
file_export(FileFormatNames format_id)1143 file_export (FileFormatNames format_id)
1144 {
1145 gchar *description = g_strconcat (_("Export As "), FORMAT_DESCRIPTION (format_id), NULL);
1146 DenemoSaveType template = FALSE;
1147 FILE_SAVE_DIALOG (description, template) g_free (description);
1148 }
1149
1150 /**
1151 * Create file saveas dialog to enable user to save the current file to
1152 *
1153 *
1154 */
1155 void
file_saveas(DenemoSaveType template)1156 file_saveas (DenemoSaveType template)
1157 {
1158 gint format_id = DENEMO_FORMAT;
1159 FILE_SAVE_DIALOG (_("Save As"), template)}
1160
1161 /**
1162 * Wrapper function for command New which asks to delete the current gui and on success creates an empty score
1163 *
1164 */
1165 void
file_newwrapper(GtkAction * action,DenemoScriptParam * param)1166 file_newwrapper (GtkAction * action, DenemoScriptParam * param)
1167 {
1168 DenemoScriptParam dummy;
1169 dummy.string = NULL;
1170 if (param == NULL)
1171 param = &dummy;
1172 DenemoProject *gui = Denemo.project;
1173 if(!Denemo.non_interactive)
1174 g_signal_handlers_block_by_func (G_OBJECT (Denemo.scorearea), G_CALLBACK (scorearea_draw_event), NULL);
1175 if (!Denemo.non_interactive && gui->notsaved)
1176 {
1177 if (confirmbox (gui))
1178 {
1179 enquire_rhythms ();
1180 deletescore (NULL, gui);
1181 }
1182 else
1183 {
1184 param->status = FALSE;
1185 g_signal_handlers_unblock_by_func (G_OBJECT (Denemo.scorearea), G_CALLBACK (scorearea_draw_event), NULL);
1186 return;
1187 }
1188 }
1189 else
1190 { if(Denemo.non_interactive)
1191 delete_all_rhythms ();
1192 else
1193 enquire_rhythms ();
1194 deletescore (NULL, gui);
1195 }
1196 deleteSchemeText ();
1197 gui->has_script = FALSE;
1198 set_enharmonic_position (0);
1199 // if (Denemo.printarea)
1200 // g_object_set_data (G_OBJECT (Denemo.printarea), "printviewupdate", (gpointer) G_MAXUINT);
1201 score_status (gui, FALSE);
1202 param->status = TRUE;
1203 if(!Denemo.non_interactive)
1204 g_signal_handlers_unblock_by_func (G_OBJECT (Denemo.scorearea), G_CALLBACK (scorearea_draw_event), NULL);
1205 }
1206
1207 #if 0
1208 /* open_user_default_template
1209 * open the user's standard template if there is one
1210 * @return 0 for success non zero for failure
1211 **/
1212 gint
1213 open_user_default_template (ImportType type)
1214 {
1215 gint ret = -1;
1216 gchar *filename = g_build_filename (get_user_data_dir (TRUE), "templates", "default.denemo", NULL);
1217 if (g_file_test (filename, G_FILE_TEST_EXISTS))
1218 {
1219 ret = open_for_real (filename, Denemo.project, TRUE, type);
1220 }
1221 g_free (filename);
1222 return ret;
1223 }
1224 #endif
1225
1226 /**
1227 * Creates dialog to say that the chosen filename already exists
1228 * and do you want to overwrite it.
1229 *
1230 */
1231 static gboolean
replace_existing_file_dialog(const gchar * filename,gint format_id)1232 replace_existing_file_dialog (const gchar * filename, gint format_id)
1233 {
1234 gboolean ret;
1235 gchar *file = create_filename (filename, format_id);
1236 if (!g_file_test (file, G_FILE_TEST_EXISTS))
1237 {
1238 g_free (file);
1239 return TRUE;
1240 }
1241
1242 gchar *primary = g_strdup_printf (_("A file with the name %s already exists"), file);
1243 ret = confirm (primary, _("Do you want to replace it?"));
1244
1245 g_free (file);
1246 g_free (primary);
1247 return ret;
1248 }
1249
1250
1251 /**
1252 * Save parts to individual files
1253 */
1254 void
file_savepartswrapper(GtkAction * action,DenemoScriptParam * param)1255 file_savepartswrapper (GtkAction * action, DenemoScriptParam * param)
1256 {
1257 DenemoProject *gui = Denemo.project;
1258 if (gui->filename->len == 0)
1259 {
1260 file_saveas (FALSE);
1261 }
1262
1263 export_lilypond_parts (gui->filename->str, gui);
1264 }
1265
1266
1267 static void
lilypond_selection_received(G_GNUC_UNUSED GtkClipboard * clipboard,const gchar * text,G_GNUC_UNUSED gpointer data)1268 lilypond_selection_received (G_GNUC_UNUSED GtkClipboard * clipboard, const gchar * text, G_GNUC_UNUSED gpointer data)
1269 {
1270 if (!text)
1271 {
1272 warningdialog (_("No selection text available"));
1273 return;
1274 }
1275 gchar *filename = g_build_filename (get_user_data_dir (TRUE), "denemopaste.ly", NULL);
1276 FILE *fp = fopen (filename, "w");
1277 if (fp)
1278 {
1279 fprintf (fp, "music = { %s }\n\\score {\n\\music\n\\layout {}\n}\n", text);
1280 fclose (fp);
1281 gint theclef = find_prevailing_clef (Denemo.project->movement);
1282 newview (NULL, NULL);
1283 gint fail = open_for_real (filename, Denemo.project, TRUE, REPLACE_SCORE);
1284 //thescore can be NULL after failed load....
1285 if (fail)
1286 {
1287 DenemoProject *gui = Denemo.project;
1288 //FIXME repeated code
1289 free_movements (gui);
1290 gtk_widget_destroy (Denemo.page);
1291 Denemo.projects = g_list_remove (Denemo.projects, gui);
1292 g_free (gui);
1293 warningdialog (_("Could not interpret selection as LilyPond notes"));
1294 return;
1295 }
1296 dnm_setinitialclef (Denemo.project->movement, (DenemoStaff *) Denemo.project->movement->currentstaff->data, theclef);
1297 call_out_to_guile ("(while (and (None?) (d-MoveToStaffDown)) (begin (d-MoveToStaffUp)(d-DeleteStaff)))");
1298 if (confirm (_("Paste from Selection"), _("Paste this music into your score?")))
1299 {
1300 DenemoProject *gui = Denemo.project;
1301 tohome (NULL, NULL);
1302 set_mark (NULL, NULL);
1303 toend (NULL, NULL);
1304 copywrapper (NULL, NULL);
1305 free_movements (gui);
1306 gtk_widget_destroy (Denemo.page);
1307 Denemo.projects = g_list_remove (Denemo.projects, gui);
1308 g_free (gui);
1309 pastewrapper (NULL, NULL);
1310 }
1311 }
1312 }
1313
1314 void
paste_clipboard(GtkAction * action,DenemoScriptParam * param)1315 paste_clipboard (GtkAction * action, DenemoScriptParam * param)
1316 {
1317 if (Denemo.project != g_list_last (Denemo.projects)->data)
1318 {
1319 warningdialog (_("Can only paste LilyPond text into the last tab, sorry"));
1320 return;
1321 }
1322 GtkClipboard *clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
1323 gtk_clipboard_request_text (clipboard, (GtkClipboardTextReceivedFunc) lilypond_selection_received, NULL);
1324
1325 }
1326
1327 static void
comment_selection_received(G_GNUC_UNUSED GtkClipboard * clipboard,const gchar * text)1328 comment_selection_received (G_GNUC_UNUSED GtkClipboard * clipboard, const gchar * text)
1329 {
1330 gchar *comment;
1331 GString *exceptions = g_string_new ("");
1332 gint i;
1333 for (i=0x1;i<0x10;i++)
1334 g_string_append_printf (exceptions, "%c", i);
1335 for (i=0x7F;i<0x100;i++)
1336 g_string_append_printf (exceptions, "%c", i);
1337
1338 if ((!text) || (*text == 0))
1339 {
1340 warningdialog (_("No selection text available"));
1341 return;
1342 }
1343 gchar *escaped = g_strescape(text, exceptions->str);
1344 gchar *info = g_strconcat(_("Inserted:\n"), escaped, NULL);
1345 comment = g_strdup_printf ("(d-Comment \"%s\")(d-InfoDialog \"%s\")", escaped, info);
1346 call_out_to_guile (comment);
1347 g_string_free (exceptions, TRUE);
1348 g_free (escaped);
1349 g_free (info);
1350 g_free (comment);
1351 }
1352 void
paste_comment(GtkAction * action,DenemoScriptParam * param)1353 paste_comment (GtkAction * action, DenemoScriptParam * param)
1354 {
1355 if(param && param->string && param->string->len)
1356 comment_selection_received (NULL, param->string->str);
1357 else
1358 {
1359 GtkClipboard *clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
1360 gtk_clipboard_request_text (clipboard, (GtkClipboardTextReceivedFunc) comment_selection_received, NULL);
1361 }
1362 }
1363 static void
export_interface(GtkAction * action,DenemoScriptParam * param,gint format_id)1364 export_interface(GtkAction* action, DenemoScriptParam* param, gint format_id){
1365 GET_1PARAM(action, param, filename);
1366 if (filename==NULL)
1367 file_export(format_id);
1368 else
1369 if (action==NULL || replace_existing_file_dialog(filename, format_id)){
1370 filesel_save (Denemo.project, filename, format_id, SAVE_COPY);
1371 force_lily_refresh(Denemo.project);
1372 }
1373 }
1374
1375 /**
1376 * Export mudela callback prompts for filename
1377 *
1378 */
1379 void
export_mudela_action(GtkAction * action,DenemoScriptParam * param)1380 export_mudela_action (GtkAction * action, DenemoScriptParam * param)
1381 {
1382 export_interface (action, param, MUDELA_FORMAT);
1383 }
1384
1385 /**
1386 * Export pdf callback prompts for filename
1387 *
1388 */
1389 void
export_pdf_action(GtkAction * action,DenemoScriptParam * param)1390 export_pdf_action (GtkAction * action, DenemoScriptParam * param)
1391 {
1392 export_interface (action, param, PDF_FORMAT);
1393 }
1394
1395 /**
1396 * Export pdf callback prompts for filename
1397 *
1398 */
1399 void
export_png_action(GtkAction * action,DenemoScriptParam * param)1400 export_png_action (GtkAction * action, DenemoScriptParam * param)
1401 {
1402 export_interface (action, param, PNG_FORMAT);
1403 }
1404
1405 /**
1406 * Export ABC callback prompts for filename
1407 *
1408 */
1409 void
export_ABC_action(GtkAction * action,DenemoScriptParam * param)1410 export_ABC_action (GtkAction * action, DenemoScriptParam * param)
1411 {
1412 export_interface (action, param, ABC_FORMAT);
1413 }
1414
1415 /**
1416 * Export MIDI callback prompts for filename
1417 *
1418 */
1419 void
export_midi_action(GtkAction * action,DenemoScriptParam * param)1420 export_midi_action (GtkAction * action, DenemoScriptParam * param)
1421 {
1422 export_interface (action, param, MIDI_FORMAT);
1423 }
1424