Added support for Play/Prev/Next/Stop in Playback service and respective

global hotkeys. It functions as a normal music player, finally!
This commit is contained in:
casey 2016-05-23 23:51:49 -07:00
parent b544ea6f1f
commit 6326162ee0
10 changed files with 90 additions and 34 deletions

View File

@ -277,7 +277,12 @@ void Player::ThreadLoop() {
}
}
this->PlaybackEnded(this);
if (this->Exited()) {
this->PlaybackStopped(this);
}
else {
this->PlaybackFinished(this);
}
this->output.reset();
this->stream.reset();

View File

@ -79,7 +79,8 @@ namespace musik { namespace core { namespace audio {
typedef sigslot::signal1<Player*> PlayerEvent;
PlayerEvent PlaybackStarted;
PlayerEvent PlaybackAlmostEnded;
PlayerEvent PlaybackEnded;
PlayerEvent PlaybackFinished;
PlayerEvent PlaybackStopped;
PlayerEvent PlaybackError;
private:

View File

@ -101,7 +101,8 @@ void Transport::StartWithPlayer(Player* newPlayer) {
newPlayer->PlaybackStarted.connect(this, &Transport::OnPlaybackStarted);
newPlayer->PlaybackAlmostEnded.connect(this, &Transport::OnPlaybackAlmostEnded);
newPlayer->PlaybackEnded.connect(this, &Transport::OnPlaybackEnded);
newPlayer->PlaybackFinished.connect(this, &Transport::OnPlaybackFinished);
newPlayer->PlaybackStopped.connect(this, &Transport::OnPlaybackStopped);
newPlayer->PlaybackError.connect(this, &Transport::OnPlaybackError);
musik::debug::info(TAG, "play()");
@ -254,7 +255,7 @@ void Transport::RemoveActive(Player* player) {
}
}
void Transport::OnPlaybackEnded(Player* player) {
void Transport::OnPlaybackFinished(Player* player) {
this->RaiseStreamEvent(Transport::StreamFinished, player);
if (this->nextPlayer) {
@ -267,6 +268,12 @@ void Transport::OnPlaybackEnded(Player* player) {
boost::async(boost::bind(&Transport::RemoveActive, this, player));
}
void Transport::OnPlaybackStopped (Player* player) {
this->RaiseStreamEvent(Transport::StreamStopped, player);
this->SetPlaybackState(Transport::PlaybackStopped);
boost::async(boost::bind(&Transport::RemoveActive, this, player));
}
void Transport::OnPlaybackError(Player* player) {
this->RaiseStreamEvent(Transport::StreamError, player);
this->SetPlaybackState(Transport::PlaybackStopped);

View File

@ -59,6 +59,7 @@ namespace musik { namespace core { namespace audio {
StreamPlaying = 1,
StreamAlmostDone = 4,
StreamFinished = 5,
StreamStopped = 6,
StreamError = -1
} StreamEventType;
@ -89,7 +90,8 @@ namespace musik { namespace core { namespace audio {
void OnPlaybackStarted(Player* player);
void OnPlaybackAlmostEnded(Player* player);
void OnPlaybackEnded(Player* player);
void OnPlaybackFinished(Player* player);
void OnPlaybackStopped(Player* player);
void OnPlaybackError(Player* player);
private:

View File

@ -177,7 +177,7 @@ int main(int argc, char* argv[])
using musik::core::LibraryFactory;
LibraryPtr library = LibraryFactory::Libraries().at(0);
GlobalHotkeys globalHotkeys(tp, library);
GlobalHotkeys globalHotkeys(playback, library);
ILayoutPtr libraryLayout(new LibraryLayout(playback, library));
ILayoutPtr consoleLayout(new MainLayout(tp, library));
@ -233,6 +233,8 @@ int main(int argc, char* argv[])
Window::WriteToScreen();
MessageQueue::Instance().Dispatch();
}
playback.Stop();
}
endwin();

View File

@ -11,7 +11,8 @@ using musik::core::audio::Transport;
using namespace musik::core::library::constants;
#define URI_AT_INDEX(x) this->playlist.at(x)->URI()
#define MESSAGE_START_NEXT_TRACK 2000
#define MESSAGE_START_NEXT_TRACK 1234
#define PREVIOUS_GRACE_PERIOD 2.0f
class StreamEvent : public IMessage {
@ -26,25 +27,51 @@ PlaybackService::PlaybackService(Transport& transport)
void PlaybackService::ProcessMessage(IMessage &message) {
if (message.MessageType() == MESSAGE_START_NEXT_TRACK) {
if (this->playlist.size() > index + 1) {
++index;
std::string uri = URI_AT_INDEX(index);
transport.Start(uri);
}
else {
if (!Next()) {
transport.Stop();
index = (size_t)-1;
}
}
}
void PlaybackService::Start(std::vector<TrackPtr>& tracks, size_t index) {
this->playlist.clear();
std::copy(tracks.begin(), tracks.end(), std::back_inserter(this->playlist));
this->Start(index);
bool PlaybackService::Next() {
if (transport.GetPlaybackState() == Transport::PlaybackStopped) {
return false;
}
if (this->playlist.size() > index + 1) {
this->Play(index + 1);
return true;
}
return false;
}
void PlaybackService::Start(size_t index) {
bool PlaybackService::Previous() {
if (transport.GetPlaybackState() == Transport::PlaybackStopped) {
return false;
}
if (transport.Position() > PREVIOUS_GRACE_PERIOD) {
this->Play(index);
return true;
}
if (index > 0) {
this->Play(index - 1);
return true;
}
return false;
}
void PlaybackService::Play(std::vector<TrackPtr>& tracks, size_t index) {
this->playlist.clear();
std::copy(tracks.begin(), tracks.end(), std::back_inserter(this->playlist));
this->Play(index);
}
void PlaybackService::Play(size_t index) {
transport.Stop();
std::string uri = URI_AT_INDEX(index);
transport.Start(uri);
@ -52,14 +79,14 @@ void PlaybackService::Start(size_t index) {
}
void PlaybackService::OnStreamEvent(int eventType, std::string uri) {
//if (eventType == Transport::StreamFinished) {
// MessageQueue::Instance().Post(
// Message::Create(this, MESSAGE_START_NEXT_TRACK, 0, 0));
//}
if (eventType == Transport::StreamAlmostDone) {
if (this->playlist.size() > this->index + 1) {
this->transport.PrepareNextTrack(URI_AT_INDEX(index + 1));
index++;
}
if (eventType == Transport::StreamFinished) {
MessageQueue::Instance().Post(
Message::Create(this, MESSAGE_START_NEXT_TRACK, 0, 0));
}
//if (eventType == Transport::StreamAlmostDone) {
// if (this->playlist.size() > this->index + 1) {
// this->transport.PrepareNextTrack(URI_AT_INDEX(index + 1));
// index++;
// }
//}
}

View File

@ -19,8 +19,12 @@ class PlaybackService : public IMessageTarget, public sigslot::has_slots<> {
Transport& GetTransport() { return this->transport; }
void Start(std::vector<TrackPtr>& tracks, size_t index);
void Start(size_t index);
void Play(std::vector<TrackPtr>& tracks, size_t index);
void Play(size_t index);
bool Next();
bool Previous();
void Stop() { transport.Stop(); }
size_t Count() { return this->playlist.size(); }
private:

View File

@ -3,8 +3,9 @@
using musik::core::LibraryPtr;
GlobalHotkeys::GlobalHotkeys(Transport& transport, LibraryPtr library)
: transport(transport) {
GlobalHotkeys::GlobalHotkeys(PlaybackService& playback, LibraryPtr library)
: playback(playback)
, transport(playback.GetTransport()) {
this->library = library;
}
@ -32,6 +33,12 @@ bool GlobalHotkeys::Handle(int64 ch) {
this->transport.SetVolume(this->transport.Volume() - 0.05);
return true;
}
else if (kn == "ALT_J") {
this->playback.Previous();
}
else if (kn == "ALT_L") {
this->playback.Next();
}
else if (kn == "^R") {
library->Indexer()->Synchronize(true);
}

View File

@ -2,7 +2,7 @@
#include "stdafx.h"
#include <core/playback/Transport.h>
#include <app/service/PlaybackService.h>
#include <core/library/ILibrary.h>
using musik::core::audio::Transport;
@ -10,12 +10,13 @@ using musik::core::LibraryPtr;
class GlobalHotkeys {
public:
GlobalHotkeys(Transport& transport, LibraryPtr library);
GlobalHotkeys(PlaybackService& playback, LibraryPtr library);
~GlobalHotkeys(); /* non-virtual; do not use as a base class */
bool Handle(int64 ch);
private:
PlaybackService& playback;
Transport& transport;
LibraryPtr library;
};

View File

@ -58,7 +58,7 @@ bool TrackListView::KeyPress(int64 ch) {
if (ch == '\n') { /* return */
size_t selected = this->GetSelectedIndex();
if (this->metadata && this->metadata->size() > selected) {
playback.Start(*this->metadata, selected);
playback.Play(*this->metadata, selected);
return true;
}
}