void BR_MidiItemTimePos::Restore (double timeOffset /*=0*/) { SetMediaItemInfo_Value(item, "C_BEATATTACHMODE", 0); for (size_t i = 0; i < savedMidiTakes.size(); ++i) { BR_MidiItemTimePos::MidiTake* midiTake = &savedMidiTakes[i]; MediaItem_Take* take = midiTake->take; int noteCount, ccCount, textCount; if (MIDI_CountEvts(take, ¬eCount, &ccCount, &textCount)) { for (int i = 0; i < noteCount; ++i) MIDI_DeleteNote(take, 0); for (int i = 0; i < ccCount; ++i) MIDI_DeleteCC(take, 0); for (int i = 0; i < textCount; ++i) MIDI_DeleteTextSysexEvt(take, 0); } if (looped && loopStart != -1 && loopEnd != -1) { SetMediaItemTakeInfo_Value(take, "D_STARTOFFS", 0); MIDI_SetItemExtents(item, TimeMap_timeToQN(loopStart), TimeMap_timeToQN(loopEnd)); SetMediaItemInfo_Value(item , "B_LOOPSRC", 1); // because MIDI_SetItemExtents() disables looping TrimItem(item, position, position + length, true); SetMediaItemTakeInfo_Value(take, "D_STARTOFFS", loopedOffset); } else { TrimItem(item, position, position + length, true); } for (size_t i = 0; i < midiTake->noteEvents.size(); ++i) midiTake->noteEvents[i].InsertEvent(take, timeOffset); for (size_t i = 0; i < midiTake->ccEvents.size(); ++i) midiTake->ccEvents[i].InsertEvent(take, timeOffset); for (size_t i = 0; i < midiTake->sysEvents.size(); ++i) midiTake->sysEvents[i].InsertEvent(take, timeOffset); } SetMediaItemInfo_Value(item, "C_BEATATTACHMODE", timeBase); }
void DeleteTempoPreserveItems (COMMAND_T* ct) { BR_Envelope tempoMap(GetTempoEnv()); if (!tempoMap.CountSelected()) return; // Get items' position info and set their timebase to time vector<BR_MidiItemTimePos> items; double firstMarker; tempoMap.GetPoint(tempoMap.GetSelected(0), &firstMarker, NULL, NULL, NULL); int itemCount = ((int)ct->user) ? CountSelectedMediaItems(NULL) : CountMediaItems(NULL); items.reserve(itemCount); for (int i = 0; i < itemCount; ++i) { MediaItem* item = ((int)ct->user) ? GetSelectedMediaItem(NULL, i) : GetMediaItem(NULL, i); double itemEnd = GetMediaItemInfo_Value(item, "D_POSITION") + GetMediaItemInfo_Value(item, "D_LENGTH"); if (itemEnd >= firstMarker) { items.push_back(BR_MidiItemTimePos(item)); SetMediaItemInfo_Value(item, "C_BEATATTACHMODE", 0); } } // Readjust unselected tempo markers double offset = 0; for (int i = 0; i < tempoMap.CountConseq(); ++i) { int startId, endId; tempoMap.GetConseq (i, &startId, &endId); if (endId == tempoMap.Count()-1) continue; // no points after selection, nothing to adjust if (startId == 0 && (++startId > endId)) continue; // skip first point // Get musical length of selection double musicalLen = 0; for (int i = startId - 1; i <= endId; ++i ) { double t0, t1, b0, b1; int s0; tempoMap.GetPoint(i, &t0, &b0, &s0, NULL); tempoMap.GetPoint(i+1, &t1, &b1, NULL, NULL); if (i == startId-1) t0 -= offset; // readjust position to original (earlier iterations moved it) if (s0 == SQUARE) musicalLen += (t1-t0) * b0 / 240; else musicalLen += (t1-t0) * (b0+b1) / 480; } // Readjust points after selection double t0, t1, b0, b1; int s0; tempoMap.GetPoint(startId - 1, &t0, &b0, &s0, NULL); tempoMap.GetPoint(endId + 1, &t1, &b1, NULL, NULL); if (s0 == SQUARE) offset = (t0 + (240*musicalLen) / b0) - t1; else offset = (t0 + (480*musicalLen) / (b0 + b1)) - t1; while (!tempoMap.GetSelection(++endId) && endId < tempoMap.Count()) { double t; tempoMap.GetPoint(endId, &t, NULL, NULL, NULL); t += offset; tempoMap.SetPoint (endId, &t, NULL, NULL, NULL); } } // Delete selected tempo markers int idOffset = 0; for (int i = 0; i < tempoMap.CountSelected(); ++i) { int id = tempoMap.GetSelected(i) - idOffset; if (id != 0) // skip first point { tempoMap.DeletePoint(id); ++idOffset; } } // Commit tempo map and restore position info PreventUIRefresh(1); if (tempoMap.Commit(false)) { for (size_t i = 0; i < items.size(); ++i) items[i].Restore(); Undo_OnStateChangeEx2(NULL, SWS_CMD_SHORTNAME(ct), UNDO_STATE_ALL, -1); } PreventUIRefresh(-1); }
static void MidiTakePreview (int mode, MediaItem_Take* take, MediaTrack* track, double volume, double startOffset, double measureSync, bool pauseDuringPrev) { /* mode: 0 -> stop * * 1 -> start * * 2 -> toggle */ // First stop any ongoing preview RegisterCsurfPlayState(false, MidiTakePreviewPlayState); if (g_itemPreviewPlaying) { if (g_ItemPreview.preview_track) { StopTrackPreview(&g_ItemPreview); SendAllNotesOff((MediaTrack*)g_ItemPreview.preview_track); } else { StopPreview(&g_ItemPreview); } g_itemPreviewPlaying = false; plugin_register("-timer",(void*)MidiTakePreviewTimer); delete g_ItemPreview.src; if (g_itemPreviewPaused && mode != 1) // requesting new preview while old one is still playing shouldn't unpause playback { if (IsPaused(NULL)) OnPauseButtonEx(NULL); g_itemPreviewPaused = false; } // Toggled preview off...treat it as stop if (mode == 2) mode = 0; } // About IsRecording: REAPER won't preview anything during recording but extension will still think preview is in progress if we let it continue here if (mode == 0 || IsRecording(NULL)) return; if (take) { PreventUIRefresh(1); // item may get resized temporarily so hide it from the user MediaItem* item = GetMediaItemTake_Item(take); MediaItem_Take* oldTake = GetActiveTake(item); bool itemMuteState = *(bool*)GetSetMediaItemInfo(item, "B_MUTE", NULL); GetSetMediaItemInfo(item, "B_MUTE", &g_bFalse); // needs to be set before getting the source SetActiveTake(take); // active item take and editor take may differ // If timebase in MIDI editor is set to Beats (source), make sure item is croped so full MIDI source is visible beforing getting the source double itemStart = -1; double itemEnd = -1; double takeOffset = 0; double itemPositionOffset = 0; if (GetToggleCommandState2(SectionFromUniqueID(SECTION_MIDI_EDITOR), 40470) > 0) // Timebase: Beats(source) { itemStart = GetMediaItemInfo_Value(item, "D_POSITION"); itemEnd = itemStart + GetMediaItemInfo_Value(item, "D_LENGTH"); takeOffset = GetMediaItemTakeInfo_Value(take, "D_STARTOFFS"); double sourceLenPPQ = GetMidiSourceLengthPPQ(take, NULL); if (takeOffset != 0) SetMediaItemTakeInfo_Value(take, "D_STARTOFFS", 0); double itemSourceStart = MIDI_GetProjTimeFromPPQPos(take, 0); if (itemSourceStart < 0) { itemPositionOffset = abs(itemSourceStart); SetMediaItemInfo_Value(item, "D_POSITION", itemStart + itemPositionOffset); itemSourceStart = MIDI_GetProjTimeFromPPQPos(take, 0); } SetMediaItemInfo_Value(item, "D_POSITION", itemSourceStart); SetMediaItemInfo_Value(item, "D_LENGTH", MIDI_GetProjTimeFromPPQPos(take, sourceLenPPQ) - itemSourceStart); } double effectiveTakeLen = EffectiveMidiTakeEnd(take, true, true, true) - GetMediaItemInfo_Value(item, "D_POSITION"); PCM_source* src = DuplicateSource((PCM_source*)item); // must be item source otherwise item/take volume won't get accounted for if (src && effectiveTakeLen > 0) { GetSetMediaItemInfo((MediaItem*)src, "D_POSITION", &g_d0); GetSetMediaItemInfo((MediaItem*)src, "D_LENGTH", &effectiveTakeLen); if (!g_ItemPreview.src) { #ifdef _WIN32 InitializeCriticalSection(&g_ItemPreview.cs); #else pthread_mutex_init(&g_ItemPreview.mutex, NULL); #endif g_ItemPreview.loop = false; } g_ItemPreview.src = src; g_ItemPreview.m_out_chan = (track) ? (-1) : (0); g_ItemPreview.curpos = startOffset; g_ItemPreview.volume = volume; g_ItemPreview.preview_track = track; // Pause before preview otherwise MidiTakePreviewPlayState will stop it g_itemPreviewPaused = pauseDuringPrev; if (g_itemPreviewPaused && IsPlaying(NULL) && !IsPaused(NULL)) OnPauseButton(); if (g_ItemPreview.preview_track) g_itemPreviewPlaying = !!PlayTrackPreview2Ex(NULL, &g_ItemPreview, 1, measureSync); else g_itemPreviewPlaying = !!PlayPreviewEx(&g_ItemPreview, 1, measureSync); if (g_itemPreviewPlaying) { plugin_register("timer",(void*)MidiTakePreviewTimer); RegisterCsurfPlayState(true, MidiTakePreviewPlayState); } else delete g_ItemPreview.src; } if (itemStart != -1) { SetMediaItemInfo_Value(item, "D_POSITION", itemStart + itemPositionOffset); SetMediaItemInfo_Value(item, "D_LENGTH", itemEnd - itemStart); if (itemPositionOffset != 0) SetMediaItemInfo_Value(item, "D_POSITION", itemStart); if (takeOffset != 0) SetMediaItemTakeInfo_Value(take, "D_STARTOFFS", takeOffset); } SetActiveTake(oldTake); GetSetMediaItemInfo(item, "B_MUTE", &itemMuteState); PreventUIRefresh(-1); } }