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 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 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; }
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; }