juk.cpp 13.2 KB
Newer Older
1 2 3 4 5 6
/***************************************************************************
                          juk.cpp  -  description
                             -------------------
    begin                : Mon Feb  4 23:40:41 EST 2002
    copyright            : (C) 2002 by Scott Wheeler
    email                : scott@slackorama.net
7
***************************************************************************/
8 9 10 11 12 13 14 15 16 17 18 19 20

/***************************************************************************
 *                                                                         *
 *   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 <klocale.h>
#include <keditcl.h>
#include <kfiledialog.h>
21
#include <kiconloader.h>
22
#include <kcmdlineargs.h>
23 24 25 26 27 28 29 30 31 32
#include <kdebug.h>

#include "juk.h"

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

JuK::JuK(QWidget *parent, const char *name) : KMainWindow(parent, name)
{
33 34 35 36
    setupActions();
    setupLayout();
    setupPlayer();
    readConfig();
37
    processArgs();
38 39 40 41
}

JuK::~JuK()
{
42 43
    saveConfig();
    delete(playTimer);
44 45 46 47 48 49 50 51
}

////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////

void JuK::setupActions()
{
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
    // file menu
    KStdAction::open(this, SLOT(openFile()), actionCollection());
    (void) new KAction(i18n("Open &Directory..."), "fileopen", 0, this, SLOT(openDirectory()), actionCollection(), "openDirectory");
    KStdAction::save(this, SLOT(saveFile()), actionCollection());
    (void) new KAction(i18n("Delete"), "edittrash", 0, this, SLOT(deleteFile()), actionCollection(), "deleteFile");
    KStdAction::quit(this, SLOT(quit()), actionCollection());

    // edit menu
    KStdAction::cut(this, SLOT(cut()), actionCollection());
    KStdAction::copy(this, SLOT(copy()), actionCollection());
    KStdAction::paste(this, SLOT(paste()), actionCollection());
    KStdAction::selectAll(this, SLOT(selectAll()), actionCollection());

    // play menu
    addToPlaylistAction = new KAction(i18n("&Add to Playlist"), "enqueue", 0, this,
                                      SLOT(addToPlaylist()), actionCollection(), "addToPlaylist");
    removeFromPlaylistAction = new KAction(i18n("&Remove from Playlist"), "dequeue", 0, this,
                                           SLOT(removeFromPlaylist()), actionCollection(), "removeFromPlaylist");
    playAction = new KAction(i18n("&Play"), "1rightarrow", 0, this, SLOT(playFile()), actionCollection(), "playFile");
    pauseAction = new KAction(i18n("P&ause"), "player_pause", 0, this, SLOT(pauseFile()), actionCollection(), "pauseFile");
    stopAction = new KAction(i18n("&Stop"), "player_stop", 0, this, SLOT(stopFile()), actionCollection(), "stopFile");

    // function menu

    showTaggerAction = new KAction(i18n("Tagger"), "tag", 0, this, SLOT(showTagger()), actionCollection(), "showTagger");
    showPlaylistAction = new KAction(i18n("Playlist Editor"), "edit", 0, this, SLOT(showPlaylist()), actionCollection(), "showPlaylist");


    // just in the toolbar
    sliderAction = new SliderAction(i18n("Track Position"), actionCollection(), "trackPositionAction");

    createGUI();
84 85 86 87
}

void JuK::setupLayout()
{
88 89 90 91 92 93
    // automagically save and restore settings
    this->setAutoSaveSettings();

    // create the main widgets
    tagger = new TaggerWidget(this);
    playlist = new PlaylistWidget(this);
94

95
    showTagger();
96

97 98 99
    // set the slider to the proper orientation and make it stay that way
    sliderAction->updateOrientation();
    connect(this, SIGNAL(dockWindowPositionChanged(QDockWindow *)), sliderAction, SLOT(updateOrientation(QDockWindow *)));
100

101 102
    // playlist item activation connection
    connect(playlist->getPlaylistList(), SIGNAL(doubleClicked(QListViewItem *)), this, SLOT(playItem(QListViewItem *)));
103
    connect(tagger->getTaggerList(), SIGNAL(doubleClicked(QListViewItem *)), this, SLOT(playItem(QListViewItem *)));
104

105
    tagger->getTaggerList()->setFocus();
106 107 108 109
}

void JuK::setupPlayer()
{
110 111 112 113 114 115 116 117 118 119 120 121 122
    trackPositionDragging=false;
    noSeek=false;
    pauseAction->setEnabled(false);
    stopAction->setEnabled(false);

    playTimer=new QTimer(this);
    connect(playTimer, SIGNAL(timeout()), this, SLOT(pollPlay()));

    if(sliderAction && sliderAction->getTrackPositionSlider() && sliderAction->getVolumeSlider()) {
        connect(sliderAction->getTrackPositionSlider(), SIGNAL(valueChanged(int)), this, SLOT(trackPositionSliderUpdate(int)));
        connect(sliderAction->getTrackPositionSlider(), SIGNAL(sliderPressed()), this, SLOT(trackPositionSliderClick()));
        connect(sliderAction->getTrackPositionSlider(), SIGNAL(sliderReleased()), this, SLOT(trackPositionSliderRelease()));
        sliderAction->getTrackPositionSlider()->setEnabled(false);
123

124 125
        connect(sliderAction->getVolumeSlider(), SIGNAL(valueChanged(int)), this, SLOT(setVolume(int)));
    }
126 127
}

128 129 130 131 132 133 134 135 136 137 138 139
void JuK::processArgs()
{
    KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
    QStringList files;
    
    for(int i = 0; i < args->count(); i++)
	files.append(args->arg(i));

    if(tagger)
	tagger->add(files);
}

140 141
void JuK::readConfig()
{
142 143 144 145 146 147 148
    KConfig *config = KGlobal::config();
    { // player settings
        KConfigGroupSaver saver(config, "Player");
        if(sliderAction && sliderAction->getVolumeSlider()) {
            int volume = config->readNumEntry("Volume", sliderAction->getVolumeSlider()->maxValue());
            sliderAction->getVolumeSlider()->setValue(volume);
        }
149 150 151 152 153
    }
}

void JuK::saveConfig()
{
154 155 156 157 158 159
    KConfig *config = KGlobal::config();
    { // player settings
        KConfigGroupSaver saver(config, "Player");
        if(sliderAction && sliderAction->getVolumeSlider())
            config->writeEntry("Volume", sliderAction->getVolumeSlider()->value());
    }
160 161
}

162 163 164 165 166 167 168 169 170 171 172 173
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// private slot definitions
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// private action slot implementations - file menu
////////////////////////////////////////////////////////////////////////////////

void JuK::openFile()
{
174 175
    QStringList files = KFileDialog::getOpenFileNames(QString::null, "*.mp3|MPEG Audio (*.mp3)");
    tagger->add(files);
176 177 178 179
}

void JuK::openDirectory()
{
180
    tagger->add(KFileDialog::getExistingDirectory());
181 182
}

183 184
void JuK::saveFile()
{
185 186
    if(tagger && tagger->isVisible())
        tagger->save();
187 188
}

189 190
void JuK::deleteFile()
{
191 192 193 194 195 196 197 198
    QPtrList<FileListItem> items(tagger->getSelectedItems());
    FileListItem *item = items.first();
    while(item) {
        if(item == playingItem)
            playingItem = 0;
        item = items.next();
    }

199 200
    if(tagger && tagger->isVisible())
        tagger->deleteFile();
201 202
}

203 204
void JuK::quit()
{
205
    delete(this);
206 207
}

208 209 210 211 212 213 214 215
////////////////////////////////////////////////////////////////////////////////
// edit menu
////////////////////////////////////////////////////////////////////////////////

void JuK::cut()
{
    if(tagger && tagger->isVisible()) {
        QPtrList<FileListItem> items(tagger->getTaggerList()->selectedItems());
Scott Wheeler's avatar
Scott Wheeler committed
216 217 218 219 220 221 222 223

        FileListItem *item = items.first();
        while(item) {
            if(item == playingItem)
                playingItem = 0;
            item = items.next();
        }

224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
        tagger->getTaggerList()->remove(items);
    }
    else if(playlist && playlist->isVisible())
        removeFromPlaylist();
}

void JuK::selectAll()
{
    if(tagger && tagger->isVisible()) {
        tagger->getTaggerList()->selectAll(true);
    }
    else if(playlist && playlist->isVisible()) {
        playlist->getPlaylistList()->selectAll(true);
    }
}

240 241 242 243 244 245
////////////////////////////////////////////////////////////////////////////////
// function menu
////////////////////////////////////////////////////////////////////////////////

void JuK::showTagger()
{
246 247 248
    playlist->hide();
    tagger->show();
    setCentralWidget(tagger);
249

250 251
    addToPlaylistAction->setEnabled(true);
    removeFromPlaylistAction->setEnabled(false);
252

253 254
    showTaggerAction->setEnabled(false);
    showPlaylistAction->setEnabled(true);
255 256 257 258
}

void JuK::showPlaylist()
{
259 260 261
    tagger->hide();
    playlist->show();
    setCentralWidget(playlist);
262

263 264
    addToPlaylistAction->setEnabled(false);
    removeFromPlaylistAction->setEnabled(true);
265

266 267
    showTaggerAction->setEnabled(true);
    showPlaylistAction->setEnabled(false);
268 269 270 271 272 273
}

////////////////////////////////////////////////////////////////////////////////
// player menu
////////////////////////////////////////////////////////////////////////////////

274 275
void JuK::addToPlaylist()
{
276 277
    QPtrList<FileListItem> items(tagger->getSelectedItems());
    playlist->add(items);
278 279 280 281
}

void JuK::removeFromPlaylist()
{
282
    QPtrList<FileListItem> items(playlist->getSelectedItems());
283
    playlist->remove(items);
284
}
285 286 287

void JuK::playFile()
{
288 289 290 291 292 293 294 295 296 297
    if(player.paused()) {
        player.play();
        if(player.playing()) {
            playAction->setEnabled(false);
            pauseAction->setEnabled(true);
            stopAction->setEnabled(true);
            playTimer->start(pollInterval);
        }
    }
    else if(playlist) {
298
        QPtrList<FileListItem> items(playlist->getSelectedItems());
299 300 301 302
        if(items.count() > 0)
            playItem(dynamic_cast<FileListItem *>(items.at(0)));
        else
            playItem(playlist->firstItem());
303
    }
304 305 306 307
}

void JuK::pauseFile()
{
308 309 310 311
    playTimer->stop();
    player.pause();
    playAction->setEnabled(true);
    pauseAction->setEnabled(false);
312 313 314 315
}

void JuK::stopFile()
{
316 317 318 319 320 321 322
    playTimer->stop();
    player.stop();
    playAction->setEnabled(true);
    pauseAction->setEnabled(false);
    stopAction->setEnabled(false);
    sliderAction->getTrackPositionSlider()->setValue(0);
    sliderAction->getTrackPositionSlider()->setEnabled(false);
323 324
    if(playingItem)
        playingItem->setPixmap(0, 0);
325 326 327 328
}

void JuK::trackPositionSliderClick()
{
329
    trackPositionDragging=true;
330 331 332 333
}

void JuK::trackPositionSliderRelease()
{
334 335
    trackPositionDragging=false;
    player.seekPosition(sliderAction->getTrackPositionSlider()->value());
336 337 338 339
}

void JuK::trackPositionSliderUpdate(int position)
{
340 341 342
    if(player.playing() && !trackPositionDragging && !noSeek) {
        player.seekPosition(position);
    }
343 344 345 346
}

void JuK::pollPlay()
{
347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366
    noSeek = true;
    if(!player.playing()) {
        playTimer->stop();
        if(player.paused()) {
            pauseFile();
        }
        else {
            if(playingItem && dynamic_cast<FileListItem*>(playingItem->itemBelow())) {
                playingItem->setPixmap(0, 0);
                playingItem = dynamic_cast<FileListItem *>(playingItem->itemBelow());
                sliderAction->getTrackPositionSlider()->setValue(0);
                player.play(playingItem->absFilePath(), player.getVolume());
                if(player.playing()) {
                    playTimer->start(pollInterval);
                    playingItem->setPixmap(0, QPixmap(UserIcon("playing")));
                }
            }
            else
                stopFile();
        }
367
    }
368 369 370
    else if(!trackPositionDragging) {
        //    kdDebug() << player.position() << " - " << sliderAction->getTrackPositionSlider()->maxValue() << endl;
        sliderAction->getTrackPositionSlider()->setValue(player.position());
371
    }
372

373 374
    if(player.playing() && float(player.totalTime() - player.currentTime()) < pollInterval * 2)
        playTimer->changeInterval(50);
375

376
    noSeek=false;
377 378 379 380
}

void JuK::setVolume(int volume)
{
381 382 383
    if(sliderAction && sliderAction->getVolumeSlider() &&
       sliderAction->getVolumeSlider()->maxValue() > 0 &&
       volume >= 0 && sliderAction->getVolumeSlider()->maxValue() >= volume)
384
    {
385
        player.setVolume(float(volume) / float(sliderAction->getVolumeSlider()->maxValue()));
386 387
    }
}
388 389 390

void JuK::playItem(QListViewItem *item)
{
391 392 393
    FileListItem *fileListItem = dynamic_cast<FileListItem *>(item);
    if(fileListItem)
        playItem(fileListItem);
394 395 396 397
}

void JuK::playItem(FileListItem *item)
{
398 399 400 401 402 403 404 405 406 407 408 409 410 411 412
    if(player.playing() || player.paused())
        stopFile();

    if(item) {
        playingItem = item;
        float volume = float(sliderAction->getVolumeSlider()->value()) / float(sliderAction->getVolumeSlider()->maxValue());
        player.play(playingItem->absFilePath(), volume);
        if(player.playing()) {
            playAction->setEnabled(false);
            pauseAction->setEnabled(true);
            stopAction->setEnabled(true);
            sliderAction->getTrackPositionSlider()->setEnabled(true);
            playingItem->setPixmap(0, QPixmap(UserIcon("playing")));
            playTimer->start(pollInterval);
        }
413 414
    }
}
415 416 417 418 419 420 421 422 423 424

void JuK::playTaggerItem(QListViewItem *item)
{

}

void JuK::playTaggerItem(FileListItem *item)
{

}