Example #1
0
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, &noteCount, &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);
}
Example #2
0
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);
}
Example #3
0
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);
	}
}