diff -r ed94e1e8390e -r 3cd404d31176 musicwidgetplugin/src/musicwidget.cpp --- a/musicwidgetplugin/src/musicwidget.cpp Fri Sep 17 08:28:52 2010 +0300 +++ b/musicwidgetplugin/src/musicwidget.cpp Mon Oct 04 00:14:19 2010 +0300 @@ -15,9 +15,8 @@ * */ -#include "musicwidget.h" - -#include +// System includes +#include #include #include #include @@ -26,174 +25,95 @@ #include #include #include -#include +#include +// User includes +#include "musicwidget.h" #include "musicwidgetdocumentloader.h" #include "mptrace.h" #include "mpenginefactory.h" #include "mpalbumcoverwidget.h" +#include "mpplaybackdata.h" +#include "mpapplicationmonitor.h" // Constants /** Docml */ -const QString MUSIC_WIDGET_DOCML = ":/gfx/music_widget.docml"; - -/** File name suffix lists for push buttons */ -const QStringList PREV_BUTTON_SUFFIXES = (QStringList() << "_l" << "_c" << "_cr"); -const QStringList PLAY_BUTTON_SUFFIXES = (QStringList() << "_cl" << "_c" << "_cr"); -const QStringList NEXT_BUTTON_SUFFIXES = (QStringList() << "_cl" << "_c" << "_r"); - -/** Prefixes for 3 piece button background graphics */ -const QLatin1String PUSH_BUTTON_NORMAL("qtg_fr_hsbutton_normal"); -const QLatin1String PUSH_BUTTON_PRESSED ("qtg_fr_hsbutton_pressed"); -const QLatin1String PUSH_BUTTON_DISABLED ("qtg_fr_hsbutton_disabled"); - -/** Push button icon colors for each of the states (Normal, Pressed and Disabled) */ -const QLatin1String ICON_COLOR_NORMAL ("qtc_button_normal"); -const QLatin1String ICON_COLOR_PRESSED ("qtc_button_pressed"); -const QLatin1String ICON_COLOR_DISABLED ("qtc_button_disabled"); +const QString MUSIC_WIDGET_DOCML = ":/docml/music_widget.docml"; /** Play and Pause icons */ -const QLatin1String ICON_PLAY ("qtg_mono_play"); -const QLatin1String ICON_PAUSE ("qtg_mono_pause"); -/** Music Player shortcut icon */ -const QLatin1String ICON_LARGE_MUSIC_PLAYER ("qtg_large_music"); -/** Music Player shortcut icon */ -const QLatin1String ICON_FIRST_TIME_USE ("qtg_large_music_empty"); -const QLatin1String ICON_DEFAULT_ART ("qtg_large_album_art"); +const QLatin1String ICON_PLAY ( "qtg_mono_play" ); +const QLatin1String ICON_PAUSE ( "qtg_mono_pause" ); + +/** Album art icon */ +const QLatin1String ICON_DEFAULT_ART ( "qtg_large_music_empty" ); /** HsWidget normal background */ -const QLatin1String WIDGET_BG_NORMAL ("qtg_fr_hswidget_normal"); +const QLatin1String WIDGET_BG_NORMAL ( "qtg_fr_hswidget_normal" ); /** Text background */ -const QLatin1String TEXT_BG_NORMAL ("qtg_fr_multimedia_trans"); +const QLatin1String TEXT_BG_NORMAL ( "qtg_fr_multimedia_trans" ); /** Separator : character and space between artist and song name */ -const QLatin1String SEPARATOR_TEXT (": "); -/** Temporary unknown artist */ -const QLatin1String TEMPORARY_UNKWNOWN_TEXT ("Unknown"); -/** Localized unknown artist */ -const QLatin1String UNKWNOWN_TEXT ("txt_mus_other_unknown_1"); +const QLatin1String SEPARATOR_TEXT ( ": " ); -/** Marquee width */ -const int MARQUEE_WIDTH = 170; /** Infinite loop value for marquee */ const int MARQUEE_LOOP_FOREVER = -1; /** Now playing view with random play */ -const QLatin1String SERVICEREQ_FIRST_TIME_USE ("appto://10207C62?activityname=MusicNowPlayingView&launchtype=standalone&shuffle=yes"); +const QLatin1String SERVICEREQ_NOW_PLAYING_VIEW_SHUFFLE ( "appto://10207C62?activityname=MusicNowPlayingView&launchtype=standalone&shuffle=yes" ); /** Main view */ -const QLatin1String SERVICEREQ_MAIN_VIEW ("appto://10207C62?activityname=MusicMainView&launchtype=standalone"); +const QLatin1String SERVICEREQ_MAIN_VIEW ( "appto://10207C62?activityname=MusicMainView&launchtype=standalone" ); /** Now playing view */ -const QLatin1String SERVICEREQ_NOW_PLAYING_VIEW ("appto://10207C62?activityname=MusicNowPlayingView&launchtype=standalone"); +const QLatin1String SERVICEREQ_NOW_PLAYING_VIEW ( "appto://10207C62?activityname=MusicNowPlayingView&launchtype=standalone" ); + +/** DOCML object names */ +const QLatin1String DOCML_CONTAINER_WIDGET ( "containerWidget" ); +const QLatin1String DOCML_BG_ICON ( "widget_background_icon" ); +const QLatin1String DOCML_ALBUM_ART ( "album_art_image" ); +const QLatin1String DOCML_TEXT_BG ( "text_bg" ); +const QLatin1String DOCML_SCROLLING_TEXT ( "scrolling_text" ); +const QLatin1String DOCML_BUTTON_GROUP_CONTAINER ( "button_group_container" ); +const QLatin1String DOCML_PREV_BUTTON ( "btn_previous" ); +const QLatin1String DOCML_PLAY_BUTTON ( "btn_play" ); +const QLatin1String DOCML_NEXT_BUTTON ( "btn_next" ); -/** DOCML object name for main widget */ -const QLatin1String DOCML_CONTAINER_WIDGET ("containerWidget"); -/** DOCML object name for widget background */ -const QLatin1String DOCML_BG_ICON ("widget_background_icon"); -/** DOCML object name for album art image */ -const QLatin1String DOCML_ALBUM_ART ("album_art_image"); -/** DOCML object name for shortcut icon background */ -const QLatin1String DOCML_SHORTCUT_ICON_BG ("shortcut_icon_background"); -/** DOCML object name for shortcut icon */ -const QLatin1String DOCML_SHORTCUT_ICON ("shortcut_icon"); -/** DOCML object name for scrolling text background */ -const QLatin1String DOCML_TEXT_BG ("text_bg"); -/** DOCML object name for scrolling text */ -const QLatin1String DOCML_SCROLLING_TEXT ("scrolling_text"); -/** DOCML object name for button group container */ -const QLatin1String DOCML_BUTTON_GROUP_CONTAINER ("button_group_container"); -/** DOCML object name for prev button */ -const QLatin1String DOCML_PREV_BUTTON ("btn_previous"); -/** DOCML object name for play button */ -const QLatin1String DOCML_PLAY_BUTTON ("btn_play"); -/** DOCML object name for next button */ -const QLatin1String DOCML_NEXT_BUTTON ("btn_next"); +/*! + \class MusicWidget + \brief Provides simple Music Player playback controls from the Home Screen. + */ - -MusicWidget::MusicWidget(QGraphicsItem* parent, Qt::WindowFlags flags): - HbWidget(parent, flags), - mShortcutArea(0), - mSongDataBG(0), - mInformationSongName(0), - mMarqueeText(0), - mPreviousPushButton(0), - mPlayPushButton(0), - mNextPushButton(0), - mMusicPlayerNoSongData(1), - mMusicPlayerUpdating(0), - mMusicPlayerBlocked(0), - mAlbumArt(0), - mArtist(0), - mTitle(0), - mMpEngine(0), - mMpPlaybackData(0) +/*! + Constructs the Music Player home screen widget. + */ +MusicWidget::MusicWidget( QGraphicsItem* parent, Qt::WindowFlags flags ): + HbWidget( parent, flags ), + mSongDataBackground( 0 ), + mMarqueeText( 0 ), + mPreviousPushButton( 0 ), + mPlayPushButton( 0 ), + mNextPushButton( 0 ), + mMusicPlayerUpdating( false ), + mMusicPlayerBlocked( false ), + mMusicPlayerRunning( false ), + mAlbumArt( 0 ), + mMpEngine( 0 ), + mMpPlaybackData( 0 ), + mMpApplicationMonitor( 0 ) { - TX_ENTRY - - // Setup UI - setupUi(); - - // Connect to MP engine and playback data - mMpEngine = MpEngineFactory::createSharedEngine(MpCommon::KMusicPlayerUid, MpEngine::HomeScreen ); - Q_ASSERT_X(mMpEngine, "music_widget", "no music player engine"); - TX_LOG_ARGS("got mp engine") - - mMpPlaybackData = mMpEngine->playbackData(); - Q_ASSERT_X(mMpPlaybackData, "music_widget", "no playback data"); - TX_LOG_ARGS("got playback data") - - // Connect outgoing signals and slots - QObject::connect(mShortcutArea, SIGNAL(clicked()), this, SLOT(shortcutButton())); - - // use signal mapper to indicate button identifiers to button event slots - QSignalMapper* signalMapperPressed = new QSignalMapper( this ); - signalMapperPressed->setMapping( mPreviousPushButton, EPrevious ); - signalMapperPressed->setMapping( mPlayPushButton, EPlayPause); - signalMapperPressed->setMapping( mNextPushButton, ENext); - - // need to use different signal mapper for pressed and released events, - // both have same mappings but they are mapped to different slots - QSignalMapper* signalMapperReleased = new QSignalMapper( this ); - signalMapperReleased->setMapping( mPreviousPushButton, EPrevious ); - signalMapperReleased->setMapping( mPlayPushButton, EPlayPause); - signalMapperReleased->setMapping( mNextPushButton, ENext); - - // Connect button events to signal maps - QObject::connect(mPreviousPushButton, SIGNAL(pressed()), signalMapperPressed, SLOT (map())); - QObject::connect(mPreviousPushButton, SIGNAL(released()), signalMapperReleased, SLOT (map())); - - QObject::connect(mPlayPushButton, SIGNAL(pressed()), signalMapperPressed, SLOT (map())); - QObject::connect(mPlayPushButton, SIGNAL(released()), signalMapperReleased, SLOT (map())); - - QObject::connect(mNextPushButton, SIGNAL(pressed()), signalMapperPressed, SLOT (map())); - QObject::connect(mNextPushButton, SIGNAL(released()), signalMapperReleased, SLOT (map())); - - // Connect mapper signals to self implemented slots - QObject::connect( signalMapperPressed, SIGNAL(mapped(int)), this, SLOT(mediaButtonPressed(int))); - QObject::connect( signalMapperReleased, SIGNAL(mapped(int)), this, SLOT(mediaButtonReleased(int))); - - // Connect clicked events - QObject::connect(mPreviousPushButton, SIGNAL(clicked()), this, SLOT(prevSong())); - QObject::connect(mPlayPushButton, SIGNAL(clicked()), this, SLOT(playSong())); - QObject::connect(mNextPushButton, SIGNAL(clicked()), this, SLOT(nextSong())); - - // MpEngine - QObject::connect(mMpEngine, SIGNAL(libraryUpdateStarted()), this, SLOT(libraryUpdateStarted())); - QObject::connect(mMpEngine, SIGNAL(libraryUpdated()), this, SLOT(libraryUpdated())); - QObject::connect(mMpEngine, SIGNAL(usbBlocked(bool)), this, SLOT(usbBlocked(bool))); - - //MpPlaybackData - QObject::connect(mMpPlaybackData, SIGNAL(albumArtReady()), this, SLOT(albumArtReady())); - QObject::connect(mMpPlaybackData, SIGNAL(playbackStateChanged()), this, SLOT(playbackStateChanged())); - QObject::connect(mMpPlaybackData, SIGNAL(playbackInfoChanged()), this, SLOT(playbackInfoChanged())); - - // Initial data from Music Player get by onShow method call - TX_EXIT + TX_LOG + HbTranslator translator( QString( "musicwidgetplugin" ) ); } /*! - Destructor -*/ + Destructor + */ MusicWidget::~MusicWidget() { + TX_ENTRY + if ( mMpEngine ) { + MpEngineFactory::close(); + } + + delete mMpApplicationMonitor; + TX_EXIT } /*! @@ -206,235 +126,66 @@ // Use document loader to load the contents MusicWidgetDocumentLoader loader; bool ok = false; - loader.load( MUSIC_WIDGET_DOCML, &ok); - Q_ASSERT_X(ok, "music_widget", "invalid title docml file"); + loader.load( MUSIC_WIDGET_DOCML, &ok ); + Q_ASSERT_X( ok, "music_widget", "invalid title docml file" ); - TX_LOG_ARGS("loaded docml") + TX_LOG_ARGS( "loaded docml" ) - QGraphicsLinearLayout* mainLayout = new QGraphicsLinearLayout(Qt::Vertical, this); - QGraphicsWidget* container = loader.findWidget(DOCML_CONTAINER_WIDGET); - mainLayout->addItem(container); + QGraphicsLinearLayout* mainLayout = new QGraphicsLinearLayout( Qt::Vertical, this ); + QGraphicsWidget* container = loader.findWidget( DOCML_CONTAINER_WIDGET ); + mainLayout->addItem( container ); + //Sets parent setLayout( mainLayout ); // Load and set widget background - HbWidget *bgWidget = qobject_cast (loader.findWidget(DOCML_BG_ICON)); - HbFrameItem *frameItem; - if (bgWidget) - { - HbFrameDrawer *drawer = new HbFrameDrawer(WIDGET_BG_NORMAL, - HbFrameDrawer::NinePieces); - frameItem = new HbFrameItem(drawer, bgWidget); - frameItem->setPreferredSize(bgWidget->preferredSize()); - bgWidget->setZValue(1); - } + HbLabel *bgWidget = qobject_cast ( loader.findWidget( DOCML_BG_ICON ) ); + HbFrameItem *frameItemWidgetBg = new HbFrameItem(); + frameItemWidgetBg->frameDrawer().setFrameGraphicsName( WIDGET_BG_NORMAL ); + frameItemWidgetBg->frameDrawer().setFrameType( HbFrameDrawer::NinePieces ); + frameItemWidgetBg->frameDrawer().setFillWholeRect( true ); + bgWidget->setBackgroundItem( frameItemWidgetBg ); // Setup album art area QGraphicsWidget *tmpWidgetPtr; - tmpWidgetPtr = loader.findWidget(DOCML_ALBUM_ART); - mAlbumArt = qobject_cast(tmpWidgetPtr); + tmpWidgetPtr = loader.findWidget( DOCML_ALBUM_ART ); + mAlbumArt = qobject_cast( tmpWidgetPtr ); mAlbumArt->setEnabled( false ); mAlbumArt->setDefaultIcon( HbIcon( ICON_DEFAULT_ART ) ); - // Load shortcut background - HbWidget *shortcutAreaLayout = qobject_cast (loader.findWidget(DOCML_SHORTCUT_ICON_BG)); - HbFrameItem *shortcutFrameItem; - if (shortcutAreaLayout) { - HbFrameDrawer *drawer = new HbFrameDrawer(WIDGET_BG_NORMAL, - HbFrameDrawer::NinePieces); - shortcutFrameItem = new HbFrameItem(drawer, shortcutAreaLayout); - shortcutFrameItem->setPreferredSize(shortcutAreaLayout->preferredSize()); - shortcutAreaLayout->setZValue(3); - } - - // Load shortcut widget and set background - mShortcutArea = qobject_cast (loader.findWidget(DOCML_SHORTCUT_ICON)); - if ( mShortcutArea ) - { - // icon needs to be put as a background so that it fills the whole button area - HbFrameDrawer* drawer = new HbFrameDrawer(ICON_LARGE_MUSIC_PLAYER, HbFrameDrawer::OnePiece); - mShortcutArea->setFrameBackground( drawer ); - } - // Set song data background - mSongDataBG = qobject_cast (loader.findWidget(DOCML_TEXT_BG)); - HbFrameItem *scrollTextItem; - if (mSongDataBG) - { - HbFrameDrawer *drawer = new HbFrameDrawer(TEXT_BG_NORMAL, - HbFrameDrawer::NinePieces); - scrollTextItem = new HbFrameItem(drawer, mSongDataBG); - scrollTextItem->setPreferredSize(mSongDataBG->preferredSize()); - mSongDataBG->setZValue(4); - mSongDataBG->hide(); // Hide initially... - } + mSongDataBackground = qobject_cast ( loader.findWidget( DOCML_TEXT_BG ) ); + HbFrameItem *frameItemSongBg = new HbFrameItem(); + frameItemSongBg->frameDrawer().setFrameGraphicsName( TEXT_BG_NORMAL ); + frameItemSongBg->frameDrawer().setFrameType( HbFrameDrawer::NinePieces ); + frameItemSongBg->frameDrawer().setFillWholeRect( true ); + mSongDataBackground->setBackgroundItem( frameItemSongBg ); + mSongDataBackground->hide(); // Set scrolling song data - mInformationSongName = qobject_cast (loader.findWidget(DOCML_SCROLLING_TEXT)); - if ( mInformationSongName ) - { - // Setting primitive marquee item values from .css doesn't work well, set in code... - mMarqueeText = new HbMarqueeItem(mInformationSongName); - HbFontSpec fs(HbFontSpec::Secondary); - mMarqueeText->setFontSpec(fs); - mMarqueeText->setTextColor(mInformationSongName->textColor()); - mMarqueeText->setMinimumWidth(MARQUEE_WIDTH); - mMarqueeText->setLoopCount(MARQUEE_LOOP_FOREVER); - } - - HbWidget *buttonGroupContainer = qobject_cast (loader.findWidget( - DOCML_BUTTON_GROUP_CONTAINER)); - if (buttonGroupContainer) - { - // Define push buttons in state at this point, check the player status later and update buttons if needed - mPreviousPushButton = qobject_cast (loader.findWidget(DOCML_PREV_BUTTON)); - defineMediaButton( *mPreviousPushButton, PUSH_BUTTON_NORMAL, PREV_BUTTON_SUFFIXES, ICON_COLOR_NORMAL ); - - mPlayPushButton = qobject_cast (loader.findWidget(DOCML_PLAY_BUTTON)); - defineMediaButton( *mPlayPushButton, PUSH_BUTTON_NORMAL, PLAY_BUTTON_SUFFIXES, ICON_COLOR_NORMAL ); - - mNextPushButton = qobject_cast (loader.findWidget(DOCML_NEXT_BUTTON)); - defineMediaButton( *mNextPushButton, PUSH_BUTTON_NORMAL, NEXT_BUTTON_SUFFIXES, ICON_COLOR_NORMAL ); - } - + mMarqueeText = qobject_cast ( loader.findWidget( DOCML_SCROLLING_TEXT ) ); + mMarqueeText->setLoopCount( MARQUEE_LOOP_FOREVER ); + + // Get buttons + HbWidget *buttonGroupContainer = qobject_cast ( loader.findWidget( + DOCML_BUTTON_GROUP_CONTAINER ) ); + if ( buttonGroupContainer ) { + // Define push buttons + mPreviousPushButton = qobject_cast ( loader.findWidget( DOCML_PREV_BUTTON ) ); + mPlayPushButton = qobject_cast ( loader.findWidget( DOCML_PLAY_BUTTON ) ); + mNextPushButton = qobject_cast ( loader.findWidget( DOCML_NEXT_BUTTON ) ); + } + TX_EXIT } /*! - Makes the push button based on information aGraphicsId and aSuffix - */ -void MusicWidget::defineMediaButton( HbPushButton& aTarget, QString aGraphicsId, QStringList aSuffix, QString aIconColor ) - { - TX_ENTRY - - TX_LOG_ARGS("graphics id: " << aGraphicsId) - TX_LOG_ARGS("icon color: " << aIconColor) - - HbFrameDrawer* drawer; - - // First check if the drawer is already created for this push button - if ( !aTarget.frameBackground()){ - // Nope, create one now - drawer = new HbFrameDrawer(aGraphicsId, HbFrameDrawer::ThreePiecesHorizontal); - aTarget.setFrameBackground( drawer ); - TX_LOG_ARGS("created drawer for button bg") - } - else { - // Frame drawer already created, only need to update frame graphics - drawer = aTarget.frameBackground(); - drawer->setFrameGraphicsName( aGraphicsId ); - TX_LOG_ARGS("using existing drawer for button bg") - } - - // Set file name suffix list, so that drawer can load correct 3-piece graphic files - drawer->setFileNameSuffixList( aSuffix ); - - // Update also the icon color - QColor color = HbColorScheme::color(aIconColor); - aTarget.icon().setColor( color ); - - // Lastly, check if the buttton is disabled - if ( aIconColor == ICON_COLOR_DISABLED ) - { - aTarget.setEnabled(false); - TX_LOG_ARGS("button disabled") - } - else - { - aTarget.setEnabled(true); - TX_LOG_ARGS("button enabled") - } - - TX_EXIT - } - -/*! - - */ -void MusicWidget::mediaButtonEvent( MediaKeyIdentifier aMediaKeyId, QString aGraphicsId, QString aIconColor ) - { - TX_ENTRY - - HbPushButton* target = NULL; - QStringList suffix; - - switch ( aMediaKeyId ) - { - case EPrevious: { - TX_LOG_ARGS("previous") - target = mPreviousPushButton; - suffix = PREV_BUTTON_SUFFIXES; - break; - } - case EPlayPause: { - TX_LOG_ARGS("play/pause") - target = mPlayPushButton; - suffix = PLAY_BUTTON_SUFFIXES; - break; - } - case ENext: { - TX_LOG_ARGS("next") - target = mNextPushButton; - suffix = NEXT_BUTTON_SUFFIXES; - break; - } - default: { - // Do proper error handling.. should not be possible to get here ever tough - TX_LOG_ARGS("unknown button") - return; - } - } - - if ( target ) - { - MusicWidget::defineMediaButton( *target, aGraphicsId, suffix, aIconColor ); - } - - TX_EXIT - } - -/*! - Emited from HbPushButton:pressed() signal, changes the button layout to 'Pressed' - */ -void MusicWidget::mediaButtonPressed( int aMediaKeyId ) - { - TX_LOG_ARGS("media key: " << aMediaKeyId ) - mediaButtonEvent( (MediaKeyIdentifier)aMediaKeyId, PUSH_BUTTON_PRESSED, ICON_COLOR_PRESSED ); - } - -/*! - Emited from HbPushButton:released() signal, changes the button layout to 'Normal' - */ -void MusicWidget::mediaButtonReleased( int aMediaKeyId ) - { - TX_LOG_ARGS("media key: " << aMediaKeyId ) - mediaButtonEvent( (MediaKeyIdentifier)aMediaKeyId, PUSH_BUTTON_NORMAL, ICON_COLOR_NORMAL ); - } - -/*! - Disables specified push button - */ -void MusicWidget::mediaButtonDisabled( int aMediaKeyId ) - { - TX_LOG_ARGS("media key: " << aMediaKeyId ) - mediaButtonEvent( (MediaKeyIdentifier)aMediaKeyId, PUSH_BUTTON_DISABLED, ICON_COLOR_DISABLED ); - } - -/*! - Disables specified push button - */ -void MusicWidget::mediaButtonEnabled( int aMediaKeyId ) - { - TX_LOG_ARGS("media key: " << aMediaKeyId ) - mediaButtonEvent( (MediaKeyIdentifier)aMediaKeyId, PUSH_BUTTON_NORMAL, ICON_COLOR_NORMAL ); - } - -/*! Manually update music widget state. */ void MusicWidget::refreshData() { TX_ENTRY + // Get current player state playbackStateChanged(); @@ -443,89 +194,64 @@ // Get current album art albumArtReady(); + TX_EXIT } /*! - Launch music player... + Launch music player. */ -void MusicWidget::launchMusicPlayer(int launchMode) +void MusicWidget::launchMusicPlayer( int launchMode ) { TX_ENTRY - //TODO: Detect if MusicPlayer is running or not properly, handle case where player not available?! - //TODO: Get service status from XQSettingManager - //TODO: Service status from signal: - //TODO: void statusChanged(const XQAiwInterfaceDescriptor& implementation, ServiceStatus currentStatus); - + QUrl url; - XQAiwRequest* req; - - if ( launchMode == ELaunchFromPlay ) - { - TX_LOG_ARGS("launch from play") - // Launch to now playing view, random play to be started! - url.setUrl(SERVICEREQ_FIRST_TIME_USE); - } - else if (mMusicPlayerNoSongData) - { - TX_LOG_ARGS("to main view") - // Launch to main view - url.setUrl(SERVICEREQ_MAIN_VIEW); - } - else - { - TX_LOG_ARGS("to now playing view") - // Launch to now playing view - url.setUrl(SERVICEREQ_NOW_PLAYING_VIEW); - } - - req = mApplicationManager.create(url); - if (req == NULL) - { - // No handlers for the URI - TX_LOG_ARGS("no req created") - return; - } - req->setBackground(false); - req->setSynchronous(false); + switch ( launchMode ) { + case ELaunchToMainView: + TX_LOG_ARGS( "to main view" ) + // Launch to main view + url.setUrl( SERVICEREQ_MAIN_VIEW ); + break; + case ELaunchToNowPlayingView: + TX_LOG_ARGS( "to now playing view" ) + // Launch to now playing view + url.setUrl( SERVICEREQ_NOW_PLAYING_VIEW ); + break; + case ELaunchToNowPlayingViewWithShuffle: + TX_LOG_ARGS( "to now playing view with shuffle" ) + // Launch to now playing view with shuffle + url.setUrl( SERVICEREQ_NOW_PLAYING_VIEW_SHUFFLE ); + break; + default: + //should never get here + TX_LOG_ARGS( "Error: invalid launchMode." ) + return; + } - // Set function parameters - QList args; - args << url.toString(); - req->setArguments(args); + XQAiwRequest* req; + req = mApplicationManager.create( url ); + if ( req ) { + req->setBackground( false ); + req->setSynchronous( false ); + + // Set function parameters + QList args; + args << url.toString(); + req->setArguments( args ); - // Send the request - bool res = req->send(); - if (!res) - { - // Request failed. - int error = req->lastError(); - // Handle error - TX_LOG_ARGS("req send error: " << error) - } - - delete req; + // Send the request + bool res = req->send(); + if ( !res ) { + // Request failed. + int error = req->lastError(); + // Handle error + TX_LOG_ARGS( "req send error: " << error ) + } + delete req; + } - TX_EXIT -} - -/*! - Return bounding rect -*/ -QRectF MusicWidget::boundingRect() const -{ - return childrenBoundingRect(); -} - -/*! - Return shape -*/ -QPainterPath MusicWidget::shape() const -{ - QPainterPath path; - path.addRect(boundingRect()); - return path; + TX_EXIT } /*! @@ -533,7 +259,33 @@ */ void MusicWidget::onInitialize() { - TX_LOG + TX_ENTRY + + // Setup UI + setupUi(); + + // Start Monitoring Music Player running status. + mMpApplicationMonitor = new MpApplicationMonitor(); + + // Check if Music Player UI is up and running + mMusicPlayerRunning = mMpApplicationMonitor->isApplicationRunning(); + + // Connect to MP engine and playback data + connectMusicPlayerEngine( mMusicPlayerRunning ); + + // Connect albumart click signal + QObject::connect( mAlbumArt, SIGNAL( clicked() ), this, SLOT( handleAlbumArtClicked() ) ); + + // Connect button clicked signals + QObject::connect( mPreviousPushButton, SIGNAL( clicked() ), this, SLOT( handlePrevButtonClicked() ) ); + QObject::connect( mPlayPushButton, SIGNAL( clicked() ), this, SLOT( handlePlayButtonClicked() ) ); + QObject::connect( mNextPushButton, SIGNAL( clicked() ), this, SLOT( handleNextButtonClicked() ) ); + + // Connect Music Player observer signal + QObject::connect( mMpApplicationMonitor, SIGNAL( applicationStatusChanged( bool ) ), + this, SLOT ( applicationStatusChanged( bool ) ) ); + + TX_EXIT } /*! @@ -541,8 +293,9 @@ */ void MusicWidget::onShow() { - TX_LOG + TX_ENTRY refreshData(); + TX_EXIT } /*! @@ -551,6 +304,9 @@ void MusicWidget::onHide() { TX_LOG + if ( mMarqueeText->isAnimating() ) { + mMarqueeText->stopAnimation(); + } } /*! @@ -562,268 +318,340 @@ } /*! - Slot for shortcut button clicked. + Slot to handle when the album art area is clicked. */ -void MusicWidget::shortcutButton() +void MusicWidget::handleAlbumArtClicked() { - TX_LOG - launchMusicPlayer(ELaunchFromShortcut); + TX_ENTRY + if ( getPlaybackState() == MpPlaybackData::NotPlaying ) { + launchMusicPlayer( ELaunchToMainView ); + } + else { + launchMusicPlayer( ELaunchToNowPlayingView ); + } + TX_EXIT } /*! Slot for previous button clicked. */ -void MusicWidget::prevSong() +void MusicWidget::handlePrevButtonClicked() { - TX_LOG - mMpEngine->skipBackward(); + TX_ENTRY + if ( mMpEngine ) { + mMpEngine->skipBackward(); + } + TX_EXIT } /*! Slot for play button clicked. Handles both Play and Pause! */ -void MusicWidget::playSong() +void MusicWidget::handlePlayButtonClicked() { TX_ENTRY - if (mMusicPlayerNoSongData && mMpPlaybackData->playbackState() != MpPlaybackData::Playing ) - { + // If nothing to play, start music player in playback view. + if ( getPlaybackState() == MpPlaybackData::NotPlaying ) { //Signal music player to start playing all songs with random - launchMusicPlayer(ELaunchFromPlay); + launchMusicPlayer( ELaunchToNowPlayingViewWithShuffle ); + } + else { + // send play/pause command. + if ( mMpEngine ) { + mMpEngine->playPause(); } - - mMpEngine->playPause(); + } TX_EXIT } + /*! Slot for next button clicked. */ -void MusicWidget::nextSong() +void MusicWidget::handleNextButtonClicked() { - TX_LOG - mMpEngine->skipForward(); + TX_ENTRY + if ( mMpEngine ) { + mMpEngine->skipForward(); + } + TX_EXIT } /*! - + Slot to handle when the music player running status changed. */ -bool MusicWidget::eventFilter(QObject *target, QEvent *event) - { - // pass the event on to the parent class - return HbWidget::eventFilter(target, event); +void MusicWidget::applicationStatusChanged( bool isRunning ) +{ + TX_ENTRY_ARGS( "running " << isRunning ); + + // Connect/disconnect engine base on music player running state. + if ( mMusicPlayerRunning != isRunning ) { + TX_LOG_ARGS("running state changed"); + mMusicPlayerRunning = isRunning; + connectMusicPlayerEngine( isRunning ); + // refresh data if musicplayer is on, otherwise clear data + if ( isRunning ) { + refreshData(); + } + else { + clearData(); + } + } + + TX_EXIT } /*! - MpEngine related + Library started refreshing. */ void MusicWidget::libraryUpdateStarted() { - TX_LOG + TX_ENTRY //Refresh Library start mMusicPlayerUpdating = true; // Update button enabled/disabled state - toggleButtons(); + updateButtons(); + TX_EXIT } /*! - MpEngine related + Library is finished refreshing. */ void MusicWidget::libraryUpdated() { - TX_LOG + TX_ENTRY //Refresh Library done mMusicPlayerUpdating = false; // Update button enabled/disabled state - toggleButtons(); + updateButtons(); + TX_EXIT } /*! - MpEngine related + USB blocking state has changed. */ void MusicWidget::usbBlocked( bool blocked ) { - TX_LOG_ARGS("blocked: " << blocked) - //Blocked state - //Mass storage mode - //Media transfer mode - //Ovi Suite mode - //Insert memory card - + TX_ENTRY_ARGS( "blocked: " << blocked ) mMusicPlayerBlocked = blocked; // Update button enabled/disabled state - toggleButtons(); + updateButtons(); + TX_EXIT } /*! - MpPlaybackData related + The album art has changed. */ void MusicWidget::albumArtReady() { TX_ENTRY HbIcon icon; - if ( mMpPlaybackData->playbackState() == MpPlaybackData::NotPlaying ) - { - TX_LOG_ARGS("1st time album art") - icon = HbIcon(ICON_FIRST_TIME_USE); + if ( getPlaybackState() == MpPlaybackData::NotPlaying ) { + TX_LOG_ARGS( "default album art" ) + icon = HbIcon( ICON_DEFAULT_ART ); + } + else { + TX_LOG_ARGS( "playback data album art" ) + if ( mMpPlaybackData ) { + mMpPlaybackData->albumArt( icon ); } - else - { - TX_LOG_ARGS("playback data album art") - mMpPlaybackData->albumArt( icon ); - } + } mAlbumArt->setIcon( icon ); mAlbumArt->setEnabled( true ); + TX_EXIT +} + +/*! + Playback state has changed. + */ +void MusicWidget::playbackStateChanged() +{ + TX_ENTRY + + if ( getPlaybackState() == MpPlaybackData::Playing ) { + TX_LOG_ARGS( "pause icon" ) + mPlayPushButton->setIcon( HbIcon( ICON_PAUSE ) ); + } + else { + TX_LOG_ARGS( "play icon" ) + mPlayPushButton->setIcon( HbIcon( ICON_PLAY ) ); + } + + // Update button enabled/disabled state + updateButtons(); TX_EXIT } -void MusicWidget::playbackStateChanged() -{ +/*! + Song data has changed. + */ +void MusicWidget::playbackInfoChanged() +{ TX_ENTRY - // Set play/pause icon and start/stop marquee. - QString iconName; + + QString songData; + QString artist; + QString title; - int state = mMpPlaybackData->playbackState(); - - TX_LOG_ARGS("state: " << state) + if ( mMpPlaybackData ) { + artist = mMpPlaybackData->artist(); + title = mMpPlaybackData->title(); + } - switch (state) - { - case MpPlaybackData::Playing: - { - TX_LOG_ARGS("pause icon, start marquee") - iconName.append(ICON_PAUSE); + if ( !title.length() ) { + artist.clear(); + title.clear(); + // Initialize marquee with something (space), to ensure text updates to display as well. + songData = " "; + TX_LOG_ARGS( "no song data" ) + } + else { + if ( !artist.length() ) { + //Show localized "Unknown" if there is no artist name + songData.append( hbTrId( "txt_muwidget_other_unknown_1" ).arg( title ) ); + } + else { + songData.append( artist ); + songData.append( SEPARATOR_TEXT ); + songData.append( title ); + } + TX_LOG_ARGS( "song data received" ) + } + + mMarqueeText->setText( songData ); + TX_LOG_ARGS( "marquee text: " << songData ) + + // Display song data if it exist. + if ( title.length() ) { + if ( !mSongDataBackground->isVisible() ) { + mSongDataBackground->show(); + } + if ( !mMarqueeText->isAnimating() ) { mMarqueeText->startAnimation(); - break; - } - case MpPlaybackData::Paused: - case MpPlaybackData::Stopped: - case MpPlaybackData::NotPlaying: - { - TX_LOG_ARGS("play icon, stop marquee") - iconName.append(ICON_PLAY); + } + } + else { + if ( mSongDataBackground->isVisible() ) { + mSongDataBackground->hide(); + } + if ( mMarqueeText->isAnimating() ) { mMarqueeText->stopAnimation(); - break; - } } - - HbIcon iconPlayPause(iconName); - mPlayPushButton->setIcon(iconPlayPause); + } TX_EXIT } /*! - MpPlaybackData related + Update buttons to disabled/enabled as required. */ -void MusicWidget::playbackInfoChanged() +void MusicWidget::updateButtons() { TX_ENTRY - // Initialize maqruee with something (space), to ensure - // text updates to display as well. - QString songData; - mArtist = mMpPlaybackData->artist(); - mTitle = mMpPlaybackData->title(); - - if ( !mTitle.length() ) - { - mArtist.clear(); - mTitle.clear(); - songData = " "; - - //1st time launch - mMusicPlayerNoSongData = true; - - TX_LOG_ARGS("no song data") - } - else - { - if ( !mArtist.length() ) - { - //Show localized "Unknown" if there is no artist name - - //TODO: Widget needs own localization?!?! - //mArtist.append( hbTrId(UNKWNOWN_TEXT) ); - - //TODO: Remove temporary unknown string when localization resolved. - mArtist.append( TEMPORARY_UNKWNOWN_TEXT ); - } - - songData.append(mArtist); - songData.append(SEPARATOR_TEXT); - songData.append(mTitle); - - mMusicPlayerNoSongData = false; - - TX_LOG_ARGS("song data received") - } - - mMarqueeText->setText(songData); - TX_LOG_ARGS("marquee text: " << songData) - - // Show dark BG to songdata only if there is songdata... - if ( mMusicPlayerNoSongData && mSongDataBG->isVisible() ) - { - TX_LOG_ARGS("hide marquee bg") - mSongDataBG->hide(); - } - else if ( !mMusicPlayerNoSongData && !mSongDataBG->isVisible() ) - { - TX_LOG_ARGS("show marquee bg") - mSongDataBG->show(); - } - - // Update button enabled/disabled state - toggleButtons(); + // All buttons disabled if updating or usb blocked + if ( mMusicPlayerUpdating || mMusicPlayerBlocked ) { + TX_LOG_ARGS( "refreshing" ) + mPreviousPushButton->setEnabled( false ); + mPlayPushButton->setEnabled( false ); + mNextPushButton->setEnabled( false ); + } + // Only play button enabled if there is no song data + else if ( getPlaybackState() == MpPlaybackData::NotPlaying ) { + TX_LOG_ARGS( "no song data" ) + mPreviousPushButton->setEnabled( false ); + mPlayPushButton->setEnabled( true ); + mNextPushButton->setEnabled( false ); + } + // Enable all buttons if there is song data + else { + TX_LOG_ARGS( "enable all buttons" ) + mPreviousPushButton->setEnabled( true ); + mPlayPushButton->setEnabled( true ); + mNextPushButton->setEnabled( true ); + } TX_EXIT } /*! - Toggle buttons to disabled/enabled as required. + Connect/disconnect Music Player engine and playback data */ -void MusicWidget::toggleButtons() -{ +void MusicWidget::connectMusicPlayerEngine( bool connect ) +{ TX_ENTRY - // All buttons disabled if updating - if ( mMusicPlayerUpdating ) - { - TX_LOG_ARGS("updating") - mediaButtonDisabled( EPlayPause ); - mediaButtonDisabled( EPrevious ); - mediaButtonDisabled( ENext ); - } + + if ( mMpEngine ) { + MpEngineFactory::close(); + mMpEngine = 0; + mMpPlaybackData = 0; + mMusicPlayerUpdating = false; + mMusicPlayerBlocked = false; + } - // All buttons disabled if blocked - else if ( mMusicPlayerBlocked ) - { - TX_LOG_ARGS("blocked") - mediaButtonDisabled( EPlayPause ); - mediaButtonDisabled( EPrevious ); - mediaButtonDisabled( ENext ); - } + if ( connect ) { + // Connect to MP engine and playback data + mMpEngine = MpEngineFactory::createSharedEngine( MpCommon::KMusicPlayerUid, MpEngine::HomeScreen ); + Q_ASSERT_X( mMpEngine, "music_widget", "no music player engine" ); + TX_LOG_ARGS( "got mp engine" ) + + mMpPlaybackData = mMpEngine->playbackData(); + Q_ASSERT_X( mMpPlaybackData, "music_widget", "no playback data" ); + TX_LOG_ARGS( "got playback data" ) - // Only play button enabled if there is no song data, 1st time use - else if ( mMusicPlayerNoSongData ) - { - TX_LOG_ARGS("no song data") - mediaButtonEnabled( EPlayPause ); - mediaButtonDisabled( EPrevious ); - mediaButtonDisabled( ENext ); - } + // MpEngine + QObject::connect( mMpEngine, SIGNAL( libraryUpdateStarted() ), this, SLOT( libraryUpdateStarted() ) ); + QObject::connect( mMpEngine, SIGNAL( libraryUpdated() ), this, SLOT( libraryUpdated() ) ); + QObject::connect( mMpEngine, SIGNAL( usbBlocked( bool ) ), this, SLOT( usbBlocked( bool ) ) ); + + //MpPlaybackData + QObject::connect( mMpPlaybackData, SIGNAL( albumArtReady() ), this, SLOT( albumArtReady() ) ); + QObject::connect( mMpPlaybackData, SIGNAL( playbackStateChanged() ), this, SLOT( playbackStateChanged() ) ); + QObject::connect( mMpPlaybackData, SIGNAL( playbackInfoChanged() ), this, SLOT( playbackInfoChanged() ) ); + } - // Enable all buttons if there is song data - else - { - TX_LOG_ARGS("enable all buttons") - mediaButtonEnabled( EPlayPause ); - mediaButtonEnabled( EPrevious ); - mediaButtonEnabled( ENext ); - } TX_EXIT } + +/*! + Get the playback state + */ +int MusicWidget::getPlaybackState() +{ + TX_ENTRY + int state; + if ( mMpPlaybackData ) { + state = mMpPlaybackData->playbackState(); + } + else { + state = MpPlaybackData::NotPlaying; + } + TX_EXIT_ARGS( "playback state = " << state ); + return state; +} + +/*! + Clear the song data + */ +void MusicWidget::clearData() +{ + TX_ENTRY + // set play button to PLAY icon. + mPlayPushButton->setIcon( HbIcon( ICON_PLAY ) ); + updateButtons(); + + // remove song data. + mMarqueeText->setText( QString( " " ) ); + mMarqueeText->stopAnimation(); + mSongDataBackground->hide(); + + // set default album art + mAlbumArt->setIcon( HbIcon( ICON_DEFAULT_ART ) ); + mAlbumArt->setEnabled( true ); + TX_EXIT +}