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

playlist.cpp

// Editeur de playlist Freebox
// Copyright (C) 2005 Freebox S.A.
//
// playlist.cpp
// This file is part of fbx-playlist.
//
// fbx-playlist 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.
//
// fbx-playlist 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 fbx-playlist; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

#include "playlist.h"
#include "vlcopt.h"

#include <QMenuBar>
#include <QMenu>
#include <QFileInfo>
#include <QMessageBox>
#include <QDialog>
#include <QFileDialog>
#include <QTextStream>
#include <QRegExp>
#include <QCloseEvent>
#include <QProcess>

#include "ui_about.h"
#include "ui_help.h"
#include "ui_license.h"
#include "ui_add_item.h"
#include "ui_add_dvd.h"
#include "ui_add_cd.h"
#include "ui_add_webmedia.h"


Playlist::Playlist()
{
    setupUi(this);
    setupMenuBar();
    setupConnections();

    filename = "";
    lock_modified = false;
    setModified(false);

    Ui::AddItem ui;
    ui.setupUi(&add_window);
    connect(ui.filmsButton, SIGNAL(clicked()), SLOT(itemAddFilms()));
    connect(ui.musicButton, SIGNAL(clicked()), SLOT(itemAddMusic()));
    connect(ui.photosButton, SIGNAL(clicked()), SLOT(itemAddPhotos()));
    connect(ui.cdaudioButton, SIGNAL(clicked()), SLOT(itemAddCD()));
    connect(ui.dvdButton, SIGNAL(clicked()), SLOT(itemAddDVD()));
    connect(ui.webmediaButton, SIGNAL(clicked()), SLOT(itemAddWebMedia()));
}

void Playlist::setModified(bool modified)
{
    QString title;

    this->modified = modified;
    fileSaveAction->setEnabled(modified);
    title = "Éditeur de playlist Freebox - [";

    if (filename == "") {
      setWindowTitle(title + "Nouvelle playlist" + (modified ? "*]" : "]"));
      return;
    }

    QFileInfo file(filename);
    setWindowTitle(title + file.completeBaseName() + (modified ? "*]" : "]"));
}

void Playlist::fileNew()
{
    if (modified && checkSave())
      return;

    playlist->clear();
    nameEdit->clear();
    locationEdit->clear();
    positionLabel->clear();

    delButton->setEnabled(false);
    upButton->setEnabled(false);
    downButton->setEnabled(false);
    itemGroupBox->setEnabled(false);

    filename = "";
    setModified(false);
}

void Playlist::fileOpen()
{
    if (modified && checkSave())
      return;

    QString s = QFileDialog::getOpenFileName(
          this, "Ouvrir une playlist...",
          QString::null, "Playlists (*.m3u);;Tous les fichiers (*)");

    if (s.isNull() || s.isEmpty())
      return;

    open(s);
}

void Playlist::open(const QString &fname)
{
    QFile file(fname);

    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
      QMessageBox::critical(this, "Éditeur de playlist Freebox",
            QString("Impossible d'ouvrir \"") +
            fname + "\".");
      return;
    }

    QTextStream stream(&file);
    QString position, name, location, vlcopt;
    QString line;

    line = stream.readLine();
    if (line != "#EXTM3U") {
      QMessageBox::critical(this, "Éditeur de playlist Freebox",
            QString("Le fichier \"") +
            fname + "\" n'est pas une playlist valide.");
      return;
    }

    filename = fname;
    delButton->setEnabled(false);
    upButton->setEnabled(false);
    downButton->setEnabled(false);
    itemGroupBox->setEnabled(false);
    nameEdit->clear();
    locationEdit->clear();
    positionLabel->clear();
    playlist->clear();
    setModified(false);

    QRegExp extinf("#EXTINF:\\d+,(.*)");
    QRegExp fake_file("#EXTVLCOPT:fake-file=(.*)");
    QString fake_loc;
    QString sound;

    QTreeWidgetItem *item = 0;
    int pos = 1;
    int i = 0;

    while (!stream.atEnd()) {
      i++;
      line = stream.readLine();

      if (line.isEmpty())
          continue;

      name = "";
      fake_loc = "";
      sound = "0";
      while (line.startsWith("#")) {
          if (extinf.exactMatch(line))
            name = extinf.cap(1);
          else if (fake_file.exactMatch(line))
            fake_loc = fake_file.cap(1);
          else if (line == "#EXTVLCOPT:sout-transcode-acodec=mpga")
            sound = "1";
          i++;
          line = stream.readLine();
      }

      if (line.startsWith("dvdsimple:")) {
          line.remove(0, 10);
          sound = sound == "0" ? "1" : "0";
      }

      location = fake_loc != "" ? fake_loc : line;

      for (unsigned i = 0;
            i < sizeof (ext_to_opt) / sizeof (*ext_to_opt); i++)
          if (ext_to_opt[i].opt == 1 || ext_to_opt[i].opt == 2)
            if (location.endsWith(ext_to_opt[i].ext)) {
                sound = sound == "0" ? "1" : "0";
                break;
            }

        position.setNum(pos++);
      item = new QTreeWidgetItem(playlist, item);
      item->setText(0, position);
      item->setText(1, name);
      item->setText(2, location);
      item->setText(3, sound);
    }
    file.close();

    if (playlist->topLevelItemCount() > 0)
      playlist->setCurrentItem(playlist->topLevelItem(0));
}

void Playlist::fileSave()
{
    if (filename.isEmpty())
      fileSaveAs();

    if (filename.isEmpty())
      return;

    QFile file(filename);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
      QMessageBox::critical(this, "Éditeur de playlist Freebox",
            QString("Impossible d'enregistrer ") +
            filename + ".");
      return;
    }

    QTextStream stream(&file);
#ifdef Q_WS_MAC
    // Use UTF-8 encoding under Mac OS X
    stream.setCodec("UTF-8");
#endif
    playlistToStream(stream);
    file.close();
    setModified(false);
}

#define endl "\n"

#include <stdio.h>

void Playlist::playlistToStream(QTextStream &stream)
{
    stream << "#EXTM3U" << endl;

    QTreeWidgetItem *item;
    for (int i = 0; i < playlist->topLevelItemCount(); i++) {
      item = playlist->topLevelItem(i);
      stream << "#EXTINF:0," << item->text(1) << endl;
      QString loc;
      bool dolby;
      int opt = 0;

      loc = item->text(2);
      dolby = item->text(3) == "1";

      for (unsigned i = 0; i < sizeof (ext_to_opt) / sizeof (*ext_to_opt);
            i++)
          if (loc.endsWith(ext_to_opt[i].ext, Qt::CaseInsensitive)) {
            opt = ext_to_opt[i].opt;
            break;
          }

      if (loc.startsWith("/dev/") || loc.endsWith(":")) {
          opt = 1;
          loc.prepend("dvdsimple:");
      }

      if (opt == 0) {
          stream << loc << endl;

      } else if (opt == 1) {
          if (!dolby)
            for (unsigned i = 0; i < sizeof (opt_dvd) / sizeof (*opt_dvd);
                  i++)
                stream << "#EXTVLCOPT:" << opt_dvd[i] << endl;
          stream << loc << endl;

      } else if (opt == 3) {
          for (unsigned i = 0; i < sizeof (opt_jpg) / sizeof (*opt_jpg); i++)
            stream << "#EXTVLCOPT:" << opt_jpg[i] << endl;
          stream << "#EXTVLCOPT:fake-file=" << loc << endl;
          stream << "fake:" << endl;

      } else {
          if (dolby)
            for (unsigned i = 0;
                  i < sizeof (opt_avi_dolby) / sizeof (*opt_avi_dolby);
                  i++)
                stream << "#EXTVLCOPT:" << opt_avi_dolby[i] << endl;
          else
            for (unsigned i = 0;
                  i < sizeof (opt_avi) / sizeof (*opt_avi); i++)
                stream << "#EXTVLCOPT:" << opt_avi[i] << endl;
          stream << loc << endl;
      }
    }

    stream.flush();
}

void Playlist::fileSaveAs()
{
    QString s = QFileDialog::getSaveFileName(
          this, "Enregistrer Sous...", QString::null,
          "Playlists (*.m3u)", 0, QFileDialog::DontConfirmOverwrite);

    if (!s.isNull() && !s.isEmpty()) {
      if (!s.endsWith(".m3u"))
          s += ".m3u";
      if (QFile::exists(s) &&
            QMessageBox::question(
                this,
                "Écraser un fichier ?",
                QString("Un fichier nomé \"") + s +
                  "\" existe déjà.\n\nVoulez-vous l'écraser ?",
                "&Oui", "&Non",
                QString::null, 0, 1) == 1)
          return;

      filename = s;
      fileSave();
    }
}

void Playlist::closeEvent(QCloseEvent *event)
{
    if (modified && checkSave()) {
      event->ignore();
      return;
    }

    event->accept();
}

void Playlist::helpLicense()
{
    QDialog a;
    Ui::License ui;
    ui.setupUi(&a);
    a.exec();
}

void Playlist::helpHelp()
{
    QDialog a;
    Ui::Help ui;
    ui.setupUi(&a);
    a.exec();
}

void Playlist::helpAbout()
{
    QDialog a;
    Ui::About ui;

    ui.setupUi(&a);
    ui.versionLabel->setText("<b>Version :</b> " VERSION);
    ui.dateLabel->setText("<b>Date :</b> " __DATE__);
    a.exec();
}

void Playlist::setupMenuBar()
{
    QMenu *fileMenu;
    QMenu *helpMenu;

    fileMenu = menuBar()->addMenu("&Playlist");
    fileNewAction = fileMenu->addAction("&Nouveau",
          this, SLOT(fileNew()), Qt::CTRL + Qt::Key_N);
    fileOpenAction = fileMenu->addAction("&Ouvrir...",
          this, SLOT(fileOpen()), Qt::CTRL + Qt::Key_O);
    fileSaveAction = fileMenu->addAction("&Enregistrer",
          this, SLOT(fileSave()), Qt::CTRL + Qt::Key_S);
    fileSaveAsAction = fileMenu->addAction("Enregistrer Sous...",
          this, SLOT(fileSaveAs()));
    fileMenu->addSeparator();
    fileQuitAction = fileMenu->addAction("Quitter",
          this, SLOT(close()));

    helpMenu = menuBar()->addMenu("&Aide");
    helpHelpAction = helpMenu->addAction("&Aide...",
          this, SLOT(helpHelp()), Qt::CTRL + Qt::Key_A);
    helpLicenseAction = helpMenu->addAction("&License...",
          this, SLOT(helpLicense()), Qt::CTRL + Qt::Key_L);
    helpMenu->addSeparator();
    helpAboutAction = helpMenu->addAction("A &propos...",
          this, SLOT(helpAbout()), Qt::CTRL + Qt::Key_P);
}

void Playlist::enableButtons()
{
    delButton->setEnabled(true);
    upButton->setEnabled(true);
    downButton->setEnabled(true);
}

void Playlist::setupConnections()
{
    connect(upButton, SIGNAL(clicked()), SLOT(moveUp()));
    connect(delButton, SIGNAL(clicked()), SLOT(itemDel()));
    connect(addButton, SIGNAL(clicked()), SLOT(itemAdd()));
    connect(downButton, SIGNAL(clicked()), SLOT(moveDown()));

    connect(playlist, SIGNAL(itemSelectionChanged()), SLOT(itemSelect()));
    connect(nameEdit, SIGNAL(textEdited(const QString &)),
          SLOT(itemUpdateName()));
    connect(locationEdit, SIGNAL(textEdited(const QString &)),
          SLOT(itemUpdateLocation()));
    connect(soundCheckBox, SIGNAL(toggled(bool)), SLOT(itemUpdateSound()));
}

int Playlist::checkSave()
{
    int i;

    i = QMessageBox::question(
          this,
          "Attention",
          "Ce document a été modifié.\n\n"
          "Voulez-vous enregistrer les modifications ?",
          "&Oui", "&Non", "&Annuler");

    switch (i) {
      case 0:
          fileSave();
          if (filename == "")
            return 1;
          return 0;
      case 1:
          return 0;
      case 2:
          return 1;
    }

    return 0;
}

void Playlist::itemNew()
{
    QTreeWidgetItem *n;
    QString position;

    n = new QTreeWidgetItem(playlist);
    position.setNum(playlist->topLevelItemCount());
    n->setText(0, position);
    n->setText(3, "0");
    playlist->setCurrentItem(n);
    setModified(true);
}

void Playlist::itemAdd()
{
    add_window.exec();
}

void Playlist::itemAddFilms()
{
    add_window.accept();
    itemAddFiles("Fichiers vidéo (*.mpg *.ts *.mpeg *.vob *.avi *.mkv *.mp4 "
            "*.mov *.mjpeg *.wmv *.wma *.asf *.ogm *.divx)");
}

void Playlist::itemAddMusic()
{
    add_window.accept();
    itemAddFiles("Fichiers audio (*.mp2 *.ogg *.mp3 *.aac *.au *.aif *.aiff "
            "*.wav)");
}

void Playlist::itemAddPhotos()
{
    add_window.accept();
    itemAddFiles("Images (*.jpg *.jpeg *.png *.pgm *.pgmyuv *.pbm *.pam *.tga "
            "*.bmp *.pnm *.xpm *.xcf *.pcx *.gif *.tif *.tiff *.lbm)");
}

void Playlist::itemAddCD()
{
    QDialog a;

    add_window.accept();
    Ui::AddCD ui;
    ui.setupUi(&a);

#ifdef Q_WS_X11
    QString lbl = ui.deviceLabel->text();
    lbl.replace("D:", "/dev/cdrom");
    ui.deviceLabel->setText(lbl);
    ui.deviceLineEdit->setText("/dev/cdrom");
#endif

#ifdef Q_WS_MAC
    QString lbl = ui.deviceLabel->text();
    lbl.replace("D:", "/dev/rdisk1");
    ui.deviceLabel->setText(lbl);
    ui.deviceLineEdit->setText("/dev/rdisk1");
#endif

    if (a.exec() == QDialog::Accepted &&
      !ui.nameLineEdit->text().isEmpty() &&
      !ui.deviceLineEdit->text().isEmpty()) {

      QTreeWidgetItem *item;
      item = itemAddToPlaylist(ui.nameLineEdit->text(),
            QString("cdda:") + ui.deviceLineEdit->text());
      item->setText(3, "0");
    }
}

void Playlist::itemAddDVD()
{
    QDialog a;

    add_window.accept();
    Ui::AddDVD ui;
    ui.setupUi(&a);

#ifdef Q_WS_X11
    QString lbl = ui.deviceLabel->text();
    lbl.replace("D:", "/dev/dvd");
    ui.deviceLabel->setText(lbl);
    ui.deviceLineEdit->setText("/dev/dvd");
#endif

#ifdef Q_WS_MAC
    QString lbl = ui.deviceLabel->text();
    lbl.replace("D:", "/dev/rdisk1");
    ui.deviceLabel->setText(lbl);
    ui.deviceLineEdit->setText("/dev/rdisk1");
#endif

    if (a.exec() == QDialog::Accepted &&
      !ui.nameLineEdit->text().isEmpty() &&
      !ui.deviceLineEdit->text().isEmpty()) {

      QTreeWidgetItem *item;
      item = itemAddToPlaylist(ui.nameLineEdit->text(),
            ui.deviceLineEdit->text());
      item->setText(3, ui.soundCheckBox->isChecked() ? "1" : "0");
    }
}

void Playlist::itemAddWebMedia()
{
    QDialog a;

    add_window.accept();
    Ui::AddWebMedia ui;
    ui.setupUi(&a);

    if (a.exec() == QDialog::Accepted &&
      !ui.nameLineEdit->text().isEmpty() &&
      !ui.deviceLineEdit->text().isEmpty()) {

      QTreeWidgetItem *item;
      item = itemAddToPlaylist(ui.nameLineEdit->text(),
            ui.deviceLineEdit->text());
      item->setText(3, "0");
    }
}

QTreeWidgetItem *Playlist::itemAddToPlaylist(const QString &name,
                                   const QString &location)
{
    QTreeWidgetItem *item;
    QString position;

    item = new QTreeWidgetItem(playlist);
    position.setNum(playlist->topLevelItemCount());
    item->setText(0, position);
    item->setText(1, name);
    item->setText(2, location);
    setModified(true);

    return item;
}

void Playlist::itemAddFiles(const QString &filter)
{
    QStringList files = QFileDialog::getOpenFileNames(
          this, "Sélectionner un ou plusieurs fichiers à ajouter...",
          QString::null, filter + ";;Tous les fichiers (*)");

    if (files.isEmpty())
      return;

    int pos;
    QString position;
    QTreeWidgetItem *item;
    QStringList list = files;
    QStringList::Iterator it = list.begin();

    pos = playlist->topLevelItemCount() + 1;
    if (pos == 1)
      item = 0;
    else
      item = playlist->topLevelItem(playlist->topLevelItemCount() - 1);
    setModified(true);

    while (it != list.end()) {
      QString location = *it;
        QFileInfo file(location);
        QString name = file.completeBaseName();

      position.setNum(pos++);
      item = new QTreeWidgetItem(playlist, item);
      item->setText(0, position);
      item->setText(1, name);
      item->setText(2, file.absoluteFilePath());
      item->setText(3, "0");
      playlist->setCurrentItem(item);
      ++it;
    }
}

void Playlist::itemDel()
{
    QTreeWidgetItem *i;
    QString position;
    int idx;

    i = getItem();
    if (!i)
      return;
    idx = playlist->indexOfTopLevelItem(i);

    delete i;
    setModified(true);

    if (playlist->topLevelItemCount() == 0) {
      delButton->setEnabled(false);
      upButton->setEnabled(false);
      downButton->setEnabled(false);
      nameEdit->clear();
        locationEdit->clear();
        positionLabel->clear();
        itemGroupBox->setEnabled(false);
        return;
    }

    for (int i = 0; i < playlist->topLevelItemCount(); i++) {
      position.setNum(i + 1);
      playlist->topLevelItem(i)->setText(0, position);
    }

    if (idx >= playlist->topLevelItemCount())
      idx--;
    playlist->setCurrentItem(playlist->topLevelItem(idx));
    playlist->setItemSelected(playlist->currentItem(), true);
}

void Playlist::itemSelect()
{
    QTreeWidgetItem *item;

    item = getItem();
    if (!item)
      return;

    lock_modified = true;
    positionLabel->setText(item->text(0));
    nameEdit->setText(item->text(1));
    locationEdit->setText(item->text(2));
    soundCheckBox->setCheckState(item->text(3) == "1" ?
          Qt::Checked : Qt::Unchecked);
    itemGroupBox->setEnabled(true);
    upButton->setEnabled(true);
    downButton->setEnabled(true);
    delButton->setEnabled(true);
    lock_modified = false;
}

void Playlist::itemUpdateName()
{
    QTreeWidgetItem *item;

    item = getItem();
    if (item)
      item->setText(1, nameEdit->text());
    if (!lock_modified)
      setModified(true);
}

void Playlist::itemUpdateLocation()
{
    QTreeWidgetItem *item;

    item = getItem();
    if (item)
      item->setText(2, locationEdit->text());
    if (!lock_modified)
      setModified(true);
}

void Playlist::itemUpdateSound()
{
    QTreeWidgetItem *item;

    item = getItem();
    if (item)
      item->setText(3, soundCheckBox->isChecked() ? "1" : "0");
    if (!lock_modified)
      setModified(true);
}

void Playlist::moveUp()
{
    QTreeWidgetItem *i;
    int idx;

    i = getItem();
    if (!i)
      return;
    idx = playlist->indexOfTopLevelItem(i);
    if (idx != 0)
      switchItems(idx, idx - 1);
}

void Playlist::moveDown()
{
    QTreeWidgetItem *i;
    int idx;

    i = getItem();
    if (!i)
      return;
    idx = playlist->indexOfTopLevelItem(i);
    if (idx != playlist->topLevelItemCount() - 1)
      switchItems(idx, idx + 1);
}

void Playlist::switchItems(int idx1, int idx2)
{
    QTreeWidgetItem *a;
    QTreeWidgetItem *b;
    QString position;

    a = playlist->topLevelItem(idx1);
    b = playlist->topLevelItem(idx2);

    position = b->text(0);
    b->setText(0, a->text(0));
    a->setText(0, position);

    a = playlist->takeTopLevelItem(idx1);
    playlist->insertTopLevelItem(idx2, a);
    playlist->setCurrentItem(a);

    setModified(true);
}

QTreeWidgetItem *Playlist::getItem()
{
    QTreeWidgetItem *item;

    item = playlist->currentItem();
    if (item)
      return item;

    QList<QTreeWidgetItem *> items;
    items = playlist->selectedItems();
    if (items.count() > 0) {
      playlist->setCurrentItem(items[0]);
      return items[0];
    }

    return 0;
}

Generated by  Doxygen 1.6.0   Back to index