#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); W::Handler* hplay = W::Handler::create(address + W::Address({u"play"}), this, &M::Player::_h_play); addHandler(get); addHandler(hqueue); addHandler(hplay); 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(ev.getData()); const W::Uint64& id = static_cast(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) { 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); } } void M::Player::h_play(const W::Event& ev) { const W::Vocabulary& data = static_cast(ev.getData()); const W::Uint64& id = static_cast(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()); scheduledToplay = true; setActive(song); if (currentIndex + 1 < _queue.size()) { nextBtn->setEnabled(true); } }