Beispiel #1
0
/**
 * Scroll score horizontally
 *
 */
static void
h_scroll (gdouble value, DenemoProject * gui)
{
  gint dest;
  if ((dest = (gint) (value + 0.5)) != gui->movement->leftmeasurenum)
    {
      set_viewport_transition (dest - gui->movement->leftmeasurenum);
      gui->movement->leftmeasurenum = dest;
      set_rightmeasurenum (gui->movement);
      if (gui->movement->currentmeasurenum > gui->movement->rightmeasurenum)
        {
          gui->movement->currentmeasurenum = gui->movement->rightmeasurenum;

        }
      else if (gui->movement->currentmeasurenum < gui->movement->leftmeasurenum)
        {
          gui->movement->currentmeasurenum = gui->movement->leftmeasurenum;

        }
      find_leftmost_allcontexts (gui->movement);
      setcurrents (gui->movement);
      draw_score_area();
    }
  update_hscrollbar (gui);
}
Beispiel #2
0
/**
 * Scroll the score vertically
 *
 */
void
vertical_scroll (GtkAdjustment * adjust, gpointer dummy)
{
  DenemoProject *gui = Denemo.project;
  gint dest;
  gdouble value = gtk_adjustment_get_value (adjust);
  if ((dest = (gint) (value + 0.5)) != gui->movement->top_staff)
    {
      gui->movement->top_staff = dest;
      //  while(gui->movement->top_staff>g_list_length (gui->movement->thescore))
      //  gui->movement->top_staff--;
      set_bottom_staff (gui);
      if (gui->movement->currentstaffnum > gui->movement->bottom_staff)
        {
          gui->movement->currentstaffnum = gui->movement->bottom_staff;
          gui->movement->currentstaff = g_list_nth (gui->movement->thescore, gui->movement->bottom_staff - 1);
          staff_set_current_primary (gui->movement);
          setcurrents (gui->movement);
          if (gui->movement->markstaffnum)
            calcmarkboundaries (gui->movement);
        }
      else if (gui->movement->currentstaffnum < gui->movement->top_staff)
        {
          gui->movement->currentstaffnum = gui->movement->top_staff;
          gui->movement->currentstaff = g_list_nth (gui->movement->thescore, gui->movement->top_staff - 1);
          staff_set_current_primary (gui->movement);
          setcurrents (gui->movement);
          if (gui->movement->markstaffnum)
            calcmarkboundaries (gui->movement);
        }
      draw_score_area();
    }
  update_vscrollbar (gui);
}
Beispiel #3
0
gboolean
open_source_audio (gchar * filename)
{
    SF_INFO sfinfo;
    DenemoRecording *temp;
    sfinfo.format = 0;

    delete_recording();

    if (filename)
    {
        gpointer sndfile = sf_open (filename, SFM_READ, &sfinfo);
        if (sndfile)
        {
            temp = (DenemoRecording *) g_malloc (sizeof (DenemoRecording));
            temp->type = DENEMO_RECORDING_AUDIO;
            temp->sndfile = sndfile;
            temp->filename = g_strdup (filename);
            temp->samplerate = sfinfo.samplerate;
            temp->channels = sfinfo.channels;
            temp->nframes = (int) sf_seek (temp->sndfile, -1, SEEK_END);
            g_info ("sndfile: %s sample rate is %d channels %d containing %d \n", sf_strerror (temp->sndfile), sfinfo.samplerate, sfinfo.channels, temp->nframes);


            temp->volume = 1.0;
            g_static_mutex_lock (&smfmutex);
            Denemo.project->movement->recording = temp;
            g_static_mutex_unlock (&smfmutex);
            update_leadin_widget (-1.0);
            if (sfinfo.channels != 2)
                warningdialog (_("Audio is not stereo - expect bad things!"));
            if (sfinfo.samplerate != 44100)
                warningdialog (_("Audio does not have 44100 sample rate: this could be bad"));
            //FIXME here generate a click track if the score is empty
            if (Denemo.project->movement->smfsync != Denemo.project->movement->changecount)
            {
                exportmidi (NULL, Denemo.project->movement);  //generate a timebase
            }
            generate_note_onsets ();
            draw_score_area();
        }
    }
    Denemo.project->movement->recording ? gtk_widget_show (Denemo.audio_vol_control) : gtk_widget_hide (Denemo.audio_vol_control);
    return (Denemo.project->movement->recording != NULL);
}
Beispiel #4
0
/**
 * Sets the si->currentstaffnum to the given value
 * if it exists, extending selection if extend_selection
 *
 */
gboolean
goto_currentstaffnum (DenemoProject * gui, gint dest, gboolean extend_selection)
{
  if ((dest > 0) && (dest <= (gint) (g_list_length (gui->movement->thescore))))
    {
      //hide_lyrics(); cannot do this here, the lyrics pane when clicked on adjusts the current staff, and so this unselects the lyrics pane.
      gui->movement->currentstaffnum = dest;
      gui->movement->currentstaff = g_list_nth (gui->movement->thescore, gui->movement->currentstaffnum - 1);
      staff_set_current_primary (gui->movement);
      setcurrents (gui->movement);
      if (extend_selection)
        calcmarkboundaries (gui->movement);
      find_leftmost_allcontexts (gui->movement);
      if(!Denemo.non_interactive)
        update_vscrollbar (gui);
      //show_lyrics();
      draw_score_area();
      return TRUE;
    }
  return FALSE;
}
Beispiel #5
0
/**
 * Sets the si->currentmeasurenum to the given value
 * if exists, making it the leftmost measure visible, not extending selection
 *
 */
static gboolean
goto_currentmeasurenum (gint dest, gint leftmeasurenum)
{
  DenemoProject *gui = Denemo.project;
  if ((dest > 0) && (dest <= (gint) (g_list_length (gui->movement->measurewidths))))
    {
      //gui->movement->leftmeasurenum = dest;
      gui->movement->currentmeasurenum = dest;
      if(leftmeasurenum)
        gui->movement->leftmeasurenum = leftmeasurenum;
      if ((dest < gui->movement->leftmeasurenum) || (dest > gui->movement->rightmeasurenum))
        center_viewport ();
      setcurrents (gui->movement);
      set_rightmeasurenum (gui->movement);
      find_leftmost_allcontexts (gui->movement);
      if(!Denemo.non_interactive)
        update_hscrollbar (gui);
      draw_score_area();
      return TRUE;
    }
  return FALSE;
}
Beispiel #6
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;
}
Beispiel #7
0
/**
 * Mouse motion callback
 *
 */
gint
scorearea_motion_notify (GtkWidget * widget, GdkEventButton * event)
{
  DenemoProject *gui = Denemo.project;
  if (gui == NULL || gui->movement == NULL)
    return FALSE;
  if (Denemo.scorearea == NULL)
    return FALSE;
  gint allocated_height = get_widget_height (Denemo.scorearea);
  gint line_height = allocated_height * gui->movement->system_height;
  if(dragging_outside)
    {
          gint incrx, incry;
          incrx=incry=0;
          if(((gint)((last_event_x - event->x_root)/gui->movement->zoom)) != 0)
            {
                incrx = -(last_event_x - event->x_root)/gui->movement->zoom;
                last_event_x = event->x_root;
            }
          if( ((gint)((last_event_y - event->y_root)/gui->movement->zoom)) != 0)
            {
                incry = -(last_event_y - event->y_root)/gui->movement->zoom;
                last_event_y = event->y_root;
            }
        if((dragging_outside==DRAG_DIRECTION_RIGHT) && (incrx > 1)
            || ((dragging_outside==DRAG_DIRECTION_LEFT) && (incrx < -1))
            || ((dragging_outside==DRAG_DIRECTION_UP) && (incry < 0))
            || ((dragging_outside==DRAG_DIRECTION_DOWN) && (incry > 0)))
            extend_selection(dragging_outside);
    return TRUE;
    }
  if (event->y < 0)
    event->y = 0.0;
  gint line_num = ((int) event->y) / line_height;


   if (last_directive && (GDK_SHIFT_MASK & event->state) && (GDK_CONTROL_MASK & event->state))
      {
          gint incrx, incry;
          incrx=incry=0;
          if(((gint)((last_event_x - event->x_root)/gui->movement->zoom)) != 0)
            {
                incrx = (last_event_x - event->x_root)/gui->movement->zoom;
                last_event_x = event->x_root;
            }
          if( ((gint)((last_event_y - event->y_root)/gui->movement->zoom)) != 0)
            {
                incry = (last_event_y - event->y_root)/gui->movement->zoom;
                last_event_y = event->y_root;
            }

        if(last_directive->graphic)
            {
                last_directive->gx -= incrx;
                last_directive->gy -= incry;
            }
        else
            {
                last_directive->tx -= incrx;
                last_directive->ty -= incry;
            }
        draw_score_area();

        return TRUE;
      }



  if(gui->movement->recording && dragging_audio)
    {
        if(gui->movement->recording->type == DENEMO_RECORDING_MIDI)
        {
            #if 0
            //This is moving only the NoteOn, so it could be moved later than the note off, and indeed later than a later note in the stream
            //- quite a bit more work needed to drag MIDI to correct the timing.
            smf_event_t *midievent;
            GList *marked_onset = gui->movement->marked_onset;
            if(marked_onset)
                {
                midievent = ((DenemoRecordedNote *)marked_onset->data)->event;
                gint shift =  2500*(event->x_root - last_event_x)/gui->movement->zoom;
                g_debug (" %f (%f %f)",shift/(double)gui->movement->recording->samplerate,
                    midievent->time_seconds,
                    ((DenemoRecordedNote *)marked_onset->data)->timing/(double)gui->movement->recording->samplerate) ;

                ((DenemoRecordedNote *)marked_onset->data)->timing += shift;

                midievent->time_seconds += shift/(double)gui->movement->recording->samplerate;
                }
            #endif
            g_warning("No drag for MIDI yet");
            return TRUE;
        }

        gui->movement->recording->leadin -= 500*(event->x_root - last_event_x)/gui->movement->zoom;//g_debug("%d %d => %d\n", (int)(10*last_event_x), (int)(10*event->x_root), (int)(10*last_event_x) - (int)(10*event->x_root));
        last_event_x = event->x_root;
        update_leadin_widget ( gui->movement->recording->leadin/(double)gui->movement->recording->samplerate);
        gtk_widget_queue_draw(Denemo.scorearea);
        return TRUE;
    }
  if(gui->movement->recording && dragging_tempo)
    {
        gdouble change = (event->x_root - last_event_x)/gui->movement->zoom;
        last_event_x = event->x_root;
        struct placement_info pi;
        get_placement_from_coordinates (&pi, event->x, 0, gui->lefts[line_num], gui->rights[line_num], gui->scales[line_num]);
        change /= pi.measure_number;
        update_tempo_widget ( change);
        set_tempo ();
        score_status (Denemo.project, TRUE);
        exportmidi (NULL, gui->movement);
        gtk_widget_queue_draw(Denemo.scorearea);
        return TRUE;
    }
#define DENEMO_MINIMUM_SYSTEM_HEIGHT (0.01)


  if (dragging_separator)
    {
      gui->movement->system_height = event->y / get_widget_height (Denemo.scorearea);
      if (gui->movement->system_height < DENEMO_MINIMUM_SYSTEM_HEIGHT)
        gui->movement->system_height = DENEMO_MINIMUM_SYSTEM_HEIGHT;
      if (gui->movement->system_height > 1.0)
        gui->movement->system_height = 1.0;
      scorearea_configure_event (Denemo.scorearea, NULL);
      draw_score_area();
      return TRUE;
    }

  if (line_height - ((int) event->y - 8) % line_height < 12)
    gdk_window_set_cursor (gtk_widget_get_window (Denemo.window), gdk_cursor_new (GDK_SB_V_DOUBLE_ARROW));
  else
    gdk_window_set_cursor (gtk_widget_get_window (Denemo.window), gdk_cursor_new (GDK_LEFT_PTR));       //FIXME? does this take time/hog memory

  transform_coords (&event->x, &event->y);
  //g_debug("Marked %d\n", gui->movement->markstaffnum);


  if (gui->lefts[line_num] == 0)
    return TRUE;




  if (lh_down || (selecting && gui->movement->markstaffnum))
    {
      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
      if (pi.the_measure != NULL)
        {                       /*don't place cursor in a place that is not there */
          change_staff (gui->movement, pi.staff_number, 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 (lh_down & !selecting)
            {
              if (gui->movement->markstaffnum)
                set_point (NULL, NULL);
              else
                set_mark (NULL, NULL);
              selecting = TRUE;
            }
          calcmarkboundaries (gui->movement);
          if (event->state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK))
            perform_command (event->state, GESTURE_MOVE, event->state & GDK_BUTTON1_MASK);

          /* redraw to show new cursor position  */
          draw_score_area();
        }
    }

  if (Denemo.project->midi_destination & MIDICONDUCT)
    {
      advance_time (0.01);
      return TRUE;
    }
  return TRUE;
}
Beispiel #8
0
/*  take an action for the passed note. Enter/edit/check the score following the mode and keyboard state. */
static gint
midiaction (gint notenum)
{
  gboolean new_measure = Denemo.project->movement->cursoroffend;
  DenemoProject *gui = Denemo.project;
  if (gui == NULL)
    return TRUE;
  if (gui->movement == NULL)
    return TRUE;
  DenemoStaff *curstaffstruct = (DenemoStaff *) gui->movement->currentstaff->data;
  enharmonic enote, prevenote;
  gboolean have_previous;
  //g_print("midiaction Adding mask %x, Chord mask %x\n", (Denemo.keyboard_state & ADDING_MASK) , (Denemo.keyboard_state & CHORD_MASK));
  notenum2enharmonic (notenum, &enote.mid_c_offset, &enote.enshift, &enote.octave);
  if (Denemo.project->movement->cursor_appending)
    have_previous = get_current (&prevenote);
  else
    have_previous = get_previous (&prevenote);

  if (!(Denemo.keyboard_state & CHECKING_MASK))
    stage_undo (gui->movement, ACTION_STAGE_END);     //undo is a queue so this is the end :)

  if ((gui->mode & INPUTEDIT) || (Denemo.keyboard_state & CHECKING_MASK))
    {
      static gboolean beep = FALSE;
      gboolean is_tied = FALSE;
      gint measure = gui->movement->currentmeasurenum;
      if (Denemo.project->movement->currentobject)
        {
          DenemoObject *curObj = Denemo.project->movement->currentobject->data;
          if (curObj->type == CHORD)
            {
              do
                {
                  curObj = Denemo.project->movement->currentobject->data;
                  chord *thechord = (chord *) curObj->object;
                  is_tied = (!Denemo.prefs.ignore_ties) && thechord->is_tied;

//#define check_midi_note(a,b,c,d) ((a->mid_c_offset==b)&&(a->enshift==c))?playnote(a,curstaffstruct->midi_channel):gdk_beep();
                  if ((Denemo.keyboard_state & CHECKING_MASK) && thechord->notes)
                    {
                      //later - find note nearest cursor and
                      note *thenote = (note *) thechord->notes->data;
//            check_midi_note(thenote, enote.mid_c_offset + 7 *(enote.octave), enote.enshift, enote.octave);
                      if ((!curObj->isinvisible) && (thenote->mid_c_offset == (enote.mid_c_offset + 7 * (enote.octave))) && (thenote->enshift == enote.enshift))
                        {
                          gint midi = dia_to_midinote (thenote->mid_c_offset) + thenote->enshift;
                          play_note (DEFAULT_BACKEND, 0 /*port */ , curstaffstruct->midi_channel, midi, 300 /*duration */ , 0);
                        }
                      else
                        {
                          gdk_beep ();
                          break;        //do not move on to next note
                        }
                    }
                  else
                    {

                      do_one_note (enote.mid_c_offset, enote.enshift, enote.octave);

                    }
                  if (Denemo.project->movement->cursor_appending)
                    break;
                    curObj = Denemo.project->movement->currentobject->data;
                    thechord = (chord *) curObj->object;
                    is_tied = (!Denemo.prefs.ignore_ties) && thechord->is_tied;
                }
              while ((!(Denemo.keyboard_state & ADDING_MASK)) && next_editable_note () && is_tied);
            }
          else //there is a current object that is not a chord
            {
              if (gui->movement->cursor_appending)
                {
                    do_one_note (enote.mid_c_offset, enote.enshift, enote.octave);
                    next_insert_or_editable_note();
                    //in some circumstance this fails to advance to the next editable note, the following checks for that.
                    if (Denemo.project->movement->currentobject)
                        {
                            curObj = Denemo.project->movement->currentobject->data;
                            if(!curObj->isinvisible)
                               next_editable_note ();
                        }
                }
              else
                gdk_beep ();
            }
          if (gui->mode & INPUTRHYTHM)
            {
              //g_print("measure was %d now %d with appending %d\n", measure, gui->movement->currentmeasurenum, gui->movement->cursor_appending);
              if (!beep && (measure != gui->movement->currentmeasurenum) && !gui->movement->cursor_appending)
                beep = TRUE;
              else if (beep)
                signal_measure_end (), beep = FALSE;
            }
        }
      else
        {                       // no current object
          do_one_note (enote.mid_c_offset, enote.enshift, enote.octave);
          next_insert_or_editable_note();//next_editable_note ();//if we have gone back from an empty measure we need this.
        }
    }
  else
    {                           // not INPUTEDIT
      action_note_into_score (enote.mid_c_offset, enote.enshift, enote.octave);
    }
  if (!(Denemo.keyboard_state & CHECKING_MASK))
    {
      stage_undo (gui->movement, ACTION_STAGE_START);
    }
  draw_score_area();     //just for advancing the cursor.
  if (!(Denemo.keyboard_state & CHECKING_MASK))
    {
      if (Denemo.prefs.immediateplayback)
        {
          gint channel = curstaffstruct->midi_channel;

          if (have_previous && check_interval (enote.mid_c_offset, enote.enshift, prevenote.mid_c_offset, prevenote.enshift))
            channel = Denemo.prefs.pitchspellingchannel;

          play_note (DEFAULT_BACKEND, 0 /*port */ , channel, notenum, 300 /*duration */ , 0);
          if(new_measure)
            signal_measure_end();
        }
    }

  return TRUE;
}