Exemplo n.º 1
0
static gint
record_timing (GtkWidget * widget, GdkEventKey * event)
{
    if (event->keyval == GDK_Escape)
    {
        call_out_to_guile ("(if (defined? 'DenemoAudioAnnotateFinished) (DenemoAudioAnnotateFinished))");
        stop_audio_playing ();
    }
    else
    {
        g_queue_push_tail (timings, GINT_TO_POINTER ((gint) (1000000 * get_playback_time ())));
        call_out_to_guile ("(DenemoAudioAnnotate)");
    }
    return TRUE;
}
Exemplo n.º 2
0
/* perform the command of the given name and store the event that triggered it */
static gchar *
perform_command (const gchar * command_name, GdkEventKey * event)
{
  Denemo.last_keyval = event->keyval;
  Denemo.last_keystate = dnm_sanitize_key_state (event);
  call_out_to_guile ("(define DenemoKeypressActivatedCommand #t)");
  execute_callback_from_name (command_name);
  call_out_to_guile ("(define DenemoKeypressActivatedCommand #f)");
  // note Denemo.project = Denemo.project; may have changed as a result of executing the command
#ifdef TESTING_REPEATED_XPOSITION_UPDATE
  if (Denemo.project->movement)
    displayhelper (Denemo.project);
#endif
  return NULL;
}
Exemplo n.º 3
0
Arquivo: midi.c Projeto: denemo/denemo
static gboolean
stop_play_callback (gchar * thescript)
{
  call_out_to_guile (thescript);
  g_free (thescript);
  return FALSE;
}
Exemplo n.º 4
0
/**
 * Mouse button press callback
 *
 */
gint
scorearea_button_press (GtkWidget * widget, GdkEventButton * event)
{
  DenemoProject *gui = Denemo.project;
  if (gui == NULL || gui->movement == NULL)
    return FALSE;
  gboolean left = (event->button != 3);
  //if the cursor is at a system separator start dragging it
  gint allocated_height = get_widget_height (Denemo.scorearea);
  gint line_height = allocated_height * gui->movement->system_height;
  gint line_num = ((int) event->y) / line_height;
  last_event_x = event->x_root;
  last_event_y = event->y_root;
  //g_debug("diff %d\n", line_height - ((int)event->y)%line_height);

  if (dragging_separator == FALSE)
    if (line_height - ((int) event->y - 8) % line_height < 12)
      {
        if (Denemo.prefs.learning)
          MouseGestureShow(_("Dragging line separator."), _("This will allow the display to show more music, split into lines. The typeset score is not affected."),
            MouseGesture);
        dragging_separator = TRUE;
        return TRUE;
      }
  dragging_separator = FALSE;

  if(gui->movement->recording)
    {
     //g_debug("audio %f %f\n", event->x, event->y);


      if(event->y < 20*gui->movement->zoom /* see draw.c for this value, the note onsets are drawn in the top 20 pixels */)
        {
            if (event->type==GDK_2BUTTON_PRESS)
                {
                    gui->movement->marked_onset_position = (gint)event->x/gui->movement->zoom;
                    if(gui->movement->marked_onset_position < (gui->leftmargin+35) + SPACE_FOR_TIME + gui->movement->maxkeywidth) {
                         if (Denemo.prefs.learning)
                            MouseGestureShow(_("Double Click Note Onset"), _("This represents detected note onsets which occur\nbefore the start of the score.\nIf they are just noise,\nor if you are working on just a portion of the audio that is ok.\nOtherwise drag with left mouse button to synchronize\nwith the start of the score."),
          MouseGesture);

                    }
                    gtk_widget_queue_draw(Denemo.scorearea);
                    return TRUE;
                } else
                {
                    gdk_window_set_cursor (gtk_widget_get_window (Denemo.window), gdk_cursor_new (left?GDK_SB_H_DOUBLE_ARROW:GDK_X_CURSOR));
                    left? (dragging_audio = TRUE) : (dragging_tempo = TRUE);
                     if (Denemo.prefs.learning)
                     left? MouseGestureShow(_("Left Drag Note Onset"), _("This moves the audio to synchronize the start with the score.\nYou can use the Leadin button for this too."),
          MouseGesture) :
                        MouseGestureShow(_("Right Drag Note Onset"), _("This changes the tempo of the score.\nUse this to synchronize the beat after setting the start"),
          MouseGesture);
                    gtk_widget_queue_draw(Denemo.scorearea);
                    return TRUE;
                }
        }

    }


  //g_debug("before %f %f\n", event->x, event->y);
  transform_coords (&event->x, &event->y);
  //g_debug("after %f %f\n", event->x, event->y);


  gtk_widget_grab_focus (widget);
  gint key = gui->movement->maxkeywidth;
  gint cmajor = key ? 0 : 5;    //allow some area for keysig in C-major

  if (gui->lefts[line_num] == 0)
    return TRUE;                //On an empty system at the bottom where there is not enough room to draw another staff.

  struct placement_info pi;
  pi.the_staff = NULL;
  if (event->y < 0)
    get_placement_from_coordinates (&pi, event->x, 0, gui->lefts[line_num], gui->rights[line_num], gui->scales[line_num]);
  else
    get_placement_from_coordinates (&pi, event->x, event->y, gui->lefts[line_num], gui->rights[line_num], gui->scales[line_num]);
  if (pi.the_staff == NULL)
    return TRUE;                //could not place the cursor
  change_staff (gui->movement, pi.staff_number, pi.the_staff);


  if (left && (gui->movement->leftmeasurenum > 1) && (event->x < (gui->leftmargin+35) + SPACE_FOR_TIME + key) && (event->x > gui->leftmargin))
    {
      if (Denemo.prefs.learning)
        MouseGestureShow(_("Press Left."), _("This moved the cursor to the measure offscreen left. The display is shifted to place that measure on screen."),
          MouseGesture);
      set_currentmeasurenum (gui, gui->movement->leftmeasurenum - 1);
      write_status (gui);
      draw_score_area();
      return TRUE;
    }
  else if (pi.nextmeasure)
    {
      if ((pi.at_edge) && ((pi.the_obj==NULL) || ((pi.the_obj->next == NULL) && (pi.offend))))//crashed here with the_obj 0x131 !!!
        {
          if ((gui->movement->currentmeasurenum != gui->movement->rightmeasurenum) &&
                (!set_currentmeasurenum (gui, gui->movement->rightmeasurenum + 1)))
              set_currentmeasurenum (gui, gui->movement->rightmeasurenum);
          else if ((gui->movement->cursor_appending) &&
                (!set_currentmeasurenum (gui, gui->movement->rightmeasurenum + 1)))
              set_currentmeasurenum (gui, gui->movement->rightmeasurenum);




          if (gui->movement->currentmeasurenum != gui->movement->rightmeasurenum) {
            if (Denemo.prefs.learning)
              MouseGestureShow(_("Press Left."), _("This moved the cursor to the measure off-screen right. The display is shifted to move the cursor to the middle."),
                MouseGesture);
          write_status (gui);
          return TRUE;
        }
        }
    }


  if (pi.the_measure != NULL)
    {                           /*don't place cursor in a place that is not there */
      //gui->movement->currentstaffnum = pi.staff_number;
      //gui->movement->currentstaff = pi.the_staff;
      gui->movement->currentmeasurenum = pi.measure_number;
      gui->movement->currentmeasure = pi.the_measure;
      gui->movement->currentobject = pi.the_obj;
      gui->movement->cursor_x = pi.cursor_x;
      gui->movement->cursor_appending = (gui->movement->cursor_x == (gint) (g_list_length ((objnode *) ((DenemoMeasure*)gui->movement->currentmeasure->data)->objects)));
      set_cursor_y_from_click (gui, event->y);
      if (event->type==GDK_2BUTTON_PRESS)
                {
                    if(gui->movement->recording &&  !g_strcmp0 (((DenemoStaff *) gui->movement->currentstaff->data)->denemo_name->str, DENEMO_CLICK_TRACK_NAME))
                        {
                            gui->movement->marked_onset_position = (gint)event->x/gui->movement->zoom;
                            if (Denemo.prefs.learning)
                                MouseGestureShow(_("Double Click on Click Track"), _("This will mark the MIDI note onset."), MouseGesture);
                            return TRUE;

                        }

                    else
                        {
                          if (Denemo.prefs.learning)
                            MouseGestureShow(_("Double Click."), _("This gives information about the object at the cursor. Click on a notehead for information about a note in a chord."),
                              MouseGesture);
                                    display_current_object();
                                    return TRUE;
                        }
                }
            else
                {
                  if (Denemo.prefs.learning)
                    MouseGestureShow(_("Press Left."), _("This moved the cursor to the object position clicked. The cursor height becomes the clicked point."),
                      MouseGesture);
                            write_status (gui);
               }
            }

  gint offset = (gint) get_click_height (gui, event->y);

   if ((((DenemoStaff *) gui->movement->currentstaff->data)->voicecontrol != DENEMO_PRIMARY)
        && (gui->movement->leftmeasurenum == 1) && (event->x > gui->leftmargin)
        && ((event->x < (gui->leftmargin+35) + SPACE_FOR_TIME + key)))
    {
          infodialog(_("The clef shown here affects the display only (as this voice is displayed on the staff above)."
          " You can change the display clef using the clef menu."
          "\nWarning! you will get confused if you set the key signature or time signature of a voice different "
          "to the staff it is typeset on. Run the Staff/Voice property editor to adjust any inconsistencies."));

    }
  if ((((DenemoStaff *) gui->movement->currentstaff->data)->voicecontrol == DENEMO_PRIMARY) && (gui->movement->leftmeasurenum == 1) && (event->x > gui->leftmargin))
    {
      if (event->x < (gui->leftmargin+35) - cmajor)
        {
        if (offset<-10)
            {
                if (Denemo.prefs.learning)
                MouseGestureShow(_("Left on Staff name."), _("This pops up the built-in staff properties. For other properties of the current staff see the staff menu or the tools icon before the clef."),
                  MouseGesture);
                staff_properties_change_cb (NULL, NULL);
            }
        else
            {
              if (Denemo.prefs.learning)
                MouseGestureShow(_("Left on initial Clef."), _("This pops up the initial clef menu."),
                  MouseGesture);
              popup_menu ("/InitialClefEditPopup");
            }
          return TRUE;
        }
      else if (event->x < (gui->leftmargin+35) + key + cmajor)
        {
          if (left)
            {
              if (offset > 0 && (offset < STAFF_HEIGHT / 2))
                {
                  if (Denemo.prefs.learning)
                    MouseGestureShow(_("Left Click on blue."), _("This adds one sharp."),
                      MouseGesture);
                if ((gui->movement->currentmeasure->next==NULL)  || confirm (_("Initial Key Signature Change"), _("Sharpen Keysignature?")))
                  call_out_to_guile ("(d-SharpenInitialKeysigs)");
                }
              else if (offset > 0 && (offset < STAFF_HEIGHT))
                {
                  if (Denemo.prefs.learning)
                    MouseGestureShow(_("Left Click on red."), _("This adds one flat."),
                      MouseGesture);
                  if ((gui->movement->currentmeasure->next==NULL) || confirm (_("Initial Key Signature Change"), _("Flatten Keysignature?")))
                    call_out_to_guile ("(d-FlattenInitialKeysigs)");
                }
            }
          else
            {
              if (Denemo.prefs.learning)
                MouseGestureShow(_("Right Click on key."), _("This pops up the key signature menu."),
                    MouseGesture);
              popup_menu ("/InitialKeyEditPopup");
            }
          return TRUE;
        }
      else if (event->x < (gui->leftmargin+35) + SPACE_FOR_TIME + key)
        {
          if (Denemo.prefs.learning)
            MouseGestureShow(_("Click on Time."), _("This pops up the time signature menu."),
                    MouseGesture);
          popup_menu ("/InitialTimeEditPopup");
          return TRUE;
        }
    }

  if (event->x < gui->leftmargin)
    {
       if (gui->braces)
        {
                gint width = BRACEWIDTH * g_list_length (gui->braces);
                //gint count = (gui->leftmargin - event->x)/BRACEWIDTH;
                if ((gui->leftmargin - event->x) < width)
                {
                    gint count = 1 + (width - gui->leftmargin + event->x)/BRACEWIDTH;


                    if ((count>0) && (count <= g_list_length (gui->braces)))
                        {
                            DenemoBrace *brace = (DenemoBrace*)g_list_nth_data (gui->braces, count-1);
                            gint choice = choose_option (_("Editing Staff Groups (Braces)"), _("Edit Start Brace"), _("Edit End Brace"));
                            gint staffnum = choice?brace->startstaff:brace->endstaff;
                            //g_print ("Count is %d for start at %d\n", count, staffnum);
                            GtkWidget *menuitem = gtk_ui_manager_get_widget (Denemo.ui_manager, "/ObjectMenu/StaffMenu/StaffGroupings");
                            goto_movement_staff_obj (NULL, -1, staffnum, 1, 0, 0);
                            if (menuitem)
                                if (choice)
                                    gtk_menu_popup (GTK_MENU (gtk_menu_item_get_submenu (GTK_MENU_ITEM (menuitem))), NULL, NULL, NULL, NULL, 0, GDK_CURRENT_TIME);
                                else
                                {
                                    if (staff_directive_get_tag ("BraceEnd"))
                                        call_out_to_guile ("(d-BraceEnd)");
                                    else
                                        warningdialog (_( "This staff grouping has no End Brace so it finishes on the lowest staff. Use the Staffs/Voices->Staff Groupings menu to place an End Brace on the desired staff"));
                                }
                            //note the popup returns as soon as the menu is popped up, so we can't go back to the original position.

                        }

                    return TRUE;
                }

        }

      if (pi.staff_number == gui->movement->currentstaffnum)
        {
          gint offset = (gint) get_click_height (gui, event->y);
          if (offset < STAFF_HEIGHT / 2)
            {
              if (((DenemoStaff *) gui->movement->currentstaff->data)->staff_directives, 1)
                {
                  if (Denemo.prefs.learning)
                    MouseGestureShow(_("Click on Staff Directives."), _("This pops up the staff directives menu for editing"),
                      MouseGesture);
                  edit_staff_properties ();//gtk_menu_popup (((DenemoStaff *) gui->movement->currentstaff->data)->staffmenu, NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time ());
                }
              return TRUE;
            }
          else if (((DenemoStaff *) gui->movement->currentstaff->data)->voice_directives, 1)
            {
              if (Denemo.prefs.learning)
                MouseGestureShow(_("Click on Voice Directives."), _("This pops up the voice directives menu for editing"),
                    MouseGesture);
              edit_voice_properties ();//gtk_menu_popup (((DenemoStaff *) gui->movement->currentstaff->data)->voicemenu, NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time ());
              return TRUE;
            }
        }
    }

  if (left)
    {
      if (!(GDK_SHIFT_MASK & event->state))
        gui->movement->markstaffnum = 0;
      lh_down = TRUE;
    }
  else
    {
      if (gui->movement->cursor_appending && (event->state==0))
        {
          if (Denemo.prefs.learning)
           {

                    MouseGestureShow(_("Right Click Appending."), _("This pops up the append menu"),
                        MouseGesture);

           }
          popup_menu ("/NoteAppendPopup");
          return TRUE;
        }

        if ((GDK_CONTROL_MASK & event->state) == GDK_CONTROL_MASK) {
            if (Denemo.prefs.learning)
                    MouseGestureShow(_("Control-Right Click."), _("This pops up menu for inserting barlines and many other sorts of objects"),
                        MouseGesture);
            gtk_menu_popup (GTK_MENU (gtk_widget_get_parent(gtk_ui_manager_get_widget (Denemo.ui_manager, "/ObjectMenu/Directives/Markings"))),
                            NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time ());
            return TRUE;
        }
      if ((GDK_SHIFT_MASK & event->state) == GDK_SHIFT_MASK) {
            if (Denemo.prefs.learning)
                    MouseGestureShow(_("Shift-Right Click."), _("This allows editing the directives/attributes of the object at the cursor"),
                        MouseGesture);
            call_out_to_guile ("(d-EditSimilar 'once)");
            return TRUE;
        }
    }



  if (left && (GDK_SHIFT_MASK & event->state) && (GDK_CONTROL_MASK & event->state))
  {
     // if current object is directive, start dragging its graphic, dragging_display=TRUE

      DenemoObject *obj;
      if (Denemo.prefs.learning)
                    MouseGestureShow(_("Control-Shift-Drag."), _("This allows dragging objects in the display.\nAll sorts of directives such as staccato dots, ornaments, repeat marks etc can be dragged if the display is too cluttered.\nThe typeset score is unaffected.\nClick on a notehead to drag things attached to the notehead,\nor off the noteheads for things attached to the whole chord."),
                        MouseGesture);

    last_directive = get_next_directive_at_cursor ();
    if(last_directive)
        {
            score_status (Denemo.project, TRUE);
            return TRUE;
        }
    infodialog (_("Control-Shift-Drag is used to tidy up the Denemo display. Useful if Denemo has created a clutter with your input music.\nIf you have several things attached to one object you can move them in turn by dragging them in turn.\nNotes, Slurs and Ties are fixed but most other things can be moved to make the input music clear. Does not affect the typeset score!\nNB! if you have dragged something to one side of a note you have to control-shift-click on the note itself to drag it back - it is where the cursor is that counts."));
    return TRUE;
 }






  set_cursor_for (event->state | (left ? GDK_BUTTON1_MASK : GDK_BUTTON3_MASK));




  //displayhelper(Denemo.project);
  draw_score(NULL);//this is needed to refresh cached values such as the prevailing time signature, before the command is invoked

  perform_command (event->state | (left ? GDK_BUTTON1_MASK : GDK_BUTTON3_MASK), GESTURE_PRESS, left);

  return TRUE;
}
Exemplo n.º 5
0
/**
 * Set the staffs properties
 * @param cbdata pointer to the callback data structure containing the preference data to set.
 * @return none
 */
static void
set_properties (struct callbackdata *cbdata)
{

  DenemoStaff *staffstruct = cbdata->staffstruct;
#if GTK_MAJOR_VERSION==3
#define ASSIGNTEXT(field) \
  if(cbdata->field) {\
    gchar *text=gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (cbdata->field));\
    if (text)\
        g_string_assign (staffstruct->field,text);\
    }
#else
#define ASSIGNTEXT(field) \
  if(cbdata->field)\
    g_string_assign (staffstruct->field,\
    gtk_entry_get_text (GTK_ENTRY (cbdata->field)))
#endif

#define ASSIGNNUMBER(field) \
  if(cbdata->field)\
    staffstruct->field = \
      atoi(gtk_entry_get_text(GTK_ENTRY (cbdata->field)))
#define ASSIGNNUMBER_1(field) \
  if(cbdata->field)\
    staffstruct->field = \
      atoi(gtk_entry_get_text(GTK_ENTRY (cbdata->field)))-1

#define ASSIGNBOOLEAN(field) \
  if(cbdata->field)\
    staffstruct->field = \
    (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (cbdata->field)));

  /* rename of set staff/voice name */
  canonicalize_denemo_name ((gchar *) gtk_entry_get_text (GTK_ENTRY (cbdata->denemo_name)), staffstruct->denemo_name);
  if(cbdata->subpart)
    {
     if(staffstruct->subpart==NULL)
        staffstruct->subpart = g_string_new ("");
     canonicalize_denemo_name ((gchar *) gtk_entry_get_text (GTK_ENTRY (cbdata->subpart)), staffstruct->subpart);
    }
  set_lily_name (staffstruct->denemo_name, staffstruct->lily_name);


  //g_debug("first %d\t", staffstruct->space_above);
  ASSIGNNUMBER (space_above);
  //g_debug("then %d\t", staffstruct->space_above);
  ASSIGNNUMBER (space_below);
  ASSIGNNUMBER (no_of_lines);
  ASSIGNNUMBER (transposition);


  /* set MIDI channel/prognum */
  ASSIGNTEXT (midi_instrument);

  ASSIGNTEXT (device_port);
  ASSIGNBOOLEAN (override_volume);
  ASSIGNNUMBER (volume);
  // ASSIGNBOOLEAN(midi_prognum_override);
  if (staffstruct->midi_instrument->len)
    {
      staffstruct->midi_prognum = get_midi_prognum (staffstruct);
      gint i;
      gchar *name;
      gint preset, bank;
      gint npresets = ParseSoundfont (Denemo.prefs.fluidsynth_soundfont->str, 0, NULL, NULL, NULL);
      if (npresets)
        {
          for (i = 0; i < npresets - 1; i++)
            {
              (void) ParseSoundfont (NULL, i, &name, &preset, &bank);
              if (!strcmp (name, staffstruct->midi_instrument->str))
                {
                  staffstruct->midi_prognum = preset;
                  gchar *scheme = g_strdup_printf ("(d-MidiInstrumentName \"%s\")", GM_Instrument_Names[preset&0xFF]);
                  call_out_to_guile (scheme);
                  g_free (scheme);
                  printf ("\nMIDI Instrument == %s (GM name %s)\nMIDI PROGRAM == %d\n", staffstruct->midi_instrument->str,  GM_Instrument_Names[preset&0xFF], staffstruct->midi_prognum);
                  break;
                }
            }
        }
      //   if(staffstruct->midi_prognum != i) /* I am not sure why this was necessary and if it is still needed*/
      //     ASSIGNNUMBER_1(midi_prognum);
      ASSIGNNUMBER_1 (midi_channel);
      printf ("\nAssigned MIDI Instrument == %s \nAssigned MIDI PROGRAM == %d i == %d\n", staffstruct->midi_instrument->str, staffstruct->midi_prognum, i);

    }
  else
    {
      ASSIGNNUMBER_1 (midi_prognum);
      ASSIGNNUMBER_1 (midi_channel);
    }
    {
      unsigned char buffer[3];/* third byte is unused but is put into the queue so must be accessible */
      /* set selected midi program on the synthesizer so that users can play MIDI controller with current staff instrument without having to do playback first*/
      g_info ("Using channel %d port %d prognum %d\n",  staffstruct->midi_channel, staffstruct->midi_port, staffstruct->midi_prognum);
      buffer[0] = 0xC0 /*MIDI_PROG_CHANGE*/ | staffstruct->midi_channel;
      buffer[1] = staffstruct->midi_prognum;
      play_midi_event (DEFAULT_BACKEND, staffstruct->midi_port, buffer);
    }
  //g_debug ("Staff Transposition %d\n", staffstruct->transposition);
  gtk_widget_queue_draw (Denemo.scorearea);
  score_status (cbdata->gui, TRUE);
}