Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deck deletion #7

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions mixxx/src/basetrackplayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,15 @@ BaseTrackPlayer::BaseTrackPlayer(QObject* pParent,
ControlObject::getControl(ConfigKey(group, "play")));
}

void BaseTrackPlayer::finalize() {
m_pChannel->finalize();
EngineBuffer* pEngineBuffer = m_pChannel->getEngineBuffer();
pEngineBuffer->slotControlStop(1.0);
}

BaseTrackPlayer::~BaseTrackPlayer()
{
qDebug() << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~BASETRACKPLAYER";
if (m_pLoadedTrack) {
emit(unloadingTrack(m_pLoadedTrack));
m_pLoadedTrack.clear();
Expand Down
3 changes: 3 additions & 0 deletions mixxx/src/basetrackplayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ class BaseTrackPlayer : public BasePlayer {
// connected. Delete me when EngineMaster supports AudioInput assigning.
EngineDeck* getEngineDeck() const;

// Tell the player we are about to delete it.
void finalize();

public slots:
void slotLoadTrack(TrackPointer track, bool bPlay=false);
void slotFinishLoading(TrackPointer pTrackInfoObject);
Expand Down
2 changes: 1 addition & 1 deletion mixxx/src/deck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ Deck::Deck(QObject* pParent,
}

Deck::~Deck() {
qDebug() << "deck deleteeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed";
}

1 change: 1 addition & 0 deletions mixxx/src/engine/enginebuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ EngineBuffer::EngineBuffer(const char * _group, ConfigObject<ConfigValue> * _con

EngineBuffer::~EngineBuffer()
{
qDebug() << "~~~~~~~~~~~~~~~~~~~~~~~~~~~enginebuffer";
#ifdef __SCALER_DEBUG__
//close the writer
df.close();
Expand Down
3 changes: 2 additions & 1 deletion mixxx/src/engine/enginechannel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@

EngineChannel::EngineChannel(const char* pGroup,
EngineChannel::ChannelOrientation defaultOrientation)
: m_group(pGroup) {
: m_group(pGroup),
m_bDying(false) {
m_pPFL = new ControlPushButton(ConfigKey(m_group, "pfl"));
m_pPFL->setButtonMode(ControlPushButton::TOGGLE);
m_pMaster = new ControlPushButton(ConfigKey(m_group, "master"));
Expand Down
4 changes: 4 additions & 0 deletions mixxx/src/engine/enginechannel.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ class EngineChannel : public EngineObject {
virtual bool isPFL();
virtual bool isMaster();

void finalize() { m_bDying = true; qDebug() << "DYING NOW " << m_group;}
bool isDying() const { return m_bDying; }

virtual void process(const CSAMPLE *pIn, const CSAMPLE *pOut, const int iBufferSize) = 0;

// TODO(XXX) This hack needs to be removed.
Expand All @@ -64,6 +67,7 @@ class EngineChannel : public EngineObject {
ControlPushButton* m_pMaster;
ControlPushButton* m_pPFL;
ControlObject* m_pOrientation;
bool m_bDying;
};

#endif
10 changes: 6 additions & 4 deletions mixxx/src/engine/enginedeck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ EngineDeck::EngineDeck(const char* group,
m_pPassing(new ControlPushButton(ConfigKey(group, "passthrough_enabled"))),
// Need a +1 here because the CircularBuffer only allows its size-1
// items to be held at once (it keeps a blank spot open persistently)
m_sampleBuffer(MAX_BUFFER_LEN+1) {
m_sampleBuffer(MAX_BUFFER_LEN+1),
m_bPassthroughIsActive(false),
m_bPassthroughWasActive(false) {

// Set up passthrough utilities and fields
m_pPassing->setButtonMode(ControlPushButton::TOGGLE);
m_pConversionBuffer = SampleUtil::alloc(MAX_BUFFER_LEN);
m_bPassthroughIsActive = false;
m_bPassthroughWasActive = false;

// Set up passthrough toggle button
connect(m_pPassing, SIGNAL(valueChanged(double)),
Expand Down Expand Up @@ -73,6 +73,7 @@ EngineDeck::~EngineDeck() {
}

void EngineDeck::process(const CSAMPLE*, const CSAMPLE * pOutput, const int iBufferSize) {
if (isDying()) return;
CSAMPLE* pOut = const_cast<CSAMPLE*>(pOutput);

// Feed the incoming audio through if passthrough is active
Expand Down Expand Up @@ -119,6 +120,7 @@ EngineBuffer* EngineDeck::getEngineBuffer() {
}

bool EngineDeck::isActive() {
if (isDying()) return false;
if (m_bPassthroughWasActive && !m_bPassthroughIsActive) {
return true;
}
Expand All @@ -128,7 +130,7 @@ bool EngineDeck::isActive() {

void EngineDeck::receiveBuffer(AudioInput input, const short* pBuffer, unsigned int nFrames) {
// Skip receiving audio input if passthrough is not active
if (!m_bPassthroughIsActive) {
if (!m_bPassthroughIsActive || isDying()) {
return;
}

Expand Down
23 changes: 23 additions & 0 deletions mixxx/src/engine/enginemaster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -349,12 +349,19 @@ void EngineMaster::process(const CSAMPLE *, const CSAMPLE *pOut, const int iBuff

Timer timer("EngineMaster::process channels");
QList<ChannelInfo*>::iterator it = m_channels.begin();
QList<ChannelInfo*> dying_channels;

for (unsigned int channel_number = 0;
it != m_channels.end(); ++it, ++channel_number) {
ChannelInfo* pChannelInfo = *it;
EngineChannel* pChannel = pChannelInfo->m_pChannel;
QString group = pChannelInfo->m_pChannel->getGroup();

if (!pChannel->isActive()) {
if (pChannel->isDying()) {
qDebug() << "this channel is DYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYING " << group << " " << channel_number;
dying_channels.push_back(pChannelInfo);
}
continue;
}

Expand Down Expand Up @@ -440,6 +447,11 @@ void EngineMaster::process(const CSAMPLE *, const CSAMPLE *pOut, const int iBuff
// We're close to the end of the callback. Wake up the engine worker
// scheduler so that it runs the workers.
m_pWorkerScheduler->runWorkers();

foreach (ChannelInfo* p, dying_channels) {
qDebug() << "we are killing a channel!";
removeChannelInfo(p);
}
}

void EngineMaster::addChannel(EngineChannel* pChannel) {
Expand Down Expand Up @@ -501,3 +513,14 @@ const CSAMPLE* EngineMaster::buffer(AudioOutput output) const {
return NULL;
}
}

void EngineMaster::removeChannelInfo(ChannelInfo* pChannelInfo) {
QString group = pChannelInfo->m_pChannel->getGroup();
qDebug() << "OFFICIALLY DELETING SHIT NOWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW " << group;
m_channels.removeAll(pChannelInfo);
SampleUtil::free(pChannelInfo->m_pBuffer);
delete pChannelInfo->m_pChannel;
delete pChannelInfo->m_pVolumeControl;
delete pChannelInfo;
emit(DeckRemoved(group));
}
6 changes: 6 additions & 0 deletions mixxx/src/engine/enginemaster.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ class EngineMaster : public EngineObject, public AudioSource {
return m_pSideChain;
}

signals:
void DeckRemoved(QString group);

private:
struct ChannelInfo {
EngineChannel* m_pChannel;
Expand Down Expand Up @@ -130,6 +133,9 @@ class EngineMaster : public EngineObject, public AudioSource {
void mixChannels(unsigned int channelBitvector, unsigned int maxChannels,
CSAMPLE* pOutput, unsigned int iBufferSize, GainCalculator* pGainCalculator);


void removeChannelInfo(ChannelInfo* pChannel);

QList<ChannelInfo*> m_channels;

CSAMPLE *m_pMaster, *m_pHead;
Expand Down
4 changes: 3 additions & 1 deletion mixxx/src/engine/enginemicrophone.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ EngineMicrophone::~EngineMicrophone() {
}

bool EngineMicrophone::isActive() {
if (isDying()) { return false; }
bool enabled = m_pEnabled->get() > 0.0;
return enabled && !m_sampleBuffer.isEmpty();
}
Expand Down Expand Up @@ -65,7 +66,7 @@ void EngineMicrophone::onInputDisconnected(AudioInput input) {
}

void EngineMicrophone::receiveBuffer(AudioInput input, const short* pBuffer, unsigned int iNumSamples) {

if (isDying()) return;
if (input.getType() != AudioPath::MICROPHONE ||
AudioInput::channelsNeededForType(input.getType()) != 1) {
// This is an error!
Expand Down Expand Up @@ -106,6 +107,7 @@ void EngineMicrophone::receiveBuffer(AudioInput input, const short* pBuffer, uns

void EngineMicrophone::process(const CSAMPLE* pInput, const CSAMPLE* pOutput, const int iBufferSize) {
Q_UNUSED(pInput);
if (isDying()) return;
CSAMPLE* pOut = const_cast<CSAMPLE*>(pOutput);

// If talkover is enabled, then read into the output buffer. Otherwise, skip
Expand Down
4 changes: 3 additions & 1 deletion mixxx/src/engine/enginepassthrough.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ EnginePassthrough::~EnginePassthrough() {
}

bool EnginePassthrough::isActive() {
if (isDying()) { return false; }
bool enabled = m_pEnabled->get() > 0.0;
return enabled && !m_sampleBuffer.isEmpty();
}
Expand Down Expand Up @@ -63,7 +64,7 @@ void EnginePassthrough::onInputDisconnected(AudioInput input) {
}

void EnginePassthrough::receiveBuffer(AudioInput input, const short* pBuffer, unsigned int nFrames) {

if (isDying()) return;
if (input.getType() != AudioPath::EXTPASSTHROUGH) {
// This is an error!
qDebug() << "WARNING: EnginePassthrough receieved an AudioInput for a non-passthrough type!";
Expand Down Expand Up @@ -96,6 +97,7 @@ void EnginePassthrough::receiveBuffer(AudioInput input, const short* pBuffer, un
}

void EnginePassthrough::process(const CSAMPLE* pInput, const CSAMPLE* pOutput, const int iBufferSize) {
if (isDying()) return;
CSAMPLE* pOut = const_cast<CSAMPLE*>(pOutput);
Q_UNUSED(pInput);

Expand Down
1 change: 1 addition & 0 deletions mixxx/src/engine/enginepregain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ EnginePregain::EnginePregain(const char * group)

EnginePregain::~EnginePregain()
{
qDebug() << "DELETED PREGAIN";
delete potmeterPregain;
delete m_pControlReplayGain;
delete m_pTotalGain;
Expand Down
3 changes: 1 addition & 2 deletions mixxx/src/mixxx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -638,10 +638,9 @@ MixxxApp::~MixxxApp()
ControlObject::getControls(&leakedControls);

if (leakedControls.size() > 0) {
qDebug() << "WARNING: The following" << leakedControls.size() << "controls were leaked:";
qDebug() << "WARNING: " << leakedControls.size() << "controls were leaked";
foreach (ControlObject* pControl, leakedControls) {
ConfigKey key = pControl->getKey();
qDebug() << key.group << key.item;
leakedConfigKeys.append(key);
}

Expand Down
58 changes: 53 additions & 5 deletions mixxx/src/playermanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ PlayerManager::PlayerManager(ConfigObject<ConfigValue>* pConfig,
this, SLOT(slotNumPreviewDecksControlChanged(double)),
Qt::DirectConnection);

connect(m_pEngine, SIGNAL(DeckRemoved(QString)),
this, SLOT(slotDeckRemoved(QString)),
Qt::DirectConnection);

// This is parented to the PlayerManager so does not need to be deleted
SamplerBank* pSamplerBank = new SamplerBank(this);
Q_UNUSED(pSamplerBank);
Expand Down Expand Up @@ -166,12 +170,12 @@ void PlayerManager::slotNumDecksControlChanged(double v) {
QMutexLocker locker(&m_mutex);
int num = (int)v;
if (num < m_decks.size()) {
// The request was invalid -- reset the value.
m_pCONumDecks->set(m_decks.size());
qDebug() << "Ignoring request to reduce the number of decks to" << num;
qDebug() << "HOOOOOOOOOOOOOLY SHIT REMOVING " << m_decks.size() - num << " DECKS";
initiateRemoveDecks(m_decks.size() - num);
return;
}

qDebug() << "ADDING DECKS SO " << m_decks.size() << " IS MORE LIKE " << num;
while (m_decks.size() < num) {
addDeckInner();
}
Expand Down Expand Up @@ -207,8 +211,35 @@ void PlayerManager::slotNumPreviewDecksControlChanged(double v) {
}
}

void PlayerManager::slotDeckRemoved(QString group) {
QMutexLocker locker(&m_mutex);
Deck* deck = reinterpret_cast<Deck*>(m_players[group]);
if (deck == NULL) {
qDebug() << "Could not cast group " << group << " to a type Deck.";
return;
}

m_players.remove(group);
QList<Deck*>::iterator it = m_decks.begin();
for ( ; it != m_decks.end(); ++it) {
qDebug() << "compare" << std::hex << *it << " and " << deck;
if (*it == deck) {
qDebug() << "I FOUND IT TOTALLY AND STUFF";
m_decks.erase(it);

// We don't need to disconnect soundmanager connections -- that was already done when
// we initiated this delete.
delete deck;
return;
}
}

qDebug() << "Couldn't find deck for group " << group << ", aborting delete";
}

void PlayerManager::addDeck() {
QMutexLocker locker(&m_mutex);
qDebug() << "DECK WAS ADDED MANUALLY AND STUFF";
addDeckInner();
m_pCONumDecks->set((double)m_decks.count());
}
Expand Down Expand Up @@ -243,6 +274,25 @@ void PlayerManager::addDeckInner() {
AudioInput(AudioInput::VINYLCONTROL, 0, number-1), pEngineDeck);
}

void PlayerManager::initiateRemoveDecks(int count) {
// Do not lock m_mutex here.
if (m_decks.count() < count) {
qDebug() << "ERROR: Not enough decks to remove " << count << " decks.";
return;
}

for (int i = 0; i < count; ++i) {
int number = m_decks.count() - i;
// EngineMaster will hear this signal and tell us to actually delete the deck.
Deck* deck = m_decks[number - 1];
qDebug() << "removing deck " << number;
m_pSoundManager->unregisterOutput(AudioOutput(AudioOutput::DECK, 0, number));
m_pSoundManager->unregisterInput(AudioInput(AudioInput::VINYLCONTROL, 0, number),
deck->getEngineDeck());
deck->finalize();
}
}

void PlayerManager::addSampler() {
QMutexLocker locker(&m_mutex);
addSamplerInner();
Expand Down Expand Up @@ -392,5 +442,3 @@ void PlayerManager::slotLoadTrackIntoNextAvailableSampler(TrackPointer pTrack) {
it++;
}
}


6 changes: 6 additions & 0 deletions mixxx/src/playermanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,18 @@ class PlayerManager : public QObject {
signals:
void loadLocationToPlayer(QString location, QString group);

private slots:
void slotDeckRemoved(QString group);

private:
TrackPointer lookupTrack(QString location);
// Must hold m_mutex before calling this method. Internal method that
// creates a new deck.
void addDeckInner();
// Must hold m_mutex before calling this method. Internal method that
// removes decks give by count starting from the end.
void initiateRemoveDecks(int count);
// Must hold m_mutex before calling this method. Internal method that
// creates a new sampler.
void addSamplerInner();
// Must hold m_mutex before calling this method. Internal method that
Expand Down
20 changes: 15 additions & 5 deletions mixxx/src/soundmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -573,18 +573,28 @@ void SoundManager::registerOutput(AudioOutput output, const AudioSource *src) {
emit(outputRegistered(output, src));
}

void SoundManager::registerInput(AudioInput input, AudioDestination *dest) {
if (m_registeredDestinations.contains(input)) {
// note that this can be totally ok if we just want a certain
// AudioInput to be going to a different AudioDest -bkgood
qDebug() << "WARNING: AudioInput already registered!";
void SoundManager::unregisterOutput(AudioOutput output) {
if (!m_registeredSources.contains(output)) {
qDebug() << "WARNING: AudioOutput not registered, can't remove!";
} else {
m_registeredSources.remove(output);
}
}

void SoundManager::registerInput(AudioInput input, AudioDestination *dest) {
m_registeredDestinations.insertMulti(input, dest);

emit(inputRegistered(input, dest));
}

void SoundManager::unregisterInput(AudioInput input, AudioDestination *dest) {
if (!m_registeredDestinations.contains(input, dest)) {
qDebug() << "WARNING: AudioInput not registered, can't remove!";
} else {
m_registeredDestinations.remove(input, dest);
}
}

QList<AudioOutput> SoundManager::registeredOutputs() const {
return m_registeredSources.keys();
}
Expand Down
Loading