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;