void CopyCutTrackGrouping(COMMAND_T* _ct) { int updates = 0; bool copyDone = false; g_trackGrpClipboard.Set(""); // reset "clipboard" for (int i=0; i <= GetNumTracks(); i++) // incl. master { MediaTrack* tr = CSurf_TrackFromID(i, false); if (tr && *(int*)GetSetMediaTrackInfo(tr, "I_SELECTED", NULL)) { SNM_ChunkParserPatcher p(tr); if (!copyDone) copyDone = (p.Parse(SNM_GET_SUBCHUNK_OR_LINE, 1, "TRACK", "GROUP_FLAGS", 0, 0, &g_trackGrpClipboard, NULL, "MAINSEND") > 0); // cut (for all selected tracks) if ((int)_ct->user) updates += p.RemoveLines("GROUP_FLAGS", true); // brutal removing ok: "GROUP_FLAGS" is not part of freeze data // single copy: the 1st found track grouping else if (copyDone) break; } } if (updates) Undo_OnStateChangeEx2(NULL, SWS_CMD_SHORTNAME(_ct), UNDO_STATE_ALL, -1); }
void ME_CCEventAtEditCursor (COMMAND_T* ct, int val, int valhw, int relmode, HWND hwnd) { BR_MouseInfo mouseInfo(BR_MouseInfo::MODE_MIDI_EDITOR_ALL); if (mouseInfo.GetMidiEditor()) { if (MediaItem_Take* take = MIDIEditor_GetTake(mouseInfo.GetMidiEditor())) { double positionPPQ = MIDI_GetPPQPosFromProjTime(take, GetCursorPositionEx(NULL)); int lane, value; if (mouseInfo.GetCCLane(&lane, &value, NULL) && value >= 0) { if (lane == CC_TEXT_EVENTS || lane == CC_SYSEX || lane == CC_BANK_SELECT || lane == CC_VELOCITY) MessageBox((HWND)mouseInfo.GetMidiEditor(), __LOCALIZE("Can't insert in velocity, text, sysex and bank select lanes","sws_mbox"), __LOCALIZE("SWS/BR - Warning","sws_mbox"), MB_OK); else { bool do14bit = (lane >= CC_14BIT_START) ? true : false; int type = (lane == CC_PROGRAM) ? (STATUS_PROGRAM) : (lane == CC_CHANNEL_PRESSURE ? STATUS_CHANNEL_PRESSURE : (lane == CC_PITCH ? STATUS_PITCH : STATUS_CC)); int channel = MIDIEditor_GetSetting_int(mouseInfo.GetMidiEditor(), "default_note_chan"); int msg2 = CheckBounds(lane, 0, 127) ? ((value >> 7) | 0) : (value & 0x7F); int msg3 = CheckBounds(lane, 0, 127) ? (value & 0x7F) : ((value >> 7) | 0); int targetLane = (do14bit) ? lane - CC_14BIT_START : lane; int targetLane2 = (do14bit) ? targetLane + 32 : lane; MIDI_InsertCC(take, true, false, positionPPQ, type, channel, (CheckBounds(targetLane, 0, 127) ? targetLane : msg2), msg3); if (do14bit) MIDI_InsertCC(take, true, false, positionPPQ, type, channel, targetLane2, msg2); Undo_OnStateChangeEx2(NULL, SWS_CMD_SHORTNAME(ct), UNDO_STATE_ITEMS, -1); } } } }
void ClearProjectStartupAction(COMMAND_T* _ct) { if (PromptClearProjectStartupAction(true)==IDYES) { g_prjActions.Get()->Set(""); Undo_OnStateChangeEx2(NULL, SWS_CMD_SHORTNAME(_ct), UNDO_STATE_MISCCFG, -1); } }
void MainSetCCLanes(COMMAND_T* _ct) { HWND me = MIDIEditor_GetActive(); MediaItem_Take* tk = me ? MIDIEditor_GetTake(me) : NULL; if (tk) { // recall lanes char laneSlot[SNM_MAX_CC_LANES_LEN], slot[32] = ""; if (_snprintfStrict(slot, sizeof(slot), "cc_lanes_slot%d", (int)_ct->user + 1) > 0) { GetPrivateProfileString("MidiEditor", slot, "", laneSlot, SNM_MAX_CC_LANES_LEN, g_SNM_IniFn.Get()); int i=0; while (laneSlot[i] && i < (SNM_MAX_CC_LANES_LEN-2)) // -2: see string termination { if (laneSlot[i] == '|') laneSlot[i] = '\n'; i++; } laneSlot[i++] = '\n'; laneSlot[i] = 0; if (replaceCCLanes(laneSlot)) Undo_OnStateChangeEx2(NULL, SWS_CMD_SHORTNAME(_ct), UNDO_STATE_ALL, -1); } } }
void RemapMIDIInputChannel(COMMAND_T* _ct) { bool updated = false; int ch = (int)_ct->user; // 0: source channel char pLine[SNM_MAX_CHUNK_LINE_LENGTH] = ""; if (ch && _snprintfStrict(pLine, sizeof(pLine), "MIDI_INPUT_CHANMAP %d\n", ch-1) <= 0) return; for (int i=1; i <= GetNumTracks(); i++) // skip master { MediaTrack* tr = CSurf_TrackFromID(i, false); if (tr && *(int*)GetSetMediaTrackInfo(tr, "I_SELECTED", NULL)) { int in = *(int*)GetSetMediaTrackInfo(tr, "I_RECINPUT", NULL); if ((in & 0x1000) == 0x1000) // midi in? { SNM_ChunkParserPatcher p(tr); char currentCh[3] = ""; int chunkPos = p.Parse(SNM_GET_CHUNK_CHAR, 1, "TRACK", "MIDI_INPUT_CHANMAP", 0, 1, currentCh, NULL, "TRACKID"); if (chunkPos > 0) { if (!ch || atoi(currentCh) != (ch-1)) updated |= p.ReplaceLine(--chunkPos, pLine); // pLine can be "", i.e. remove line } else updated |= p.InsertAfterBefore(0, pLine, "TRACK", "TRACKHEIGHT", 1, 0, "TRACKID"); } } } if (updated) Undo_OnStateChangeEx2(NULL, SWS_CMD_SHORTNAME(_ct), UNDO_STATE_ALL, -1); }
void ToggleWriteEnvExists(COMMAND_T* _ct) { bool updated = false; // restore write modes if (g_toolbarAutoModeToggles.GetSize()) { for (int i=0; i < g_toolbarAutoModeToggles.GetSize(); i++) { SNM_TrackInt* tri = g_toolbarAutoModeToggles.Get(i); GetSetMediaTrackInfo(tri->m_tr, "I_AUTOMODE", &(tri->m_int)); updated = true; } g_toolbarAutoModeToggles.Empty(true); } // set read mode and store previous write modes else { for (int i=0; i <= GetNumTracks(); i++) // incl. master { MediaTrack* tr = CSurf_TrackFromID(i, false); int autoMode = tr ? *(int*)GetSetMediaTrackInfo(tr, "I_AUTOMODE", NULL) : -1; if (autoMode >= 2 /* touch */ && autoMode <= 4 /* latch */) { GetSetMediaTrackInfo(tr, "I_AUTOMODE", &g_i1); // set read mode g_toolbarAutoModeToggles.Add(new SNM_TrackInt(tr, autoMode)); updated = true; } } } if (updated) { Undo_OnStateChangeEx2(NULL, SWS_CMD_SHORTNAME(_ct), UNDO_STATE_ALL, -1); RefreshToolbar(SWSGetCommandID(ToggleWriteEnvExists)); // in case auto-refresh toolbar option is off.. } }
// I_FOLDERDEPTH : // 0=normal, 1=track is a folder parent, // -1=track is the last in the innermost folder // -2=track is the last in the innermost and next-innermost folders, etc void SetTracksFolderState(COMMAND_T* _ct) { bool updated = false; for (int i=1; i <= GetNumTracks(); i++) // skip master { MediaTrack* tr = CSurf_TrackFromID(i, false); if (tr && *(int*)GetSetMediaTrackInfo(tr, "I_SELECTED", NULL)) { int newState = (int)_ct->user; int curState = *(int*)GetSetMediaTrackInfo(tr, "I_FOLDERDEPTH", NULL); if ((int)_ct->user == -1) // last in folder? { if (SNM_GetTrackDepth(tr)>0) newState = curState<0 ? curState-1 : -1; else newState = curState; } else if ((int)_ct->user == -2) // very last in folder? { int depth = SNM_GetTrackDepth(tr); if (depth>0) newState = depth * (-1); else newState = curState; } if (curState!=newState) { GetSetMediaTrackInfo(tr, "I_FOLDERDEPTH", &newState); updated = true; } } } if (updated) Undo_OnStateChangeEx2(NULL, SWS_CMD_SHORTNAME(_ct), UNDO_STATE_ALL, -1); }
void RestoreTracksFolderStates(COMMAND_T* _ct) { bool updated = false; const char* strState = !_ct->user ? "I_FOLDERDEPTH" : "I_FOLDERCOMPACT"; WDL_PtrList_DeleteOnDestroy<SNM_TrackInt>* saveList = !_ct->user ? &g_trackFolderStates : &g_trackFolderCompactStates; for (int i=1; i <= GetNumTracks(); i++) // skip master { MediaTrack* tr = CSurf_TrackFromID(i, false); if (tr && *(int*)GetSetMediaTrackInfo(tr, "I_SELECTED", NULL)) { for(int j=0; j < saveList->GetSize(); j++) { SNM_TrackInt* savedTF = saveList->Get(j); int current = *(int*)GetSetMediaTrackInfo(tr, strState, NULL); if (savedTF->m_tr == tr && ((!_ct->user && savedTF->m_int != current) || (_ct->user && *(int*)GetSetMediaTrackInfo(tr, "I_FOLDERDEPTH", NULL) == 1 && savedTF->m_int != current))) { GetSetMediaTrackInfo(tr, strState, &(savedTF->m_int)); updated = true; break; } } } } if (updated) Undo_OnStateChangeEx2(NULL, SWS_CMD_SHORTNAME(_ct), UNDO_STATE_ALL, -1); }
void ToggleArmTrackEnv(COMMAND_T* _ct) { bool updated = false; for (int i=0; i <= GetNumTracks(); i++) // incl. master { MediaTrack* tr = CSurf_TrackFromID(i, false); if (tr && *(int*)GetSetMediaTrackInfo(tr, "I_SELECTED", NULL)) { SNM_ArmEnvParserPatcher p(tr); switch(_ct->user) { // all envs case 0: p.SetNewValue(-1);//toggle updated = (p.ParsePatch(-1) > 0); break; case 1: p.SetNewValue(1);//arm updated = (p.ParsePatch(-1) > 0); break; case 2: p.SetNewValue(0); //disarm updated = (p.ParsePatch(-1) > 0); break; // track vol/pan/mute envs case 3: updated = (p.ParsePatch(SNM_TOGGLE_CHUNK_INT, 2, "VOLENV2", "ARM", 0, 1) > 0); break; case 4: updated = (p.ParsePatch(SNM_TOGGLE_CHUNK_INT, 2, "PANENV2", "ARM", 0, 1) > 0); break; case 5: updated = (p.ParsePatch(SNM_TOGGLE_CHUNK_INT, 2, "MUTEENV", "ARM", 0, 1) > 0); break; // receive envs case 6: p.SetNewValue(-1); //toggle updated = (p.ParsePatch(-2) > 0); break; case 7: p.SetNewValue(-1); //toggle updated = (p.ParsePatch(-3) > 0); break; case 8: p.SetNewValue(-1); //toggle updated = (p.ParsePatch(-4) > 0); break; // plugin envs case 9: p.SetNewValue(-1); //toggle updated = (p.ParsePatch(-5) > 0); break; } } } if (updated) Undo_OnStateChangeEx2(NULL, SWS_CMD_SHORTNAME(_ct), UNDO_STATE_ALL, -1); }
void RemoveAllEnvsSelTracks(COMMAND_T* _ct) { bool updated = false; for (int i=0; i <= GetNumTracks(); i++) // incl. master if (MediaTrack* tr = CSurf_TrackFromID(i, false)) if (tr && *(int*)GetSetMediaTrackInfo(tr, "I_SELECTED", NULL)) { SNM_TrackEnvParserPatcher p(tr); updated |= p.RemoveEnvelopes(); } if (updated) Undo_OnStateChangeEx2(NULL, SWS_CMD_SHORTNAME(_ct), UNDO_STATE_ALL, -1); }
void SelOnlyTrackWithSelEnv(COMMAND_T* _ct) { bool updated = false; if (MediaTrack* envtr = GetTrackWithSelEnv()) for (int i=0; i <= GetNumTracks(); i++) // incl. master if (envtr == CSurf_TrackFromID(i, false)) { updated = SNM_SetSelectedTrack(NULL, envtr, true); break; } if (updated) Undo_OnStateChangeEx2(NULL, SWS_CMD_SHORTNAME(_ct), UNDO_STATE_ALL, -1); }
void RemoveTrackGrouping(COMMAND_T* _ct) { int updates = 0; for (int i=0; i <= GetNumTracks(); i++) // incl. master { MediaTrack* tr = CSurf_TrackFromID(i, false); if (tr && *(int*)GetSetMediaTrackInfo(tr, "I_SELECTED", NULL)) { SNM_ChunkParserPatcher p(tr); updates += p.RemoveLines("GROUP_FLAGS", true); // brutal removing ok: "GROUP_FLAGS" is not part of freeze data } } if (updates) Undo_OnStateChangeEx2(NULL, SWS_CMD_SHORTNAME(_ct), UNDO_STATE_ALL, -1); }
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); }
void SetProjectStartupAction(COMMAND_T* _ct) { if (PromptClearProjectStartupAction(false) == IDNO) return; char idstr[SNM_MAX_ACTION_CUSTID_LEN]; lstrcpyn(idstr, __LOCALIZE("Paste command ID or identifier string here","sws_mbox"), sizeof(idstr)); if (PromptUserForString(GetMainHwnd(), SWS_CMD_SHORTNAME(_ct), idstr, sizeof(idstr), true)) { WDL_FastString msg; if (int cmdId = SNM_NamedCommandLookup(idstr)) { // more checks: http://forum.cockos.com/showpost.php?p=1252206&postcount=1618 if (int tstNum = CheckSwsMacroScriptNumCustomId(idstr)) { msg.SetFormatted(256, __LOCALIZE_VERFMT("%s failed: unreliable command ID '%s'!","sws_DLG_161"), SWS_CMD_SHORTNAME(_ct), idstr); msg.Append("\n"); // localization note: msgs shared with the CA editor if (tstNum==-1) msg.Append(__LOCALIZE("For SWS/S&M actions, you must use identifier strings (e.g. _SWS_ABOUT), not command IDs (e.g. 47145).\nTip: to copy such identifiers, right-click the action in the Actions window > Copy selected action cmdID/identifier string.","sws_mbox")); else if (tstNum==-2) msg.Append(__LOCALIZE("For macros/scripts, you must use identifier strings (e.g. _f506bc780a0ab34b8fdedb67ed5d3649), not command IDs (e.g. 47145).\nTip: to copy such identifiers, right-click the macro/script in the Actions window > Copy selected action cmdID/identifier string.","sws_mbox")); MessageBox(GetMainHwnd(), msg.Get(), __LOCALIZE("S&M - Error","sws_DLG_161"), MB_OK); } else { g_prjActions.Get()->Set(idstr); Undo_OnStateChangeEx2(NULL, SWS_CMD_SHORTNAME(_ct), UNDO_STATE_MISCCFG, -1); msg.SetFormatted(256, __LOCALIZE_VERFMT("'%s' is defined as project startup action","sws_mbox"), kbd_getTextFromCmd(cmdId, NULL)); char prjFn[SNM_MAX_PATH] = ""; EnumProjects(-1, prjFn, sizeof(prjFn)); if (*prjFn) { msg.Append("\n"); msg.AppendFormatted(SNM_MAX_PATH, __LOCALIZE_VERFMT("for %s","sws_mbox"), prjFn); } msg.Append("."); MessageBox(GetMainHwnd(), msg.Get(), SWS_CMD_SHORTNAME(_ct), MB_OK); } } else { msg.SetFormatted(256, __LOCALIZE_VERFMT("%s failed: command ID or identifier string '%s' not found in the 'Main' section of the action list!","sws_DLG_161"), SWS_CMD_SHORTNAME(_ct), idstr); MessageBox(GetMainHwnd(), msg.Get(), __LOCALIZE("S&M - Error","sws_DLG_161"), MB_OK); } } }
void ME_RestoreNoteSelSlot (COMMAND_T* ct, int val, int valhw, int relmode, HWND hwnd) { if (MediaItem_Take* take = MIDIEditor_GetTake(MIDIEditor_GetActive())) { int slot = (int)ct->user; for (int i = 0; i < g_midiNoteSel.Get()->GetSize(); i++) { if (slot == g_midiNoteSel.Get()->Get(i)->GetSlot()) { g_midiNoteSel.Get()->Get(i)->Restore(take); Undo_OnStateChangeEx2(NULL, SWS_CMD_SHORTNAME(ct), UNDO_STATE_ALL, -1); return; } } } }
void ClearStartupAction(COMMAND_T* _ct) { int type=(int)_ct->user; if (PromptClearStartupAction(type, true)==IDYES) { if (!type) { g_prjActions.Get()->Set(""); Undo_OnStateChangeEx2(NULL, SWS_CMD_SHORTNAME(_ct), UNDO_STATE_MISCCFG, -1); } else { g_globalAction.Set(""); WritePrivateProfileString("Misc", "GlobalStartupAction", NULL, g_SNM_IniFn.Get()); } } }
void RenumberRegions(COMMAND_T* ct) { MarkerList ml(NULL, true); DeleteAllRegions(); int iID = 1; for (int i = 0; i < ml.m_items.GetSize(); i++) { MarkerItem* mi = ml.m_items.Get(i); if (mi->IsRegion()) { mi->SetNum(iID++); mi->AddToProject(); } } g_pMarkerList->Update(); UpdateTimeline(); Undo_OnStateChangeEx2(NULL, SWS_CMD_SHORTNAME(ct), UNDO_STATE_MISCCFG, -1); }
void ME_ShowUsedCCLanesDetect14Bit (COMMAND_T* ct, int val, int valhw, int relmode, HWND hwnd) { if (MediaItem_Take* take = MIDIEditor_GetTake(MIDIEditor_GetActive())) { RprTake rprTake(take); if (RprMidiCCLane* laneView = new (nothrow) RprMidiCCLane(rprTake)) { int defaultHeight = 67; // same height FNG versions use (to keep behavior identical) set<int> usedCC = GetUsedCCLanes(MIDIEditor_GetTake(MIDIEditor_GetActive()), 2); for (int i = 0; i < laneView->countShown(); ++i) if (usedCC.find(laneView->getIdAt(i)) == usedCC.end()) laneView->remove(i--); // Special case: Bank select and CC0 (from FNG version to keep behavior identical) if (usedCC.find(0) != usedCC.end() && usedCC.find(CC_BANK_SELECT) != usedCC.end() && !laneView->isShown(131)) laneView->append(131, defaultHeight); for (set<int>::iterator it = usedCC.begin(); it != usedCC.end(); ++it) { if (!laneView->isShown(*it)) laneView->append(*it, defaultHeight); else { for (int i = 0; i < laneView->countShown(); ++i) { if (laneView->getIdAt(i) == *it && laneView->getHeight(i) == 0) laneView->setHeightAt(i, defaultHeight); } } } if (laneView->countShown() == 0) laneView->append(-1, 0); delete laneView; Undo_OnStateChangeEx2(NULL, SWS_CMD_SHORTNAME(ct), UNDO_STATE_ITEMS, -1); } } }
void SetMIDIInputChannel(COMMAND_T* _ct) { bool updated = false; int ch = (int)_ct->user; // 0: all channels for (int i=1; i <= GetNumTracks(); i++) // skip master { MediaTrack* tr = CSurf_TrackFromID(i, false); if (tr && *(int*)GetSetMediaTrackInfo(tr, "I_SELECTED", NULL)) { int in = *(int*)GetSetMediaTrackInfo(tr, "I_RECINPUT", NULL); if (((in & 0x1000) == 0x1000) && ((in & 0x1F) != ch)) { in &= 0x1FE0; in |= ch; GetSetMediaTrackInfo(tr, "I_RECINPUT", &in); updated = true; } } } if (updated) Undo_OnStateChangeEx2(NULL, SWS_CMD_SHORTNAME(_ct), UNDO_STATE_ALL, -1); }
void PasteTrackGrouping(COMMAND_T* _ct) { int updates = 0; for (int i=0; i <= GetNumTracks(); i++) // incl. master { MediaTrack* tr = CSurf_TrackFromID(i, false); if (tr && *(int*)GetSetMediaTrackInfo(tr, "I_SELECTED", NULL)) { SNM_ChunkParserPatcher p(tr); updates += p.RemoveLines("GROUP_FLAGS", true); // brutal removing ok: "GROUP_FLAGS" is not part of freeze data int patchPos = p.Parse(SNM_GET_CHUNK_CHAR, 1, "TRACK", "TRACKHEIGHT", 0, 0, NULL, NULL, "MAINSEND"); if (patchPos > 0) { p.GetChunk()->Insert(g_trackGrpClipboard.Get(), --patchPos); p.IncUpdates(); // as we're directly working on the cached chunk.. updates++; } } } if (updates) Undo_OnStateChangeEx2(NULL, SWS_CMD_SHORTNAME(_ct), UNDO_STATE_ALL, -1); }
bool FindWnd::FindMarkerRegion(int _dir) { if (!_dir) return false; bool update = false, found = false; if (g_searchStr && *g_searchStr) { double startPos = GetCursorPositionEx(NULL); int id, x = 0; bool bR; double dPos, dRend, dMinMaxPos = _dir < 0 ? -DBL_MAX : DBL_MAX; const char *cName; while ((x=EnumProjectMarkers2(NULL, x, &bR, &dPos, &dRend, &cName, &id))) { if (_dir == 1 && dPos > startPos) { if (stristr(cName, g_searchStr)) { found = true; dMinMaxPos = min(dPos, dMinMaxPos); } } else if (_dir == -1 && dPos < startPos) { if (stristr(cName, g_searchStr)) { found = true; dMinMaxPos = max(dPos, dMinMaxPos); } } } UpdateNotFoundMsg(found); if (found) { SetEditCurPos2(NULL, dMinMaxPos, true, false); update = true; } } if (update) Undo_OnStateChangeEx2(NULL, __LOCALIZE("Find: change edit cursor position","sws_undo"), UNDO_STATE_ALL, -1); // in case the pref "undo pt for edit cursor positions" is enabled.. return update; }
void DeleteTempo (COMMAND_T* ct) { // Get tempo map BR_Envelope tempoMap(GetTempoEnv()); if (!tempoMap.CountSelected()) return; int offset = 0; // Loop through selected points and perform BPM calculations int skipped = 0; for (int i = 0; i < tempoMap.CountSelected(); ++i) { int id = tempoMap.GetSelected(i) + offset; if (id == 0) continue; // Get tempo points double t1, t2, t3, t4; double b1, b2, b3, b4; int s0, s1, s2, s3; tempoMap.GetPoint(id, &t2, &b2, &s2, NULL); bool P0 = tempoMap.GetPoint(id-2, NULL, NULL, &s0, NULL); bool P1 = tempoMap.GetPoint(id-1, &t1, &b1, &s1, NULL); bool P3 = tempoMap.GetPoint(id+1, &t3, &b3, &s3, NULL); bool P4 = tempoMap.GetPoint(id+2, &t4, &b4, NULL, NULL); // Hold new values double Nt1, Nb1; double Nt3, Nb3; // If previous point doesn't exist, fake it if (!P0) s0 = SQUARE; // Get P2-P3 length double m2; if (s2 == SQUARE) m2 = b2*(t3-t2) / 240; else m2 = (b2+b3)*(t3-t2) / 480; ///// CALCULATE BPM VALUES ///// //////////////////////////////// if (P3) { if (s0 == SQUARE) { if (s1 == SQUARE) { Nt1 = t1; Nb1 = (240*m2 + b1*(t2-t1)) / (t3-t1); } else { Nt1 = t1; Nb1 = (480*m2 + (b1+b2)*(t2-t1)) / (t3-t1) - b3; } // Check new value is legal if (Nb1 > MAX_BPM || Nb1 < MIN_BPM) SKIP(skipped, 1); // Next point stays the same P3 = false; } else { // If P4 exists... if (P4) { if (s1 == SQUARE) { if (s3 == SQUARE) { Nt3 = t2 + 240*m2 / b1; Nb3 = b3*(t4-t3) / (t4-Nt3); } else { Nt3 = t2 + 240*m2 / b1; Nb3 = (b3+b4)*(t4-t3) / (t4-Nt3) - b4; } } else { if (s3 == SQUARE) { double f1 = (b1+b2)*(t2-t1) + 480*m2; double f2 = b3*(t4-t3); double a = b1; double b = (a*(t1+t4) + f1+f2) / 2; double c = a*(t1*t4) + f1*t4 + f2*t1; Nt3 = c / (b + sqrt(pow(b,2) - a*c)); Nb3 = f2 / (t4 - Nt3); } else { double f1 = (b1+b2)*(t2-t1) + 480*m2; double f2 = (b3+b4)*(t4-t3); double a = b1-b4; double b = (a*(t1+t4) + f1+f2) / 2; double c = a*(t1*t4) + f1*t4 + f2*t1; Nt3 = c / (b + sqrt(pow(b,2) - a*c)); Nb3 = f2 / (t4 - Nt3) - b4; } } // Check new position is legal if ((Nt3 - t1) < MIN_TEMPO_DIST || (t4 - Nt3) < MIN_TEMPO_DIST) SKIP(skipped, 1); } // If P4 does not exist else { if (s1 == SQUARE) { Nt3 = t2 + 240*m2 / b1; Nb3 = b3; } else { Nt3 = t3; Nb3 = (480*m2 + (b1+b2)*(t2-t1)) / (t3-t1) - b1; } // Check new position is legal if ((Nt3 - t1) < MIN_TEMPO_DIST) SKIP(skipped, 1); } // Check new value is legal if (Nb3 > MAX_BPM || Nb3 < MIN_BPM) SKIP(skipped, 1); // Previous point stays the same P1 = false; } } else { // No surrounding points get edited P1 = false; P3 = false; } ///// SET NEW BPM ///// /////////////////////// // Previous point if (P1) tempoMap.SetPoint(id-1, &Nt1, &Nb1, NULL, NULL); // Next point if (P3) tempoMap.SetPoint(id+1, &Nt3, &Nb3, NULL, NULL); // Delete point tempoMap.DeletePoint(id); --offset; } // Commit changes if (tempoMap.Commit()) Undo_OnStateChangeEx2(NULL, SWS_CMD_SHORTNAME(ct), UNDO_STATE_ALL, -1); // Warn user if some points weren't processed static bool s_warnUser = true; if (s_warnUser && skipped != 0) { char buffer[512]; _snprintfSafe(buffer, sizeof(buffer), __LOCALIZE_VERFMT("%d of the selected points didn't get processed because some points would end up with illegal BPM or position. Would you like to be warned if it happens again?", "sws_mbox"), skipped); int userAnswer = ShowMessageBox(buffer, __LOCALIZE("SWS - Warning", "sws_mbox"), 4); if (userAnswer == 7) s_warnUser = false; } }
static void ApplyGrooveInMidiEditor(COMMAND_T* ct, int val, int valhw, int relmode, HWND hwnd) { ApplyGrooveInMidiEditor(0, &ct->user); Undo_OnStateChangeEx2(NULL, SWS_CMD_SHORTNAME(ct), UNDO_STATE_ITEMS, -1); }
void GotoAnsSelectRegion(COMMAND_T* _ct) { if (GotoMarkerRegion(NULL, ((int)_ct->user)+1, SNM_REGION_MASK, true)) Undo_OnStateChangeEx2(NULL, SWS_CMD_SHORTNAME(_ct), UNDO_STATE_ALL, -1); }
void InsertMarker(COMMAND_T* _ct) { AddProjectMarker2(NULL, false, (int)_ct->user && (GetPlayStateEx(NULL)&1) ? GetPlayPositionEx(NULL) : GetCursorPositionEx(NULL), 0.0, "", -1, 0); UpdateTimeline(); Undo_OnStateChangeEx2(NULL, SWS_CMD_SHORTNAME(_ct), UNDO_STATE_MISCCFG, -1); }
void GotoMarker(COMMAND_T* _ct) { if (GotoMarkerRegion(NULL, ((int)_ct->user)+1, SNM_MARKER_MASK)) Undo_OnStateChangeEx2(NULL, SWS_CMD_SHORTNAME(_ct), UNDO_STATE_ALL, -1); }
static void ShowOnlyTopCCLane(COMMAND_T* ct, int val, int valhw, int relmode, HWND hwnd) { ShowOnlyTopCCLane(UNDO_STATE_ITEMS, &ct->user); Undo_OnStateChangeEx2(NULL, SWS_CMD_SHORTNAME(ct), UNDO_STATE_ITEMS, -1); }
static void HideUnusedCCLanes(COMMAND_T* ct, int val, int valhw, int relmode, HWND hwnd) { HideUnusedCCLanes(UNDO_STATE_ITEMS, &ct->user); Undo_OnStateChangeEx2(NULL, SWS_CMD_SHORTNAME(ct), UNDO_STATE_ITEMS, -1); }
static void CycleThroughMidiLanes(COMMAND_T* ct, int val, int valhw, int relmode, HWND hwnd) { CycleThroughMidiLanes(UNDO_STATE_ITEMS, &ct->user); Undo_OnStateChangeEx2(NULL, SWS_CMD_SHORTNAME(ct), UNDO_STATE_ITEMS, -1); }
void ContinuousActionStopAll () { if (g_actionInProgress && g_actionInProgress->DoUndo && g_actionInProgress->DoUndo()) Undo_OnStateChangeEx2(NULL, SWS_CMD_SHORTNAME(SWSGetCommandByID(g_actionInProgress->cmd)), UNDO_STATE_ALL, -1); ContinuousActionInit(false, 0, NULL); }