Skip to content

Commit

Permalink
stop current song with asio
Browse files Browse the repository at this point in the history
  • Loading branch information
blumamir committed Jan 29, 2020
1 parent 7541369 commit cc86372
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 31 deletions.
51 changes: 23 additions & 28 deletions src/alsa_frames_transfer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
namespace wavplayeralsa {

AlsaFramesTransfer::AlsaFramesTransfer() :
alsa_wait_timer_(alsa_ios_),
should_be_playing_(false)
{}
alsa_wait_timer_(alsa_ios_)
{
// we use the stop flag to indicate if a song is currently playing or not
alsa_ios_.stop();
}


AlsaFramesTransfer::~AlsaFramesTransfer() {
Expand Down Expand Up @@ -100,13 +102,12 @@ namespace wavplayeralsa {
alsa_ios_.reset();
alsa_ios_.post(std::bind(&AlsaFramesTransfer::FramesToPcmTransferLoop, this, boost::system::error_code()));
alsa_ios_.run();
PcmDrop();
}
catch(const std::runtime_error &e) {
logger_->error("error while playing current wav file. stopped transfering frames to alsa. exception is: {}", e.what());
}
player_events_callback_->NoSongPlayingStatus(file_id_);
should_be_playing_ = false;

}

void AlsaFramesTransfer::FramesToPcmTransferLoop(boost::system::error_code error_code) {
Expand All @@ -119,11 +120,6 @@ namespace wavplayeralsa {
std::stringstream err_desc;
int err;

if(should_be_playing_ == false) {
// if we need to stop playing, just return. droping the frames from the pcm will be done later
return;
}

// calculate how many frames to write
snd_pcm_sframes_t frames_to_deliver;
if( (frames_to_deliver = snd_pcm_avail_update(alsa_playback_handle_)) < 0) {
Expand Down Expand Up @@ -181,28 +177,27 @@ namespace wavplayeralsa {

bool is_currently_playing = IsAlsaStatePlaying();

if(should_be_playing_ == false) {
logger_->info("will stop transfering frames to alsa, and drop current frames from pcm");
}
else if(!is_currently_playing) {
if(!is_currently_playing) {
logger_->info("playing audio file ended successfully (transfered all frames to pcm and it is empty)");
}

if(!is_currently_playing || should_be_playing_ == false) {
int err;
if( (err = snd_pcm_drop(alsa_playback_handle_)) < 0 ) {
std::stringstream err_desc;
err_desc << "snd_pcm_drop failed (" << snd_strerror(err) << ")";
throw std::runtime_error(err_desc.str());
}
return;
}

CheckSongStartTime();

alsa_wait_timer_.expires_from_now(boost::posix_time::millisec(5));
alsa_wait_timer_.async_wait(std::bind(&AlsaFramesTransfer::PcmDrainLoop, this, std::placeholders::_1));
}

void AlsaFramesTransfer::PcmDrop()
{
int err;
if( (err = snd_pcm_drop(alsa_playback_handle_)) < 0 ) {
std::stringstream err_desc;
err_desc << "snd_pcm_drop failed (" << snd_strerror(err) << ")";
throw std::runtime_error(err_desc.str());
}
}

bool AlsaFramesTransfer::IsAlsaStatePlaying() {
int status = snd_pcm_state(alsa_playback_handle_);
return (status == SND_PCM_STATE_RUNNING) || (status == SND_PCM_STATE_PREPARED);
Expand Down Expand Up @@ -231,7 +226,6 @@ namespace wavplayeralsa {
}

logger_->info("start playing file {} from position {} mili-seconds ({} seconds)", file_id_, position_in_ms, position_in_seconds);
should_be_playing_ = true;
playing_thread_ = std::thread(&AlsaFramesTransfer::TransferFramesWrapper, this);
}

Expand All @@ -249,10 +243,11 @@ namespace wavplayeralsa {
*/
bool AlsaFramesTransfer::Stop() {

// there is a possible race condition here, if we copy the value, and then audio reaches it's end,
// but that is ok for our use (we don't need a precise indication, just a general idea)
bool is_playing = should_be_playing_;
should_be_playing_ = false;
bool is_playing = !(alsa_ios_.stopped());

alsa_wait_timer_.cancel();
alsa_ios_.stop();

if(playing_thread_.joinable()) {
playing_thread_.join();
}
Expand Down
5 changes: 2 additions & 3 deletions src/alsa_frames_transfer.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,10 @@ namespace wavplayeralsa {
void TransferFramesWrapper();
bool IsAlsaStatePlaying();
void CheckSongStartTime();
// once all frames are written to pcm, this function runs until pcm is empty,
// while allowing the cancelation with the should_be_playing_ flag
// once all frames are written to pcm, this function runs until pcm is empty
void PcmDrainLoop(boost::system::error_code error_code);
void FramesToPcmTransferLoop(boost::system::error_code error_code);
void PcmDrop();

private:
std::shared_ptr<spdlog::logger> logger_;
Expand Down Expand Up @@ -154,7 +154,6 @@ namespace wavplayeralsa {
boost::asio::io_service alsa_ios_;
boost::asio::deadline_timer alsa_wait_timer_;
std::thread playing_thread_;
std::atomic_bool should_be_playing_; // used to cancel the playing thread

private:
// position reporting
Expand Down

0 comments on commit cc86372

Please sign in to comment.