diff -urN ../denemo-cvs/denemo/src/commandfuncs.c ./src/commandfuncs.c --- ../denemo-cvs/denemo/src/commandfuncs.c 2007-07-10 01:34:42.000000000 +0100 +++ ./src/commandfuncs.c 2007-07-29 08:42:46.000000000 +0100 @@ -1,5 +1,5 @@ -/* commandfuncs.cpp - * functions invoked by user keypresses +/* commandfuncs.c + * functions invoked by user keypresses in score area * * for Denemo, a gtk+ frontend to GNU Lilypond * (c) 1999-2005 Matthew Hiller, Adam Tee @@ -25,6 +25,7 @@ #include "exportlilypond.h" #include "exportxml.h" #include "prefops.h" +#include "keyresponses.h" /** * Macro to get the current DenemoObject @@ -37,6 +38,35 @@ /** + * Move the current rhythm on to the next one + * FIXME re-arrange the list of rhythms each time as well so that it + * is easy to alternate rhythms. + */ +void nextrhythm(DenemoGUI *gui) { + if(!gui->si->rhythmicsubmode) + return; + if(gui->si->currhythm==NULL) + gui->si->currhythm = g_list_last(gui->si->rhythms); + gtk_widget_set_state(((RhythmPattern *)gui->si->currhythm->data)->button, GTK_STATE_NORMAL); + if(gui->si->currhythm->next) + gui->si->currhythm = gui->si->currhythm->next; + else + gui->si->currhythm = gui->si->rhythms; +#define g (gui->si->rstep) + g = ((RhythmPattern*)gui->si->currhythm->data)->rsteps; + + if(((RhythmElement*)g->data)->icon) { + gtk_tool_button_set_label(((RhythmPattern *)gui->si->currhythm->data)->button,((RhythmElement*)g->data)->icon); + } + gtk_widget_set_state(((RhythmPattern *)gui->si->currhythm->data)->button, GTK_STATE_PRELIGHT); + g_print("selected active\n"); +#undef g +} + + + + +/** * Helper function for calculating the * beam and stem direction */ @@ -399,16 +429,40 @@ * */ void -shiftcursor (DenemoScore * si, gint note_value) +shiftcursor (DenemoGUI *gui, gint note_value) { - gint oldstaffletter_y = si->staffletter_y; + gint oldstaffletter_y = gui->si->staffletter_y; + + gui->si->staffletter_y = note_value; + gui->si->cursor_y = jumpcursor (gui->si->cursor_y, oldstaffletter_y, + gui->si->staffletter_y); + + /* in rhytmicsubmode we insert a note using the next step of the rhythm pattern */ +#define g (gui->si->rstep) + if(gui->si->rhythmicsubmode) { + if(g) { + GList *h; + for(h = ((RhythmElement*)g->data)->functions;h;h=h->next) { + ((GtkFunction)h->data)(gui), displayhelper(gui); + } + g = g->next;/* list is circular */ + if(((RhythmElement*)g->data)->icon) { + gtk_tool_button_set_label(((RhythmPattern *)gui->si->currhythm->data)->button,((RhythmElement*)g->data)->icon); - si->staffletter_y = note_value; - si->cursor_y = jumpcursor (si->cursor_y, oldstaffletter_y, - si->staffletter_y); + } + } + } +#undef g } + /** + * badly named and incorrectly described (below) + * this is really a "find_or_create_insertion_point" function + * that is, if the current measure is full it moves into the next one + * (or creates a new one and moves into it) + * if it is not full, it does nothing. +old misleading comment: * Goto the next measure * Goto the next measure in the score. A new measure will * be created if required @@ -475,6 +529,9 @@ nextmeasure (si, FALSE); + + + /* Now actually create the chord */ mudela_obj_new = newchord (duration, 0, 0); if (mode == INPUTBLANK && (rest != TRUE)) diff -urN ../denemo-cvs/denemo/src/commandfuncs.h ./src/commandfuncs.h --- ../denemo-cvs/denemo/src/commandfuncs.h 2007-01-24 19:44:26.000000000 +0000 +++ ./src/commandfuncs.h 2007-07-17 16:20:04.000000000 +0100 @@ -52,7 +52,7 @@ cursordown (DenemoGUI *gui); void -shiftcursor (DenemoScore *si, gint note_value); +shiftcursor (DenemoGUI *gui, gint note_value); @@ -142,4 +142,8 @@ void beamandstemdirhelper (DenemoScore * si); + +void +nextrhythm(DenemoGUI *gui); + #endif /*COMMANDFUNCSH */ diff -urN ../denemo-cvs/denemo/src/denemoui.xml ./src/denemoui.xml --- ../denemo-cvs/denemo/src/denemoui.xml 2007-01-24 19:44:26.000000000 +0000 +++ ./src/denemoui.xml 2007-07-19 09:16:33.000000000 +0100 @@ -45,6 +45,7 @@ + @@ -160,4 +161,8 @@ + + + + diff -urN ../denemo-cvs/denemo/src/draw.c ./src/draw.c --- ../denemo-cvs/denemo/src/draw.c 2007-02-23 21:23:53.000000000 +0000 +++ ./src/draw.c 2007-08-03 12:55:02.000000000 +0100 @@ -395,7 +395,7 @@ redgc = gcs_redgc (); } - /* Set informagcs_redgc ();tion about the state at the current measure, + /* Set information about the state at the current measure, if necessary */ memcpy (itp->curaccs, itp->keyaccs, SEVENGINTS); diff -urN ../denemo-cvs/denemo/src/exportlilypond.c ./src/exportlilypond.c --- ../denemo-cvs/denemo/src/exportlilypond.c 2007-03-18 11:50:37.000000000 +0000 +++ ./src/exportlilypond.c 2007-08-03 12:58:13.000000000 +0100 @@ -337,7 +337,7 @@ output_figured_bass (DenemoScore * si, GString ** pfigures, chord * pchord) { GString *figures = *pfigures; - gint duration = 4; //internaltomuduration (pchord->baseduration); + gint duration = internaltomuduration (pchord->baseduration); gint numdots = pchord->numdots; GString *fig_str; /*working copy of figures string */ char *str; /* pointer into the figure string fig_str */ @@ -1390,7 +1390,7 @@ if (figures) { - fprintf (fp, "BassFiguresLine = \\context FiguredBass\n" "\\figures {\n"); + fprintf (fp, "BassFiguresLine = \\context FiguredBass\n" "\\figuremode {\n"); fprintf (fp, "%s", figures->str); fprintf (fp, " \n}\n"); } @@ -1439,7 +1439,7 @@ for (tmp = lyricsstaffs; tmp; tmp = tmp->next) { if (! strcmp (curstaffstruct->lily_name->str, (gchar *) tmp->data)) - fprintf (fp, "\n\t\t \\lyricsto %s \\new Lyrics \\%sLyrics\n", + fprintf (fp, "\n\t\t \\lyricsto %s \\context Lyrics \\%sLyrics\n", (gchar *) tmp->data, (gchar *) tmp->data); } } @@ -1449,7 +1449,6 @@ fprintf (fp, "\t\t\\%s\n", curstaffstruct->lily_name->str); } - if (si->has_figures) fprintf (fp, "\t\t\\BassFiguresLine\n"); if (context) @@ -1518,17 +1517,18 @@ } +#if 0 if (figures) { fprintf (fp, "BassFiguresLine = \\context FiguredBass\n" - "\\figures {\n" + "\\figuremode {\n" /*"\\set FiguredBass.BassFigure\n" " \\override #'font-relative-size = #-3\n" */ ); fprintf (fp, "%s", figures->str); fprintf (fp, " \n}\n"); } - +#endif @@ -1547,7 +1547,7 @@ GList *tmp; for (tmp = lyricsstaffs; tmp; tmp = tmp->next) { - fprintf (fp, "\n\t\t \\lyricsto %s \\new Lyrics \\%sLyrics\n", + fprintf (fp, "\n\t\t \\lyricsto %s \\context Lyrics \\%sLyrics\n", (gchar *) tmp->data, (gchar *) tmp->data); } diff -urN ../denemo-cvs/denemo/src/kbd-custom.c ./src/kbd-custom.c --- ../denemo-cvs/denemo/src/kbd-custom.c 2007-01-24 19:44:26.000000000 +0000 +++ ./src/kbd-custom.c 2007-07-17 16:20:04.000000000 +0100 @@ -342,6 +342,10 @@ {KBD_CATEGORY_OTHER, N_("CloseRepeat"), (GtkFunction) insert_closerepeat}, {KBD_CATEGORY_OTHER, N_("OpenCloseRepeat"), (GtkFunction) insert_opencloserepeat}, + {KBD_CATEGORY_OTHER, N_("FirstRhythm"), + (GtkFunction) nextrhythm/* temp should be edit first rhythm*/}, + {KBD_CATEGORY_OTHER, N_("NextRhythm"), + (GtkFunction) nextrhythm}, {KBD_CATEGORY_MEASURE, N_("AppendMesauresToScore"), (GtkFunction) append_measure_score} diff -urN ../denemo-cvs/denemo/src/keyresponses.c ./src/keyresponses.c --- ../denemo-cvs/denemo/src/keyresponses.c 2007-01-24 19:44:26.000000000 +0000 +++ ./src/keyresponses.c 2007-07-27 10:36:18.000000000 +0100 @@ -1,4 +1,4 @@ -/* keyresponses.cpp +/* keyresponses.c * switching station for processing user keypresses * * for Denemo, a gtk+ frontend to GNU Lilypond @@ -35,6 +35,45 @@ if ((ki = lookup_keybinding (gui->prefs->the_keymap, event->keyval, event->state))) { + + /* in rhythmicsubmode when a duration is entered set up a singleton rhythm pattern that + is just this one duration */ + if(gui->si->rhythmicsubmode) + if( + ki->func.nocallback==(gpointer)insert_chord_0key || + ki->func.nocallback==(gpointer)insert_chord_1key || + ki->func.nocallback==(gpointer)insert_chord_2key || + ki->func.nocallback==(gpointer)insert_chord_3key || + ki->func.nocallback==(gpointer)insert_chord_4key || + ki->func.nocallback==(gpointer)insert_chord_5key || + ki->func.nocallback==(gpointer)insert_chord_6key || + + ki->func.nocallback==(gpointer)insert_rest_0key || + ki->func.nocallback==(gpointer)insert_rest_1key || + ki->func.nocallback==(gpointer)insert_rest_2key || + ki->func.nocallback==(gpointer)insert_rest_3key || + ki->func.nocallback==(gpointer)insert_rest_4key || + ki->func.nocallback==(gpointer)insert_rest_5key || + ki->func.nocallback==(gpointer)insert_rest_6key) + + +{ +#define g (gui->si->rstep) + RhythmElement *relement = (RhythmElement*)g_malloc0(sizeof(RhythmElement)); + relement->functions = g_list_append(NULL, (gpointer)ki->func.callback); + if(gui->si->currhythm) { + gtk_widget_set_state(((RhythmPattern *)gui->si->currhythm->data)->button, GTK_STATE_NORMAL); + } else if(g) { + g_list_free(((RhythmElement*)g->data)->functions); + g->next = g->prev = NULL; + g_list_free(g); + } + g = g_list_append(NULL,relement); + g->next = g->prev = g; + gui->si->currhythm = NULL; /* FIXME memory leak on returning to a + rhythmic pattern on rhythm toolbar. */ + return 0; + } if (ki->callback_action == -1) ki->func.nocallback (gui); else @@ -42,8 +81,9 @@ displayhelper (gui); //gtk_signal_emit_stop_by_name(widget, "key_press_event"); //gtk_signal_emit_stop_by_name(gui->window, "key_press_event"); - //gtk_widget_draw (gui->scorearea, NULL); + gtk_widget_draw (gui->scorearea, NULL); return 1; +#undef g } return 0; } @@ -110,7 +150,7 @@ void go_to_A_key (DenemoGUI * gui) { - shiftcursor (gui->si, 5); + shiftcursor (gui, 5); } /** @@ -120,7 +160,7 @@ void go_to_B_key (DenemoGUI * gui) { - shiftcursor (gui->si, 6); + shiftcursor (gui, 6); } /** @@ -130,7 +170,7 @@ void go_to_C_key (DenemoGUI * gui) { - shiftcursor (gui->si, 0); + shiftcursor (gui, 0); } /** @@ -140,7 +180,7 @@ void go_to_D_key (DenemoGUI * gui) { - shiftcursor (gui->si, 1); + shiftcursor (gui, 1); } /** @@ -150,7 +190,7 @@ void go_to_E_key (DenemoGUI * gui) { - shiftcursor (gui->si, 2); + shiftcursor (gui, 2); } /** @@ -160,7 +200,7 @@ void go_to_F_key (DenemoGUI * gui) { - shiftcursor (gui->si, 3); + shiftcursor (gui, 3); } /** @@ -170,7 +210,7 @@ void go_to_G_key (DenemoGUI * gui) { - shiftcursor (gui->si, 4); + shiftcursor (gui, 4); } /** @@ -179,7 +219,11 @@ void octave_up_key (DenemoGUI * gui) { + if(gui->si->rhythmicsubmode) + tonechange(gui->si, TRUE); gui->si->cursor_y += 7; + if(gui->si->rhythmicsubmode) + tonechange(gui->si, FALSE); } /** @@ -188,7 +232,11 @@ void octave_down_key (DenemoGUI * gui) { + if(gui->si->rhythmicsubmode) + tonechange(gui->si, TRUE); gui->si->cursor_y -= 7; + if(gui->si->rhythmicsubmode) + tonechange(gui->si, FALSE); } /** @@ -530,6 +578,16 @@ /* And delete */ deleteobject (gui); } + /* if you are following a rhythmic pattern then backup the pattern */ + if(gui->si->rhythmicsubmode) + { +#define g (gui->si->rstep) + g = g->prev; /* list is circular - should we stop at beginning? */ + if(((RhythmElement*)g->data)->icon) { + gtk_tool_button_set_label(((RhythmPattern *)gui->si->currhythm->data)->button,((RhythmElement*)g->data)->icon); + } +#undef g + } } void diff -urN ../denemo-cvs/denemo/src/view.c ./src/view.c --- ../denemo-cvs/denemo/src/view.c 2007-07-10 01:34:43.000000000 +0100 +++ ./src/view.c 2007-07-30 13:26:52.000000000 +0100 @@ -1,4 +1,4 @@ -/* view.cpp +/* view.c * Functions to create a new view of the main window * * for Denemo, a gtk+ frontend to GNU Lilypond @@ -153,7 +153,7 @@ if (confirmbox (gui)) { file_open (NULL, gui); - } +} } else { @@ -317,6 +317,315 @@ insert_rest_4key (gui); displayhelper (gui); } +/** + * Rhythm callback toggle rhythm entry submode + * + */ +void +toggle_rhythmicsubmode(GtkCheckButton *button, DenemoGUI * gui) { + + gui->si->rhythmicsubmode = !gui->si->rhythmicsubmode; + +} + + +/** + * Rhythm callback select rhythm + * + */ +void +select_rhythm_pattern(GtkToolButton *toolbutton, RhythmPattern *r) { + r->gui->si->currhythm = g_list_find(r->gui->si->rhythms, r); + r->gui->si->rstep = r->rsteps; +#define g (r->gui->si->rstep) + if(((RhythmElement*)g->data)->icon) { + gtk_tool_button_set_label(((RhythmPattern *)r->gui->si->currhythm->data)->button,((RhythmElement*)g->data)->icon); + } + gtk_widget_set_state(GTK_WIDGET(((RhythmPattern *)r->gui->si->currhythm->data)->button), GTK_STATE_ACTIVE); + g_print("selected active\n"); + +#undef g +} + +/* duration_code(gpointer function) + * return an ascii code to indicate what duration (if any) function gives. + * '0x0' means not a duration + * chars 0123456 are the standard note durations + * + */ +gchar duration_code(gpointer fn) { + 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':0; +} +/* modifier_code(gpointer function) + * return an ascii code to indicate what modifier (if any) function gives. + * '0x0' means not a valid modifier for a rhythmic duration + * char '.' means a dotted note, '(' and ')' mean start and end slur + * r to x are rests + * others to be defined + * + */ +gchar modifier_code(gpointer fn) { + return fn==(gpointer)insert_triplet ? '~': + (gpointer)add_dot_key ? '.': + fn==(gpointer)toggle_begin_slur ? '(': + fn==(gpointer)toggle_end_slur ? ')': + fn==(gpointer)insert_rest_0key ? 'r': + fn==(gpointer)insert_rest_1key ? 's': + fn==(gpointer)insert_rest_2key ? 't': + fn==(gpointer)insert_rest_3key ? 'u': + fn==(gpointer)insert_rest_4key ? 'v': + fn==(gpointer)insert_rest_5key ? 'w': + fn==(gpointer)insert_rest_6key ? 'x':0; +} + + +/** + * Callback to translate keypresses into rhythm elements + * + */ +static gint +translate_rhythm (GtkWidget * widget, GdkEvent * event,RhythmPattern *r) +{ + KeybindingInfo *ki; + static gpointer last_data;/* for delete */ + RhythmElement *relement; + + if(r->rsteps==NULL){ + last_data = NULL; + } + +#if 0 +#define GDK_Shift_L 0xFFE1 +#define GDK_Shift_R 0xFFE2 +#define GDK_Alt_L 0xFFE9 +#define GDK_Return 0xFF0D + if (event->key.keyval == GDK_Alt_L || + event->key.keyval == GDK_Shift_L || + event->key.keyval == GDK_Shift_R || + event->key.keyval == GDK_Return + ) + return FALSE; +#endif + +#define GDK_BackSpace 0xFF08 /* to save including gdkkeysyms.h */ + if (event->key.keyval == GDK_BackSpace) { + if(r->rsteps) { + relement = (RhythmElement *)(g_list_last(r->rsteps)->data); + relement->functions = g_list_remove(relement->functions, last_data); + if(relement->functions == NULL) + r->rsteps = g_list_delete_link(r->rsteps, g_list_last(r->rsteps)); + } + return FALSE; + } + +#define GDK_Return 0xFF0D + if (event->key.keyval == GDK_Return) + return FALSE; + if ((ki = lookup_keybinding (r->gui->prefs->the_keymap, event->key.keyval, + event->key.state))) + { + g_print("keyval %d state %d cac=%d fn=%p\n", event->key.keyval, + event->key.state, ki->callback_action, ki->func.callback ); + if (ki->callback_action != -1) + return TRUE; + else + { + + event->key.state = 0; + event->key.keyval = duration_code(ki->func.callback); + if(event->key.keyval) { + relement = (RhythmElement*)g_malloc0(sizeof(RhythmElement)); + relement->functions = g_list_append(NULL, (gpointer)ki->func.callback); + r->rsteps = g_list_append(r->rsteps, relement); + last_data =(gpointer)ki->func.callback; + return FALSE; + } + event->key.keyval = modifier_code(ki->func.callback); + if(event->key.keyval) { + if(r->rsteps) { + relement = (RhythmElement *)(g_list_last(r->rsteps)->data); + } + else { + relement = (RhythmElement*)g_malloc0(sizeof(RhythmElement)); + } + relement->functions = g_list_append(relement->functions, (gpointer)ki->func.callback); + if(r->rsteps==NULL) { + r->rsteps = g_list_append(r->rsteps, relement); + } + last_data =(gpointer)ki->func.callback; + return FALSE; + } + + } + } + + return TRUE; +} + + +/* edit a rhythm pattern + */ +void +rhythm_edit ( DenemoGUI *gui, RhythmPattern *r) +{ + GtkWidget *dialog; + GtkWidget *entry; + GtkWidget *label; + + + dialog = gtk_dialog_new_with_buttons (_("Enter Rhythm"), + GTK_WINDOW (gui->window), + (GtkDialogFlags) (GTK_DIALOG_MODAL | + GTK_DIALOG_DESTROY_WITH_PARENT), + GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, + GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, + NULL); + + + label = gtk_label_new (_("Type a rhythm followed by Enter key")); + + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), label, + TRUE, TRUE, 0); + + entry = gtk_entry_new (); + + g_signal_connect (GTK_OBJECT (entry), "key_press_event", + G_CALLBACK (translate_rhythm), r); + + + + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), entry, + TRUE, TRUE, 0); + gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE); + gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT); + gtk_widget_grab_focus (entry); + gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); + gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE); + gtk_widget_show_all (dialog); + + if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) + { + const gchar *pattern = gtk_entry_get_text (GTK_ENTRY (entry)); + g_print("rsteps is %p entry is %s\n", r->rsteps, pattern); + gtk_tool_button_set_label(r->button,pattern); + /* fill the r->rsteps with icons for each step */ + GList *g; + gint i; + RhythmElement *el; + for(g=r->rsteps, i=0;g;g=g->next, i+=g_list_length(el->functions)) { + el = (RhythmElement*)g->data; + + gchar *fmt; + fmt = g_strdup_printf("%%.%ds<%c>%s",i,*(pattern+i),pattern+i+1); + g_printf("format string %s\n", fmt); + el->icon = g_strdup_printf(fmt, pattern); + g_print("el->icon = %s\n", el->icon); + g_free(fmt); + + } + /* make the list circular */ + r->rsteps->prev = g_list_last(r->rsteps); + g_list_last(r->rsteps)->next = r->rsteps; + } else + { + g_list_free(r->rsteps); + r->rsteps = NULL; + } + gtk_widget_destroy (dialog); +} + +/* + * take user input for a rhythmic pattern to be placed + * as a button on the rhythm toolbar + */ +static void +create_rhythm_cb (GtkAction * action, DenemoGUI * gui) +{ + +GSList*g = gtk_action_get_proxies(action); + if(g && g->data) { + static GtkWidget *label_widget; + if(label_widget==NULL) { + label_widget = gtk_label_new(NULL); + gtk_tool_button_set_label_widget(g->data, label_widget); + gtk_widget_show(label_widget); + } + + g_print("for %s\n", g_type_name(G_TYPE_FROM_INSTANCE(g->data))); + g_print("label is %s\n", gtk_tool_button_get_label( GTK_TOOL_BUTTON(g->data))); + + gchar *labelstr = g_strdup_printf("Create rhythm: %s", "here"); + g_print("label is %p\n",label_widget); + if(label_widget){ + g_print("edit first rhythm %p is %s", label_widget, g_type_name(G_TYPE_FROM_INSTANCE(label_widget))); + gtk_label_set_markup (GTK_LABEL (label_widget),labelstr); + } + g_free(labelstr); + } + + if(g && g->data) { + /* make one rhythm */ + RhythmPattern *r = (RhythmPattern*)g_malloc0(sizeof(RhythmPattern)); + r->gui = gui; + GtkToolButton *button = gtk_tool_button_new(NULL, NULL); + r->button = button; + rhythm_edit(gui, r); + if(r->rsteps==NULL) + { + gtk_widget_destroy(button); + g_free(r); + } else + { + GtkWidget *toolbar = gtk_widget_get_parent(g->data); + gtk_toolbar_insert(toolbar, button, -1); + gtk_widget_show(button); + gui->si->rstep = r->rsteps; + gui->si->rhythms = g_list_append(gui->si->rhythms , r); + gui->si->currhythm = g_list_last(gui->si->rhythms); + gui->si->rhythmicsubmode = gui->si->rhythms; + g_signal_connect (G_OBJECT (button), "clicked", + G_CALLBACK (select_rhythm_pattern), (gpointer)r); + } + } + +} +/* + * delete a rhythmic pattern and its button + * + */ +static void +delete_rhythm_cb (GtkAction * action, DenemoGUI * gui) +{ + if(gui->si->rhythmicsubmode == FALSE) + return; + if(gui->si->currhythm==NULL) + return; + RhythmPattern *r =(RhythmPattern *)gui->si->currhythm->data; + gtk_widget_destroy(r->button); + /* list is circular, so before we free it we have to break it */ + r->rsteps->prev->next = NULL; + r->rsteps->prev = NULL; + GList *g; + for(g=r->rsteps;g;g=g->next) + g_free(g->data); + g_list_free(r->rsteps); + g_free(r); + g_print("length %d\n", g_list_length(gui->si->rhythms)); + gui->si->rhythms = g_list_remove(gui->si->rhythms, gui->si->currhythm->data); + g_print("length %d %p\n", g_list_length(gui->si->rhythms), gui->si->rhythms); + gui->si->currhythm = g_list_last(gui->si->rhythms); + + if(gui->si->currhythm == NULL) + gui->si->rhythmicsubmode = FALSE /**/; + else + gui->si->rstep = ((RhythmPattern *)gui->si->currhythm->data)->rsteps; +} /** * Menu entries with shortcut keys, tooltips, and callback functions @@ -516,7 +825,14 @@ G_CALLBACK (insert_rest_3key_cb)}, {"InsertSixteenthRest", "denemo-sixteenth-rest", N_("Sixteenth rest"), NULL, N_("Sixteenth rest"), - G_CALLBACK (insert_rest_4key_cb)} + G_CALLBACK (insert_rest_4key_cb)}, + /* Rhythm entry */ + {"CreateRhythm", NULL, N_("Create a rhythm"), NULL, + N_("Create a rhythm"), + G_CALLBACK (create_rhythm_cb)}, + {"DeleteRhythm", NULL, N_("Delete a rhythm"), NULL, + N_("Delete a rhythm"), + G_CALLBACK (delete_rhythm_cb)} }; @@ -546,6 +862,30 @@ gtk_widget_show (widget); } } +/** + * Function to toggle whether rhythm toolbar is visible + * + */ +static void +toggle_rhythm_toolbar (GtkAction * action, DenemoGUI * gui) +{ + GtkWidget *widget; + widget = gtk_ui_manager_get_widget (gui->ui_manager, "/RhythmToolBar"); + if (GTK_WIDGET_VISIBLE (widget) && gui->prefs->rhythm_palette == TRUE) + { + gtk_widget_hide (widget); + } + else if (GTK_WIDGET_VISIBLE (widget) + && gui->prefs->rhythm_palette == FALSE) + { + gtk_widget_hide (widget); + } + else + { + gtk_widget_show (widget); + gui->si->rhythmicsubmode = gui->si->rhythms; /*FIXME provide a button to set this */ + } +} /** * entries for View menu @@ -554,6 +894,9 @@ {"ToggleNotationToolbar", NULL, N_("_Notation Toolbar"), NULL, NULL, G_CALLBACK (toggle_notation_toolbar), FALSE} , + {"ToggleRhythmToolbar", NULL, N_("_Rhythmic Patterns"), NULL, NULL, + G_CALLBACK (toggle_rhythm_toolbar), FALSE} + , {"ToggleArticulationPalette", NULL, N_("_Articulation Palette"), NULL, NULL, G_CALLBACK (toggle_articulation_palette), FALSE} @@ -672,7 +1015,7 @@ /* This part is taken more-or-less directly from the gtk+ tutorial */ accel_group = gtk_accel_group_new (); action_group = gtk_action_group_new ("MenuActions"); - /* This also sets si as the callback data for all the functions in the + /* This also sets gui as the callback data for all the functions in the * menubar, which is precisely what we want. */ gtk_action_group_add_actions (action_group, menu_entries, G_N_ELEMENTS (menu_entries), gui); @@ -689,7 +1032,11 @@ gtk_window_add_accel_group (GTK_WINDOW (gui->window), accel_group); - data_dir = g_build_filename (get_data_dir (), "denemoui.xml", NULL); + data_dir = g_build_filename ( +#ifdef USE_LOCAL_DENEMOUI +get_data_dir (), +#endif + "denemoui.xml", NULL); if (!gtk_ui_manager_add_ui_from_file (ui_manager, data_dir, &error)) { g_message ("building menu failed: %s", error->message); @@ -712,19 +1059,37 @@ gtk_box_pack_start (GTK_BOX (main_vbox), toolbar, FALSE, TRUE, 0); GTK_WIDGET_UNSET_FLAGS(toolbar, GTK_CAN_FOCUS); gtk_widget_show (toolbar); - +#if 0 +/* what were these for???? */ widget = gtk_ui_manager_get_widget (ui_manager, "/ToolBar/Open"); /*gtk_tool_item_set_is_important (GTK_TOOL_ITEM (widget), TRUE); */ widget = gtk_ui_manager_get_widget (ui_manager, "/ToolBar/Save"); /*gtk_tool_item_set_is_important (GTK_TOOL_ITEM (widget), TRUE); */ - +#endif toolbar = gtk_ui_manager_get_widget (ui_manager, "/EntryToolBar"); + g_print("EntryToolbar is %p\n", toolbar); gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_ICONS); gtk_box_pack_start (GTK_BOX (main_vbox), toolbar, FALSE, TRUE, 0); GTK_WIDGET_UNSET_FLAGS(toolbar, GTK_CAN_FOCUS); gtk_widget_show (toolbar); + toolbar = gtk_ui_manager_get_widget (ui_manager, "/RhythmToolBar"); + gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_TEXT); + gtk_box_pack_start (GTK_BOX (main_vbox), toolbar, FALSE, TRUE, 0); +/* GTK_WIDGET_UNSET_FLAGS(toolbar, GTK_CAN_FOCUS); */ + +#if 0 +/* could not get this to work */ + widget = gtk_check_button_new_with_label("Rhythm Entry"); + GtkToolItem *item = gtk_tool_item_new(); + gtk_container_add(item, widget); + gtk_toolbar_insert(toolbar, item, -1); + gtk_widget_show_all(item); + g_signal_connect(G_OBJECT (widget), "clicked", + G_CALLBACK (toggle_rhythmicsubmode), (gpointer)gui) ; + gtk_widget_show (toolbar); +#endif score_and_scroll_hbox = gtk_hbox_new (FALSE, 1); gtk_box_pack_start (GTK_BOX (main_vbox), score_and_scroll_hbox, TRUE, TRUE, @@ -801,6 +1166,10 @@ gcs_init (gui->window->window); if (gui->prefs->articulation_palette) toggle_articulation_palette (NULL, gui); + if (!gui->prefs->rhythm_palette) + toggle_rhythm_toolbar (NULL, gui); + else + gui->si->rhythmicsubmode = gui->si->rhythms; if (!gui->prefs->notation_palette) { --- ../denemo-cvs/denemo/include/denemo/denemo_types.h 2007-08-02 20:13:08.000000000 +0100 +++ ./include/denemo/denemo_types.h 2007-07-28 11:24:14.000000000 +0100 @@ -112,23 +112,24 @@ */ typedef struct { - DenemoObjType type; /**< The type of object contained in the GList */ - gchar *user_string;/**< Holds user's original text parsed to generated this + DenemoObjType type; + gchar *user_string;/* holds user's original text parsed to generated this object */ gint basic_durinticks; - gint durinticks; /**< Duration of object */ - gint starttick; /**< When the object occurs */ - gint starttickofnextnote; /**< When the next object occurs */ - /**< Allots extra space for accidentals or reverse-aligned notes if + gint durinticks; + gint starttick; + gint starttickofnextnote; + /* Allots extra space for accidentals or reverse-aligned notes if * the stem is down */ - gint space_before; /**< Used to specify how much space is needed before the object */ - gint minpixelsalloted; /**< Holds x co-ordinate relative to the beginning of the measure. */ - gint x; /**< used in mousing.c x position */ - gboolean isstart_beamgroup; /**< TRUE if object is the start of a beam group */ - gboolean isend_beamgroup; /**< TRUE if this is the end of a beam group */ - /* Mudelaobjunion u; has become a pointer*/ - gpointer object; - gboolean isinvisible; /**< If object is set TRUE it will be rendered white and will not be seen. If it is set FALSE then it will be black. */ + gint space_before; + gint minpixelsalloted; + /* Holds x co-ordinate relative to the beginning of the measure. */ + gint x; + gboolean isstart_beamgroup; + gboolean isend_beamgroup; + /* mudelaobjunion u; has become a pointer*/ + gpointer object; + gboolean isinvisible; }DenemoObject; @@ -159,49 +160,50 @@ */ typedef struct { - measurenode *measures; /**< This is a pointer to each measure in the staff */ - gint sclef; /**< Set initial clef see denemo_objects.h clefs */ - gint skey; /**< Set the inital keysig. >0=sharps <0 = flats */ - gint skey_isminor; /**< Values 0 = major, 1 = minor, 2 = mode */ - gint skeyaccs[7]; /**< Value used for current keysignature */ - gint stime1; /**< This is the initial timesig numerator */ - gint stime2; /**< This is the initial timesig denominator */ - gint leftmost_clefcontext; /**< The first clef used in a staff */ - gint leftmost_keysigcontext; /**< The first or initial keysig used in a staff. */ - gint leftmost_keywidth; /**< Space allowed for initial keysig */ - gint leftmost_time1context; /**< This is the initial timesig numerator */ - gint leftmost_time2context; /**< This is the initial timesig denominator */ - - gint leftmost_keyaccs[7]; /**< Rirst keysignature used in the staff */ - gint leftmost_stem_directive; /**< Rirst stem directive used in the staff */ - DenemoContext context; /**< New variable to define the context in which this staff appears */ + measurenode *measures; + gint sclef; + gint skey; + gint skey_isminor; //25112005 Changed use to incorporate modes values 0 - major, 1 - minor, 2 - mode + gint skeyaccs[7]; + gint stime1; + gint stime2; + gint leftmost_clefcontext; + gint leftmost_keysigcontext; + gint leftmost_keywidth; + gint leftmost_time1context; + gint leftmost_time2context; + gint leftmost_keyaccs[7]; + gint leftmost_stem_directive; + /*New variable to define the context in which this staff appears*/ + DenemoContext context; /* * Staff Parameters * Added Adam Tee 27/1/2000, 2001 */ - gint no_of_lines; /**< Number of lines on the staff */ - gint transposition; /**< Determines if the notes are to be played back at pitch or not */ - gint pos_in_half_lines; /**< I believe this maybe broken. It does not seem to do much*/ - gint volume; /**< Volume used for midi/csound playback */ + gint no_of_lines; + gint transposition; + gint pos_in_half_lines; + gint volume; /* Back to Hiller stuff */ GString *staff_name; /* RTS: I've introduced the staff name here, the other two are versions of the voice name; however I'm still sticking to the unwritten convention that each staff's voices are contiguous in si->thescore. Without this you can't have same named voices in different staffs. */ - GString *denemo_name; /**< denemo_name gets copied into lily_name */ - GString *lily_name; /**< this is the name of the staff that is export to lilypond */ - GString *midi_instrument; /**< midi instrument name used for the staff when exported via midi */ - - gint space_above; /**< space above the staff used in the denemo gui */ - gint space_below; /**< space below the staff used in the denemo gui */ - gint voicenumber; /**< presently set to 2 for any non-primary voices; we might want to + GString *denemo_name; + GString *lily_name; + GString *midi_instrument; + + gint space_above; + gint space_below; + gint voicenumber; + /* presently set to 2 for any non-primary voices; we might want to * change that, though */ - measurenode ** is_parasite; /**< points to address of host staff's measures + measurenode ** is_parasite; /* points to address of host staff's measures field if measures are owned by another staff */ - gint nummeasures; /**< Number of measures in the staff*/ + gint nummeasures; /*Number of measures in the staff*/ }DenemoStaff; @@ -265,6 +267,9 @@ gboolean createclones; gboolean articulation_palette; gboolean notation_palette; +#if 1 + gboolean rhythm_palette; +#endif gboolean saveparts; /*Automatically save parts*/ /*Auto save data*/ gboolean autosave; @@ -384,6 +389,9 @@ }DenemoScoreConfig; + + + /* *It contains * within it a DenemoPrefs *, and when Denemo supports editing @@ -404,17 +412,19 @@ */ typedef struct DenemoScore { - gboolean readonly; /**< Indicates if the file is readonly or not */ - GList *curlilynode; /**< the node of the lily parse tree on display + /*Indicator for open file readonly*/ + gint readonly; + GList *curlilynode; /* the node of the lily parse tree on display in textwindow */ - GList *lily_file; /**< root of lily file parse, see lilyparser.y etc */ - DenemoScoreConfig *config; /**< contains the paper configuration of the score*/ + GList *lily_file; /* root of lily file parse, see lilyparser.y etc */ + DenemoScoreConfig *config; /*contains the paper configuration of the score*/ - gint leftmeasurenum; /**< start at 1 */ - gint rightmeasurenum;/**< start at 1 */ + gint leftmeasurenum; /* start at 1 */ + gint rightmeasurenum;/* start at 1 */ gint top_staff; gint bottom_staff; - gint measurewidth; /**< List of all minimum measure widths */ + gint measurewidth; + /* List of all minimum measure widths */ GList *measurewidths; gint widthtoworkwith; gint staffspace; @@ -427,8 +437,9 @@ staffnode *currentstaff; gint currentstaffnum; measurenode *currentmeasure; - gint currentmeasurenum;/**< start at 1 */ - objnode *currentobject; /**< currentobject points to the note preceding the cursor when the + gint currentmeasurenum;/* start at 1 */ + objnode *currentobject; + /* currentobject points to the note preceding the cursor when the * cursor is appending. == NULL only when currentmeasure is empty. */ gint cursor_x; gint cursor_y; @@ -451,10 +462,17 @@ gint curmeasure_stem_directive; gboolean is_grace_mode; - /* Is there a figured bass present, is so this relates the bass + /* Is there a figured bass present, if so this relates the bass * with its figures staff, if one is present */ staff_info * has_figures; staff_info *has_fakechords; + + /* support for INPUTNORMAL sub mode RHYTMIC */ + gboolean rhythmicsubmode; + GList *rhythms;/* list of RhythmPattern s */ + GList *currhythm; /* currently in use element of rhythms */ + GList *rstep; /* step within RhythmPattern->rsteps, the current element of the current rhythm pattern */ + /* Now stuff that's used for marking areas */ gint markstaffnum; gint markmeasurenum; @@ -467,7 +485,9 @@ gint lastobjmarked; gboolean haschanged; - gboolean is_slured; /** Temp field for testing for a slur*/ + + /*Temp field for testing for a slur*/ + gboolean is_slured; /* Fields used for MIDI playback */ gint tempo; @@ -554,6 +574,33 @@ }DenemoGUI; +/* + * RhythmPattern: structure to pass giving information when in rhythmicsubmode; +*/ + +typedef struct RhythmPattern +{ + GList *rsteps;/* the data are RhythmElements */ + GtkToolButton *button;/* the button on the rhythm toolbar which invokes this rhythm */ + DenemoGUI *gui; +} RhythmPattern; + + +/* + * RhythmElement: information about one element of a RhythmPatternwhen in rhythmicsubmode; +*/ + +typedef struct RhythmElement +{ + GList* functions;/* data in list are functions to be called including modifiers eg insert_chord_3key, add dot, slur ... */ + gpointer icon;/* icon when this element is active FIXME at present just a string */ + +} RhythmElement; + + + + + struct cs_callback { GtkWidget *entry;