diff --git a/campcaster/src/modules/core/include/LiveSupport/Core/Playlist.h b/campcaster/src/modules/core/include/LiveSupport/Core/Playlist.h index 4c66e5396..fdf115465 100644 --- a/campcaster/src/modules/core/include/LiveSupport/Core/Playlist.h +++ b/campcaster/src/modules/core/include/LiveSupport/Core/Playlist.h @@ -883,6 +883,23 @@ class Playlist : public Configurable, */ virtual bool eliminateGaps(void) throw (); + + /** + * Find the playlist element at the specified offset. + * + * This is used by the Master Panel to display the contents + * of the currently playing Playlist. + * When there are more than one playlist elements at the given + * offset, the one with the greatest relativeOffset is chosen. + * Can return a 0 pointer if there is no playlist element at + * the given offset. + * + * @param offset the elapsed time relative to the Playlist. + * @return the playlist element at the given offset. + */ + Ptr::Ref + findAtOffset(Ptr::Ref offset) const + throw (); }; diff --git a/campcaster/src/modules/core/src/Playlist.cxx b/campcaster/src/modules/core/src/Playlist.cxx index 664897962..b95fa5356 100644 --- a/campcaster/src/modules/core/src/Playlist.cxx +++ b/campcaster/src/modules/core/src/Playlist.cxx @@ -901,3 +901,33 @@ Playlist :: eliminateGaps(void) throw () } } + +/*------------------------------------------------------------------------------ + * Find the playlist element at the specified offset. + *----------------------------------------------------------------------------*/ +Ptr::Ref +Playlist :: findAtOffset(Ptr::Ref offset) const + throw () +{ + Ptr::Ref playlistElement; + + PlaylistElementListType::const_reverse_iterator it; + PlaylistElementListType::const_reverse_iterator rend + = elementList->rend(); + for (it = elementList->rbegin(); it != rend; ++it) { + time_duration currentStart = it->first; + if (currentStart <= *offset) { + Ptr::Ref + currentElement = it->second; + time_duration currentEnd = currentStart + + *currentElement->getPlayable() + ->getPlaylength(); + if (currentEnd > *offset) { + playlistElement = currentElement; + } + } + } + + return playlistElement; +} + diff --git a/campcaster/src/modules/core/src/PlaylistTest.cxx b/campcaster/src/modules/core/src/PlaylistTest.cxx index 28682f663..597076c48 100644 --- a/campcaster/src/modules/core/src/PlaylistTest.cxx +++ b/campcaster/src/modules/core/src/PlaylistTest.cxx @@ -481,3 +481,46 @@ PlaylistTest :: eliminateGapsLastItemTest(void) } + +/*------------------------------------------------------------------------------ + * Test the findAtOffset() method. + *----------------------------------------------------------------------------*/ +void +PlaylistTest :: findAtOffsetTest(void) throw (CPPUNIT_NS::Exception) +{ + Ptr::Ref offset(new time_duration()); + Ptr::Ref playlistElement; + + *offset = seconds(-1); + playlistElement = playlist->findAtOffset(offset); + CPPUNIT_ASSERT(!playlistElement); + + *offset = seconds(0); + playlistElement = playlist->findAtOffset(offset); + CPPUNIT_ASSERT(playlistElement); + CPPUNIT_ASSERT(playlistElement->getPlayable()->getId()->getId() == 0x10001); + + *offset = seconds(11); + playlistElement = playlist->findAtOffset(offset); + CPPUNIT_ASSERT(playlistElement); + CPPUNIT_ASSERT(playlistElement->getPlayable()->getId()->getId() == 0x10002); + + *offset = seconds(20); + playlistElement = playlist->findAtOffset(offset); + CPPUNIT_ASSERT(playlistElement); + CPPUNIT_ASSERT(playlistElement->getPlayable()->getId()->getId() == 0x10002); + + *offset = microseconds(30123456); + playlistElement = playlist->findAtOffset(offset); + CPPUNIT_ASSERT(playlistElement); + CPPUNIT_ASSERT(playlistElement->getPlayable()->getId()->getId() == 0x2); + + *offset = seconds(34); + playlistElement = playlist->findAtOffset(offset); + CPPUNIT_ASSERT(!playlistElement); + + *offset = hours(1); + playlistElement = playlist->findAtOffset(offset); + CPPUNIT_ASSERT(!playlistElement); +} + diff --git a/campcaster/src/modules/core/src/PlaylistTest.h b/campcaster/src/modules/core/src/PlaylistTest.h index bb696ea32..69ff7bb91 100644 --- a/campcaster/src/modules/core/src/PlaylistTest.h +++ b/campcaster/src/modules/core/src/PlaylistTest.h @@ -73,6 +73,7 @@ class PlaylistTest : public CPPUNIT_NS::TestFixture CPPUNIT_TEST(addPlayableTest); CPPUNIT_TEST(eliminateGapsTest); CPPUNIT_TEST(eliminateGapsLastItemTest); + CPPUNIT_TEST(findAtOffsetTest); CPPUNIT_TEST_SUITE_END(); private: @@ -156,6 +157,14 @@ class PlaylistTest : public CPPUNIT_NS::TestFixture void eliminateGapsLastItemTest(void) throw (CPPUNIT_NS::Exception); + /** + * Test the findAtOffset() method. + * + * @exception CPPUNIT_NS::Exception on test failures. + */ + void + findAtOffsetTest(void) throw (CPPUNIT_NS::Exception); + public: diff --git a/campcaster/src/products/gLiveSupport/src/NowPlaying.cxx b/campcaster/src/products/gLiveSupport/src/NowPlaying.cxx index d920c5e76..1f36fa9e0 100644 --- a/campcaster/src/products/gLiveSupport/src/NowPlaying.cxx +++ b/campcaster/src/products/gLiveSupport/src/NowPlaying.cxx @@ -183,22 +183,11 @@ NowPlaying :: setPlayable(Ptr::Ref playable) throw () pack_end(*pauseButton, Gtk::PACK_SHRINK, 2); pauseButton->show(); } + this->playable = playable; isActive = true; isPaused = false; - - titleLabel->set_text(*playable->getTitle()); - - Ptr::Ref - creator = playable->getMetadata("dc:creator"); - if (creator) { - creatorLabel->set_text(*creator); - } else { - creatorLabel->set_text(""); - } - - audioLength = TimeConversion::roundToNearestSecond( - playable->getPlaylength()); resetRemainsTimeState(); + onUpdateTime(); } else { if (isActive && !isPaused) { @@ -211,8 +200,9 @@ NowPlaying :: setPlayable(Ptr::Ref playable) throw () creatorLabel->set_text(""); elapsedTime->set_text(""); remainsTime->set_text(""); + playlistLabel->set_text(""); resetRemainsTimeState(); - audioLength.reset(); + this->playable.reset(); } } @@ -317,8 +307,11 @@ NowPlaying :: onUpdateTime(void) throw () return; } + Ptr::Ref totalLength + = TimeConversion::roundToNearestSecond( + playable->getPlaylength()); Ptr::Ref remains(new time_duration( - *audioLength - *elapsed )); + *totalLength - *elapsed)); switch (remainsTimeState) { case TIME_GREEN : if (*remains <= seconds(20)) { @@ -337,10 +330,56 @@ NowPlaying :: onUpdateTime(void) throw () } setRemainsTimeColor(remainsTimeState); + Ptr::Ref innerPlayable = playable; + Ptr::Ref innerElapsed = elapsed; + Ptr::Ref innerRemains = remains; + Glib::ustring playlistInfo; + bool isFirst = true; + + while (innerPlayable->getType() == Playable::PlaylistType) { + if (isFirst) { + isFirst = false; + } else { + playlistInfo += " >>> "; + } + playlistInfo += *innerPlayable->getTitle(); + playlistInfo += " ["; + playlistInfo += *TimeConversion::timeDurationToHhMmSsString( + innerRemains); + playlistInfo += "/"; + playlistInfo += *TimeConversion::timeDurationToHhMmSsString( + innerPlayable->getPlaylength()); + playlistInfo += "]"; + + Ptr::Ref element + = innerPlayable->getPlaylist() + ->findAtOffset(elapsed); + if (!element) { + break; + } + innerPlayable = element->getPlayable(); + *innerElapsed -= *element->getRelativeOffset(); + *innerRemains = *TimeConversion::roundToNearestSecond( + innerPlayable->getPlaylength()) + - *innerElapsed; + } + + playlistLabel->set_text(playlistInfo); + + titleLabel->set_text(*innerPlayable->getTitle()); + + Ptr::Ref + creator = innerPlayable->getMetadata("dc:creator"); + if (creator) { + creatorLabel->set_text(*creator); + } else { + creatorLabel->set_text(""); + } + elapsedTime->set_text(*TimeConversion::timeDurationToHhMmSsString( - elapsed )); + innerElapsed )); remainsTime->set_text(*TimeConversion::timeDurationToHhMmSsString( - remains )); + innerRemains )); } diff --git a/campcaster/src/products/gLiveSupport/src/NowPlaying.h b/campcaster/src/products/gLiveSupport/src/NowPlaying.h index 603f58499..168e7e1d7 100644 --- a/campcaster/src/products/gLiveSupport/src/NowPlaying.h +++ b/campcaster/src/products/gLiveSupport/src/NowPlaying.h @@ -84,9 +84,9 @@ class NowPlaying : public Gtk::HBox, bool isPaused; /** - * The length of the item currently playing. + * The item which is currently playing. */ - Ptr::Ref audioLength; + Ptr::Ref playable; /** * The label holding the title of the now playing item.