diff --git a/corax/corax.cpp b/corax/corax.cpp index 742ef81..1365ba3 100644 --- a/corax/corax.cpp +++ b/corax/corax.cpp @@ -43,7 +43,7 @@ Corax::Corax(QObject *parent): attributes->addAttribute(W::String(u"connectionsCount"), new M::String(W::String(u"0"), W::Address({u"attributes", u"connectionCount"}))); attributes->addAttribute(W::String(u"name"), new M::String(W::String(u"Corax"), W::Address({u"attributes", u"name"}))); - attributes->addAttribute(W::String(u"version"), new M::String(W::String(u"0.0.2"), W::Address({u"attributes", u"version"}))); + attributes->addAttribute(W::String(u"version"), new M::String(W::String(u"0.0.3"), W::Address({u"attributes", u"version"}))); attributes->addAttribute(W::String(u"players"), new M::String(W::String(u"0"), W::Address({u"attributes", u"players"}))); createCaches(); diff --git a/corax/models/player.cpp b/corax/models/player.cpp index 4c58204..5533af5 100644 --- a/corax/models/player.cpp +++ b/corax/models/player.cpp @@ -4,27 +4,43 @@ M::Player::Player(const W::Address& address, QObject* parent): M::Model(address, parent), controls(), views(), - playPauseBtn(new M::Button(address + W::Address{u"Play"})), + 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) + 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->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())); } @@ -93,23 +109,9 @@ void M::Player::h_get(const W::Event& ev) void M::Player::onPlayPauseBtn() { if (playing) { - playPauseBtn->setLabel(W::String(u"Play")); - playing = false; - - switch (mode) { - case playBack: - broadcast(new W::Vocabulary(), W::Address{u"pause"}); - break; - } + pause(); } else { - playPauseBtn->setLabel(W::String(u"Pause")); - playing = true; - - switch (mode) { - case playBack: - broadcast(new W::Vocabulary(), W::Address{u"play"}); - break; - } + play(); } } @@ -120,24 +122,174 @@ void M::Player::h_queue(const W::Event& ev) 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) { - current = song; - 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()); - - W::Vector* add = new W::Vector(); - add->push(avc); - - W::Vocabulary* res = new W::Vocabulary(); - res->insert(u"add", add); - res->insert(u"remove", new W::Vector()); - - broadcast(res, W::Address{u"viewsChange"}); - playPauseBtn->setEnabled(true); - } else { - _queue.push_back(song); - _queueView->push(song->getAddress()); + 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); + } +} + diff --git a/corax/models/player.h b/corax/models/player.h index 4265af9..eb1e096 100644 --- a/corax/models/player.h +++ b/corax/models/player.h @@ -32,13 +32,18 @@ namespace M { playPause, currentPlayback, queue, - picture + picture, + prev, + next }; enum Mode { playBack }; + void play(); + void pause(); + protected: void h_subscribe(const W::Event & ev) override; @@ -52,15 +57,26 @@ namespace M { ItemMap controls; ItemMap views; M::Button* playPauseBtn; + M::Button* nextBtn; + M::Button* prevBtn; M::List* _queueView; Queue _queue; ProxySong* current; uint64_t counter; + uint64_t currentIndex; Mode mode; bool playing; + bool scheduledToplay; + + void setActive(ProxySong* song); + void setActive(uint64_t index); private slots: void onPlayPauseBtn(); + void onNextBtn(); + void onPrevBtn(); + void onSongReady(); + void onSongNotReady(); }; } diff --git a/lib/wDatabase/database.cpp b/lib/wDatabase/database.cpp index 0a230e8..05d0307 100644 --- a/lib/wDatabase/database.cpp +++ b/lib/wDatabase/database.cpp @@ -175,6 +175,8 @@ void Database::clear() lmdb::txn transaction = lmdb::txn::begin(environment); dbi.drop(transaction); transaction.commit(); + + elements.clear(); } void Database::addModel(M::Model* model) diff --git a/lib/wModel/icatalogue.cpp b/lib/wModel/icatalogue.cpp index 3eb4401..2733c07 100644 --- a/lib/wModel/icatalogue.cpp +++ b/lib/wModel/icatalogue.cpp @@ -44,6 +44,15 @@ void M::ICatalogue::clear() broadcast(new W::Vocabulary(), W::Address{u"clear"}); } + + std::map::iterator aItr = activeChildren.begin(); + std::map::iterator aEnd = activeChildren.end(); + for (; aItr != aEnd; ++aItr) { + removeModel(aItr->second); + aItr->second->deleteLater(); + } + activeChildren.clear(); + emit countChange(0); } diff --git a/libjs/wController/controller.js b/libjs/wController/controller.js index 268f67d..acaf370 100644 --- a/libjs/wController/controller.js +++ b/libjs/wController/controller.js @@ -188,7 +188,7 @@ var Controller = Subscribable.inherit({ } if (this._registered) { - global.registerForeignController(pair.n, pair.c); + global.unregisterForeignController(pair.n, pair.c); } pair.c.off("serviceMessage", this._onControllerServiceMessage, this); diff --git a/libjs/wController/file/audio.js b/libjs/wController/file/audio.js index 17c6951..deb316c 100644 --- a/libjs/wController/file/audio.js +++ b/libjs/wController/file/audio.js @@ -34,7 +34,6 @@ var Audio = File.inherit({ this._waitingForFrames = false; } - this.initialized = true; return ac; }, _h_responseFrames: function(ev) { diff --git a/libjs/wController/file/file.js b/libjs/wController/file/file.js index c922e4e..f220558 100644 --- a/libjs/wController/file/file.js +++ b/libjs/wController/file/file.js @@ -63,6 +63,11 @@ var File = Controller.inherit({ if (ac) { this.trigger("additionalChange"); } + + if (!this.initialized) { + this.initialized = true; + this.trigger("ready"); + } }, "needData": function() { if (this._need === 0) { diff --git a/libjs/wController/localModel.js b/libjs/wController/localModel.js index b728c2a..4a67050 100644 --- a/libjs/wController/localModel.js +++ b/libjs/wController/localModel.js @@ -30,7 +30,7 @@ var LocalModel = Subscribable.inherit({ for (i = 0; i < this._foreignControllers.length; ++i) { var pair = this._foreignControllers[i]; global.unsubscribeForeignController(pair.n, pair.c); - global.registerForeignController(pair.n, pair.c); + global.unregisterForeignController(pair.n, pair.c); pair.c.destructor(); } diff --git a/libjs/wController/player.js b/libjs/wController/player.js index bae734a..10b8aa7 100644 --- a/libjs/wController/player.js +++ b/libjs/wController/player.js @@ -27,11 +27,8 @@ var Player = Controller.inherit({ this.views = Object.create(null); this.mode = PlayerMode.straight.playback; this._audio = null; - this._source = new Source(); - this._asset = new AV.Asset(this._source); - this._player = new AV.Player(this._asset); - this._player.play(); this._createStateMachine(); + this._createPlayingInfrastructure(); this.addHandler("get"); this.addHandler("viewsChange"); @@ -54,6 +51,8 @@ var Player = Controller.inherit({ if (ItemType.reversed[t] !== undefined) { switch (t) { case ItemType.straight.playPause: + case ItemType.straight.prev: + case ItemType.straight.next: var btn = new Button(address.clone()); btn.itemType = t; this.controls[t] = btn; @@ -61,10 +60,10 @@ var Player = Controller.inherit({ this.trigger("newElement", btn, t); break; default: - this.trigger("serviceMessage", "An attempt to add ItemType " + ItemType.reversed[t] + " to controls of the Player, but it's not qualified to be a control"); + this.trigger("serviceMessage", "An attempt to add ItemType " + ItemType.reversed[t] + " to controls of the Player, but it's not qualified to be a control", 1); } } else { - this.trigger("serviceMessage", "An unrecgnized item ItemType in Player: " + t); + this.trigger("serviceMessage", "An unrecgnized item ItemType in Player: " + t, 1); } }, _addView: function(type, address) { @@ -79,7 +78,7 @@ var Player = Controller.inherit({ if (ItemType.reversed[t] !== undefined) { switch (t) { case ItemType.straight.queue: - this.trigger("serviceMessage", "Queue is not supported yet in Player"); + this.trigger("serviceMessage", "Queue is not supported yet in Player", 1); break; case ItemType.straight.currentPlayback: ctrl = new Vocabulary(address.clone()); @@ -96,10 +95,10 @@ var Player = Controller.inherit({ supported = false; //just to avoid adding with addController, since ImageById is not a controller break; default: - this.trigger("serviceMessage", "An attempt to add ItemType " + ItemType.reversed[t] + " to views of the Player, but it's not qualified to be a view"); + this.trigger("serviceMessage", "An attempt to add ItemType " + ItemType.reversed[t] + " to views of the Player, but it's not qualified to be a view", 1); } } else { - this.trigger("serviceMessage", "An unrecgnized item ItemType in Player: " + t); + this.trigger("serviceMessage", "An unrecognized item ItemType in Player: " + t, 1); } if (supported) { @@ -110,6 +109,16 @@ var Player = Controller.inherit({ this.trigger("newElement", ctrl, t); } }, + _createPlayingInfrastructure() { + if (this._source) { + this._source.reset(); + this._asset.stop(); + this._player.stop(); + } + this._source = new Source(); + this._asset = new AV.Asset(this._source); + this._player = new AV.Player(this._asset); + }, _createStateMachine: function() { this._fsm = new StateMachine("initial", graphs[this.mode]); this._fsm.on("stateChanged", this._onStateChanged, this); @@ -159,7 +168,7 @@ var Player = Controller.inherit({ size = remove.length(); for (i = 0; i < size; ++i) { - this._removeView(remove.at(i)); + this._removeView(remove.at(i).valueOf()); } size = add.length(); @@ -179,6 +188,9 @@ var Player = Controller.inherit({ this._fsm.manipulation("noMoreFrames"); } }, + _onControllerReady: function() { + this._fsm.manipulation("controllerReady"); + }, _onNewPlayBackElement: function(key, element) { switch (key) { case "image": @@ -191,6 +203,7 @@ var Player = Controller.inherit({ this._audio = new Audio(new Address(["music", element.toString()])); this.addForeignController("Corax", this._audio); this._audio.on("newFrames", this._onAudioNewFrames, this); + this._audio.on("ready", this._onControllerReady, this); this._fsm.manipulation("controller"); } break; @@ -199,7 +212,7 @@ var Player = Controller.inherit({ _onNewRemoveBackElement: function(key) { switch (key) { case "image": - this._removeView(new Uint64(ItemType.straight.picture)); + this._removeView(ItemType.straight.picture); break; case "audio": this.removeForeignController(this._audio); @@ -210,14 +223,35 @@ var Player = Controller.inherit({ _onStateChanged: function(e) { switch (e.newState) { case "initial": + if (e.manipulation === "noController") { + + this.removeForeignController(this._audio); + this._audio.destructor(); + this._audio = null; + this._createPlayingInfrastructure(); + } break; case "initialPlaying": + if (e.manipulation === "noController") { + this._player.pause(); + + this.removeForeignController(this._audio); + this.audio.destructor(); + this._audio = null; + this._createPlayingInfrastructure(); + } break; + case "controllerNotReady": + break + case "controllerNotReadyPlaying": + break case "hasController": break; case "hasControllerPlaying": if (this._audio.hasMore()) { this._audio.requestMore(); + + this._player.play(); //todo temporal } else { this._fsm.manipulation("noMoreFrames"); } @@ -249,10 +283,30 @@ var Player = Controller.inherit({ } }, _removeControl: function(type) { - //TODO + var ctrl = this.controls[type]; + if (ctrl !== undefined) { + this.trigger("removeElement", type); + this.removeController(ctrl); + ctrl.destructor(); + } }, _removeView: function(type) { - //TODO + var view = this.views[type]; + if (view !== undefined) { + this.trigger("removeElement", type); + + if (type !== ItemType.straight.picture) { + this.removeController(view); + } + if (type === ItemType.straight.currentPlayback) { + if (this.views[ItemType.straight.picture]) { + this._removeView(ItemType.straight.picture); + } + this._fsm.manipulation("noController"); + } + delete this.views[type]; + view.destructor(); + } } }); @@ -261,6 +315,8 @@ ItemType.add("playPause"); ItemType.add("currentPlayback"); ItemType.add("queue"); ItemType.add("picture"); +ItemType.add("prev"); +ItemType.add("next"); var PlayerMode = new Enum("PlayerMode"); PlayerMode.add("playback"); @@ -270,34 +326,48 @@ Player.ItemType = ItemType; var graphs = Object.create(null); graphs[PlayerMode.straight.playback] = { "initial": { - controller: "hasController", + controller: "controllerNotReady", play: "initialPlaying" }, "initialPlaying": { pause: "initial", - controller: "hasControllerPlaying" + controller: "controllerNotReadyPlaying" + }, + "controllerNotReady": { + play: "controllerNotReadyPlaying", + controllerReady: "hasController" + }, + "controllerNotReadyPlaying": { + pause: "controllerNotReady", + controllerReady: "hasControllerPlaying" }, "hasController": { newFrames: "paused", - play: "hasControllerPlaying" + play: "hasControllerPlaying", + noController: "initial" }, "hasControllerPlaying": { newFrames: "playing", - pause: "hasController" + pause: "hasController", + noController: "initialPlaying" }, "paused": { play: "playing", + noController: "initial", noMoreFrames: "pausedAllLoaded" }, "pausedAllLoaded": { - play: "playingAllLoaded" + play: "playingAllLoaded", + noController: "initial" }, "playing": { pause: "paused", - noMoreFrames: "playingAllLoaded" + noMoreFrames: "playingAllLoaded", + noController: "initialPlaying" }, "playingAllLoaded": { - pause: "pausedAllLoaded" + pause: "pausedAllLoaded", + noController: "initialPlaying" } } diff --git a/lorgar/core/lorgar.js b/lorgar/core/lorgar.js index be3b0af..85082e6 100644 --- a/lorgar/core/lorgar.js +++ b/lorgar/core/lorgar.js @@ -142,6 +142,9 @@ this._emptyHelper = new LocalModel(); + this._gc.on("serviceMessage", this._onServiceMessage, this); + this._ps.on("serviceMessage", this._onServiceMessage, this); + this._gc.on("themeSelected", this.setTheme, this); this._ps.on("pageName", this._onPageName, this); }, @@ -175,6 +178,24 @@ address: this._currentPageCtl.getPairAddress().toArray() }, "", name); }, + "_onServiceMessage": function(text, severity) { + var fn; + + switch (severity) { + case 2: + fn = console.error; + break; + case 1: + fn = console.warn; + break; + case 0: + default: + fn = console.info; + break; + } + + fn(text); + }, "_onSocketConnected": function(name) { console.log(name + " socket connected"); var node = this._nodes[name]; @@ -301,6 +322,8 @@ this._playerCtl.register(this.dispatcher, this._nodes["Corax"].socket); this._playerCtl.subscribe(); this._mainLayout.appendPlayer(this._playerCtl); + + this._playerCtl.on("serviceMessage", this._onServiceMessage, this); }, "setTheme": function(theme) { View.setTheme(theme); diff --git a/lorgar/css/main.css b/lorgar/css/main.css index 26e4c65..96402ed 100644 --- a/lorgar/css/main.css +++ b/lorgar/css/main.css @@ -47,5 +47,13 @@ div.dragging .draggable { } .disabled { - opacity: 0.7; + opacity: 0.5; +} + +.button { + cursor: pointer +} + +.button.disabled { + cursor: not-allowed } diff --git a/lorgar/views/button.js b/lorgar/views/button.js index 05bb72a..db915f7 100644 --- a/lorgar/views/button.js +++ b/lorgar/views/button.js @@ -20,6 +20,7 @@ Layout.fn.constructor.call(this, controller, base); this.addClass("hoverable"); + this.addClass("button"); this._enabled = true; this._hasLabel = false; this._e.addEventListener("click", this._onClick.bind(this), false); @@ -27,10 +28,8 @@ controller.on("setEnabled", this._onSetEnabled, this); controller.on("setLabel", this._onSetLabel, this); - if (controller.initialized) { - this._onSetEnabled(controller.enabled); - this._onSetLabel(controller.hasLabel, controller.label); - } + this._onSetEnabled(controller.enabled); + this._onSetLabel(controller.hasLabel, controller.label); }, "destructor": function() { this._f.off("setEnabled", this._onSetEnabled, this); diff --git a/lorgar/views/player.js b/lorgar/views/player.js index 4bb27a7..160333c 100644 --- a/lorgar/views/player.js +++ b/lorgar/views/player.js @@ -30,6 +30,8 @@ GridLayout.fn.constructor.call(this, ctrl, options); this._playPause = null; + this._prev = null; + this._next = null; this._picture = null; this._cpbCtrl = null; this._infoModels = { @@ -39,16 +41,17 @@ } ctrl.on("newElement", this._onNewElement, this); + ctrl.on("removeElement", this._onRemoveElement, this); var artist = new Label(this._infoModels.artist); var album = new Label(this._infoModels.album); var song = new Label(this._infoModels.song); var spacer = new View(helper); - this.append(artist, 0, 2, 1, 1, GridLayout.Aligment.LeftCenter); - this.append(song, 1, 2, 1, 1, GridLayout.Aligment.LeftCenter); - this.append(album, 2, 2, 1, 1, GridLayout.Aligment.LeftCenter); - this.append(spacer, 0, 3, 3, 1, GridLayout.Aligment.LeftCenter); + this.append(artist, 0, 4, 1, 1, GridLayout.Aligment.LeftCenter); + this.append(song, 1, 4, 1, 1, GridLayout.Aligment.LeftCenter); + this.append(album, 2, 4, 1, 1, GridLayout.Aligment.LeftCenter); + this.append(spacer, 0, 5, 3, 1, GridLayout.Aligment.LeftCenter); this._uncyclic.push(this._infoModels.artist.destructor.bind(this._infoModels.artist)); this._uncyclic.push(this._infoModels.song.destructor.bind(this._infoModels.song)); @@ -56,6 +59,7 @@ }, destructor: function() { this._f.off("newElement", this._onNewElement, this); + this._f.off("removeElement", this._onRemoveElement, this); this._clearCpbCtrl(); GridLayout.fn.destructor.call(this); @@ -73,7 +77,15 @@ switch (type) { case ItemType.straight.playPause: this._playPause = new Button(ctrl); - this.append(this._playPause, 0, 1, 3, 1); + this.append(this._playPause, 0, 2, 3, 1); + break; + case ItemType.straight.prev: + this._prev = new Button(ctrl); + this.append(this._prev, 0, 1, 3, 1); + break; + case ItemType.straight.next: + this._next = new Button(ctrl); + this.append(this._next, 0, 3, 3, 1); break; case ItemType.straight.queue: break; @@ -92,6 +104,33 @@ break; } }, + _onRemoveElement: function(type) { + var ItemType = Enum.storage["ItemType"]; + + switch (type) { + case ItemType.straight.playPause: + this._playPause.destructor(); + this._playPause = null; + break; + case ItemType.straight.prev: + this._prev.destructor(); + this._prev = null; + break; + case ItemType.straight.next: + this._next.destructor(); + this._next = null; + break; + case ItemType.straight.queue: + break; + case ItemType.straight.currentPlayback: + this._clearCpbCtrl(); + break; + case ItemType.straight.picture: + this._picture.destructor(); + this._picture = null; + break; + } + }, _onCpbNewElement: function(key, value) { var model = this._infoModels[key];