|  | @@ -12,12 +12,24 @@ Player::Player(std::shared_ptr<MercuryManager> manager, std::shared_ptr<AudioSin
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void Player::pause()
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -    this->currentTrack->audioStream->isPaused = true;
 | 
	
		
			
				|  |  | +    if (currentTrack != nullptr)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        if (currentTrack->audioStream != nullptr)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            this->currentTrack->audioStream->isPaused = true;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void Player::play()
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -    this->currentTrack->audioStream->isPaused = false;
 | 
	
		
			
				|  |  | +    if (currentTrack != nullptr)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        if (currentTrack->audioStream != nullptr)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            this->currentTrack->audioStream->isPaused = false;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void Player::setVolume(uint32_t volume)
 | 
	
	
		
			
				|  | @@ -39,7 +51,13 @@ void Player::setVolume(uint32_t volume)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void Player::seekMs(size_t positionMs)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -    this->currentTrack->audioStream->seekMs(positionMs);
 | 
	
		
			
				|  |  | +    if (currentTrack != nullptr)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        if (currentTrack->audioStream != nullptr)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            this->currentTrack->audioStream->seekMs(positionMs);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |      // VALGRIND_DO_LEAK_CHECK;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -50,11 +68,11 @@ void Player::feedPCM(uint8_t *data, size_t len)
 | 
	
		
			
				|  |  |      if (this->audioSink->softwareVolumeControl)
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  |          int16_t* psample;
 | 
	
		
			
				|  |  | -        uint32_t pmax;
 | 
	
		
			
				|  |  | +        int32_t temp;
 | 
	
		
			
				|  |  |          psample = (int16_t*)(data);
 | 
	
		
			
				|  |  | -        for (int32_t i = 0; i < (len / 2); i++)
 | 
	
		
			
				|  |  | +        size_t half_len = len / 2;
 | 
	
		
			
				|  |  | +        for (uint32_t i = 0; i < half_len; i++)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            int32_t temp;
 | 
	
		
			
				|  |  |              // Offset data for unsigned sinks
 | 
	
		
			
				|  |  |              if (this->audioSink->usign)
 | 
	
		
			
				|  |  |              {
 | 
	
	
		
			
				|  | @@ -78,27 +96,44 @@ void Player::runTask()
 | 
	
		
			
				|  |  |      this->isRunning = true;
 | 
	
		
			
				|  |  |      while (isRunning)
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  | -        if (this->trackQueue.wpop(currentTrack)) {
 | 
	
		
			
				|  |  | +        if(nextTrack != nullptr && nextTrack->loaded)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            this->nextTrackMutex.lock();
 | 
	
		
			
				|  |  | +            currentTrack = this->nextTrack;
 | 
	
		
			
				|  |  | +            this->nextTrack = nullptr;
 | 
	
		
			
				|  |  | +            this->nextTrackMutex.unlock();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |              currentTrack->audioStream->startPlaybackLoop(pcmOut, 4096 / 4);
 | 
	
		
			
				|  |  |              currentTrack->loadedTrackCallback = nullptr;
 | 
	
		
			
				|  |  |              currentTrack->audioStream->streamFinishedCallback = nullptr;
 | 
	
		
			
				|  |  |              currentTrack->audioStream->audioSink = nullptr;
 | 
	
		
			
				|  |  |              currentTrack->audioStream->pcmCallback = nullptr;
 | 
	
		
			
				|  |  | -        } else {
 | 
	
		
			
				|  |  | -            usleep(100);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            delete currentTrack;
 | 
	
		
			
				|  |  | +            currentTrack = nullptr;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +        else
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            usleep(10000);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      free(pcmOut);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void Player::stop() {
 | 
	
		
			
				|  |  | +    CSPOT_LOG(info, "Trying to stop");
 | 
	
		
			
				|  |  |      this->isRunning = false;
 | 
	
		
			
				|  |  | -    CSPOT_LOG(info, "Stopping player");
 | 
	
		
			
				|  |  | -    this->trackQueue.clear();
 | 
	
		
			
				|  |  |      cancelCurrentTrack();
 | 
	
		
			
				|  |  | -    CSPOT_LOG(info, "Track cancelled");
 | 
	
		
			
				|  |  |      std::scoped_lock lock(this->runningMutex);
 | 
	
		
			
				|  |  | -    CSPOT_LOG(info, "Done");
 | 
	
		
			
				|  |  | +    if(this->nextTrack != nullptr)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        delete this->nextTrack;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    this->isRunning = false;
 | 
	
		
			
				|  |  | +    CSPOT_LOG(info, "Track cancelled");
 | 
	
		
			
				|  |  | +    cancelCurrentTrack();
 | 
	
		
			
				|  |  | +    CSPOT_LOG(info, "Stopping player");
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void Player::cancelCurrentTrack()
 | 
	
	
		
			
				|  | @@ -115,21 +150,32 @@ void Player::cancelCurrentTrack()
 | 
	
		
			
				|  |  |  void Player::handleLoad(std::shared_ptr<TrackReference> trackReference, std::function<void()>& trackLoadedCallback, uint32_t position_ms, bool isPaused)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |      std::lock_guard<std::mutex> guard(loadTrackMutex);
 | 
	
		
			
				|  |  | -    cancelCurrentTrack();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      pcmDataCallback framesCallback = [=](uint8_t *frames, size_t len) {
 | 
	
		
			
				|  |  |          this->feedPCM(frames, len);
 | 
	
		
			
				|  |  |       };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    auto loadedLambda = trackLoadedCallback;
 | 
	
		
			
				|  |  | +    this->nextTrackMutex.lock();
 | 
	
		
			
				|  |  | +    if(this->nextTrack != nullptr)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        delete this->nextTrack;
 | 
	
		
			
				|  |  | +        this->nextTrack = nullptr;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    this->nextTrack = new SpotifyTrack(this->manager, trackReference, position_ms, isPaused);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    this->nextTrack->trackInfoReceived = this->trackChanged;
 | 
	
		
			
				|  |  | +    this->nextTrack->loadedTrackCallback = [this, framesCallback, trackLoadedCallback]() {
 | 
	
		
			
				|  |  | +        trackLoadedCallback();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        this->nextTrackMutex.lock();
 | 
	
		
			
				|  |  | +        this->nextTrack->audioStream->streamFinishedCallback = this->endOfFileCallback;
 | 
	
		
			
				|  |  | +        this->nextTrack->audioStream->audioSink = this->audioSink;
 | 
	
		
			
				|  |  | +        this->nextTrack->audioStream->pcmCallback = framesCallback;
 | 
	
		
			
				|  |  | +        this->nextTrack->loaded = true;
 | 
	
		
			
				|  |  | +        this->nextTrackMutex.unlock();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    auto track = std::make_shared<SpotifyTrack>(this->manager, trackReference, position_ms, isPaused);
 | 
	
		
			
				|  |  | -    track->trackInfoReceived = this->trackChanged;
 | 
	
		
			
				|  |  | -    track->loadedTrackCallback = [this, track, framesCallback, loadedLambda]() {
 | 
	
		
			
				|  |  | -        loadedLambda();
 | 
	
		
			
				|  |  | -        track->audioStream->streamFinishedCallback = this->endOfFileCallback;
 | 
	
		
			
				|  |  | -        track->audioStream->audioSink = this->audioSink;
 | 
	
		
			
				|  |  | -        track->audioStream->pcmCallback = framesCallback;
 | 
	
		
			
				|  |  | -        this->trackQueue.push(track);
 | 
	
		
			
				|  |  | +        cancelCurrentTrack();
 | 
	
		
			
				|  |  |      };
 | 
	
		
			
				|  |  | +    this->nextTrackMutex.unlock();
 | 
	
		
			
				|  |  |  }
 |