void ListCtrl::calcVirtualSize( Size& sz ) { setVirtualSizeCached(); sz.empty(); int nTotalRow = getTotalRows(); for (int i = 0; i < nTotalRow; i++) { sz.cy += getRowHeight(i); } int nTotalCol = getTotalColumns(); for (int i = 0; i < nTotalCol; i++) { sz.cx += getColumnWidth(i); } }
void ListCtrl::calcCellRect() { WFX_CONDITION(m_nStartRow != -1); WFX_CONDITION(m_nEndRow != -1); WFX_CONDITION(m_nStartCol != -1); WFX_CONDITION(m_nEndCol != -1); WFX_CONDITION(m_nEndRow >= m_nStartRow); WFX_CONDITION(m_nEndCol >= m_nEndCol); m_rgRectFast.clear(); m_rgRect.clear(); m_rgRowNumRect.clear(); ULONG nTotalRow = getTotalRows(); ULONG nTotalCol = getTotalColumns(); ULONG nSeqBarWidth = getRowNumBarWidth(); ULONG nHeadHeight = getHeadHeight(); Rect rcWid = getClientRect(); Rect rcCell = rcWid; Rect rcRowNum = rcWid; ULONG nWidth = 0; ULONG nHeight = 0; rcRowNum.right = rcRowNum.left + nSeqBarWidth; rcCell.left += nSeqBarWidth + 1; rcCell.top += nHeadHeight + 1; m_rgRectFast.resize(m_nEndRow - m_nStartRow + 1); for (LONG nRow = m_nStartRow; nRow <= m_nEndRow; nRow++) { nHeight = getRowHeight(nRow); rcCell.bottom = rcCell.top + nHeight; rcRowNum.top = rcCell.top; rcRowNum.bottom = rcCell.bottom; m_rgRowNumRect.push_back(rcRowNum); if (rcCell.bottom > rcWid.bottom) rcCell.bottom = rcWid.bottom; m_rgRectFast[nRow - m_nStartRow].resize(m_nEndCol - m_nStartCol + 1); for (LONG nCol = m_nStartCol; nCol <= m_nEndCol; nCol++) { nWidth = getColumnWidth(nCol); rcCell.right = rcCell.left + nWidth; m_rgRect.insert(std::make_pair(CellID(nRow, nCol), rcCell)); m_rgRectFast[nRow - m_nStartRow][nCol - m_nStartCol] = rcCell; rcCell.left += rcCell.right - rcCell.left; } rcCell.left = rcWid.left + nSeqBarWidth + 1; rcCell.top += rcCell.bottom - rcCell.top; } }
BOOL ListCtrl::calcRow() { ULONG nOldStartRow = m_nStartRow; ULONG nOldEndRow = m_nEndRow; m_nStartRow = m_nEndRow = -1; Rect rcDraw = getClientRect(); LONG nOffset = getVOffset(); //TRACE(L"nOffset = %d", nOffset); ULONG nTotalRow = getTotalRows(); LONG nSumHeight = 0; for (ULONG nRow = 0; nRow < nTotalRow; nRow++) { nSumHeight += getRowHeight(nRow); if (nSumHeight >= nOffset) { m_nStartRow = nRow; break; } } nSumHeight = 0; LONG nViewHeight = rcDraw.bottom - rcDraw.top; for (ULONG nRow = m_nStartRow; nRow < nTotalRow; nRow++) { nSumHeight += getRowHeight(nRow); if (nSumHeight > nViewHeight) { m_nEndRow = nRow; break; } } if (nSumHeight <= nViewHeight) { m_nEndRow = nTotalRow - 1; } //TRACE(L"m_nStartRow = %d", m_nStartRow); //TRACE(L"m_nEndRow = %d", m_nEndRow); return (m_nStartRow != nOldStartRow || m_nEndRow != nOldEndRow); }
void Sequencer::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) { AudioPlayHead::CurrentPositionInfo pos (pluginAudioProcessor->lastPosInfo); // If we aren't playing... if (! pos.isPlaying) { if (noteOffs.size() > 0) { // Send any upcoming note-off events Array<NoteOff*> notesToRemove; for (int i = 0; i < noteOffs.size(); i++) { int noteNumber = noteOffs[i]->noteNumber; MidiMessage m2 = MidiMessage::noteOff (1, noteNumber); midiMessages.addEvent (m2, 0); playingNotes.set (noteNumber, false); notesToRemove.add (noteOffs[i]); } for (int i = 0; i < notesToRemove.size(); i++) { // Remove the event from the note-off event list // (We do this in two steps so that the noteOffs array isn't modified inside a loop) noteOffs.removeObject (notesToRemove[i], true); } } return; } double ppq = pos.ppqPosition; double timeInSeconds = pos.timeInSeconds; double bpm = pos.bpm; //if (primary) { SharedState::getInstance()->setPpqPosition (ppq); SharedState::getInstance()->setTimeInSeconds (timeInSeconds); SharedState::getInstance()->setBpm (bpm); //} /* int numerator = pos.timeSigNumerator; int denominator = pos.timeSigDenominator; const int ppqPerBar = (numerator * 4 / denominator); // e.g. 4 if 4/4 const double beats = (fmod (ppq, ppqPerBar) / ppqPerBar) * numerator; const int bar = ((int) ppq) / ppqPerBar + 1; const int beat = ((int) beats) + 1; const int ticks = ((int) (fmod (beats, 1.0) * 960.0)); */ double tickCountPrecise = fmod (ppq * speed * ticksPerCol, getTotalCols() * ticksPerCol); tickCount = (int)tickCountPrecise; lastPlayheadColPrecise = tickCountPrecise / ticksPerCol; jassert (lastPlayheadColPrecise >= 0.0) jassert (lastPlayheadColPrecise <= 16.0) //if (primary) { SharedState::getInstance()->setPlayheadColPrecise (lastPlayheadColPrecise); //} if (tickCount != lastTickCount) { lastTickCount = tickCount; // Check if we should be degrading... int panelIndex = pluginAudioProcessor->getPanelIndex(); int state = SharedState::getInstance()->getState(panelIndex); if (state == Panel::DEGRADING_SLOW || state == Panel::DEGRADING_FAST) { // degrade at most once per tempo sweep, in column 0 if (getPlayheadCol() == 0) { if (!columnZeroDegradeUpdate) { SharedState::getInstance()->degradeStep(panelIndex); columnZeroDegradeUpdate = true; } } else { columnZeroDegradeUpdate = false; } } else { columnZeroDegradeUpdate = false; if (state == Panel::ACTIVE) { if (SharedState::kDegradeAfterInactiveSec > 0 && (SharedState::getInstance()->getLastTouchElapsedMs(panelIndex) >= SharedState::kDegradeAfterInactiveSec * 1000)) { DBG(String(Time::currentTimeMillis()) + " " + "Start degrading panel " + String(panelIndex)); SharedState::getInstance()->startDegrade(panelIndex); } } } // Update starfield if necessary if (SharedState::getInstance()->getStarFieldActive()) { // bug:67 - for production running, we could assert that the following is true: // SharedState::getInstance()->allAttracting() // but that won't work if someone turns on the star field by hand via the sequencer GUI if (pluginAudioProcessor->getPanelIndex() == 0) { SharedState::getInstance()->updateStarField(); } } bool playCol = false; // play the current column of notes? float velocity = 0.9f; // Swing... // If we're on an odd column if (getPlayheadCol() % 2 != 0) { // If we've waited for enough ticks for the swing if (tickCount == (getPlayheadCol() * ticksPerCol) + swingTicks) { playCol = true; } } else { // Else we're on an even column // If we're on the first tick of the column... if (tickCount % ticksPerCol == 0) { playCol = true; } } // Calculate the latency double beatsPerSec = bpm * speed * ticksPerCol / 60.0; double secPerBeat = 1.0 / beatsPerSec; double tickOffset = tickCountPrecise - tickCount; int tickOffsetSamples = tickOffset * secPerBeat * sampleRate; tickOffsetSamples = jmax (buffer.getNumSamples() - tickOffsetSamples - 1, 0); // Send any upcoming note-off events Array<NoteOff*> notesToRemove; for (int i = 0; i < noteOffs.size(); i++) { if (noteOffs[i]->tick == tickCount) { int noteNumber = noteOffs[i]->noteNumber; MidiMessage m2 = MidiMessage::noteOff (1, noteNumber); midiMessages.addEvent (m2, tickOffsetSamples); playingNotes.set (noteNumber, false); notesToRemove.add (noteOffs[i]); } } for (int i = 0; i < notesToRemove.size(); i++) { // Remove the event from the note-off event list // (We do this in two steps so that the noteOffs array isn't modified inside a loop) noteOffs.removeObject (notesToRemove[i], true); } // If we should play the current column of notes if (playCol) { int panelIndex = pluginAudioProcessor->getPanelIndex(); int tabIndex = pluginAudioProcessor->getTabIndex(); for (int i = 0; i < getTotalRows(); i++) { Cell* cell = getCellAt (panelIndex, tabIndex, i, getPlayheadCol()); if (cell->isOn()) { int noteNumber = cell->getNoteNumber(); // If this note is currently playing if (playingNotes[noteNumber] == true) { Array<NoteOff*> notesToRemove; // Remove any pending note-offs for (int j = 0; j < noteOffs.size(); j++) { if (noteOffs[j]->noteNumber == noteNumber) { notesToRemove.add (noteOffs[j]); } } for (int j = 0; j < notesToRemove.size(); j++) { noteOffs.removeObject (notesToRemove[j], true); } // Send a note-off before retriggering MidiMessage m = MidiMessage::noteOff (1, noteNumber); midiMessages.addEvent (m, tickOffsetSamples); playingNotes.set (noteNumber, false); } // Play this note MidiMessage m = MidiMessage::noteOn (1, noteNumber, velocity); midiMessages.addEvent (m, tickOffsetSamples); playingNotes.set (noteNumber, true); // Add an upcoming note-off event NoteOff* no; noteOffs.add (no = new NoteOff()); no->tick = (tickCount + noteLength) % (ticksPerCol * getTotalCols()); no->noteNumber = noteNumber; } } } } }
void ListCtrl::onDraw( HDC hdc, const Rect& rcPaint ) { Rect rc = getRect(); if (!verify()) { WfxRender::drawFrame(hdc, rc, WBTN_BKGND_MOUSE, getDispatcher()); return; } LCDrawItemInfo* pDrawItemInfo = getDrawItemInfo(); pDrawItemInfo->clear(); pDrawItemInfo->m_hDC = hdc; Rect rcCell; DWORD dwState = WCS_NORMAL; ULONG nLayer = 0; BOOL bRowexpanded = FALSE; COLORREF clrText = 0; LONG nLayerOffset = 0; LONG nTotalRow = getTotalRows(); LONG nTotalCol = getTotalColumns(); ULONG nSeqBarWidth = getRowNumBarWidth(); ObjectAdapterBase* pOjbect = NULL; for (LONG nRow = m_nStartRow, nRowNum = 0; nRow <= m_nEndRow; nRow++, nRowNum++) { pDrawItemInfo->m_nRow = nRow; WFX_CONDITION(m_rgRowNumRect.size() > nRowNum); pDrawItemInfo->m_prcItem = &m_rgRowNumRect[nRowNum]; pDrawItemInfo->m_dwState = 0; onDrawSeqBar(pDrawItemInfo); nLayer = getLayer(nRow); nLayerOffset = (nLayer - 1) * 30; clrText = getColor(nLayer); if (m_bHasSubItem) { bRowexpanded = isExpanded(nRow); } pOjbect = m_pArrayAdapter->getAt(nRow); WFX_CONDITION(pOjbect != NULL); for (LONG nCol = m_nStartCol; nCol <= m_nEndCol; nCol++) { WFX_CONDITION(nCol < pOjbect->getCount()); AttributeBase* pAttribute = pOjbect->getAt(nCol); WFX_CONDITION(pAttribute != NULL); CellID cellID(nRow, nCol); dwState = WCS_NORMAL; if (m_bHasSubItem && nCol == 0) { if (bRowexpanded) { dwState |= WCS_EXPAND; } else { dwState |= WCS_CLOSE; } } if (m_cellSelected == cellID) { dwState |= WCS_SELECTED; } if (m_cellMouseMove == cellID) { dwState |= WCS_MOUSEMOVE; } rcCell = getCellRect(nRow, nCol); rcCell.left += nLayerOffset; pDrawItemInfo->m_nCol = nCol; pDrawItemInfo->m_prcItem = &rcCell; pDrawItemInfo->m_dwState = dwState; pDrawItemInfo->m_pszText = pAttribute->getText().c_str(); pDrawItemInfo->m_dwFormat = pAttribute->getFormat(); onDrawItem(pDrawItemInfo); } } WfxRender::drawFrame(hdc, rc, WBTN_BKGND_MOUSE, getDispatcher()); }
BOOL ListCtrl::verify() const { ULONG nTotalRow = getTotalRows(); ULONG nTotalCol = getTotalColumns(); return nTotalRow > 0 && nTotalCol > 0; }