bool replaceCCLanes(const char* _newCClanes) { bool updated = false; HWND me = MIDIEditor_GetActive(); MediaItem_Take* tk = me ? MIDIEditor_GetTake(me) : NULL; if (tk) { MediaItem* item = GetMediaItemTake_Item(tk); int tkIdx = GetTakeIndex(item, tk); // NULL item managed if (tkIdx >= 0) { SNM_TakeParserPatcher p(item, CountTakes(item)); WDL_FastString takeChunk; int tkPos, tklen; if (p.GetTakeChunk(tkIdx, &takeChunk, &tkPos, &tklen)) { SNM_ChunkParserPatcher ptk(&takeChunk, false); int pos = ptk.Parse(SNM_GET_CHUNK_CHAR, 1, "SOURCE", "VELLANE", 0, 0); if (pos > 0) { pos--; // see SNM_ChunkParserPatcher // Remove all lanes for this take if (ptk.RemoveLines("VELLANE")) { ptk.GetChunk()->Insert(_newCClanes, pos); // default lane (min sized) updated = p.ReplaceTake(tkPos, tklen, ptk.GetChunk()); } } } } } return updated; }
void TakeRandomCols(COMMAND_T* = NULL) { COLORREF cr; // All black check if (AllBlack()) return; for (int i = 1; i <= GetNumTracks(); i++) { MediaTrack* tr = CSurf_TrackFromID(i, false); for (int j = 0; j < GetTrackNumMediaItems(tr); j++) { MediaItem* mi = GetTrackMediaItem(tr, j); if (*(bool*)GetSetMediaItemInfo(mi, "B_UISEL", NULL)) { for (int h = 0; h < CountTakes(mi); h++) { while (!(cr = g_custColors[rand() % 16])); cr |= 0x1000000; GetSetMediaItemTakeInfo(GetTake(mi, h), "I_CUSTOMCOLOR", &cr); } } } } Undo_OnStateChange(__LOCALIZE("Set takes in selected item(s) to random custom color(s)","sws_undo")); UpdateTimeline(); }
void RegionsFromItems(COMMAND_T* ct) { // Ignore the fact that the user may have items selected with the exact same times. Just blindly create regions! WDL_TypedBuf<MediaItem*> items; SWS_GetSelectedMediaItems(&items); bool bUndo = false; for (int i = 0; i < items.GetSize(); i++) { MediaItem_Take* take = GetActiveTake(items.Get()[i]); if (take) { char* cName = (char*)GetSetMediaItemTakeInfo(take, "P_NAME", NULL); double dStart = *(double*)GetSetMediaItemInfo(items.Get()[i], "D_POSITION", NULL); double dEnd = *(double*)GetSetMediaItemInfo(items.Get()[i], "D_LENGTH", NULL) + dStart; AddProjectMarker(NULL, true, dStart, dEnd, cName, -1); bUndo = true; } else if (!CountTakes(items.Get()[i])) /* In case of an empty item there is no take so process item instead */ { double dStart = *(double*)GetSetMediaItemInfo(items.Get()[i], "D_POSITION", NULL); double dEnd = *(double*)GetSetMediaItemInfo(items.Get()[i], "D_LENGTH", NULL) + dStart; AddProjectMarker(NULL, true, dStart, dEnd, NULL, -1); bUndo = true; } } if (bUndo) { UpdateTimeline(); Undo_OnStateChangeEx(SWS_CMD_SHORTNAME(ct), UNDO_STATE_MISCCFG, -1); } }
/****************************************************************************** * BR_MidiItemTimePos * ******************************************************************************/ BR_MidiItemTimePos::BR_MidiItemTimePos (MediaItem* item) : item (item), position (GetMediaItemInfo_Value(item, "D_POSITION")), length (GetMediaItemInfo_Value(item, "D_LENGTH")), timeBase (GetMediaItemInfo_Value(item, "C_BEATATTACHMODE")), looped (!!GetMediaItemInfo_Value(item, "B_LOOPSRC")), loopStart (-1), loopEnd (-1), loopedOffset (0) { // When restoring position and lenght, the only way to restore it for looped MIDI items is to use MIDI_SetItemExtents which will disable looping // for the whole item. Since we have no idea what will happen before this->Restore() is called take data for active MIDI item right now instead of // in this->Restore() (for example, if client calls SetIgnoreTempo() from BR_Util.h before restoring to disable "ignore project tempo" length of MIDI item source may change) if (looped) { if (MediaItem_Take* activeTake = GetActiveTake(item)) { double sourceLenPPQ = GetMidiSourceLengthPPQ(activeTake, true); loopStart = MIDI_GetProjTimeFromPPQPos(activeTake, sourceLenPPQ); // we're not using MIDI_GetProjTimeFromPPQPos(activeTake, 0) because later we will use MIDI_SetItemExtents to make sure looped item loopEnd = MIDI_GetProjTimeFromPPQPos(activeTake, sourceLenPPQ*2); // position info is restored and 0 PPQ in take could theoretically be behind project start in which case MIDI_SetItemExtents wont' work properly loopedOffset = GetMediaItemTakeInfo_Value(activeTake, "D_STARTOFFS"); } } int takeCount = CountTakes(item); for (int i = 0; i < takeCount; ++i) { MediaItem_Take* take = GetTake(item, i); int noteCount, ccCount, textCount; int midiEventCount = MIDI_CountEvts(take, ¬eCount, &ccCount, &textCount); // In case of looped item, if active take wasn't midi, get looped position here for first MIDI take if (looped && loopStart == -1 && loopEnd == -1 && IsMidi(take, NULL) && (midiEventCount > 0 || i == takeCount - 1)) { double sourceLenPPQ = GetMidiSourceLengthPPQ(take, true); loopStart = MIDI_GetProjTimeFromPPQPos(take, sourceLenPPQ); loopEnd = MIDI_GetProjTimeFromPPQPos(take, sourceLenPPQ*2); loopedOffset = GetMediaItemTakeInfo_Value(take, "D_STARTOFFS"); } if (midiEventCount > 0) { savedMidiTakes.push_back(BR_MidiItemTimePos::MidiTake(take, noteCount, ccCount, textCount)); BR_MidiItemTimePos::MidiTake* midiTake = &savedMidiTakes.back(); for (int i = 0; i < noteCount; ++i) midiTake->noteEvents.push_back(BR_MidiItemTimePos::MidiTake::NoteEvent(take, i)); for (int i = 0; i < ccCount; ++i) midiTake->ccEvents.push_back(BR_MidiItemTimePos::MidiTake::CCEvent(take, i)); for (int i = 0; i < textCount; ++i) midiTake->sysEvents.push_back(BR_MidiItemTimePos::MidiTake::SysEvent(take, i)); } } }
void MainSaveCCLanes(COMMAND_T* _ct) { HWND me = MIDIEditor_GetActive(); MediaItem_Take* tk = me ? MIDIEditor_GetTake(me) : NULL; if (tk) { MediaItem* item = GetMediaItemTake_Item(tk); int tkIdx = GetTakeIndex(item, tk); // NULL item managed if (tkIdx >= 0) { SNM_TakeParserPatcher p(item, CountTakes(item)); WDL_FastString takeChunk; if (p.GetTakeChunk(tkIdx, &takeChunk)) { SNM_ChunkParserPatcher ptk(&takeChunk, false); // check start/end position of lanes in the chunk int firstPos = 0, lastPos = 0, laneCpt = 0; int pos = ptk.Parse(SNM_GET_CHUNK_CHAR, 1, "SOURCE", "VELLANE", laneCpt, 0); while (pos > 0) { lastPos = pos; if (!firstPos) firstPos = pos; pos = ptk.Parse(SNM_GET_CHUNK_CHAR, 1, "SOURCE", "VELLANE", ++laneCpt, 0); } if (firstPos > 0) { firstPos--; // see SNM_ChunkParserPatcher char laneSlot[SNM_MAX_CC_LANES_LEN] = ""; int eolLastPos = lastPos; const char* pp = ptk.GetChunk()->Get(); //ok 'cause read only while (pp[eolLastPos] && pp[eolLastPos] != '\n') eolLastPos++; int i = firstPos, j=0; while (pp[i] && i<eolLastPos && j < (SNM_MAX_CC_LANES_LEN-1) ) { //-1 see string termination if (pp[i] != '\n') laneSlot[j++] = pp[i]; else laneSlot[j++] = '|'; i++; } laneSlot[j] = 0; // store lanes char slot[32] = ""; if (_snprintfStrict(slot, sizeof(slot), "cc_lanes_slot%d", (int)_ct->user + 1) > 0) WritePrivateProfileString("MidiEditor", slot, laneSlot, g_SNM_IniFn.Get()); } } } } }
void TakeGradient(COMMAND_T* = NULL) { int tCurPos = 0; for (int i = 1; i <= GetNumTracks(); i++) { MediaTrack* tr = CSurf_TrackFromID(i, false); for (int j = 0; j < GetTrackNumMediaItems(tr); j++) { MediaItem* mi = GetTrackMediaItem(tr, j); if (*(bool*)GetSetMediaItemInfo(mi, "B_UISEL", NULL)) { for (int h = 0; h < CountTakes(mi); h++) { COLORREF cr = CalcGradient(g_crGradStart, g_crGradEnd, (double)tCurPos++ / (CountTakes(mi)-1)) | 0x1000000; GetSetMediaItemTakeInfo(GetTake(mi, h), "I_CUSTOMCOLOR", &cr); } tCurPos = 0; } } } Undo_OnStateChange(__LOCALIZE("Set takes in selected item(s) to color gradient","sws_undo")); UpdateTimeline(); }
void MainCreateCCLane(COMMAND_T* _ct) { bool updated = false; HWND me = MIDIEditor_GetActive(); MediaItem_Take* tk = me ? MIDIEditor_GetTake(me) : NULL; if (tk) { MediaItem* item = GetMediaItemTake_Item(tk); int tkIdx = GetTakeIndex(item, tk); // null item managed there if (tkIdx >= 0) { SNM_TakeParserPatcher p(item, CountTakes(item)); WDL_FastString takeChunk; int tkPos, tklen; if (p.GetTakeChunk(tkIdx, &takeChunk, &tkPos, &tklen)) { SNM_ChunkParserPatcher ptk(&takeChunk, false); // check current lanes bool lanes[SNM_MAX_CC_LANE_ID+1]; int i=0; while(i <= SNM_MAX_CC_LANE_ID) lanes[i++]=false; char lastLaneId[4] = ""; //max in v3.6: "133" int tkFirstPos = 0, laneCpt = 0; int pos = ptk.Parse(SNM_GET_CHUNK_CHAR, 1, "SOURCE", "VELLANE", laneCpt, 1, lastLaneId); while (pos > 0) { if (!tkFirstPos) tkFirstPos = pos; lanes[atoi(lastLaneId)] = true; // atoi: 0 on failure, lane 0 won't be used anyway.. pos = ptk.Parse(SNM_GET_CHUNK_CHAR, 1, "SOURCE", "VELLANE", ++laneCpt, 1, lastLaneId); } if (tkFirstPos > 0) { tkFirstPos--; // see SNM_ChunkParserPatcher // find the first unused index i=1; while(lanes[i] && i <= SNM_MAX_CC_LANE_ID) i++; char newLane[SNM_MAX_CHUNK_LINE_LENGTH] = ""; if (_snprintfStrict(newLane, sizeof(newLane), "VELLANE %d 50 0\n", i) > 0) ptk.GetChunk()->Insert(newLane, tkFirstPos); // "update" take updated = p.ReplaceTake(tkPos, tklen, ptk.GetChunk()); } } } } if (updated) Undo_OnStateChangeEx2(NULL, SWS_CMD_SHORTNAME(_ct), UNDO_STATE_ALL, -1); }
// note: PCM_source.Load/SaveState() won't always work // e.g. getting an empty take src, turning wav src into midi, etc.. bool SNM_GetSetSourceState(MediaItem* _item, int _takeIdx, WDL_FastString* _state, bool _setnewvalue) { bool ok = false; if (_item && _state && g_script_strs.Find(_state)>=0) { if (_takeIdx<0) _takeIdx = *(int*)GetSetMediaItemInfo(_item, "I_CURTAKE", NULL); int tkPos, tklen; WDL_FastString takeChunk; SNM_TakeParserPatcher p(_item, CountTakes(_item)); if (p.GetTakeChunk(_takeIdx, &takeChunk, &tkPos, &tklen)) { SNM_ChunkParserPatcher ptk(&takeChunk, false); // set if (_setnewvalue) { // standard case: a source is defined if (ptk.ReplaceSubChunk("SOURCE", 1, 0, _state->Get())) // no break keyword here: we're already at the end of the item.. ok = p.ReplaceTake(tkPos, tklen, ptk.GetChunk()); // replacing an empty take else { WDL_FastString newTkChunk("TAKE\n"); newTkChunk.Append(_state); ok = p.ReplaceTake(tkPos, tklen, &newTkChunk); } } // get else { if (ptk.GetSubChunk("SOURCE", 1, 0, _state)<0) _state->Set(""); // empty take ok = true; } } } return ok; }
void TakeOrderedCol(COMMAND_T* = NULL) { UpdateCustomColors(); int tCurPos = 0; for (int i = 1; i <= GetNumTracks(); i++) { MediaTrack* tr = CSurf_TrackFromID(i, false); for (int j = 0; j < GetTrackNumMediaItems(tr); j++) { MediaItem* mi = GetTrackMediaItem(tr, j); if (*(bool*)GetSetMediaItemInfo(mi, "B_UISEL", NULL)) { for (int h = 0; h < CountTakes(mi); h++) { COLORREF cr = g_custColors[tCurPos++ % 16] | 0x1000000; GetSetMediaItemTakeInfo(GetTake(mi, h), "I_CUSTOMCOLOR", &cr); } tCurPos = 0; } } } Undo_OnStateChange(__LOCALIZE("Set takes in selected item(s) to ordered custom colors","sws_undo")); UpdateTimeline(); }
bool BR_MidiEditor::Build () { m_take = (m_midiEditor) ? SWS_MIDIEditor_GetTake(m_midiEditor) : m_take; if (m_take) { MediaItem* item = GetMediaItemTake_Item(m_take); int takeId = GetTakeId(m_take, item); if (takeId >= 0) { SNM_TakeParserPatcher p(item, CountTakes(item)); WDL_FastString takeChunk; if (p.GetTakeChunk(takeId, &takeChunk)) { SNM_ChunkParserPatcher ptk(&takeChunk, false); LineParser lp(false); int laneId = 0; WDL_FastString lineLane; while (ptk.Parse(SNM_GET_SUBCHUNK_OR_LINE, 1, "SOURCE", "VELLANE", laneId++, -1, &lineLane)) { lp.parse(lineLane.Get()); m_ccLanes.push_back(lp.gettoken_int(1)); m_ccLanesHeight.push_back(lp.gettoken_int(((m_midiEditor) ? 2 : 3))); if (!m_midiEditor && m_ccLanesHeight.back() == 0) m_ccLanesHeight.back() = INLINE_MIDI_LANE_DIVIDER_H; // sometimes REAPER will return 0 when lane is completely hidden, but divider will still be visible lineLane.DeleteSub(0, lineLane.GetLength()); } WDL_FastString dataLine; if (ptk.Parse(SNM_GET_SUBCHUNK_OR_LINE, 1, "SOURCE", "HASDATA", 0, -1, &dataLine)) { lp.parse(dataLine.Get()); m_ppq = lp.gettoken_int(2); } else if (ptk.Parse(SNM_GET_SUBCHUNK_OR_LINE, 1, "SOURCE", "FILE", 0, -1, &dataLine)) { lp.parse(dataLine.Get()); m_ppq = GetMIDIFilePPQ (lp.gettoken_str(1)); if (!m_ppq) return false; } else return false; WDL_FastString lineView; if (ptk.Parse(SNM_GET_SUBCHUNK_OR_LINE, 1, "SOURCE", "CFGEDITVIEW", 0, -1, &lineView)) { lp.parse(lineView.Get()); m_startPos = (m_midiEditor) ? lp.gettoken_float(1) : GetMediaItemInfo_Value(GetMediaItemTake_Item(m_take), "D_POSITION"); m_hZoom = (m_midiEditor) ? lp.gettoken_float(2) : GetHZoomLevel(); m_vPos = (m_midiEditor) ? lp.gettoken_int(3) : lp.gettoken_int(7); m_vZoom = (m_midiEditor) ? lp.gettoken_int(4) : lp.gettoken_int(6); } else return false; WDL_FastString lineFilter; if (ptk.Parse(SNM_GET_SUBCHUNK_OR_LINE, 1, "SOURCE", "EVTFILTER", 0, -1, &lineFilter)) { lp.parse(lineFilter.Get()); m_filterEnabled = !!GetBit(lp.gettoken_int(7), 0); m_filterInverted = !!GetBit(lp.gettoken_int(7), 2); m_filterChannel = lp.gettoken_int(1); m_filterEventType = lp.gettoken_int(2); m_filterEventParam = !!lp.gettoken_int(16); m_filterEventVal = !!lp.gettoken_int(8); m_filterEventPos = !!lp.gettoken_int(14); m_filterEventLen = !!lp.gettoken_int(9); m_filterEventParamLo = lp.gettoken_int(17); m_filterEventParamHi = lp.gettoken_int(18); m_filterEventValLo = lp.gettoken_int(4); m_filterEventValHi = lp.gettoken_int(5); m_filterEventPosRepeat = lp.gettoken_float(15); m_filterEventPosLo = lp.gettoken_float(12); m_filterEventPosHi = lp.gettoken_float(13); m_filterEventLenLo = lp.gettoken_float(10); m_filterEventLenHi = lp.gettoken_float(11); } else return false; WDL_FastString lineProp; if (ptk.Parse(SNM_GET_SUBCHUNK_OR_LINE, 1, "SOURCE", "CFGEDIT", 0, -1, &lineProp)) { lp.parse(lineProp.Get()); m_pianoroll = (m_midiEditor) ? lp.gettoken_int(6) : 0; // inline midi editor doesn't have piano roll modes m_drawChannel = lp.gettoken_int(9) - 1; m_noteshow = lp.gettoken_int(18); m_timebase = (m_midiEditor) ? lp.gettoken_int(19) : PROJECT_SYNC; } else return false; // A few "corrections" for easier manipulation afterwards if (m_filterChannel == 0) m_filterChannel = ~m_filterChannel; if (m_filterEventParamLo < 0) m_filterEventParamLo = 0; if (m_filterEventParamHi < 0) m_filterEventParamHi = INT_MAX; if (m_filterEventValLo < 0) m_filterEventValLo = 0; if (m_filterEventValHi < 0) m_filterEventValHi = INT_MAX; if (m_filterEventPosLo < 0) m_filterEventPosLo = 0; if (m_filterEventPosHi < 0) m_filterEventPosHi = INT_MAX; m_filterEventLenLo = (m_filterEventLenLo < 0) ? (0) : (m_ppq * 4 * m_filterEventLenLo); m_filterEventLenHi = (m_filterEventLenHi < 0) ? (INT_MAX) : (m_ppq * 4 * m_filterEventLenHi); m_filterEventPosLo = (m_filterEventPosLo < 0) ? (0) : (m_ppq * 4 * m_filterEventPosLo); m_filterEventPosHi = (m_filterEventPosHi < 0) ? (INT_MAX) : (m_ppq * 4 * m_filterEventPosHi); m_filterEventPosRepeat = (m_filterEventPosRepeat < 0) ? (0) : (m_ppq * 4 * m_filterEventPosRepeat); return true; } } } return false; }