Logo Search packages:      
Sourcecode: lastfm version File versions  Download package

player.cpp

/***************************************************************************
 *   Copyright (C) 2005 - 2006 by Christian Muehlhaeuser, Last.fm Ltd.     *
 *   chris@last.fm                                                         *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Steet, Fifth Floor, Boston, MA  02111-1307, USA.          *
 ***************************************************************************/

#include <QtGui>
#include <QHttp>
#include <QFileInfo>
#include <QMovie>
#include <QTcpSocket>
#include <QHostAddress>

#include "aboutdialog.h"
#include "coverloader.h"
#include "imagefader.h"
#include "playback.h"
#include "player.h"
#include "settings.h"
#include "settingsdialog.h"
#include "song.h"
#include "tagdialog.h"
#include "trayicon/trayicon.h"
#include "urldialog.h"
#include "webserviceconnector.h"

#ifdef WIN32
#include <windows.h>
#endif

#ifdef Q_WS_MAC
#include <ApplicationServices/ApplicationServices.h>

static pascal OSErr
getURLEvent( const AppleEvent *appEvent, AppleEvent *reply, long handlerRefcon )
{
    DescType type;
    Size size;

    char buf[1024];
    AEGetParamPtr( appEvent, keyDirectObject, typeChar, &type, &buf, 1023, &size );
    buf[size] = '\0';

    if ( WebserviceConnector::instance()->isConnected() )
        Player::transmitCli( QString::fromUtf8( buf ).remove( 0, 9 ) );
    else
        Settings::instance()->setCommandLine( QString::fromUtf8( buf ).remove( 0, 9 ) );
}
#endif


Player::Player( QWidget *parent, QString commandLine )
    : QMainWindow( parent )
    , m_wsConnector( new WebserviceConnector() )
    , m_playback( new Playback() )
    , m_stationDialog( 0 )
    , m_tagDialog( 0 )
    , m_timer( new QTimer() )
    , m_coverLoader( new CoverLoader( this, QApplication::applicationDirPath() + "/cache/" ) )
    , m_coverBuffer( new QBuffer() )
    , m_animation( 0 )
    , m_proxyConnected( false )
{
    #ifdef Q_WS_MAC
    AEInstallEventHandler( 'GURL', 'GURL', NewAEEventHandlerUPP( getURLEvent ), 0, false );
    #endif

    qDebug() << "Plugin dirs:" << QApplication::libraryPaths();

    Settings::instance()->setCommandLine( commandLine );
    ui.setupUi( this );
    QIcon icon( QApplication::applicationDirPath() + "/data/icon.png" );
    setWindowIcon( icon );

    animationStop();
    ui.frame->raise();
    ui.logoLabel->raise();
    ui.tagButton->raise();
    ui.blogButton->raise();

    menu = new QMenu( this );
    stationAction = new QAction( tr( "Change &Station..." ), this );
    urlAction = new QAction( tr( "Enter Station &Address..." ), this );
    recordAction = new QAction( tr( "Record to &Profile" ), this );
    discoveryAction = new QAction( tr( "&Discovery Mode" ), this );
    refreshAction = new QAction( tr( "&Refresh" ), this );
    configureAction = new QAction( tr( "&Settings..." ), this );
    externalPlayerAction = new QAction( tr( "Use &External Player" ), this );
    onTopAction = new QAction( tr( "Stay on &Top" ), this );
    aboutAction = new QAction( tr( "&About" ), this );
    loveAction = new QAction( tr( "&Love Song" ), this );
    skipAction = new QAction( tr( "&Skip Song" ), this );
    banAction = new QAction( tr( "&Ban Song" ), this );
    QAction *quitAction = new QAction( tr( "&Exit" ), this );

    #ifdef Q_WS_MAC
    stationAction->setShortcut( tr( "Ctrl+N" ) );
    urlAction->setShortcut( tr( "Ctrl+G" ) );
    refreshAction->setShortcut( tr( "Ctrl+R" ) );

    QMenu *fileMenu = menuBar()->addMenu( tr( "&File" ) );
    fileMenu->addAction( configureAction );
    fileMenu->addAction( aboutAction );

    QMenu *streamMenu = menuBar()->addMenu( tr( "&Controls" ) );
    streamMenu->addAction( stationAction );
    streamMenu->addAction( urlAction );
    streamMenu->addSeparator();
    streamMenu->addAction( recordAction );
    streamMenu->addAction( discoveryAction );
    streamMenu->addSeparator();
    streamMenu->addAction( refreshAction );
    #endif

    QMenu *trayMenu = new QMenu( this );
    trayMenu->addAction( stationAction );
    trayMenu->addAction( configureAction );
    trayMenu->addSeparator();
    trayMenu->addAction( recordAction );
    trayMenu->addAction( discoveryAction );
    trayMenu->addSeparator();
    trayMenu->addAction( loveAction );
    trayMenu->addAction( banAction );
    trayMenu->addSeparator();
    trayMenu->addAction( skipAction );
    trayMenu->addSeparator();
    trayMenu->addAction( quitAction );

    recordAction->setCheckable( true );
    recordAction->setChecked( true );
    discoveryAction->setCheckable( true );
    discoveryAction->setChecked( false );
    onTopAction->setCheckable( true );
    onTopAction->setChecked( false );
    externalPlayerAction->setCheckable( true );
    externalPlayerAction->setChecked( Settings::instance()->soundSystem() == Settings::instance()->externalSoundSystem() );

    menu->addAction( stationAction );
    menu->addAction( urlAction );
    menu->addSeparator();
    menu->addAction( recordAction );
    menu->addAction( discoveryAction );
    menu->addAction( refreshAction );
    menu->addSeparator();
    menu->addAction( configureAction );
    menu->addAction( externalPlayerAction );
    menu->addAction( onTopAction );
    menu->addSeparator();
    menu->addAction( aboutAction );

    init();
    m_timer->setInterval( 1000 );
    m_fader = new ImageFader();
    ui.volumeSlider->setValue( Settings::instance()->volume() );
    volumeChanged( Settings::instance()->volume() );

    m_trayIcon = new TrayIcon( QPixmap( QApplication::applicationDirPath() + "/data/icon.png" ).scaled( 24, 24, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ), "Last.fm Radio", trayMenu, this, "lastfmtray" );
    m_trayIcon->show();

    QShortcut *shortcut = new QShortcut( QApplication::desktop() );
    shortcut->setKey( QKeySequence( "CTRL+ALT+O" ) );
    shortcut->setContext( Qt::ApplicationShortcut );
    connect( shortcut, SIGNAL( activated() ), this, SLOT( openStationDialog() ) );

    connect( Settings::instance(), SIGNAL( reconnect() ), this, SLOT( handshake() ) );
    connect( Settings::instance(), SIGNAL( resetAudio() ), m_playback, SLOT( initSound() ) );
    connect( m_trayIcon, SIGNAL( clicked( QPoint, int ) ), this, SLOT( restoreWindow() ) );
    connect( m_trayIcon, SIGNAL( doubleClicked( QPoint ) ), this, SLOT( restoreWindow() ) );
    connect( m_timer, SIGNAL( timeout() ), this, SLOT( updateTimeBar() ) );
    connect( m_fader, SIGNAL( fadeProgress( const QPixmap & ) ), ui.coverImage, SLOT( setPixmap( const QPixmap & ) ) );
    connect( m_coverLoader, SIGNAL( requestFinished( bool ) ), this, SLOT( coverLoaded( bool ) ) );

    connect( stationAction, SIGNAL( triggered() ), this, SLOT( openStationDialog() ) );
    connect( urlAction, SIGNAL( triggered() ), this, SLOT( openUrlDialog() ) );
    connect( recordAction, SIGNAL( toggled( bool ) ), m_wsConnector, SLOT( recordToProfile( bool ) ) );
    connect( discoveryAction, SIGNAL( toggled( bool ) ), m_wsConnector, SLOT( discoveryMode( bool ) ) );
    connect( refreshAction, SIGNAL( triggered() ), m_wsConnector, SLOT( metaData() ) );
    connect( configureAction, SIGNAL( triggered() ), this, SLOT( openSettingsDialog() ) );
    connect( externalPlayerAction, SIGNAL( toggled( bool ) ), this, SLOT( useExternalPlayer( bool ) ) );
    connect( onTopAction, SIGNAL( toggled( bool ) ), this, SLOT( setStayOnTop( bool ) ) );
    connect( aboutAction, SIGNAL( triggered() ), this, SLOT( openAbout() ) );
    connect( loveAction, SIGNAL( triggered() ), m_wsConnector, SLOT( love() ) );
    connect( skipAction, SIGNAL( triggered() ), m_wsConnector, SLOT( skip() ) );
    connect( banAction, SIGNAL( triggered() ), m_wsConnector, SLOT( ban() ) );
    connect( quitAction, SIGNAL( triggered() ), this, SLOT( close() ) );

    connect( m_playback, SIGNAL( playbackStarting() ), this, SLOT( playbackStarting() ) );
    connect( m_playback, SIGNAL( playbackFinished() ), this, SLOT( playbackFinished() ) );
    connect( m_playback, SIGNAL( proxyClientConnected() ), this, SLOT( proxyClientConnected() ) );
    connect( m_playback, SIGNAL( proxyClientDisconnected() ), this, SLOT( proxyClientDisconnected() ) );

    connect( m_wsConnector, SIGNAL( handshakeResult( bool, bool, QUrl ) ), this, SLOT( handshakeResult( bool, bool, QUrl ) ) );
    connect( m_wsConnector, SIGNAL( metaDataResult( Song, bool ) ), this, SLOT( metaDataResult( Song, bool ) ) );
    connect( m_wsConnector, SIGNAL( changeStationPrepared() ), this, SLOT( changeStationPrepared() ) );
    connect( m_wsConnector, SIGNAL( changeStationResult( bool ) ), this, SLOT( changeStationResult( bool ) ) );
    connect( m_wsConnector, SIGNAL( actionStarted() ), this, SLOT( animationStart() ) );
    connect( m_wsConnector, SIGNAL( actionFinished() ), this, SLOT( animationStop() ) );
    connect( m_wsConnector, SIGNAL( lovePrepared() ), this, SLOT( lovePrepared() ) );
    connect( m_wsConnector, SIGNAL( skipPrepared() ), this, SLOT( skipPrepared() ) );
    connect( m_wsConnector, SIGNAL( banPrepared() ), this, SLOT( banPrepared() ) );

    connect( ui.loveButton, SIGNAL( clicked() ), m_wsConnector, SLOT( love() ) );
    connect( ui.skipButton, SIGNAL( clicked() ), m_wsConnector, SLOT( skip() ) );
    connect( ui.banButton, SIGNAL( clicked() ), m_wsConnector, SLOT( ban() ) );
    connect( ui.volumeSlider, SIGNAL( valueChanged( int ) ), this, SLOT( volumeChanged( int ) ) );
    connect( ui.togglePlayButton, SIGNAL( clicked() ), this, SLOT( togglePlayback() ) );
    connect( ui.menuButton, SIGNAL( clicked() ), this, SLOT( openMenu() ) );
    connect( ui.coverImage, SIGNAL( clicked() ), this, SLOT( browseAlbum() ) );
    connect( ui.artistLabel, SIGNAL( clicked() ), this, SLOT( browseArtist() ) );
    connect( ui.albumLabel, SIGNAL( clicked() ), this, SLOT( browseAlbum() ) );
    connect( ui.trackLabel, SIGNAL( clicked() ), this, SLOT( browseTrack() ) );
    connect( ui.tagButton, SIGNAL( clicked() ), this, SLOT( openTagDialog() ) );
    connect( ui.blogButton, SIGNAL( clicked() ), this, SLOT( openJournalMenu() ) );

    if ( Settings::instance()->positionX() > 0 && Settings::instance()->positionY() > 0 )
    {
        // prevent window from disappearing if the desktop geometry changed
        if ( Settings::instance()->positionX() < QApplication::desktop()->width() && Settings::instance()->positionY() < QApplication::desktop()->height() )
            move( Settings::instance()->positionX(), Settings::instance()->positionY() );
    }

    if ( Settings::instance()->username().isEmpty() || Settings::instance()->password().isEmpty() )
    {
        // we need to call this to prevent qt shutting down the app after the user closed the settings dialog
        QApplication::setQuitOnLastWindowClosed( false );
        openSettingsDialog();
        QApplication::setQuitOnLastWindowClosed( true );
    }

    handshake();
}


Player::~Player()
{
    delete m_playback;
    delete m_wsConnector;
}


bool
Player::transmitCli( QString parameter )
{
    QTcpSocket *socket = new QTcpSocket( 0 );
    socket->connectToHost( QHostAddress::LocalHost, 32213 );
    if ( socket->waitForConnected( 500 ) )
    {
        if ( parameter.length() > 0 )
        {
            socket->write( parameter.toLocal8Bit(), parameter.length() );
            socket->flush();
        }

        socket->close();
        delete socket;
        return true;
    }

    delete socket;
    return false;
}


void
Player::init()
{
    loadDefaultCover();

    QPixmap image;
    image.load( QApplication::applicationDirPath() + "/data/artist.png" );
    ui.artistImage->setPixmap( image );
    image.load( QApplication::applicationDirPath() + "/data/album.png" );
    ui.albumImage->setPixmap( image );
    image.load( QApplication::applicationDirPath() + "/data/song.png" );
    ui.songImage->setPixmap( image );
    image.load( QApplication::applicationDirPath() + "/data/volume_left.png" );
    ui.volumeLow->setPixmap( image );
    image.load( QApplication::applicationDirPath() + "/data/volume_right.png" );
    ui.volumeHigh->setPixmap( image );
    image.load( QApplication::applicationDirPath() + "/data/curve.png" );
    ui.curveLabel->setPixmap( image );

    ui.togglePlayButton->setImages( QApplication::applicationDirPath(), "/data/buttons/play_enabled.png", "/data/buttons/play_enabled.png", "/data/buttons/play_hover.png", "/data/buttons/stop_disabled.png" );
    ui.loveButton->setImages( QApplication::applicationDirPath(), "/data/buttons/love_enabled.png", "/data/buttons/love_down.png", "/data/buttons/love_hover.png", "/data/buttons/love_disabled.png" );
    ui.skipButton->setImages( QApplication::applicationDirPath(), "/data/buttons/skip_enabled.png", "/data/buttons/skip_down.png", "/data/buttons/skip_hover.png", "/data/buttons/skip_disabled.png" );
    ui.banButton->setImages ( QApplication::applicationDirPath(), "/data/buttons/ban_enabled.png", "/data/buttons/ban_down.png", "/data/buttons/ban_hover.png", "/data/buttons/ban_disabled.png" );
    ui.menuButton->setImages( QApplication::applicationDirPath(), "/data/buttons/config_enabled.png", "/data/buttons/config_down.png", "/data/buttons/config_hover.png", "/data/buttons/config_disabled.png" );
    ui.tagButton->setImages ( QApplication::applicationDirPath(), "/data/buttons/tag_normal.png", "/data/buttons/tag_down.png", "/data/buttons/tag_hover.png", "/data/buttons/tag_disabled.png" );
    ui.blogButton->setImages( QApplication::applicationDirPath(), "/data/buttons/blog_normal.png", "/data/buttons/blog_down.png", "/data/buttons/blog_hover.png", "/data/buttons/blog_disabled.png" );

    ui.stationLabel->setText( "<font color='white'><b>Connecting to server...</b></font>" );
    ui.togglePlayButton->setToolTip( "Choose a station and start playback" );

    stationAction->setEnabled( false );
    urlAction->setEnabled( false );
    recordAction->setEnabled( false );
    discoveryAction->setEnabled( false );
    refreshAction->setEnabled( false );

    ui.togglePlayButton->setEnabled( false );
    ui.loveButton->setEnabled( false );
    ui.skipButton->setEnabled( false );
    ui.banButton->setEnabled ( false );
    ui.tagButton->setEnabled ( false );
    ui.blogButton->setEnabled( false );

    loveAction->setEnabled( false );
    skipAction->setEnabled( false );
    banAction->setEnabled ( false );
}


void
Player::handshake()
{
    if ( m_playback->isPlaying() )
        m_playback->stopPlayback();

    m_wsConnector->handshake( Settings::instance()->username(), Settings::instance()->password() );
}


void
Player::loadDefaultCover()
{
    QPixmap image;
    image.load( QApplication::applicationDirPath() + "/data/nocover.png" );

    if ( !ui.coverImage->pixmap()->isNull() )
        m_fader->startFade( ui.coverImage->pixmap()->toImage(), image.toImage(), 1500 );
    else
        ui.coverImage->setPixmap( image );
}


void
Player::handshakeResult( bool connected, bool loginDone, const QUrl &streamUrl )
{
    if ( loginDone )
    {
        ui.stationLabel->setText( "<font color='white'><b>Please press Play to choose a Station!</b></font>" );

        stationAction->setEnabled( true );
        urlAction->setEnabled( true );
        recordAction->setEnabled( true );
        refreshAction->setEnabled( true );
        discoveryAction->setEnabled( m_wsConnector->isSubscriber() );
        ui.togglePlayButton->setEnabled( true );

        m_streamUrl = streamUrl;
        if ( !Settings::instance()->commandLine().isEmpty() && Settings::instance()->commandLine().length() > 9 )
        {
            m_wsConnector->changeStation( Settings::instance()->commandLine() );
            Settings::instance()->setCommandLine( "" );
        }
        else
            if ( Settings::instance()->resumePlayback() && !Settings::instance()->resumeStation().isEmpty() )
                m_wsConnector->changeStation( Settings::instance()->resumeStation() );
            else
                openStationDialog();
    }
    else
    {
        if ( connected )
            QMessageBox::critical( 0, "Error", "Login failed! Please check your username and password!\n" );
        else
            QMessageBox::critical( 0, "Error", "Can't connect to server! Make sure your Internet connection is working and your proxy settings are correct!\n" );

        openSettingsDialog();
    }
}


void
Player::metaDataResult( const Song &song, bool discovery )
{
    if ( !m_playback->isPlaying() )
        return;

    Playback::instance()->playingSong->fetch( song );

    if ( m_wsConnector->isSubscriber() )
        discoveryAction->setEnabled( discovery );

    if ( Playback::instance()->playingSong->duration() == 0 )
    {
        ui.timeBar->setMaximum( 100 );
        ui.timeBar->setValue( 100 );
    }
    else
    {
        ui.timeBar->setMaximum( Playback::instance()->playingSong->duration() );
        ui.timeBar->setValue( 0 );
    }

    if ( !m_timer->isActive() )
        m_timer->start();

    ui.tagButton->setEnabled ( true );
    ui.blogButton->setEnabled( true );
    ui.loveButton->setEnabled( true );
    ui.skipButton->setEnabled( true );
    ui.banButton->setEnabled ( true );
    loveAction->setEnabled( true );
    skipAction->setEnabled( true );
    banAction->setEnabled ( true );

    ui.artistLabel->setText( Playback::instance()->playingSong->artist() );
    ui.albumLabel->setText( Playback::instance()->playingSong->album() );
    ui.trackLabel->setText( Playback::instance()->playingSong->track() );

    if ( Settings::instance()->debug() )
        ui.stationLabel->setText( "<font color='white'><b>Debug: " + Playback::instance()->playingSong->station() + "</b></font>" );
    else
        ui.stationLabel->setText( "<font color='white'><b>" + Playback::instance()->playingSong->station() + "</b></font>" );

    m_coverBuffer->close();
    if ( Playback::instance()->playingSong->cover().isEmpty() )
        loadDefaultCover();
    else
    {
        m_coverLoader->setHost( Playback::instance()->playingSong->cover().host() );
        if ( Settings::instance()->proxyUsage() && !Settings::instance()->proxyHost().isEmpty() )
            m_coverLoader->setProxy( Settings::instance()->proxyHost(), Settings::instance()->proxyPort(), Settings::instance()->proxyUsername(), Settings::instance()->proxyPassword() );

        if ( !Playback::instance()->playingSong->cover().encodedQuery().isEmpty() )
            m_coverLoader->get( Playback::instance()->playingSong->cover().path() + "?" + QString( Playback::instance()->playingSong->cover().encodedQuery() ), m_coverBuffer );
        else
            m_coverLoader->get( Playback::instance()->playingSong->cover().path(), m_coverBuffer );
    }
}


void
Player::updateTimeBar()
{
    Playback::instance()->playingSong->setProgress( Playback::instance()->playingSong->progress() + 1 );
    ui.timeBar->setValue( Playback::instance()->playingSong->progress() );
}


void
Player::animationStart()
{
    if ( m_animation && m_animation->currentFrameNumber() == 102 )
    {
        m_animation->stop();
        delete m_animation;
        m_animation = 0;
    }

    if ( !m_animation || m_animation->state() != QMovie::Running )
    {
        if ( m_animation )
            delete m_animation;

        m_animation = new QMovie( QApplication::applicationDirPath() + "/data/progress_active.mng" );
        connect( m_animation, SIGNAL( frameChanged( int ) ), this, SLOT( animationStart() ) );

        ui.logoLabel->setMovie( m_animation );
        m_animation->start();
    }
}


void
Player::animationStop()
{
    if ( m_animation )
    {
        delete m_animation;
        m_animation = 0;
    }

    QPixmap image;
    image.load( QApplication::applicationDirPath() + "/data/progress_inactive.png" );
    ui.logoLabel->setPixmap( image );
}


void
Player::coverLoaded( bool error )
{
    if ( !Playback::instance()->isPlaying() )
        return;

    if ( !error && m_coverBuffer->size() > 0 )
    {
        QPixmap cover;
        cover.loadFromData( m_coverBuffer->buffer() );

        if ( !cover.isNull() )
        {
            m_fader->startFade( ui.coverImage->pixmap()->toImage(), cover.scaled( 110, 110, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ).toImage(), 1500 );
            return;
        }
    }

    QPixmap cover;
    cover.load( QApplication::applicationDirPath() + "/data/nocover.png" );
    m_fader->startFade( ui.coverImage->pixmap()->toImage(), cover.toImage(), 1500 );
}


void
Player::skipPrepared()
{
    m_playback->setDirectSkip();

    loveAction->setEnabled( false );
    skipAction->setEnabled( false );
    banAction->setEnabled ( false );

    ui.loveButton->setEnabled( false );
    ui.skipButton->setEnabled( false );
    ui.banButton->setEnabled ( false );
}


void
Player::lovePrepared()
{
    ui.loveButton->setEnabled( false );
}


void
Player::banPrepared()
{
    m_playback->setDirectSkip();

    loveAction->setEnabled( false );
    skipAction->setEnabled( false );
    banAction->setEnabled ( false );

    ui.loveButton->setEnabled( false );
    ui.skipButton->setEnabled( false );
    ui.banButton->setEnabled ( false );
}


void
Player::setStayOnTop( bool checked )
{
    if ( checked )
        setWindowFlags( windowFlags() | Qt::WindowStaysOnTopHint );
     else
        setWindowFlags( windowFlags() ^ Qt::WindowStaysOnTopHint );

    show();
}


void
Player::useExternalPlayer( bool checked )
{
    if ( checked )
        Settings::instance()->setSoundSystem( Settings::instance()->externalSoundSystem() );
    else
        Settings::instance()->setSoundSystem( 0 );

    m_playback->initSound();
}


void
Player::playbackStarting()
{
    qDebug( "Playback starting!" );

    ui.togglePlayButton->setImages( QApplication::applicationDirPath(), "/data/buttons/stop_enabled.png", "/data/buttons/stop_down.png", "/data/buttons/stop_hover.png", "/data/buttons/stop_disabled.png" );
    ui.togglePlayButton->setToolTip( "Stop playback" );
}


void
Player::playbackFinished()
{
    qDebug( "Playback finished!" );

    ui.artistLabel->setText( "" );
    ui.albumLabel->setText( "" );
    ui.trackLabel->setText( "" );
    ui.stationLabel->setText( "<font color='white'><b>Please press Play to choose a Station!</b></font>" );

    ui.togglePlayButton->setImages( QApplication::applicationDirPath(), "/data/buttons/play_enabled.png", "/data/buttons/play_enabled.png", "/data/buttons/play_hover.png", "/data/buttons/stop_disabled.png" );
    ui.togglePlayButton->setToolTip( "Choose a station and start playback" );

    loveAction->setEnabled( false );
    skipAction->setEnabled( false );
    banAction->setEnabled ( false );

    ui.loveButton->setEnabled( false );
    ui.skipButton->setEnabled( false );
    ui.banButton->setEnabled ( false );

    ui.timeBar->setValue( 0 );
    m_timer->stop();
    loadDefaultCover();
    animationStop();
}


void
Player::openAbout()
{
    AboutDialog about( this );
    about.exec();
}


void
Player::openMenu()
{
    menu->exec( QCursor::pos() );
}


void
Player::openUrlDialog()
{
    UrlDialog urlDialog( this );
    urlDialog.exec();
}


void
Player::openSettingsDialog()
{
    SettingsDialog dialog( this );
    dialog.exec();
}


void
Player::openStationDialog()
{
    if ( !m_stationDialog )
    {
        m_stationDialog = new StationDialog( this );
        connect( m_stationDialog, SIGNAL( finished( int ) ), this, SLOT( freeStationDialog() ) );
    }

    m_stationDialog->show();
    m_stationDialog->activateWindow();
    m_stationDialog->raise();
}


void
Player::openTagDialog()
{
    if ( m_playback->isPlaying() )
    {
        if ( !m_tagDialog )
            m_tagDialog = new TagDialog( this );

        m_tagDialog->setSong( Playback::instance()->playingSong );
        m_tagDialog->show();

        // yes, we really call toggleCollapse twice. this is a stupid work-around for restoring my layout, since show() destroys it.
        // this means: we actually don't want to toggle it ;-).
        m_tagDialog->toggleCollapse();
        m_tagDialog->toggleCollapse();

        m_tagDialog->raise();
        m_tagDialog->activateWindow();
    }
}


void
Player::openJournalMenu()
{
    if ( m_playback->isPlaying() )
    {
        QMenu journalMenu( this );

        QAction *artistAction = new QAction( QIcon( QApplication::applicationDirPath() + "/data/artist.png" ), tr( "Write a Journal about this Artist" ), this );
        QAction *albumAction = new QAction( QIcon( QApplication::applicationDirPath() + "/data/album.png" ), tr( "Write a Journal about this Album" ), this );
        QAction *trackAction = new QAction( QIcon( QApplication::applicationDirPath() + "/data/song.png" ), tr( "Write a Journal about this Track" ), this );
        journalMenu.addAction( artistAction );
        journalMenu.addAction( albumAction );
        journalMenu.addAction( trackAction );

        connect( artistAction, SIGNAL( triggered() ), this, SLOT( journalArtist() ) );
        connect( albumAction, SIGNAL( triggered() ), this, SLOT( journalAlbum() ) );
        connect( trackAction, SIGNAL( triggered() ), this, SLOT( journalTrack() ) );

        journalMenu.exec( QCursor::pos() );
    }
}


void
Player::changeStationPrepared()
{
    ui.stationLabel->setText( "<font color='white'><b>Connecting to station, please wait...</b></font>" );
}


void
Player::changeStationResult( bool error )
{
    if ( error && !m_playback->isPlaying() )
        playbackFinished();

    if ( !error && !m_playback->isPlaying() )
    {
        QString m3uUrl = QApplication::applicationDirPath() + "/data/default.m3u";

        if ( Settings::instance()->soundSystem() == Settings::instance()->externalSoundSystem() && !m_proxyConnected )
        {
            #ifdef WIN32
            WCHAR val[1024];
            memset( val, 0, 1024 );
            MultiByteToWideChar( CP_UTF8, 0, m3uUrl.toAscii(), m3uUrl.length(), val, 1024 );
            ShellExecute( 0, 0, val, NULL, NULL, SW_SHOW );
            #endif

            #ifdef Q_WS_MAC
            FSRef f;
            FSPathMakeRef( m3uUrl.toAscii().data(), &f, false );
            LSOpenFSRef( &f, NULL );

            FSRef application;
            LSGetApplicationForItem( &f, kLSRolesAll, &application, NULL );

            LSLaunchFSRefSpec launchSpec = { &application, 1, &f, NULL, kLSLaunchDefaults | kLSLaunchDontAddToRecents, NULL };
            LSOpenFromRefSpec( &launchSpec, NULL );
            #endif
        }

        int res = QMessageBox::Ok;
        #ifdef Q_WS_X11
        while ( Settings::instance()->soundSystem() == Settings::instance()->externalSoundSystem() && !m_proxyConnected && res != QMessageBox::Cancel)
        {
            res = QMessageBox::information( this, "Attention", "Start your media-player with the following url, now: http://localhost:32214", QMessageBox::Ok, QMessageBox::Cancel );
        }
        #endif

        if ( Settings::instance()->soundSystem() != Settings::instance()->externalSoundSystem() || res == QMessageBox::Ok )
        {
            if ( !m_playback->startPlayback( m_streamUrl ) )
            {
                QMessageBox::information( this, "Error", "Can't open sound-device! Please make sure your settings are correct!" );
                animationStop();
            }
        }
        else
            animationStop();
    }
}


void
Player::volumeChanged( int value )
{
    m_playback->setVolume( value );
    Settings::instance()->setVolume( value );
}


void
Player::togglePlayback()
{
    if ( m_playback->isPlaying() )
    {
        animationStop();
        Playback::instance()->stopPlayback();
    }
    else
        openStationDialog();
}


void
Player::browseArtist()
{
    Settings::instance()->startBrowser( Playback::instance()->playingSong->artistUrl() );
}


void
Player::browseAlbum()
{
    Settings::instance()->startBrowser( Playback::instance()->playingSong->albumUrl() );
    return;
}


void
Player::browseTrack()
{
    Settings::instance()->startBrowser( Playback::instance()->playingSong->trackUrl() );
}


void
Player::journalArtist()
{
    Settings::instance()->startBrowser( QString( "http://www.last.fm/user/%1/journal/&action=create&artistname=%2" )
                                        .arg( Settings::instance()->username() )
                                        .arg( Playback::instance()->playingSong->artist() ) );
}


void
Player::journalAlbum()
{
    Settings::instance()->startBrowser( QString( "http://www.last.fm/user/%1/journal/&action=create&artistname=%2&albumname=%3" )
                                        .arg( Settings::instance()->username() )
                                        .arg( Playback::instance()->playingSong->artist() )
                                        .arg( Playback::instance()->playingSong->album() ) );
}


void
Player::journalTrack()
{
    Settings::instance()->startBrowser( QString( "http://www.last.fm/user/%1/journal/&action=create&artistname=%2&trackname=%3" )
                                        .arg( Settings::instance()->username() )
                                        .arg( Playback::instance()->playingSong->artist() )
                                        .arg( Playback::instance()->playingSong->track() ) );
}


void
Player::dragEnterEvent( QDragEnterEvent *event )
{
    if ( event->mimeData()->hasFormat( "text/plain" ) && event->mimeData()->text().startsWith( "lastfm://" ) )
        event->acceptProposedAction();
}


void
Player::dropEvent( QDropEvent *event )
{
    QString station = event->mimeData()->text().remove( 0, 9 ).split( "\n" )[0];
    m_wsConnector->changeStation( station );

    event->acceptProposedAction();
}


void
Player::proxyClientConnected()
{
    m_proxyConnected = true;
}


void
Player::proxyClientDisconnected()
{
    m_proxyConnected = false;
}


void
Player::closeEvent( QCloseEvent *event )
{
    delete m_trayIcon;

    Settings::instance()->setPositionX( pos().x() );
    Settings::instance()->setPositionY( pos().y() );
    Settings::instance()->save();
}


Generated by  Doxygen 1.6.0   Back to index