int FindFirstUnusedGroup() { bool grp[SNM_MAX_TRACK_GROUPS]; memset(grp, 0, sizeof(bool)*SNM_MAX_TRACK_GROUPS); for (int i=0; i <= GetNumTracks(); i++) // incl. master { //JFB TODO? exclude selected tracks? if (MediaTrack* tr = CSurf_TrackFromID(i, false)) { SNM_ChunkParserPatcher p(tr); WDL_FastString grpLine; if (p.Parse(SNM_GET_SUBCHUNK_OR_LINE, 1, "TRACK", "GROUP_FLAGS", 0, 0, &grpLine, NULL, "TRACKHEIGHT")) { LineParser lp(false); if (!lp.parse(grpLine.Get())) { for (int j=1; j < lp.getnumtokens(); j++) { // skip 1st token GROUP_FLAGS int val = lp.gettoken_int(j); for (int k=0; k < SNM_MAX_TRACK_GROUPS; k++) { int grpMask = int(pow(2.0, k*1.0)); grp[k] |= ((val & grpMask) == grpMask); } } } } } } for (int i=0; i < SNM_MAX_TRACK_GROUPS; i++) if (!grp[i]) return i; return -1; }
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 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); }
// 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 SelPrevItem(COMMAND_T* ctx) { // Find the last selected MediaItem* prevMi = NULL; for (int i = 1; i <= GetNumTracks(); i++) { MediaTrack* tr = CSurf_TrackFromID(i, false); if (GetTrackVis(tr) & 2) { for (int j = 0; j < GetTrackNumMediaItems(tr); j++) { MediaItem* mi = GetTrackMediaItem(tr, j); if (*(bool*)GetSetMediaItemInfo(mi, "B_UISEL", NULL)) { if (prevMi) { if (ctx->user == 0) Main_OnCommand(40289, 0); // Unselect all items GetSetMediaItemInfo(prevMi, "B_UISEL", &g_bTrue); UpdateTimeline(); return; } } prevMi = mi; } } } }
void RecSrcOut(COMMAND_T* = NULL) { // Set the rec source to output // Set to mono or stereo based on first item for (int i = 1; i <= GetNumTracks(); i++) { int iMode = 1; // 5 = mono, 1 = stereo MediaTrack* tr = CSurf_TrackFromID(i, false); if (*(int*)GetSetMediaTrackInfo(tr, "I_SELECTED", NULL)) { if (GetTrackNumMediaItems(tr)) { MediaItem* mi = GetTrackMediaItem(tr, 0); if (GetMediaItemNumTakes(mi)) { MediaItem_Take* mit = GetMediaItemTake(mi, 0); PCM_source* p = (PCM_source*)GetSetMediaItemTakeInfo(mit, "P_SOURCE", NULL); if (p && p->GetNumChannels() == 1) iMode = 5; } } GetSetMediaTrackInfo(tr, "I_RECMODE", &iMode); } } }
/* Return the last tap score of a row: the grade of the tap that completed * the row. If the row has no tap notes, return -1. If any tap notes aren't * graded (any tap is TNS_NONE) or are missed (TNS_MISS), return it. */ int NoteDataWithScoring::LastTapNoteScoreTrack(unsigned row) const { float scoretime = -9999; int best_track = -1; for( int t=0; t<GetNumTracks(); t++ ) { /* Skip empty tracks and mines */ TapNote tn = GetTapNote(t, row); if( tn.type == TapNote::empty || tn.type == TapNote::mine ) continue; TapNoteScore tns = GetTapNoteScore(t, row); if( tns == TNS_MISS || tns == TNS_NONE ) return t; float tm = GetTapNoteOffset(t, row); if(tm < scoretime) continue; scoretime = tm; best_track = t; } return best_track; }
int NoteDataWithScoring::GetNumNWithScore( TapNoteScore tns, int MinTaps, const float fStartBeat, float fEndBeat ) const { if( fEndBeat == -1 ) fEndBeat = GetNumBeats(); int iStartIndex = BeatToNoteRow( fStartBeat ); int iEndIndex = BeatToNoteRow( fEndBeat ); iStartIndex = max( iStartIndex, 0 ); iEndIndex = min( iEndIndex, GetNumRows()-1 ); int iNumSuccessfulDoubles = 0; for( int i=iStartIndex; i<=iEndIndex; i++ ) { int iNumNotesThisIndex = 0; TapNoteScore minTapNoteScore = TNS_MARVELOUS; for( int t=0; t<GetNumTracks(); t++ ) { switch( GetTapNote(t, i).type ) { case TapNote::tap: case TapNote::hold_head: iNumNotesThisIndex++; minTapNoteScore = min( minTapNoteScore, GetTapNoteScore(t, i) ); break; } } if( iNumNotesThisIndex >= MinTaps && minTapNoteScore >= tns ) iNumSuccessfulDoubles++; } return iNumSuccessfulDoubles; }
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 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 ColorChildren(COMMAND_T* = NULL) { int iParentDepth; COLORREF crParentColor; bool bSelected = false; MediaTrack* gfd = NULL; for (int i = 1; i <= GetNumTracks(); i++) { MediaTrack* tr = CSurf_TrackFromID(i, false); int iType; int iFolder = GetFolderDepth(tr, &iType, &gfd); if (bSelected) GetSetMediaTrackInfo(tr, "I_CUSTOMCOLOR", &crParentColor); if (iType == 1) { if (!bSelected && *(int*)GetSetMediaTrackInfo(tr, "I_SELECTED", NULL)) { iParentDepth = iFolder; bSelected = true; } crParentColor = *(COLORREF*)GetSetMediaTrackInfo(tr, "I_CUSTOMCOLOR", NULL); } if (iType + iFolder <= iParentDepth) bSelected = false; } Undo_OnStateChangeEx(__LOCALIZE("Set track(s) children to same color","sws_undo"), UNDO_STATE_TRACKCFG, -1); }
void SelItems::Restore(MediaTrack* tr) { bool* bUsed = NULL; if (m_selItems.GetSize()) { bUsed = new bool[m_selItems.GetSize()]; memset(bUsed, 0, sizeof(bool) * m_selItems.GetSize()); } if (tr == NULL) { PreventUIRefresh(1); for (int i = 1; i <= GetNumTracks(); i++) Match(CSurf_TrackFromID(i, false), bUsed); PreventUIRefresh(-1); } else Match(tr, bUsed); // Delete unused items for (int i = m_selItems.GetSize()-1; i >= 0 ; i--) if (!bUsed[i]) m_selItems.Delete(i, true); delete[] bUsed; }
void SelULItem(COMMAND_T* = NULL) { UnselOnTracks(); for (int i = 1; i <= GetNumTracks(); i++) { MediaTrack* tr = CSurf_TrackFromID(i, false); int iNumItems = GetTrackNumMediaItems(tr); if (*(int*)GetSetMediaTrackInfo(tr, "I_SELECTED", NULL) && iNumItems) { MediaItem* pUL = GetTrackMediaItem(tr, 0); double dFirstPos = *(double*)GetSetMediaItemInfo(pUL, "D_POSITION", NULL); float fFIPMy = *(float*)GetSetMediaItemInfo(pUL, "F_FREEMODE_Y", NULL); for (int j = 1; j < iNumItems; j++) { if (dFirstPos != *(double*)GetSetMediaItemInfo(GetTrackMediaItem(tr, j), "D_POSITION", NULL)) break; if (fFIPMy > *(float*)GetSetMediaItemInfo(GetTrackMediaItem(tr, j), "F_FREEMODE_Y", NULL)) { pUL = GetTrackMediaItem(tr, j); fFIPMy = *(float*)GetSetMediaItemInfo(pUL, "F_FREEMODE_Y", NULL); } } GetSetMediaItemInfo(pUL, "B_UISEL", &g_bTrue); } } UpdateTimeline(); }
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.. } }
int CheckTrackParam(COMMAND_T* ct) { int iNumTracks = GetNumTracks(); for (int i = 1; i <= iNumTracks; i++) if (GetMediaTrackInfo_Value(CSurf_TrackFromID(i, false), (const char*)ct->user) != 0.0) return true; return false; }
void HideAll(COMMAND_T* = NULL) { for (int i = 1; i <= GetNumTracks(); i++) SetTrackVis(CSurf_TrackFromID(i, false), 0); TrackList_AdjustWindows(MAJORADJUST); UpdateTimeline(); Undo_OnStateChangeEx(__LOCALIZE("Hide all tracks","sws_undo"), UNDO_STATE_TRACKCFG, -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); }
/* See NoteData::GetNumHands(). */ int NoteDataWithScoring::GetSuccessfulHands( float fStartBeat, float fEndBeat ) const { if( fEndBeat == -1 ) fEndBeat = GetNumBeats(); int iStartIndex = BeatToNoteRow( fStartBeat ); int iEndIndex = BeatToNoteRow( fEndBeat ); /* Clamp to known-good ranges. */ iStartIndex = max( iStartIndex, 0 ); iEndIndex = min( iEndIndex, GetNumRows()-1 ); int iNum = 0; for( int i=iStartIndex; i<=iEndIndex; i++ ) { if( !RowNeedsHands(i) ) continue; bool Missed = false; for( int t=0; t<GetNumTracks(); t++ ) { TapNote tn = GetTapNoteX(t, i); if( tn.type == TapNote::empty ) continue; if( tn.type == TapNote::mine ) // mines don't count continue; if( GetTapNoteScore(t, i) <= TNS_BOO ) Missed = true; } if( Missed ) continue; /* Check hold scores. */ for( int j=0; j<GetNumHoldNotes(); j++ ) { const HoldNote &hn = GetHoldNote(j); HoldNoteResult hnr = GetHoldNoteResult( hn ); /* Check if the row we're checking is in range. */ if( !hn.RowIsInRange(i) ) continue; /* If a hold is released *after* a hands containing it, the hands is * still good. So, ignore the judgement and only examine iLastHeldRow * to be sure that the hold was still held at the point of this row. * (Note that if the hold head tap was missed, then iLastHeldRow == i * and this won't fail--but the tap check above will have already failed.) */ if( hnr.iLastHeldRow < i ) Missed = true; } if( !Missed ) iNum++; } return iNum; }
void UnbypassFX(COMMAND_T* = NULL) { for (int i = 0; i <= GetNumTracks(); i++) { MediaTrack* tr = CSurf_TrackFromID(i, false); if (*(int*)GetSetMediaTrackInfo(tr, "I_SELECTED", NULL)) GetSetMediaTrackInfo(tr, "I_FXEN", &g_i1); } }
void SelItems::Save(MediaTrack* tr) { m_selItems.Empty(true); if (tr == NULL) for (int i = 1; i <= GetNumTracks(); i++) Add(CSurf_TrackFromID(i, false)); else Add(tr); }
MediaTrack* GuidToTrack(const GUID* guid) { if (guid) for (int i=0; i<=GetNumTracks(); i++) if (MediaTrack* tr = CSurf_TrackFromID(i, false)) if (TrackMatchesGuid(tr, guid)) return tr; return NULL; }
void DisableMPSend(COMMAND_T* = NULL) { for (int i = 1; i <= GetNumTracks(); i++) { MediaTrack* tr = CSurf_TrackFromID(i, false); if (*(int*)GetSetMediaTrackInfo(tr, "I_SELECTED", NULL)) GetSetMediaTrackInfo(tr, "B_MAINSEND", &g_bFalse); } }
void UnsetMonMedia(COMMAND_T* = NULL) { for (int i = 1; i <= GetNumTracks(); i++) { MediaTrack* tr = CSurf_TrackFromID(i, false); if (*(int*)GetSetMediaTrackInfo(tr, "I_SELECTED", NULL)) GetSetMediaTrackInfo(tr, "I_RECMONITEMS", &g_i0); } }
int SNM_GetTrackDepth(MediaTrack* _tr) { int depth = 0; for (int i=1; i <= GetNumTracks(); i++) // skip master if (MediaTrack* tr = CSurf_TrackFromID(i, false)) { depth += *(int*)GetSetMediaTrackInfo(tr, "I_FOLDERDEPTH", NULL); if (_tr==tr) return depth; } return depth; }
MediaTrack* GetFirstSelectedTrack() { for (int j = 0; j <= GetNumTracks(); j++) { MediaTrack* tr = CSurf_TrackFromID(j, false); if (tr && *(int*)GetSetMediaTrackInfo(tr, "I_SELECTED", NULL)) return tr; } return NULL; }
// native assumption: only 1 env selected at a time (v4.13) MediaTrack* GetTrackWithSelEnv() { if (TrackEnvelope* env = GetSelectedTrackEnvelope(NULL)) for (int i=0; i <= GetNumTracks(); i++) // incl. master if (MediaTrack* tr = CSurf_TrackFromID(i, false)) for (int j=0; j < CountTrackEnvelopes(tr); j++) if (env == GetTrackEnvelope(tr, j)) return tr; return NULL; }
void ColorTrackNext(COMMAND_T* = NULL) { for (int i = 0; i < GetNumTracks(); i++) { MediaTrack* tr = CSurf_TrackFromID(i, false); if (*(int*)GetSetMediaTrackInfo(tr, "I_SELECTED", NULL)) GetSetMediaTrackInfo(tr, "I_CUSTOMCOLOR", GetSetMediaTrackInfo(CSurf_TrackFromID(i+1, false), "I_CUSTOMCOLOR", NULL)); } Undo_OnStateChangeEx(__LOCALIZE("Set track(s) to previous track's color","sws_undo"), UNDO_STATE_TRACKCFG, -1); }
void MuteRecvs(COMMAND_T* = NULL) { for (int i = 1; i <= GetNumTracks(); i++) { MediaTrack* tr = CSurf_TrackFromID(i, false); if (*(int*)GetSetMediaTrackInfo(tr, "I_SELECTED", NULL)) for (int j = 0; GetSetTrackSendInfo(tr, -1, j, "P_SRCTRACK", NULL); j++) GetSetTrackSendInfo(tr, -1, j, "B_MUTE", &g_bTrue); } }
void UnmuteSends(COMMAND_T* = NULL) { for (int i = 1; i <= GetNumTracks(); i++) { MediaTrack* tr = CSurf_TrackFromID(i, false); if (*(int*)GetSetMediaTrackInfo(tr, "I_SELECTED", NULL)) for (int j = 0; GetSetTrackSendInfo(tr, 0, j, "P_DESTTRACK", NULL); j++) GetSetTrackSendInfo(tr, 0, j, "B_MUTE", &g_bFalse); } }
bool FilteredVisState::UpdateReaper(bool bHideFiltered) { bool bChanged = false; // Remove tracks from filteredOut that aren't in the project for (int i = 0; i < m_filteredOut.GetSize(); i++) if (CSurf_TrackToID(m_filteredOut.Get(i)->tr, false) <= 0) m_filteredOut.Delete(i--, true); for (int i = 1; i <= GetNumTracks(); i++) { MediaTrack* tr = CSurf_TrackFromID(i, false); int iVis = GetTrackVis(tr); int iNewVis = iVis; bool bShow = !bHideFiltered || MatchesFilter(tr); // Is this track in the filteredOut list? int j; for (j = 0; j < m_filteredOut.GetSize(); j++) if (m_filteredOut.Get(j)->tr == tr) break; if (j < m_filteredOut.GetSize()) { if (bShow) { iNewVis = m_filteredOut.Get(j)->iVis; m_filteredOut.Delete(j, true); } else iNewVis = 0; } else if (!bShow) { iNewVis = 0; TrackVisState* tvs = m_filteredOut.Add(new TrackVisState); tvs->tr = tr; tvs->iVis = iVis; } if (iVis != iNewVis) { SetTrackVis(tr, iNewVis); bChanged = true; } } if (bChanged) { TrackList_AdjustWindows(false); UpdateTimeline(); } return bChanged; }