playermanager.cpp 9.17 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/***************************************************************************
                          playermanager.cpp
                             -------------------
    begin                : Sat Feb 14 2004
    copyright            : (C) 2004 by Scott Wheeler
    email                : wheeler@kde.org
***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

#include <kdebug.h>

#include <qslider.h>
21
#include <qtimer.h>
22 23

#include "playermanager.h"
24
#include "playlistinterface.h"
25
#include "slideraction.h"
26
#include "statuslabel.h"
27 28 29
#include "actioncollection.h"

using namespace ActionCollection;
30 31 32 33 34 35 36 37 38 39 40

PlayerManager *PlayerManager::m_instance = 0;

////////////////////////////////////////////////////////////////////////////////
// protected members
////////////////////////////////////////////////////////////////////////////////

PlayerManager::PlayerManager() :
    QObject(0, "PlayerManager"),
    Player(),
    m_sliderAction(0),
41
    m_playlistInterface(0),
42
    m_statusLabel(0),
43 44 45
    m_player(0),
    m_timer(0),
    m_noSeek(false)
46 47 48 49 50 51
{
    setup();
}

PlayerManager::~PlayerManager()
{
52
    delete m_player;
53 54 55 56 57 58 59 60 61 62 63 64 65
}

////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////

PlayerManager *PlayerManager::instance() // static
{
    if(!m_instance)
        m_instance = new PlayerManager;
    return m_instance;
}

66 67
bool PlayerManager::playing() const
{
68
    if(!player())
69 70
        return false;

71
    return player()->playing();
72 73 74 75
}

bool PlayerManager::paused() const
{
76
    if(!player())
77 78
        return false;

79
    return player()->paused();
80 81 82 83
}

float PlayerManager::volume() const
{
84
    if(!player())
85 86
        return 0;

87
    return player()->volume();
88 89 90 91
}

long PlayerManager::totalTime() const
{
92
    if(!player())
93 94
        return 0;

95
    return player()->totalTime();
96 97 98
}

long PlayerManager::currentTime() const
99
{
100
    if(!player())
101 102
        return 0;

103
    return player()->currentTime();
104 105 106 107
}

int PlayerManager::position() const
{
108
    if(!player())
109 110
        return 0;

111
    return player()->position();
112 113
}

114
void PlayerManager::setPlaylistInterface(PlaylistInterface *interface)
115 116 117 118
{
    m_playlistInterface = interface;
}

119 120 121 122 123
void PlayerManager::setStatusLabel(StatusLabel *label)
{
    m_statusLabel = label;
}

124 125 126 127 128 129
////////////////////////////////////////////////////////////////////////////////
// public slots
////////////////////////////////////////////////////////////////////////////////

void PlayerManager::play(const QString &fileName)
{
130
    if(!player() || !m_playlistInterface)
131 132
        return;

133
    if(fileName.isNull()) {
134 135
	if(player()->paused())
            player()->play();
136
        else if(player()->playing())
137
            player()->seekPosition(0);
138 139 140 141 142
        else {
            QString file = m_playlistInterface->currentFile();
            if(!file.isNull())
                player()->play(file);
	}
143
    }
144
    else
145
        player()->play(fileName);
146

147
    // Make sure that the player() actually starts before doing anything.
148

149
    if(!player()->playing()) {
150 151 152
        stop();
        return;
    }
153

154 155 156 157
    action("pause")->setEnabled(true);
    action("stop")->setEnabled(true);
    action("forward")->setEnabled(true);
    action("back")->setEnabled(true);
158

159 160
    m_sliderAction->trackPositionSlider()->setValue(0);
    m_sliderAction->trackPositionSlider()->setEnabled(true);
161 162

    m_timer->start(m_pollInterval);
163 164 165 166
}

void PlayerManager::pause()
{
167
    if(!player())
168 169
        return;

170 171 172 173 174 175
    if(player()->paused()) {
        play();
        return;
    }

    m_timer->stop();
176
    action("pause")->setEnabled(false);
177 178

    player()->pause();
179 180 181 182
}

void PlayerManager::stop()
{
183
    if(!player())
184 185
        return;

186 187
    m_timer->stop();

188 189 190 191
    action("pause")->setEnabled(false);
    action("stop")->setEnabled(false);
    action("back")->setEnabled(false);
    action("forward")->setEnabled(false);
192 193 194 195 196 197 198

    m_sliderAction->trackPositionSlider()->setValue(0);
    m_sliderAction->trackPositionSlider()->setEnabled(false);

    m_statusLabel->clear();

    player()->stop();
199 200
}

Laurent Montel's avatar
Laurent Montel committed
201
void PlayerManager::setVolume(float volume)
202
{
203
    if(!player())
204 205
        return;

206
    player()->setVolume(volume);
207 208
}

209
void PlayerManager::seek(long seekTime)
210
{
211
    if(!player())
212
        return;
213

214
    player()->seek(seekTime);
215 216
}

217
void PlayerManager::seekPosition(int position)
218
{
219 220 221 222
    if(!player())
        return;

    if(!player()->playing() || m_noSeek)
223
        return;
224

225 226
    slotUpdateTime(position);
    player()->seekPosition(position);
227 228
}

229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
void PlayerManager::forward()
{
    QString file = m_playlistInterface->nextFile();
    if(!file.isNull())
        play(file);
    else
        stop();
}

void PlayerManager::back()
{
    QString file = m_playlistInterface->previousFile();
    if(!file.isNull())
        play(file);
    else
        stop();
}

247 248 249
////////////////////////////////////////////////////////////////////////////////
// private slots
////////////////////////////////////////////////////////////////////////////////
250

251
void PlayerManager::slotPollPlay()
252
{
253
    if(!player() || !m_playlistInterface)
254
        return;
255

256
    m_noSeek = true;
257

258
    if(!player()->playing()) {
259
        m_timer->stop();
260 261 262 263 264
        QString nextFile = m_playlistInterface->nextFile();
        if(!nextFile.isNull())
            play();
        else
            stop();
265 266
    }
    else if(!m_sliderAction->dragging()) {
267
        m_sliderAction->trackPositionSlider()->setValue(player()->position());
268

269 270 271 272
        if(m_statusLabel) {
            m_statusLabel->setItemTotalTime(player()->totalTime());
            m_statusLabel->setItemCurrentTime(player()->currentTime());
        }
273
    }
274

275 276 277 278
    // Ok, this is weird stuff, but it works pretty well.  Ordinarily we don't
    // need to check up on our playing time very often, but in the span of the
    // last interval, we want to check a lot -- to figure out that we've hit the
    // end of the song as soon as possible.
279

280 281 282
    if(player()->playing() &&
       player()->totalTime() > 0 &&
       float(player()->totalTime() - player()->currentTime()) < m_pollInterval * 2)
283 284 285
    {
        m_timer->changeInterval(50);
    }
286

287
    m_noSeek = false;
288 289
}

290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313
void PlayerManager::slotSetOutput(int system)
{
    stop();
    delete m_player;
    m_player = Player::createPlayer(system);
}

void PlayerManager::slotSetVolume(int volume)
{
    setVolume(float(volume) / float(m_sliderAction->volumeSlider()->maxValue()));
}

void PlayerManager::slotUpdateTime(int position)
{
    if(!m_statusLabel)
        return;

    float positionFraction = float(position) / m_sliderAction->trackPositionSlider()->maxValue();
    float totalTime = float(m_player->totalTime());
    long seekTime = long(positionFraction * totalTime + 0.5); // "+0.5" for rounding

    m_statusLabel->setItemCurrentTime(seekTime);
}

314 315 316 317
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////

318 319 320 321 322 323 324 325
Player *PlayerManager::player() const
{
    if(!m_player)
        instance()->setup();

    return m_player;
}

326 327 328 329
void PlayerManager::setup()
{
    // All of the actions required by this class should be listed here.

330 331 332 333 334
    if(!action("pause") ||
       !action("stop") ||
       !action("back") ||
       !action("forward") ||
       !action("trackPositionAction"))
335 336 337 338 339 340

    {
        kdWarning(65432) << k_funcinfo << "Could not find all of the required actions." << endl;
        return;
    }

341 342
    // initialize action states

343 344 345 346
    action("pause")->setEnabled(false);
    action("stop")->setEnabled(false);
    action("back")->setEnabled(false);
    action("forward")->setEnabled(false);
347

348 349
    // setup sliders

350
    m_sliderAction = action<SliderAction>("trackPositionAction");
351

352 353 354 355 356 357 358
    connect(m_sliderAction, SIGNAL(signalPositionChanged(int)),
            this, SLOT(seekPosition(int)));
    connect(m_sliderAction->trackPositionSlider(), SIGNAL(valueChanged(int)),
            this, SLOT(slotUpdateTime(int)));
    connect(m_sliderAction->volumeSlider(), SIGNAL(valueChanged(int)),
            this, SLOT(slotSetVolume(int)));

359
    KAction *outputAction = action("outputSelect");
360 361 362 363

    if(outputAction) {
        int mediaSystem = static_cast<KSelectAction *>(outputAction)->currentItem();
        m_player = Player::createPlayer(mediaSystem);
Scott Wheeler's avatar
Scott Wheeler committed
364
        connect(outputAction, SIGNAL(activated(int)), this, SLOT(slotSetOutput(int)));
365 366 367
    }
    else
        m_player = Player::createPlayer();
368

369 370 371 372 373 374
    float volume =
        float(m_sliderAction->volumeSlider()->value()) /
	float(m_sliderAction->volumeSlider()->maxValue());

    m_player->setVolume(volume);

375 376
    m_timer = new QTimer(this, "play timer");
    connect(m_timer, SIGNAL(timeout()), this, SLOT(slotPollPlay()));
377 378 379
}

#include "playermanager.moc"