296 lines
7.6 KiB
C++
296 lines
7.6 KiB
C++
#include "player.h"
|
|
|
|
M::Player::Player(const W::Address& address, QObject* parent):
|
|
M::Model(address, parent),
|
|
controls(),
|
|
views(),
|
|
playPauseBtn(new M::Button(address + W::Address{u"play"})),
|
|
nextBtn(new M::Button(address + W::Address{u"next"})),
|
|
prevBtn(new M::Button(address + W::Address{u"prev"})),
|
|
_queueView(new M::List(address + W::Address{u"queueView"})),
|
|
_queue(),
|
|
current(0),
|
|
counter(0),
|
|
currentIndex(0),
|
|
mode(playBack),
|
|
playing(false),
|
|
scheduledToplay(false)
|
|
{
|
|
W::Handler* get = W::Handler::create(address + W::Address({u"get"}), this, &M::Player::_h_get);
|
|
W::Handler* hqueue = W::Handler::create(address + W::Address({u"queue"}), this, &M::Player::_h_queue);
|
|
addHandler(get);
|
|
addHandler(hqueue);
|
|
|
|
playPauseBtn->setLabel(W::String(u"Play"));
|
|
playPauseBtn->setEnabled(false);
|
|
connect(playPauseBtn, SIGNAL(activated()), this, SLOT(onPlayPauseBtn()));
|
|
|
|
nextBtn->setLabel(W::String(u"Next"));
|
|
nextBtn->setEnabled(false);
|
|
connect(nextBtn, SIGNAL(activated()), this, SLOT(onNextBtn()));
|
|
|
|
prevBtn->setLabel(W::String(u"Prev"));
|
|
prevBtn->setEnabled(false);
|
|
connect(prevBtn, SIGNAL(activated()), this, SLOT(onPrevBtn()));
|
|
|
|
addModel(playPauseBtn);
|
|
addModel(nextBtn);
|
|
addModel(prevBtn);
|
|
addModel(_queueView);
|
|
|
|
controls.insert(std::make_pair(playPause, playPauseBtn->getAddress()));
|
|
controls.insert(std::make_pair(next, nextBtn->getAddress()));
|
|
controls.insert(std::make_pair(prev, prevBtn->getAddress()));
|
|
views.insert(std::make_pair(queue, _queueView->getAddress()));
|
|
}
|
|
|
|
M::Player::~Player()
|
|
{
|
|
|
|
}
|
|
|
|
void M::Player::set(const W::Object& value)
|
|
{
|
|
throw 14; //what do you expect here? not implemented, and not sure it ever would be
|
|
}
|
|
|
|
void M::Player::set(W::Object* value)
|
|
{
|
|
set(*value);
|
|
}
|
|
|
|
M::Model::ModelType M::Player::getType() const
|
|
{
|
|
return M::Model::player;
|
|
}
|
|
|
|
void M::Player::h_subscribe(const W::Event& ev)
|
|
{
|
|
M::Model::h_subscribe(ev);
|
|
|
|
h_get(ev);
|
|
}
|
|
|
|
void M::Player::h_get(const W::Event& ev)
|
|
{
|
|
W::Vector* ctrls = new W::Vector();
|
|
ItemMap::const_iterator citr = controls.begin();
|
|
ItemMap::const_iterator cend = controls.end();
|
|
|
|
for (; citr != cend; ++citr) {
|
|
W::Vocabulary* cvc = new W::Vocabulary();
|
|
cvc->insert(u"type", new W::Uint64(citr->first));
|
|
cvc->insert(u"address", citr->second);
|
|
|
|
ctrls->push(cvc);
|
|
}
|
|
|
|
W::Vector* vws = new W::Vector();
|
|
ItemMap::const_iterator vitr = views.begin();
|
|
ItemMap::const_iterator vend = views.end();
|
|
|
|
for (; vitr != vend; ++vitr) {
|
|
W::Vocabulary* vvc = new W::Vocabulary();
|
|
vvc->insert(u"type", new W::Uint64(vitr->first));
|
|
vvc->insert(u"address", vitr->second);
|
|
|
|
vws->push(vvc);
|
|
}
|
|
|
|
W::Vocabulary* res = new W::Vocabulary();
|
|
|
|
res->insert(u"controls", ctrls);
|
|
res->insert(u"views", vws);
|
|
res->insert(u"mode", new W::Uint64(mode));
|
|
|
|
response(res, W::Address({u"get"}), ev);
|
|
}
|
|
|
|
void M::Player::onPlayPauseBtn()
|
|
{
|
|
if (playing) {
|
|
pause();
|
|
} else {
|
|
play();
|
|
}
|
|
}
|
|
|
|
void M::Player::h_queue(const W::Event& ev)
|
|
{
|
|
const W::Vocabulary& data = static_cast<const W::Vocabulary&>(ev.getData());
|
|
|
|
const W::Uint64& id = static_cast<const W::Uint64&>(data.at(u"id"));
|
|
ProxySong* song = new ProxySong(id, address + W::Address{W::String(W::Uint64(counter++).toString())});
|
|
addModel(song);
|
|
_queue.push_back(song);
|
|
_queueView->push(song->getAddress());
|
|
|
|
if (current == 0) {
|
|
scheduledToplay = true;
|
|
setActive(song);
|
|
}
|
|
|
|
if (currentIndex + 1 < _queue.size()) {
|
|
nextBtn->setEnabled(true);
|
|
}
|
|
}
|
|
|
|
void M::Player::play()
|
|
{
|
|
if (!playing) {
|
|
playPauseBtn->setLabel(W::String(u"Pause"));
|
|
playing = true;
|
|
|
|
switch (mode) {
|
|
case playBack:
|
|
if (current == 0) {
|
|
scheduledToplay = true;
|
|
} else {
|
|
if (current->isReady()) {
|
|
scheduledToplay = false;
|
|
broadcast(new W::Vocabulary(), W::Address{u"play"});
|
|
break;
|
|
} else {
|
|
scheduledToplay = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void M::Player::pause()
|
|
{
|
|
if (playing) {
|
|
playPauseBtn->setLabel(W::String(u"Play"));
|
|
playing = false;
|
|
|
|
switch (mode) {
|
|
case playBack:
|
|
scheduledToplay = false;
|
|
broadcast(new W::Vocabulary(), W::Address{u"pause"});
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void M::Player::onSongReady()
|
|
{
|
|
emit serviceMessage("Song is ready");
|
|
playPauseBtn->setEnabled(true);
|
|
if (scheduledToplay) {
|
|
scheduledToplay = false;
|
|
if (playing) {
|
|
scheduledToplay = false;
|
|
broadcast(new W::Vocabulary(), W::Address{u"play"});
|
|
} else {
|
|
play();
|
|
}
|
|
}
|
|
}
|
|
|
|
void M::Player::onSongNotReady()
|
|
{
|
|
playPauseBtn->setEnabled(false);
|
|
emit serviceMessage("Something happend to the current song, not sure yet what to do");
|
|
}
|
|
|
|
void M::Player::onNextBtn()
|
|
{
|
|
if (currentIndex + 1 < _queue.size()) {
|
|
if (playing) {
|
|
pause();
|
|
scheduledToplay = true;
|
|
}
|
|
setActive(currentIndex + 1);
|
|
}
|
|
}
|
|
|
|
void M::Player::onPrevBtn()
|
|
{
|
|
if (currentIndex > 0) {
|
|
if (playing) {
|
|
pause();
|
|
scheduledToplay = true;
|
|
}
|
|
setActive(currentIndex - 1);
|
|
}
|
|
}
|
|
|
|
void M::Player::setActive(ProxySong* song)
|
|
{
|
|
if (current == song) {
|
|
return;
|
|
}
|
|
|
|
bool found = false;
|
|
int index;
|
|
for (index = 0; index < _queue.size(); ++index) {
|
|
if (_queue.at(index) == song) {
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (found) {
|
|
setActive(index);
|
|
} else {
|
|
emit serviceMessage("An attempt to set active a song which is no in the queue, not supposed to happen");
|
|
return;
|
|
}
|
|
}
|
|
|
|
void M::Player::setActive(uint64_t index)
|
|
{
|
|
if (index >= _queue.size()) {
|
|
emit serviceMessage("An attempt to set active a song which is no in the queue, not supposed to happen");
|
|
return;
|
|
}
|
|
|
|
ProxySong* song = _queue.at(index);
|
|
currentIndex = index;
|
|
if (currentIndex + 1 < _queue.size()) {
|
|
nextBtn->setEnabled(true);
|
|
} else {
|
|
nextBtn->setEnabled(false);
|
|
}
|
|
|
|
if (currentIndex > 0) {
|
|
prevBtn->setEnabled(true);
|
|
} else {
|
|
prevBtn->setEnabled(false);
|
|
}
|
|
|
|
W::Vocabulary* res = new W::Vocabulary();
|
|
W::Vector* add = new W::Vector();
|
|
W::Vector* remove = new W::Vector();
|
|
if (current != 0) {
|
|
disconnect(current, SIGNAL(ready()), this, SLOT(onSongReady()));
|
|
disconnect(current, SIGNAL(notReady()), this, SLOT(onSongNotReady()));
|
|
remove->push(new W::Uint64(currentPlayback));
|
|
}
|
|
current = song;
|
|
connect(song, SIGNAL(ready()), this, SLOT(onSongReady()));
|
|
connect(song, SIGNAL(notReady()), this, SLOT(onSongNotReady()));
|
|
views.insert(std::make_pair(currentPlayback, song->getAddress()));
|
|
W::Vocabulary* avc = new W::Vocabulary();
|
|
avc->insert(u"type", new W::Uint64(currentPlayback));
|
|
avc->insert(u"address", song->getAddress());
|
|
|
|
add->push(avc);
|
|
|
|
res->insert(u"add", add);
|
|
res->insert(u"remove", remove);
|
|
|
|
|
|
broadcast(res, W::Address{u"viewsChange"});
|
|
if (song->isReady()) {
|
|
playPauseBtn->setEnabled(true);
|
|
if (scheduledToplay) {
|
|
play();
|
|
}
|
|
} else {
|
|
playPauseBtn->setEnabled(false);
|
|
}
|
|
}
|
|
|