diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | e2de64d6f1beb9e492daf5b886e19933c1fa41dd (patch) | |
tree | 9047cf9e6b5c43878d5bf82660adae77ceee097a /kaudiocreator | |
download | tdemultimedia-e2de64d6f1beb9e492daf5b886e19933c1fa41dd.tar.gz tdemultimedia-e2de64d6f1beb9e492daf5b886e19933c1fa41dd.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdemultimedia@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kaudiocreator')
53 files changed, 6600 insertions, 0 deletions
diff --git a/kaudiocreator/Makefile.am b/kaudiocreator/Makefile.am new file mode 100644 index 00000000..d14c030c --- /dev/null +++ b/kaudiocreator/Makefile.am @@ -0,0 +1,44 @@ +INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/libkcddb \ + -I$(top_builddir)/libkcddb -I$(top_srcdir)/kscd $(all_includes) + +bin_PROGRAMS = kaudiocreator + +kaudiocreator_SOURCES = main.cpp kaudiocreator.cpp encoder.cpp \ + encoderconfigimp.cpp job.cpp jobqueimp.cpp ripper.cpp tracksimp.cpp \ + encoderedit.ui jobque.ui tracks.ui infodialog.ui wizard.ui general.ui \ + cdconfig.ui ripconfig.ui encoderoutput.ui encoderconfig.ui encodefile.ui \ + prefs.kcfgc encoder_prefs.kcfgc encodefileimp.cpp + +EXTRA_DIST = encoder.h kaudiocreator.h kaudiocreator.desktop encoderconfigimp.h \ + obqueimp.h ripper.h tracksimp.h encodefileimp.h + +kaudiocreator_LDFLAGS = $(all_libraries) $(KDE_RPATH) -lkutils + +METASOURCES = AUTO + +messages: rc.cpp + $(XGETTEXT) *.cpp *.h -o $(podir)/kaudiocreator.pot + +kaudiocreator_LDADD = $(LIB_KIO) $(top_builddir)/libkcddb/libkcddb.la \ + $(top_builddir)/kscd/libkcompactdisc.la + +KDE_ICON = AUTO + +SUBDIRS = icons + +xdg_apps_DATA = kaudiocreator.desktop +kde_kcfg_DATA = kaudiocreator.kcfg kaudiocreator_encoders.kcfg + +appdata_DATA = kaudiocreatorui.rc eventsrc +appdatadir = $(kde_datadir)/kaudiocreator + +servicedata_DATA = audiocd_extract.desktop +servicedatadir = $(kde_datadir)/konqueror/servicemenus + +updatedir = $(kde_datadir)/kconf_update +update_DATA = kaudiocreator-meta.upd kaudiocreator-libkcddb.upd +update_SCRIPTS = upgrade-kaudiocreator-metadata.sh + +encoderconfig.o: wizard.h +kaudiocreator.o: ../libkcddb/configbase.h +tracksimp.o: ../libkcddb/configbase.h ../libkcddb/cdinfodialogbase.h diff --git a/kaudiocreator/TODO b/kaudiocreator/TODO new file mode 100644 index 00000000..a53851e9 --- /dev/null +++ b/kaudiocreator/TODO @@ -0,0 +1,19 @@ +Change regexp infro to say that it is modifing the track names, not filename. + +Add option to disable message box + +Rip & Encode one track at a time."? +Maybe even better is "maximum uncoded wav's" with a number field as grip has +it (www.nostatic.org/grip). + +Good point, however I would prefer the dialog again on a manual query and not after startup or switching a cd. + +Add the ability to encode files. + +Rip and encode only 1 track at a time. (i.e. using audiocd:/ ioslave). +Plugin system for encoders (user friendly things, again use audiocd plugin system) + +If possible restart jobs that have failed. +--- +Enhance kdedirs kcontrol config dialog to let users specify global kde temp dir + Tmp files are stored in $KDEHOME/tmp-$HOST/appname diff --git a/kaudiocreator/audiocd_extract.desktop b/kaudiocreator/audiocd_extract.desktop new file mode 100644 index 00000000..6955ba06 --- /dev/null +++ b/kaudiocreator/audiocd_extract.desktop @@ -0,0 +1,54 @@ +[Desktop Entry] +ServiceTypes=media/audiocd +Actions=Extract; +X-KDE-Priority=TopLevel + +[Desktop Action Extract] +Name=Extract and Encode Audio Tracks +Name[bg]=Извличане и кодиране на аудио диск +Name[bs]=Ripujte i kodirajte audio CDove +Name[ca]=Extracció i codificació de pistes d'àudio +Name[cs]=Získat a enkódovat zvukové stopy +Name[da]=Udtræk og indkod lydspor +Name[de]=Musikstücke auslesen und kodieren +Name[el]=Εξαγωγή και κωδικοποίηση Κομματιών ήχου +Name[es]=Extrae y codifica pistas de audio +Name[et]=Ekstrakti ja kodeeri audiorajad +Name[eu]=Erauzi eta kodetu audio pistak +Name[fa]=استخراج و کدبندی شیارهای صوتی +Name[fi]=Siirrä ja koodaa ääniraitoja +Name[fr]=Extrait et encode des pistes audio +Name[ga]=Rianta Fuaime á mBaint Amach agus á nIonchódú +Name[gl]=Extraer e Codificar Pistas de Son +Name[he]=הוצאה וקידוד רצועות שמע +Name[hu]=Hangsávok kinyerése és tömörítése +Name[is]=Afrita og kóða hljóðspor +Name[it]=Estrai e comprimi le tracce audio +Name[ja]=オーディオトラックを取り出しエンコード +Name[kk]=Аудио жолсызықтарды оқып алу мен қалыптастыру +Name[km]=ស្រង់ចេញ និងអ៊ិនកូដបទអូឌីយ៉ូ +Name[ko]=오디오 트랙 추출 및 인코딩 +Name[lt]=Audio takelių išgavimas ir įkodavimas +Name[nb]=Pakk ut og dekod lydfiler +Name[nds]=Musikstücken utlesen un koderen +Name[ne]=निकाल्ने र सङ्केतन अडियो ट्रयाक +Name[nl]=Audio-tracks rippen en coderen +Name[nn]=Hent og kod lydspor +Name[pa]=ਆਡੀਓ ਟਰੈਕ ਖੋਲੋ ਅਤੇ ਇੰਕੋਡ +Name[pl]=Odzyskaj i przekoduj ścieżki audio +Name[pt]=Extracção e Codificação de Faixas de Áudio +Name[pt_BR]=Extrair e Converter Faixas de Áudio +Name[ru]=Извлечь и закодировать дорожки +Name[sk]=Vytiahnuť a zakódovať audio stopy +Name[sl]=Zajemite in zakodirajte glasbo +Name[sr]=Издваја и кодира аудио стазе +Name[sr@Latn]=Izdvaja i kodira audio staze +Name[sv]=Hämta och koda ljudspår +Name[th]=โปรแกรมสำหรับดึงข้อมูลและเข้ารหัสเพลง +Name[tr]=Ses İzlerini Aktar ve Kodla +Name[uk]=Витягає і кодує звукові доріжки +Name[zh_CN]=提取并编码音轨 +Name[zh_HK]=擷取並將音軌編碼 +Name[zh_TW]=展開並編碼音軌 +Exec=kaudiocreator %u +Icon=kaudiocreator diff --git a/kaudiocreator/cdconfig.ui b/kaudiocreator/cdconfig.ui new file mode 100644 index 00000000..3c688699 --- /dev/null +++ b/kaudiocreator/cdconfig.ui @@ -0,0 +1,61 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>CdConfig</class> +<widget class="QWidget"> + <property name="name"> + <cstring>CdConfig</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>517</width> + <height>148</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_performCDDBauto</cstring> + </property> + <property name="text"> + <string>&Perform CDDB lookup automatically</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_autoRip</cstring> + </property> + <property name="text"> + <string>&Automatically rip all tracks upon a successful CDDB retrieval</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer1</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<slots> + <slot access="protected" specifier="non virtual">configureAudioCD()</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/kaudiocreator/configure.in.in b/kaudiocreator/configure.in.in new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/kaudiocreator/configure.in.in diff --git a/kaudiocreator/encodefile.ui b/kaudiocreator/encodefile.ui new file mode 100644 index 00000000..21163f87 --- /dev/null +++ b/kaudiocreator/encodefile.ui @@ -0,0 +1,345 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>EncodeFile</class> +<widget class="KDialog"> + <property name="name"> + <cstring>EncodeFile</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>339</width> + <height>452</height> + </rect> + </property> + <property name="caption"> + <string>Encode File</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout5</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>&File to encode:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>file</cstring> + </property> + </widget> + <widget class="KURLRequester"> + <property name="name"> + <cstring>file</cstring> + </property> + <property name="showLocalProtocol"> + <bool>true</bool> + </property> + </widget> + </hbox> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox2</cstring> + </property> + <property name="title"> + <string>Track</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QSpinBox" row="3" column="1"> + <property name="name"> + <cstring>track</cstring> + </property> + <property name="minValue"> + <number>1</number> + </property> + </widget> + <widget class="QLabel" row="3" column="0"> + <property name="name"> + <cstring>textLabel4</cstring> + </property> + <property name="text"> + <string>Track:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="4" column="0"> + <property name="name"> + <cstring>textLabel5</cstring> + </property> + <property name="text"> + <string>Comment:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLineEdit" row="4" column="1"> + <property name="name"> + <cstring>track_comment</cstring> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="text"> + <string>Title:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + <property name="hAlign" stdset="0"> + </property> + </widget> + <widget class="QLabel" row="0" column="0" rowspan="2" colspan="1"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>Artist:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLineEdit" row="1" column="1" rowspan="2" colspan="1"> + <property name="name"> + <cstring>track_title</cstring> + </property> + </widget> + <widget class="QLineEdit" row="0" column="1"> + <property name="name"> + <cstring>track_artist</cstring> + </property> + </widget> + </grid> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox1</cstring> + </property> + <property name="title"> + <string>Album</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLineEdit" row="1" column="1"> + <property name="name"> + <cstring>artist</cstring> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel6</cstring> + </property> + <property name="text"> + <string>Artist:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + <property name="hAlign" stdset="0"> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>textLabel7</cstring> + </property> + <property name="text"> + <string>Album:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + <property name="hAlign" stdset="0"> + </property> + </widget> + <widget class="QLineEdit" row="2" column="1"> + <property name="name"> + <cstring>album</cstring> + </property> + </widget> + <widget class="QSpinBox" row="3" column="1"> + <property name="name"> + <cstring>year</cstring> + </property> + <property name="maxValue"> + <number>99999</number> + </property> + </widget> + <widget class="QLabel" row="3" column="0"> + <property name="name"> + <cstring>textLabel8</cstring> + </property> + <property name="text"> + <string>Year:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + <property name="hAlign" stdset="0"> + </property> + </widget> + <widget class="QLabel" row="4" column="0"> + <property name="name"> + <cstring>textLabel9</cstring> + </property> + <property name="text"> + <string>Genre:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + <property name="hAlign" stdset="0"> + </property> + </widget> + <widget class="QComboBox" row="4" column="1"> + <property name="name"> + <cstring>genre</cstring> + </property> + </widget> + <widget class="QLabel" row="5" column="0"> + <property name="name"> + <cstring>textLabel10</cstring> + </property> + <property name="text"> + <string>Comment:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLineEdit" row="5" column="1"> + <property name="name"> + <cstring>comment</cstring> + </property> + </widget> + </grid> + </widget> + <spacer> + <property name="name"> + <cstring>spacer8</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>16</height> + </size> + </property> + </spacer> + <widget class="Line"> + <property name="name"> + <cstring>line1</cstring> + </property> + <property name="frameShape"> + <enum>HLine</enum> + </property> + <property name="frameShadow"> + <enum>Sunken</enum> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer> + <property name="name"> + <cstring>spacer6</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>121</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>encodeButton</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>&Encode File</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>closeButton</cstring> + </property> + <property name="text"> + <string>&Close</string> + </property> + </widget> + </hbox> + </widget> + </vbox> +</widget> +<connections> + <connection> + <sender>closeButton</sender> + <signal>clicked()</signal> + <receiver>EncodeFile</receiver> + <slot>accept()</slot> + </connection> +</connections> +<tabstops> + <tabstop>file</tabstop> + <tabstop>track_artist</tabstop> + <tabstop>track_title</tabstop> + <tabstop>track</tabstop> + <tabstop>track_comment</tabstop> + <tabstop>artist</tabstop> + <tabstop>album</tabstop> + <tabstop>year</tabstop> + <tabstop>genre</tabstop> + <tabstop>comment</tabstop> + <tabstop>encodeButton</tabstop> + <tabstop>closeButton</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kdialog.h</includehint> + <includehint>kurlrequester.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> +</includehints> +</UI> diff --git a/kaudiocreator/encodefileimp.cpp b/kaudiocreator/encodefileimp.cpp new file mode 100644 index 00000000..e7345173 --- /dev/null +++ b/kaudiocreator/encodefileimp.cpp @@ -0,0 +1,82 @@ +/** + * This file is part of the KAudioCreator package + * Copyright (C) 2003 Benjamin C Meyer (ben+kaudiocreator at meyerhome dot net) + * + * 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 library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "encodefileimp.h" +#include "job.h" + +#include <qspinbox.h> +#include <qlineedit.h> +#include <kurlrequester.h> +#include <qcombobox.h> +#include <kmessagebox.h> + +EncodeFileImp::EncodeFileImp(QWidget* parent, + const char* name) : EncodeFile(parent, name), m_genres(KCDDB::Genres()) { + genre->insertStringList(m_genres.i18nList()); + // Specify to only accept wav files + file->setFilter("*.wav|Wav Files"); + + connect(file,SIGNAL(textChanged(const QString &)),this,SLOT(enableEncodeButton(const QString &))); + connect(encodeButton,SIGNAL(clicked()),this,SLOT(encode())); +} + +/** + * When the user presses the encode button create a job with all of the current + * selection options and emit a signal with it. + */ +void EncodeFileImp::encode(){ + Job *newJob = new Job(); + + newJob->location = file->url(); + + newJob->album = album->text(); + newJob->genre = m_genres.i18n2cddb(genre->currentText()); + if(newJob->genre.isEmpty()) + newJob->genre = "Pop"; + newJob->group = artist->text(); + newJob->comment = comment->text(); + newJob->year = year->value(); + newJob->track = track->value(); + + newJob->track_title = track_title->text(); + if ((track_artist->text()).isEmpty()) + newJob->track_artist = artist->text(); + else + newJob->track_artist = track_artist->text(); + newJob->track_comment = track_comment->text(); + + newJob->removeTempFile = false; + + emit(startJob(newJob)); + + // Same message and *strings* from tracksimp.cpp + int counter(1); + KMessageBox::information(this, + i18n("%1 Job(s) have been started. You can watch their progress in the " \ + "jobs section.").arg(counter), + i18n("Jobs have started"), i18n("Jobs have started")); +} + +void EncodeFileImp::enableEncodeButton(const QString &text){ + encodeButton->setEnabled(!text.isEmpty()); +} + + +#include "encodefileimp.moc" diff --git a/kaudiocreator/encodefileimp.h b/kaudiocreator/encodefileimp.h new file mode 100644 index 00000000..f64b3b16 --- /dev/null +++ b/kaudiocreator/encodefileimp.h @@ -0,0 +1,57 @@ +/** + * This file is part of the KAudioCreator package + * Copyright (C) 2003 Benjamin C Meyer (ben+kaudiocreator at meyerhome dot net) + * + * 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 library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef ENCODEFILEIMP_H +#define ENCODEFILEIMP_H + +#include "libkcddb/genres.h" +#include "encodefile.h" +#include "qmap.h" + +class Job; + +/** + * This class lets the user encode a file. + */ +class EncodeFileImp : public EncodeFile { + +Q_OBJECT + +signals: + // Start encoding this wav file + void startJob(Job *newJob); + +public: + EncodeFileImp(QWidget* parent = 0, const char* name = 0); + +protected slots: + // Encode button + void encode(); + // Enable encode button when user selects a file + void enableEncodeButton(const QString &text); + +private: + // List of genres and i18n versions + KCDDB::Genres m_genres; + +}; + +#endif // ENCODEFILEIMP_H + diff --git a/kaudiocreator/encoder.cpp b/kaudiocreator/encoder.cpp new file mode 100644 index 00000000..5dc0ef54 --- /dev/null +++ b/kaudiocreator/encoder.cpp @@ -0,0 +1,331 @@ +/** + * This file is part of the KAudioCreator package + * Copyright (C) 2003 Benjamin C Meyer (ben+kaudiocreator at meyerhome dot net) + * + * 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 library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "encoder.h" + +#include "prefs.h" +#include "encoder_prefs.h" +#include "encoderoutput.h" + +#include <qregexp.h> +#include <qdir.h> +#include <kstandarddirs.h> +#include <kmessagebox.h> +#include <kurl.h> +#include <kdebug.h> +#include <knotifyclient.h> +#include <qtextedit.h> +#include <kinputdialog.h> + +/** + * Constructor, load settings. + */ +Encoder::Encoder( QObject* parent, const char* name):QObject(parent,name),reportCount(0) { + loadSettings(); +} + +/** + * Load the settings for this class. + */ +void Encoder::loadSettings() { + loadEncoder(Prefs::currentEncoder()); + // If the cpu count change then try + for(uint i=0; i<(uint)Prefs::numberOfCpus(); i++) + tendToNewJobs(); +} + +EncoderPrefs* Encoder::loadEncoder( int encoder ){ + EncoderPrefs* prefs; + QString currentEncoderGroup = QString("Encoder_%1").arg(encoder); + prefs = EncoderPrefs::prefs(currentEncoderGroup); + if ( !EncoderPrefs::hasPrefs(currentEncoderGroup) ) { + KMessageBox::sorry(0, i18n("No encoder has been selected.\nPlease select an encoder in the configuration."), i18n("No Encoder Selected")); + prefs->setCommandLine(QString::null); + } + + return prefs; +} + +/** + * Deconstructor, remove pending jobs, remove current jobs. + */ +Encoder::~Encoder() { + pendingJobs.clear(); + + QMap<KShellProcess*, Job*>::Iterator pit; + for( pit = jobs.begin(); pit != jobs.end(); ++pit ) { + Job *job = jobs[pit.key()]; + KShellProcess *process = pit.key(); + threads.remove(process); + process->kill(); + QFile::remove(job->newLocation); + delete job; + delete process; + } + jobs.clear(); +} + +/** + * @return The number of active jobs + */ +int Encoder::activeJobCount() { + return jobs.count(); +} + +/** + * @return The number of pending jobs + */ +int Encoder::pendingJobCount() { + return pendingJobs.count(); +} + +/** + * Stop this job with the matching id. + * @param id the id number of the job to stop. + */ +void Encoder::removeJob(int id ) { + QMap<KShellProcess*, Job*>::Iterator it; + for( it = jobs.begin(); it != jobs.end(); ++it ) { + if ( it.data()->id == id ) { + KShellProcess *process = it.key(); + Job *job = jobs[it.key()]; + threads.remove(process); + process->kill(); + jobs.remove(process); + delete job; + delete process; + break; + } + } + Job *job = pendingJobs.first(); + while(job ) { + if ( job->id == id) + break; + job = pendingJobs.next(); + } + if ( job ) { + pendingJobs.remove(job); + delete job; + } + tendToNewJobs(); +} + +/** + * Adds job to the que of jobs to encode. + * @param job the job to encode. + */ +void Encoder::encodeWav(Job *job ) { + emit(addJob(job, i18n("Encoding (%1): %2 - %3").arg(loadEncoder(job->encoder)->extension()) + .arg(job->track_artist).arg(job->track_title))); + pendingJobs.append(job); + tendToNewJobs(); +} + +/** + * See if there are are new jobs to attend too. If we are all loaded up + * then just loop back in a few seconds and check agian. + */ +void Encoder::tendToNewJobs() { + if ( pendingJobs.count() == 0 ) { + emit jobsChanged(); + return; + } + + // If we are currently ripping the max try again in a little bit. + if ( (int)threads.count() >= Prefs::numberOfCpus() ) { + emit jobsChanged(); + return; + } + + Job *job = pendingJobs.first(); + pendingJobs.remove(job); + + EncoderPrefs* prefs = loadEncoder(job->encoder); + + QString desiredFile = Prefs::fileFormat(); + desiredFile.replace( QRegExp("~"), QDir::homeDirPath() ); + { + QMap <QString,QString> map; + map.insert("extension", prefs->extension()); + Job jobx = *job; + jobx.fix(Prefs::replaceInput(), Prefs::replaceOutput()); + jobx.fix("/", "%2f"); + // If the user wants anything regexp replaced do it now... + desiredFile = jobx.replaceSpecialChars(desiredFile, false, map); + } + + while ( QFile::exists( desiredFile ) ) { + bool ok; + QString text = KInputDialog::getText( + i18n("File Already Exists"), i18n("Sorry, file already exists. Please pick a new name:"), + desiredFile, &ok ); + if ( ok && !text.isEmpty() ) + desiredFile = text; + else { + emit jobsChanged(); + updateProgress(job->id, -1); + return; + } + } + + int lastSlash = desiredFile.findRev('/',-1); + if ( lastSlash == -1 || + !(KStandardDirs::makeDir( desiredFile.mid(0,lastSlash), 0775)) ) { + KMessageBox::sorry(0, i18n("Cannot place file, unable to make directories."), i18n("Encoding Failed")); + emit jobsChanged(); + updateProgress(job->id, -1); + return; + } + + job->newLocation = desiredFile; + reportCount = 0; + + QString command = prefs->commandLine(); { + QMap <QString,QString> map; + map.insert("extension", prefs->extension()); + map.insert("f", job->location); + map.insert("o", desiredFile); + command = job->replaceSpecialChars(command, true, map); + } + + updateProgress(job->id, 1); + + job->errorString = command; + KShellProcess *proc = new KShellProcess(); + proc->setPriority(Prefs::niceLevel()); + + *proc << QFile::encodeName(command); + connect(proc, SIGNAL(receivedStdout(KProcess *, char *, int )), + this, SLOT(receivedThreadOutput(KProcess *, char *, int ))); + connect(proc, SIGNAL(receivedStderr(KProcess *, char *, int )), + this, SLOT(receivedThreadOutput(KProcess *, char *, int ))); + connect(proc, SIGNAL(processExited(KProcess *)), this, SLOT(jobDone(KProcess *))); + jobs.insert(proc, job); + threads.append(proc); + + proc->start(KShellProcess::NotifyOnExit, KShellProcess::AllOutput); + emit jobsChanged(); +} + +/** + * We have received some output from a thread. See if it contains %. + * @param proc the process that has new output. + * @param buffer the output from the process + * @param buflen the length of the buffer. + */ +void Encoder::receivedThreadOutput(KProcess *process, char *buffer, int length ) { + if ( Prefs::fullDecoderDebug() && buffer) + kdDebug(60002) << buffer << endl; + + // Make sure we have a job to send an update too. + if(jobs.find((KShellProcess*)process) == jobs.end()){ + kdDebug(60002) << "Encoder::receivedThreadOutput Job doesn't exists. Line: " << __LINE__ << endl; + return; + } + + Job *job = jobs[(KShellProcess*)process]; + + // Keep the output in the event it fails. + job->output += QString(buffer).mid(0,length); + + // Make sure the output string has a % symble in it. + QString output = QString(buffer).mid(0,length); + if ( output.find('%') == -1 && reportCount < 5 ) { + kdDebug(60002) << "No \'%%\' in output. Report as bug w/encoder options if progressbar doesn't fill." << endl; + reportCount++; + return; + } + //qDebug(QString("Pre cropped: %1").arg(output).latin1()); + output = output.mid(output.find('%')-loadEncoder(job->encoder)->percentLength(),2); + //qDebug(QString("Post cropped: %1").arg(output).latin1()); + bool conversionSuccessfull = false; + int percent = output.toInt(&conversionSuccessfull); + //qDebug(QString("number: %1").arg(percent).latin1()); + if ( percent >= 0 && percent < 100 && conversionSuccessfull ) { + emit(updateProgress(job->id, percent)); + } + // If it was just some random output that couldn't be converted then don't report the error. + else + if ( conversionSuccessfull ) + kdWarning("Percent done:\"%d\" is not >= 0 && < 100.", percent); +} + +/** + * When the process is done encoding a file this function is called. + * @param job the job that just finished. + */ +void Encoder::jobDone(KProcess *process ) { + // Normal error checking here. + if ( !process) + return; + + //qDebug("Process exited with status: %d", process->exitStatus()); + + Job *job = jobs[(KShellProcess*)process]; + threads.remove((KShellProcess*)process); + jobs.remove((KShellProcess*)process); + + bool showDebugBox = false; + if ( process->exitStatus() == 127 ) { + KMessageBox::sorry(0, i18n("The selected encoder was not found.\nThe wav file has been removed. Command was: %1").arg(job->errorString), i18n("Encoding Failed")); + emit(updateProgress(job->id, -1)); + } + else if ( QFile::exists(job->newLocation) ) { + // fyi segfaults return 136 + if ( process->exitStatus() != 0 ) { + if ( KMessageBox::questionYesNo(0, i18n("The encoder exited with a error. Please check that the file was created.\nDo you want to see the full encoder output?"), i18n("Encoding Failed"),i18n("Show Output"),i18n("Skip Output")) == KMessageBox::Yes ) + { + showDebugBox = true; + } + } + else{ + //qDebug("Must be done: %d", (process->exitStatus())); + emit(updateProgress(job->id, 100)); + KNotifyClient::event("track encoded"); + if ( job->lastSongInAlbum) + KNotifyClient::event("cd encoded"); + } + } + else + { + if ( KMessageBox::questionYesNo(0, i18n("The encoded file was not created.\nPlease check the encoder options.\nThe wav file has been removed.\nDo you want to see the full encoder output?"), i18n("Encoding Failed"),i18n("Show Output"),i18n("Skip Output")) == KMessageBox::Yes ) + { + showDebugBox = true; + } + emit( updateProgress( job->id, -1 ) ); + } + + if ( job->removeTempFile ) + QFile::remove( job->location ); + + if( showDebugBox ){ + EncoderOutput dlg( 0, "Encoder Output" ); + job->output = job->errorString + "\n\n\n" + job->output; + dlg.output->setText(job->output); + dlg.exec(); + } + + delete job; + delete process; + tendToNewJobs(); +} + +#include "encoder.moc" + diff --git a/kaudiocreator/encoder.h b/kaudiocreator/encoder.h new file mode 100644 index 00000000..2398d2fb --- /dev/null +++ b/kaudiocreator/encoder.h @@ -0,0 +1,68 @@ +/** + * This file is part of the KAudioCreator package + * Copyright (C) 2003 Benjamin C Meyer (ben+kaudiocreator at meyerhome dot net) + * + * 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 library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef ENCODER_H +#define ENCODER_H + +#include <qobject.h> + +#include <qptrlist.h> +#include <qmap.h> +#include "job.h" +#include <kprocess.h> + +class EncoderPrefs; + +class Encoder : public QObject { + +Q_OBJECT + +signals: + void addJob(Job *job, const QString &name); + void updateProgress(int id, int progress); + void jobsChanged(); + +public: + Encoder( QObject* parent = 0, const char* name = 0); + ~Encoder(); + int activeJobCount(); + int pendingJobCount(); + +public slots: + void removeJob(int id); + void encodeWav(Job *job); + void loadSettings(); + EncoderPrefs* loadEncoder( int encoder ); + +private slots: + void receivedThreadOutput(KProcess *process, char *buffer, int buflen); + void jobDone(KProcess *process); + void tendToNewJobs(); + +private: + QPtrList<Job> pendingJobs; + QPtrList<KShellProcess> threads; + QMap<KShellProcess*, Job*> jobs; + + int reportCount; +}; + +#endif // ENCODER_H + diff --git a/kaudiocreator/encoder_prefs.kcfgc b/kaudiocreator/encoder_prefs.kcfgc new file mode 100644 index 00000000..075a4321 --- /dev/null +++ b/kaudiocreator/encoder_prefs.kcfgc @@ -0,0 +1,7 @@ +# Code generation options for kconfig_compiler +File=kaudiocreator_encoders.kcfg +#IncludeFiles=defines.h +ClassName=EncoderPrefs +Singleton=false +CustomAdditions=true +Mutators=true diff --git a/kaudiocreator/encoder_prefs_addons.h b/kaudiocreator/encoder_prefs_addons.h new file mode 100644 index 00000000..067f4d79 --- /dev/null +++ b/kaudiocreator/encoder_prefs_addons.h @@ -0,0 +1,8 @@ + +public: + static EncoderPrefs *prefs(const QString &groupName); + static bool hasPrefs(const QString &groupName); + static void deletePrefs(const QString &groupName); + +private: + static QDict<EncoderPrefs> *m_prefs; diff --git a/kaudiocreator/encoderconfig.ui b/kaudiocreator/encoderconfig.ui new file mode 100644 index 00000000..edab93fb --- /dev/null +++ b/kaudiocreator/encoderconfig.ui @@ -0,0 +1,293 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>EncoderConfig</class> +<widget class="QWidget"> + <property name="name"> + <cstring>EncoderConfig</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>434</width> + <height>349</height> + </rect> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QListBox" row="0" column="0" rowspan="3" colspan="1"> + <property name="name"> + <cstring>kcfg_currentEncoder</cstring> + </property> + </widget> + <widget class="QPushButton" row="0" column="1" rowspan="1" colspan="2"> + <property name="name"> + <cstring>addEncoder</cstring> + </property> + <property name="text"> + <string>&Add...</string> + </property> + </widget> + <widget class="QPushButton" row="1" column="1" rowspan="1" colspan="2"> + <property name="name"> + <cstring>removeEncoder</cstring> + </property> + <property name="text"> + <string>&Remove</string> + </property> + </widget> + <widget class="QPushButton" row="2" column="1" rowspan="1" colspan="2"> + <property name="name"> + <cstring>configureEncoder</cstring> + </property> + <property name="text"> + <string>&Configure...</string> + </property> + </widget> + <widget class="Line" row="4" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>line1</cstring> + </property> + <property name="frameShape"> + <enum>HLine</enum> + </property> + <property name="frameShadow"> + <enum>Sunken</enum> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + </widget> + <widget class="QGroupBox" row="5" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>GroupBox3</cstring> + </property> + <property name="title"> + <string>Encoded File Location</string> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>TextLabel2_2</cstring> + </property> + <property name="text"> + <string>Location:</string> + </property> + </widget> + <widget class="QLineEdit"> + <property name="name"> + <cstring>kcfg_fileFormat</cstring> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>encoderWizardButton</cstring> + </property> + <property name="text"> + <string>&Wizard</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QLabel" row="6" column="0"> + <property name="name"> + <cstring>TextLabel1_2</cstring> + </property> + <property name="text"> + <string>&Number of wav files to encode at a time:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_numberOfCpus</cstring> + </property> + </widget> + <widget class="QSpinBox" row="6" column="1"> + <property name="name"> + <cstring>kcfg_numberOfCpus</cstring> + </property> + <property name="minValue"> + <number>1</number> + </property> + </widget> + <spacer row="6" column="2"> + <property name="name"> + <cstring>Spacer4_2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QLayoutWidget" row="3" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>layout2</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>currentEncoderText</cstring> + </property> + <property name="text"> + <string>Current encoder:</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>currentEncoderName</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape"> + <enum>LineEditPanel</enum> + </property> + <property name="frameShadow"> + <enum>Sunken</enum> + </property> + <property name="lineWidth"> + <number>1</number> + </property> + </widget> + </hbox> + </widget> + <spacer row="10" column="0"> + <property name="name"> + <cstring>Spacer3</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>30</height> + </size> + </property> + </spacer> + <widget class="QGroupBox" row="9" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>groupBox3</cstring> + </property> + <property name="title"> + <string>Encoder Priority</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QSlider" row="0" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>kcfg_NiceLevel</cstring> + </property> + <property name="minValue"> + <number>-19</number> + </property> + <property name="maxValue"> + <number>19</number> + </property> + <property name="lineStep"> + <number>5</number> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="tickmarks"> + <enum>NoMarks</enum> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>Highest</string> + </property> + </widget> + <widget class="QLabel" row="1" column="2"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="text"> + <string>Lowest</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="1" column="1"> + <property name="name"> + <cstring>textLabel4</cstring> + </property> + <property name="text"> + <string>Normal</string> + </property> + <property name="alignment"> + <set>AlignCenter</set> + </property> + </widget> + </grid> + </widget> + </grid> +</widget> +<connections> + <connection> + <sender>kcfg_currentEncoder</sender> + <signal>highlighted(const QString&)</signal> + <receiver>currentEncoderName</receiver> + <slot>setText(const QString&)</slot> + </connection> + <connection> + <sender>encoderWizardButton</sender> + <signal>clicked()</signal> + <receiver>EncoderConfig</receiver> + <slot>encoderWizard()</slot> + </connection> +</connections> +<tabstops> + <tabstop>kcfg_currentEncoder</tabstop> + <tabstop>addEncoder</tabstop> + <tabstop>removeEncoder</tabstop> + <tabstop>configureEncoder</tabstop> + <tabstop>kcfg_fileFormat</tabstop> + <tabstop>encoderWizardButton</tabstop> + <tabstop>kcfg_numberOfCpus</tabstop> +</tabstops> +<includes> + <include location="local" impldecl="in implementation">encoderconfig.ui.h</include> +</includes> +<slots> + <slot>encoderWizard()</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/kaudiocreator/encoderconfig.ui.h b/kaudiocreator/encoderconfig.ui.h new file mode 100644 index 00000000..fd95a75a --- /dev/null +++ b/kaudiocreator/encoderconfig.ui.h @@ -0,0 +1,25 @@ +/**************************************************************************** +** ui.h extension file, included from the uic-generated form implementation. +** +** If you wish to add, delete or rename functions or slots use +** Qt Designer which will update this file, preserving your code. Create an +** init() function in place of a constructor, and a destroy() function in +** place of a destructor. +*****************************************************************************/ + +#include "wizard.h" +#include <qlineedit.h> + +/** + * Load up the wizard with the encoder fileFormat string. Save it if OK is hit. + */ +void EncoderConfig::encoderWizard(){ + fileWizard wizard(this, "Encoder File Format Wizard", true); + wizard.fileFormat->setText(kcfg_fileFormat->text()); + + // Show dialog and save results if ok is pressed. + bool okClicked = wizard.exec(); + if(okClicked){ + kcfg_fileFormat->setText(wizard.fileFormat->text()); + } +} diff --git a/kaudiocreator/encoderconfigimp.cpp b/kaudiocreator/encoderconfigimp.cpp new file mode 100644 index 00000000..feebae7d --- /dev/null +++ b/kaudiocreator/encoderconfigimp.cpp @@ -0,0 +1,289 @@ +/** + * This file is part of the KAudioCreator package + * Copyright (C) 2003 Benjamin C Meyer (ben+kaudiocreator at meyerhome dot net) + * + * 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 library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "encoderconfigimp.h" +#include "encoderedit.h" +#include "prefs.h" + +#include <qpushbutton.h> +#include <qlineedit.h> +#include <kconfigdialog.h> +#include <kmessagebox.h> +#include <klocale.h> +#include <kconfig.h> + +/** + * Constructor. + */ +EncoderConfigImp::EncoderConfigImp( QWidget* parent, const char* name) : + EncoderConfig (parent, name) { + connect(addEncoder, SIGNAL(clicked()), this, SLOT(addEncoderSlot())); + connect(removeEncoder, SIGNAL(clicked()), this, SLOT(removeEncoderSlot())); + connect(configureEncoder, SIGNAL(clicked()), this, SLOT(configureEncoderSlot())); + connect(kcfg_currentEncoder, SIGNAL(doubleClicked ( QListBoxItem * )),this, SLOT(configureEncoderSlot())); + + // If there are no encoders then store the three default ones. + if( Prefs::lastKnownEncoder() == 0){ + EncoderPrefs *encPrefs; + + encPrefs = EncoderPrefs::prefs("Encoder_0"); + encPrefs->setEncoderName(i18n("Ogg Vorbis")); + encPrefs->setCommandLine("oggenc -o %o --artist %{artist} --album %{albumtitle} --title %{title} --date %{year} --tracknum %{number} --genre %{genre} %f"); + encPrefs->setExtension("ogg"); + encPrefs->setPercentLength(4); + encPrefs->writeConfig(); + + encPrefs = EncoderPrefs::prefs("Encoder_1"); + encPrefs->setEncoderName(i18n("MP3")); + encPrefs->setCommandLine("lame --preset standard --tt %{title} --ta %{artist} --tl %{albumtitle} --ty %{year} --tn %{number} --tg %{genre} %f %o"); + encPrefs->setExtension("mp3"); + encPrefs->setPercentLength(2); + encPrefs->writeConfig(); + + encPrefs = EncoderPrefs::prefs("Encoder_2"); + encPrefs->setEncoderName(i18n("Wav")); + encPrefs->setCommandLine("mv %f %o"); + encPrefs->setExtension("wav"); + encPrefs->setPercentLength(2); + encPrefs->writeConfig(); + + encPrefs = EncoderPrefs::prefs("Encoder_3"); + encPrefs->setEncoderName(i18n("FLAC")); + encPrefs->setCommandLine("flac --best -o %o --tag=Artist=%{artist} --tag=Album=%{albumtitle} --tag=Date=%{year} --tag=Title=%{title} --tag=Tracknumber=%{number} --tag=Genre=%{genre} %f"); + encPrefs->setExtension("flac"); + encPrefs->setPercentLength(2); + encPrefs->writeConfig(); + + Prefs::setLastKnownEncoder(3); + Prefs::writeConfig(); + } + + loadEncoderList(); +} + +/** + * Clear map + * Clear listbox + * Load list of encoders. + */ +void EncoderConfigImp::loadEncoderList(){ + encoderNames.clear(); + kcfg_currentEncoder->clear(); + + bool foundCurrentEncoder = false; + + int lastEncoder = 0; + int lastKnownEncoder = Prefs::lastKnownEncoder(); + lastKnownEncoder++; + for( int i=0; i<=lastKnownEncoder; i++ ){ + QString currentGroup = QString("Encoder_%1").arg(i); + if(EncoderPrefs::hasPrefs(currentGroup)){ + lastEncoder = i; + EncoderPrefs *encPrefs = EncoderPrefs::prefs(currentGroup); + QString encoderName = encPrefs->encoderName(); + kcfg_currentEncoder->insertItem(encoderName); + encoderNames.insert(encoderName, currentGroup); + if(Prefs::currentEncoder() == i) + foundCurrentEncoder = true; + } + } + if(lastEncoder != Prefs::lastKnownEncoder()){ + Prefs::setLastKnownEncoder(lastEncoder); + Prefs::writeConfig(); + } + + // Make sure that the current encoder is valid. + if(!foundCurrentEncoder && kcfg_currentEncoder->count() > 0) + kcfg_currentEncoder->setCurrentItem(0); +} + +/** + * Find empty group + * bring up dialog for that group. + */ +void EncoderConfigImp::addEncoderSlot(){ + bool foundEmptyGroup = false; + uint number = 0; + QString groupName; + while(!foundEmptyGroup){ + groupName = QString("Encoder_%1").arg(number); + if(!EncoderPrefs::hasPrefs(groupName)) + foundEmptyGroup = true; + else + number++; + } + + if(KConfigDialog::showDialog(groupName.latin1())) + return; + + KConfigDialog *dialog = new KConfigDialog(this, groupName.latin1(), EncoderPrefs::prefs(groupName), + KDialogBase::Swallow, + KDialogBase::Ok | KDialogBase::Cancel | KDialogBase::Help); + dialog->setCaption(i18n("Configure Encoder")); + dialog->addPage(new EncoderEdit(0, groupName.latin1()), i18n("Encoder Configuration"), "package_settings"); + connect(dialog, SIGNAL(settingsChanged()), this, SLOT(loadEncoderList())); + dialog->show(); +} + +/** + * If + * Something is selected + * There is more then 1 thing left + * The user says ok to delete. + * Is not the current encoder. + * Then + * The group is removed from the list + * Deleted from the config. + */ +void EncoderConfigImp::removeEncoderSlot(){ + if(!kcfg_currentEncoder->selectedItem()){ + KMessageBox:: sorry(this, i18n("Please select an encoder."), i18n("No Encoder Selected")); + return; + } + if(kcfg_currentEncoder->count() <= 1){ + KMessageBox:: sorry(this, i18n("At least one encoder must exist."), i18n("Can Not Remove")); + return; + } + if(KMessageBox::warningContinueCancel(this, i18n("Delete encoder?"), i18n("Delete Encoder"),KStdGuiItem::del()) + == KMessageBox::Cancel ) + return; + + QString groupName = encoderNames[kcfg_currentEncoder->currentText()]; + kcfg_currentEncoder->removeItem(kcfg_currentEncoder->currentItem()); + + delete KConfigDialog::exists(groupName.latin1()); + + EncoderPrefs::deletePrefs(groupName); +} + +/** + * If + * Something is selected + * Group exists + * Then + * Bring up dialog + */ +void EncoderConfigImp::configureEncoderSlot() { + if(!kcfg_currentEncoder->selectedItem()){ + KMessageBox:: sorry(this, i18n("Please select an encoder."), i18n("No Encoder Selected")); + return; + } + QString groupName = encoderNames[kcfg_currentEncoder->currentText()]; + KConfig &config = *KGlobal::config(); + if(!config.hasGroup(groupName)) + return; + + if(KConfigDialog::showDialog(groupName.latin1())) + return; + + KConfigDialog *dialog = new KConfigDialog(this, groupName.latin1(), EncoderPrefs::prefs(groupName), + KDialogBase::Swallow, + KDialogBase::Ok | KDialogBase::Cancel | KDialogBase::Help); + dialog->setCaption(i18n("Configure Encoder")); + dialog->addPage(new EncoderEdit(0, groupName.latin1()), i18n("Encoder Configuration"), "package_settings"); + connect(dialog, SIGNAL(destroyed(QObject *)), this, SLOT(updateEncoder(QObject *))); + connect(dialog, SIGNAL(settingsChanged()), this, SIGNAL(encoderUpdated())); + connect(dialog, SIGNAL(settingsChanged(const char *)), this, SLOT(updateEncoder(const char *))); + dialog->show(); +} + +/** + * If object exists update encoder + */ +void EncoderConfigImp::updateEncoder(QObject * obj){ + if(!obj) + return; + updateEncoder(obj->name()); +} + +/** + * If + * Exists + * Then + * Get name + * Make sure group exists + * Update name + * Update Map + * If current encoder update also. + */ +void EncoderConfigImp::updateEncoder(const char *dialogName){ + QString groupName = dialogName; + QString encoderName; + bool found = false; + QMap<QString, QString>::Iterator it; + for ( it = encoderNames.begin(); it != encoderNames.end(); ++it ) { + if(it.data() == groupName){ + found = true; + encoderName = it.key(); + } + } + if(!found) + return; + if(!EncoderPrefs::hasPrefs(groupName)) + return; + QString newName = EncoderPrefs::prefs(groupName)->encoderName(); + if(newName == encoderName) + return; + + QListBoxItem *item = kcfg_currentEncoder->findItem(encoderName); + if(!item) + return; + kcfg_currentEncoder->changeItem(newName, kcfg_currentEncoder->index(item)); + + encoderNames.insert(newName, groupName); + encoderNames.erase(encoderName); +} + +QDict<EncoderPrefs> *EncoderPrefs::m_prefs = 0; + +EncoderPrefs *EncoderPrefs::prefs(const QString &groupName) +{ + if (!m_prefs) + { + m_prefs = new QDict<EncoderPrefs>(); + m_prefs->setAutoDelete(true); + } + EncoderPrefs *encPrefs = m_prefs->find(groupName); + if (encPrefs) + return encPrefs; + + encPrefs = new EncoderPrefs(groupName); + encPrefs->readConfig(); + m_prefs->insert(groupName, encPrefs); + return encPrefs; +} + +bool EncoderPrefs::hasPrefs(const QString &groupName) +{ + KConfig &config = *KGlobal::config(); + return config.hasGroup(groupName); +} + +void EncoderPrefs::deletePrefs(const QString &groupName) +{ + KConfig &config = *KGlobal::config(); + config.deleteGroup(groupName); + if (!m_prefs) + return; + m_prefs->remove(groupName); +} + +#include "encoderconfigimp.moc" + diff --git a/kaudiocreator/encoderconfigimp.h b/kaudiocreator/encoderconfigimp.h new file mode 100644 index 00000000..9d402637 --- /dev/null +++ b/kaudiocreator/encoderconfigimp.h @@ -0,0 +1,57 @@ +/** + * This file is part of the KAudioCreator package + * Copyright (C) 2003 Benjamin C Meyer (ben+kaudiocreator at meyerhome dot net) + * + * 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 library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef ENCODERCONFIGIMP_H +#define ENCODERCONFIGIMP_H + +#include "encoderconfig.h" +#include "encoder_prefs.h" +#include <qmap.h> +#include <qdict.h> + +/** + * Class mainly build to manage encoder list. + */ +class EncoderConfigImp : public EncoderConfig { + +Q_OBJECT + +signals: + void encoderUpdated(); + +public: + EncoderConfigImp( QWidget* parent = 0, const char* name = 0); + +private slots: + void addEncoderSlot(); + void removeEncoderSlot(); + void configureEncoderSlot(); + + void updateEncoder(QObject * obj); + void updateEncoder(const char *dialogName); + void loadEncoderList(); + +private: + // Name, groupName + QMap<QString, QString> encoderNames; +}; + +#endif + diff --git a/kaudiocreator/encoderedit.ui b/kaudiocreator/encoderedit.ui new file mode 100644 index 00000000..6a0fa7f0 --- /dev/null +++ b/kaudiocreator/encoderedit.ui @@ -0,0 +1,98 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>EncoderEdit</class> +<widget class="QWidget"> + <property name="name"> + <cstring>EncoderEdit</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>456</width> + <height>129</height> + </rect> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLineEdit" row="1" column="1"> + <property name="name"> + <cstring>kcfg_commandLine</cstring> + </property> + <property name="text"> + <string>app.exe %f %o</string> + </property> + </widget> + <widget class="QLineEdit" row="0" column="1"> + <property name="name"> + <cstring>kcfg_encoderName</cstring> + </property> + <property name="minimumSize"> + <size> + <width>320</width> + <height>0</height> + </size> + </property> + <property name="text"> + <string>Unknown Encoder</string> + </property> + </widget> + <widget class="QLineEdit" row="2" column="1"> + <property name="name"> + <cstring>kcfg_extension</cstring> + </property> + <property name="text"> + <string>wav</string> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>textLabel5</cstring> + </property> + <property name="text"> + <string>Extension:</string> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel6</cstring> + </property> + <property name="text"> + <string>Command line:</string> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel4</cstring> + </property> + <property name="text"> + <string>Name:</string> + </property> + </widget> + <spacer row="3" column="1"> + <property name="name"> + <cstring>spacer14</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>16</height> + </size> + </property> + </spacer> + </grid> +</widget> +<tabstops> + <tabstop>kcfg_encoderName</tabstop> + <tabstop>kcfg_commandLine</tabstop> + <tabstop>kcfg_extension</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/kaudiocreator/encoderoutput.ui b/kaudiocreator/encoderoutput.ui new file mode 100644 index 00000000..1cc26be4 --- /dev/null +++ b/kaudiocreator/encoderoutput.ui @@ -0,0 +1,103 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>EncoderOutput</class> +<widget class="QDialog"> + <property name="name"> + <cstring>EncoderOutput</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>460</width> + <height>460</height> + </rect> + </property> + <property name="caption"> + <string>Encoder Output</string> + </property> + <property name="sizeGripEnabled"> + <bool>true</bool> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QTextEdit"> + <property name="name"> + <cstring>output</cstring> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + <property name="text"> + <string>The output....</string> + </property> + <property name="wordWrap"> + <enum>WidgetWidth</enum> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>Layout1</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <spacer> + <property name="name"> + <cstring>Horizontal Spacing2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>buttonOk</cstring> + </property> + <property name="text"> + <string>&OK</string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="autoDefault"> + <bool>true</bool> + </property> + <property name="default"> + <bool>true</bool> + </property> + </widget> + </hbox> + </widget> + </vbox> +</widget> +<connections> + <connection> + <sender>buttonOk</sender> + <signal>clicked()</signal> + <receiver>EncoderOutput</receiver> + <slot>accept()</slot> + </connection> +</connections> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/kaudiocreator/eventsrc b/kaudiocreator/eventsrc new file mode 100644 index 00000000..31ff062c --- /dev/null +++ b/kaudiocreator/eventsrc @@ -0,0 +1,528 @@ +[!Global!] +IconName=kaudiocreator +Comment=KAudioCreator +Comment[bn]=কে-অডিও-ক্রিয়েটার +Comment[cy]=KCreuyddSain +Comment[mk]=КАудиоКреатор +Comment[ne]=केडीई अडियो सर्जक +Comment[pa]=ਕੇ-ਆਡੀਓ-ਨਿਰਮਾਤਾ +Comment[sv]=Kaudiocreator +Comment[tg]=KОфарандаи Садо +Comment[tr]=Kaudiocreator + +[no jobs left] +Name=All jobs finished +Name[bg]=Всички задачи завършиха +Name[br]=Echu eo pep dlead +Name[bs]=Svi zadaci su završeni +Name[ca]=Han acabat tots els treballs +Name[cs]=Všechny úkoly dokončeny +Name[da]=Alle job færdige +Name[de]=Alle Aufgaben sind abgeschlossen. +Name[el]=Όλες οι εργασίες ολοκληρώθηκαν +Name[eo]=Ĉiuj taskoj finiĝis +Name[es]=Todos los trabajos finalizados +Name[et]=Kõik tööd lõpetatud +Name[eu]=Lan guztiak amaituta +Name[fa]=همۀ کارها تمام شد +Name[fi]=Kaikki työt ovat valmistuneet +Name[fr]=Toutes les tâches sont terminées +Name[gl]=Todos os traballos rematados +Name[he]=כל העבודות הסתיימו +Name[hu]=Az összes feladat befejeződött +Name[is]=Öllum verkum lokið +Name[it]=Tutti i processi sono terminati +Name[ja]=全ジョブ完了 +Name[kk]=Бүкіл тапсырмалар бітті +Name[km]=បានបញ្ចប់ការងារទាំងអស់ +Name[ko]=모든 작업 완료됨 +Name[lt]=Visi darbai baigti +Name[mk]=Сите задачи се завршени +Name[nb]=Alle jobbene er utført +Name[nds]=All Opgaven beendt +Name[ne]=सबै काम समाप्त भयो +Name[nl]=Alle taken voltooid +Name[nn]=Alle jobbar ferdige +Name[pa]=ਸਭ ਕੰਮ ਖਤਮ +Name[pl]=Wszystkie zadania ukończone +Name[pt]=Todos os trabalhos terminados +Name[pt_BR]=Todos os trabalhos finalizados +Name[ru]=Все задания выполнены +Name[sk]=Všetky úlohy skončili +Name[sl]=Vsa opravila zaključena +Name[sr]=Сви послови завршени +Name[sr@Latn]=Svi poslovi završeni +Name[sv]=Alla jobb är klara +Name[th]=งานทั้งหมดเสร็จสิ้น +Name[tr]=Tüm görevler tamamlandı +Name[uk]=Всі задачі виконано +Name[zh_CN]=全部任务都已完成 +Name[zh_HK]=工作全部完成 +Name[zh_TW]=所有工作均已完成 +Comment=All of the jobs in the queue have been finished +Comment[bg]=Всички задачи в опашката завършиха +Comment[br]=Echu eo pep dlead el lost +Comment[bs]=Svi zadaci u redu čekanja su završeni +Comment[ca]=Han acabat tots els treballs de la cua +Comment[cs]=Všechny úkoly ve frontě byly dokončeny +Comment[da]=Alle job i køen er færdige +Comment[de]=Alle Aufgaben der Warteschlange sind fertig. +Comment[el]=Όλες οι εργασίες της ουράς ολοκληρώθηκαν +Comment[es]=Se han terminado todos los trabajos de la cola +Comment[et]=Kõik järjekorras olnud tööd on lõpetatud +Comment[eu]=Ilarako lan guztiak amaitu dira +Comment[fa]=همۀ کارهای درون صف تمام شدهاند +Comment[fi]=Kaikki työt jonossa ovat valmistuneet +Comment[fr]=Toutes les tâches dans la file d'attente sont terminées +Comment[gl]=Atinxíronse todos os traballos na lista +Comment[he]=כל העבודות בתור הסתיימו +Comment[hu]=A sorban várakozó feladatok befejeződtek +Comment[is]=Öllum verkum í biðröð hefur verið lokið +Comment[it]=Tutti i processi in coda sono terminati +Comment[ja]=キューにある全ジョブが完了しました +Comment[kk]=Бүкіл кезектегі тапсырмалар бітті +Comment[km]=ការងារទាំងអស់នៅក្នុងជួរ ត្រូវបានបញ្ចប់ហើយ +Comment[ko]=큐에 있는 모든 작업이 완료됨 +Comment[lt]=Visi surikiuoti darbai atlikti +Comment[mk]=Сите задачи во редицата завршија +Comment[nb]=Alle jobbene i køen er utført +Comment[nds]=All Opgaven binnen de Töövreeg sünd beendt +Comment[ne]=लाममा रहेको सबै काम समाप्त भयो +Comment[nl]=Alle taken in de wachtrij zijn voltooid +Comment[nn]=Alle jobbane i køen er ferdige +Comment[pa]=ਕਤਾਰ ਵਿੱਚ ਸਭ ਕੰਮਾਂ ਨੂੰ ਖਤਮ ਕਰ ਦਿੱਤਾ ਗਿਆ ਹੈ +Comment[pl]=Wszystkie zadania z kolejko zostały ukończone +Comment[pt]=Todos os trabalhos em fila foram terminados +Comment[pt_BR]=Todos os trabalhos na fila foram finalizados +Comment[ru]=Все задания очереди завершены +Comment[sk]=Všetky úlohy v rade skončili +Comment[sl]=Vsa opravila iz vrste so bila zaključena +Comment[sr]=Сви послови из редоследа су завршени +Comment[sr@Latn]=Svi poslovi iz redosleda su završeni +Comment[sv]=Alla jobb i kön är klara +Comment[th]=งานทั้งหมดในคิวเสร็จหมดแล้ว +Comment[tr]=Listedeki tüm görevler tamamlandı. +Comment[uk]=Закінчено всі задачі в черзі +Comment[zh_CN]=队列中的全部任务都已完成 +Comment[zh_HK]=佇列中所有工作已完成 +Comment[zh_TW]=所有佇列中的工作都已完成 + +[track ripped] +Name=Track Ripped +Name[bg]=Запис на пътечка +Name[bn]=ট্র্যাক রিপ করা হয়েছে +Name[br]=Roudenn eztennet +Name[bs]=Numera ripovana +Name[ca]=Extractor de peces +Name[cs]=Stopa ripována +Name[cy]=Trac wedi'i Rhwygo +Name[da]=Spor rippet +Name[de]=Stück ausgelesen +Name[el]=Το κομμάτι εξήχθη +Name[es]=Pista extraida +Name[et]=Rada ripitud +Name[eu]=Pista erauztua +Name[fa]=شیار شکافته شد +Name[fi]=Kappale kopioitu +Name[fr]=Piste extraite +Name[ga]=Rian Sractha +Name[gl]=Pista Ext +Name[he]=רצועות נקרעו +Name[hu]=Hangsáv kimásolva +Name[is]=Lag afritað +Name[it]=Track compressa +Name[ja]=トラックのリッピング終了 +Name[kk]=Жолсызық оқып алынды +Name[km]=បានច្រៀកបទ +Name[ko]=트랙 추출됨 +Name[lt]=Takelis nurašytas +Name[mk]=Спуштена песна +Name[nb]=Spor innlest +Name[nds]=Stück utleest +Name[ne]=ट्रयाक काटियो +Name[nl]=Track geript +Name[nn]=Spor innlese +Name[pa]=ਟਰੈਕ ਰਿਪ +Name[pl]=Zgrany utwór +Name[pt]=Faixa Extraída +Name[pt_BR]=Faixa convertida +Name[ru]=Дорожка скопирована +Name[sl]=Skladba zajeta +Name[sr]=Нумера исчупана +Name[sr@Latn]=Numera isčupana +Name[sv]=Spår lagrat +Name[ta]=தடம் பிரிக்கப்பட்டது +Name[tg]=Шиор Канда шудааст +Name[th]=เพลงที่ทำการดึงข้อมูลแล้ว +Name[tr]=Parça Dönüştürüldü +Name[uk]=Витягнута доріжка +Name[zh_CN]=音轨已抓取 +Name[zh_HK]=已擷取的音軌 +Name[zh_TW]=音軌已擷取 +Comment=Track finished ripping +Comment[bg]=Завършване на запис на пътечка +Comment[bn]=ট্র্যাক রিপ করা শেষ +Comment[br]=Echu eo eztenniñ ar roudenn +Comment[bs]=Završeno ripovanje numere +Comment[ca]=Ha acabat l'extracció de la peça +Comment[cs]=Ripování stopy dokončeno +Comment[cy]=Wedi gorffen rhwygo'r trac +Comment[da]=Spor færdig med at blive rippet +Comment[de]=Das Stück ist fertig ausgelesen. +Comment[el]=Η εξαγωγή του κομματιού ολοκληρώθηκε +Comment[es]=Finalizó la extracción de la pista +Comment[et]=Raja rippimine lõpetatud +Comment[eu]=Pistaren erauzketa amaituta +Comment[fa]= شیار به شکافتن پایان داد +Comment[fi]=Kappaleen kaappaaminen valmis +Comment[fr]=Extraction de la piste terminée +Comment[gl]=Rematou a extracción da pista +Comment[he]=קריעת רצועות הסתיימה +Comment[hu]=A hangsáv kimásolása befejeződött +Comment[is]=Afritun lags lauk +Comment[it]=Estrazione traccia terminata +Comment[ja]=トラックのリッピングが終了しました +Comment[kk]=Жолсызықты оқып алу аяқталды +Comment[km]=បានបញ្ចប់ការច្រៀកបទ +Comment[ko]=트랙 추출 완료됨 +Comment[lt]=Takelio nurašymas baigėsi +Comment[mk]=Крај на спуштањето на песната +Comment[nb]=Spor ferdig innlest +Comment[nds]=Dat Stück wöör utleest +Comment[ne]=ट्रयाक कटाइ समाप्त भयो +Comment[nl]=Klaar met rippen van track +Comment[nn]=Spor ferdig innlese +Comment[pl]=Zakończono zgrywanie utworu +Comment[pt]=A faixa foi extraída +Comment[pt_BR]=Finalização da conversão da faixa +Comment[ru]=Копирование дорожки завершено +Comment[sk]=Dokončené ripovanie stopy +Comment[sl]=Zajemanje skladbe končano +Comment[sr]=Чупање нумере завршено +Comment[sr@Latn]=Čupanje numere završeno +Comment[sv]=Spåret har lagrats klart +Comment[ta]=தடம் பிரித்தலை முடித்தது +Comment[th]=เพลงที่ทำการดึงข้อมูลเสียงเสร็จแล้ว +Comment[tr]=Parçanın dönüştürülmesi tamamlandı +Comment[uk]=Витягування доріжки закінчено +Comment[zh_CN]=音轨抓取完成 +Comment[zh_HK]=已完成擷取的音軌 +Comment[zh_TW]=音軌已完成擷取 + +[cd ripped] +Name=CD Ripped +Name[bg]=Запис на аудио диск +Name[bn]=সিডি রিপ করা হয়েছে +Name[br]=CD eztennet +Name[bs]=CD ripovan +Name[ca]=Extractor de CD +Name[cs]=CD ripováno +Name[cy]=CD wedi'i Rhwygo +Name[da]=Cd rippet +Name[de]=CD ausgelesen +Name[el]=Το CD εξήχθη +Name[es]=CD extraido +Name[et]=CD ripitud +Name[eu]=CD-a erauztua +Name[fa]=دیسک فشرده شکافته شد +Name[fi]=CD kopioitu +Name[fr]=CD extrait +Name[ga]=CD Sractha +Name[gl]=CD Extraído +Name[he]=תקליטור נקרע +Name[hu]=CD kimásolva +Name[is]=Diskur afritaður +Name[it]=CD estratto +Name[ja]=CD のリッピング終了 +Name[kk]=CD оқып алынды +Name[km]=បានច្រៀកស៊ីឌី +Name[ko]=CD 추출됨 +Name[lt]=CD nurašytas +Name[mk]=CD-то е спуштено +Name[nb]=CD innlest +Name[nds]=CD utleest +Name[ne]=CD काटियो +Name[nl]=CD geript +Name[nn]=CD innlesen +Name[pa]=CD ਰਿਪ +Name[pl]=Zgrane CD +Name[pt]=CD Extraído +Name[pt_BR]=CD Convertido +Name[ru]=CD скопирован +Name[sk]=Ripovanie CD dokončené +Name[sl]=CD zajet +Name[sr]=CD је изгребован +Name[sr@Latn]=CD je izgrebovan +Name[sv]=Cd lagrad +Name[ta]=CD பிரிக்கப்பட்டது +Name[tg]=Диски Фишурда Канда шудааст +Name[th]=ซีดีบันทึกเสียงที่ทำการดึงข้อมูลแล้ว +Name[tr]=CD Dönüştürüldü +Name[uk]=Витягнутий музичний КД +Name[uz]=Kompakt-disk ripper +Name[uz@cyrillic]=Компакт-диск риппер +Name[zh_CN]=CD 已抓取 +Name[zh_HK]=已擷取的 CD +Name[zh_TW]=光碟已擷取 +Comment=CD finished ripping +Comment[bg]=Завършване на запис на аудио диск +Comment[bn]=সিডি রিপ করা শেষ +Comment[br]=Echu eo eztenniñ ar CD +Comment[bs]=Završeno ripovanje CDa +Comment[ca]=Ha acabat l'extracció del CD +Comment[cs]=Ripování CD dokončeno +Comment[cy]=Wedi gorffen rhwygo'r CD +Comment[da]=Cd færdig med at blive rippet +Comment[de]=Die CD ist fertig ausgelesen. +Comment[el]=Η εξαγωγή του CD ολοκληρώθηκε +Comment[es]=Finalizó la extracción del CD +Comment[et]=CD rippimine lõpetatud +Comment[eu]=CD-aren erauztea amaituta +Comment[fa]=دیسک فشرده به شکافتن پایان داد +Comment[fi]=CD:n kaappaaminen valmis +Comment[fr]=extraction du CD terminée +Comment[gl]=Rematou a extracción do CD +Comment[he]=קריעת תקליטור הסתיימה +Comment[hu]=A CD kimásolása befejeződött +Comment[is]=Afritun disks lauk +Comment[it]=Estrazione CD terminata +Comment[ja]=CD のリッピングが終了しました +Comment[kk]=CD оқып алуы аяқталды +Comment[km]=បានបញ្ចប់ការច្រៀកស៊ីឌី +Comment[ko]=CD 추출 완료됨 +Comment[lt]=CD nurašymas baigtas +Comment[mk]=Крај на спуштањето на CD +Comment[nb]=CD ferdig innlest +Comment[nds]=De CD wöör utleest +Comment[ne]=CD कटाइ समाप्त भयो +Comment[nl]=Klaar met rippen van cd +Comment[nn]=CD ferdig innlesen +Comment[pa]=CD ਰਪਿੰਗ ਖਤਮ +Comment[pl]=Zakończono zgrywanie CD +Comment[pt]=O CD foi extraído +Comment[pt_BR]=Finalização da conversão do CD +Comment[ru]=Копирование CD завершено +Comment[sk]=Dokončené ripovanie CD +Comment[sl]=Zajemanje CD-ja končano +Comment[sr]=Гребовање CD-а је завршено +Comment[sr@Latn]=Grebovanje CD-a je završeno +Comment[sv]=Cd:n har lagrats klart +Comment[ta]=CD பிரித்தல் முடிந்தது +Comment[th]=ซีดีบันทึกเสียงที่ทำการดึงข้อมูลเสร็จแล้ว +Comment[tr]=CD dönüştürme işlemi tamamlandı +Comment[uk]=Видирання КД завершено +Comment[zh_CN]=CD 抓取完成 +Comment[zh_HK]=已完成擷取的 CD +Comment[zh_TW]=光碟已完成擷取 + +[track encoded] +Name=Track Encoded +Name[bg]=Кодиране на пътечка +Name[bn]=ট্র্যাক এনকোড করা হয়েছে +Name[br]=Roudenn kodet +Name[bs]=Numera kodirana +Name[ca]=Codificador de peces +Name[cs]=Stopa převedena +Name[cy]=Trac wedi'i Amgodio +Name[da]=Spor indkodet +Name[de]=Stück kodiert +Name[el]=Το κομμάτι κωδικοποιήθηκε +Name[eo]=Trako kodigita +Name[es]=Pista codificada +Name[et]=Rada kodeeritud +Name[eu]=Pista kodetuta +Name[fa]=شیار کدبندی شد +Name[fi]=Kappale koodattu +Name[fr]=Piste encodée +Name[ga]=Rian Ionchódaithe +Name[gl]=Pista Codificada +Name[he]=רצועות קודדו +Name[hu]=Hangsáv kódolása kész +Name[is]=Lag kóðað +Name[it]=Traccia codificata +Name[ja]=トラックのエンコード終了 +Name[kk]=Жолсызық қалыптастырылды +Name[km]=បានអ៊ិនកូដបទ +Name[ko]=트랙 인코딩됨 +Name[lt]=Takelis įkoduotas +Name[mk]=Кодирање на песната +Name[nb]=Spor koda +Name[nds]=Stück kodeert +Name[ne]=ट्रयाक सङ्केतन गरियो +Name[nl]=Track gecodeerd +Name[nn]=Spor koda +Name[pa]=ਟਰੈਕ ਇੰਕੋਡਿੰਡ +Name[pl]=Utwór zakodowany +Name[pt]=Faixa Codificada +Name[pt_BR]=Faixa codificada +Name[ro]=Pistă codată +Name[ru]=Дорожка преобразована +Name[sk]=Ripovanie stopy dokončené +Name[sl]=Skladba kodirana +Name[sr]=Нумера је искодирана +Name[sr@Latn]=Numera je iskodirana +Name[sv]=Spår kodat +Name[ta]=தடம் மறையாக்கப்பட்டது +Name[tg]=Шиор Рамзӣ кунонида шудааст +Name[th]=เพลงที่เข้ารหัสแล้ว +Name[tr]=Parça Dönüştürücü +Name[uk]=Закодована доріжка +Name[zh_CN]=音轨已编码 +Name[zh_HK]=已編碼的音軌 +Name[zh_TW]=音軌已編碼 +Comment=Track finished encoding +Comment[bg]=Завършване на кодиране на пътечка +Comment[bn]=ট্র্যাক এনকোডিং করা শেষ +Comment[bs]=Završeno kodiranje numere +Comment[ca]=Ha acabat la codificació de la peça +Comment[cs]=Převod stopy dokončen +Comment[cy]=Wedi gorffen amgodio'r trac +Comment[da]=Spor færdig med at blive indkodet +Comment[de]=Das Stück ist fertig kodiert. +Comment[el]=Τέλος κωδικοποίησης κομματιού +Comment[eo]=Kodigo de trako finiĝis +Comment[es]=Finalizó la codificación de la pista +Comment[et]=Raja kodeerimine lõpetatud +Comment[eu]=Pistaren kodetzea amaituta +Comment[fa]=شیار به کدبندی پایان داد +Comment[fi]=Kappaleen koodaaminen valmis +Comment[fr]=Encodage de la piste terminé +Comment[gl]=Rematou a codificación da pista +Comment[he]=קידוד רצועה הסתיים +Comment[hu]=A hangsáv kódolása befejeződött +Comment[is]=Kóðun lags lauk +Comment[it]=Codifica traccia terminata +Comment[ja]=トラックのエンコードが終了しました +Comment[kk]=Жолсызықты қалыптастыру аяқталды +Comment[km]=បានបញ្ចប់ការអ៊ិនកូដបិទ +Comment[ko]=트랙 인코딩 완료됨 +Comment[lt]=Takelio įkodavimas baigtas +Comment[mk]=Заврши кодирањето на песната +Comment[nb]=Spor ferdig koda +Comment[nds]=Dat Stück wöör kodeert +Comment[ne]=ट्रयाक सङ्केतन समाप्त भयो +Comment[nl]=Klaar met coderen van track +Comment[nn]=Spor ferdig koda +Comment[pa]=ਟਰੈਕ ਮੁਕੰਮਲ ਇੰਕੋਡਿੰਗ +Comment[pl]=Zakończono kodowanie utworu +Comment[pt]=A faixa foi codificada +Comment[pt_BR]=Finalização da codificação da faixa +Comment[ru]=Преобразование дорожки завершено +Comment[sk]=Dokončené kódovanie stopy +Comment[sl]=Kodiranje skladbe končano +Comment[sr]=Кодирање нумере је завршено +Comment[sr@Latn]=Kodiranje numere je završeno +Comment[sv]=Spåret har kodats klart +Comment[ta]=தடம் மறையாக்கத்தை முடித்தது +Comment[th]=เพลงที่ทำการเข้ารหัสเสร็จแล้ว +Comment[tr]=Parça kodlama bitirildi +Comment[uk]=Кодування доріжки закінчене +Comment[zh_CN]=音轨编码完成 +Comment[zh_HK]=已完成編碼的音軌 +Comment[zh_TW]=音軌已完成編碼 + +[cd encoded] +Name=CD Encoded +Name[bg]=Кодиране на аудио диск +Name[bn]=সিডি এনকোড করা হয়েছে +Name[br]=CD kodet +Name[bs]=CD kodiran +Name[ca]=Codificador de CD +Name[cs]=CD převedeno +Name[cy]=CD wedi'i Amgodio +Name[da]=Cd indkodet +Name[de]=CD kodiert +Name[el]=Το CD κωδικοποιήθηκε +Name[es]=CD codificado +Name[et]=CD kodeeritud +Name[eu]=CD-a kodetuta +Name[fa]=دیسک فشرده کدبندی شد +Name[fi]=CD koodattu +Name[fr]=CD encodé +Name[ga]=CD Ionchódaithe +Name[gl]=CD Codificado +Name[he]=תקליטור קודד +Name[hu]=CD kódolása kész +Name[is]=Diskur kóðaður +Name[it]=CD codificato +Name[ja]=CD のエンコード終了 +Name[kk]=CD қалыптастырылды +Name[km]=បានអ៊ិនកូដស៊ីឌី +Name[ko]=CD 인코딩됨 +Name[lt]=CD įkoduotas +Name[mk]=Кодирано CD +Name[nb]=CD koda +Name[nds]=CD kodeert +Name[ne]=CD सङ्केतन गरियो +Name[nl]=CD gecodeerd +Name[nn]=CD koda +Name[pa]=CD ਇੰਕੋਡਿੰਡ +Name[pl]=Zakodowane CD +Name[pt]=CD Codificado +Name[pt_BR]=CD Codificado +Name[ro]=CD codat +Name[ru]=Преобразование CD завершено +Name[sk]=CD zakódované +Name[sl]=CD kodiran +Name[sr]=CD је искодиран +Name[sr@Latn]=CD je iskodiran +Name[sv]=Cd kodad +Name[ta]=CD மறையாக்கப்பட்டது +Name[tg]=Диски Фишурда Рамзӣ кунонида шудааст +Name[th]=ซีดีที่ทำการเข้ารหัส +Name[tr]=CD Dönüştürücü +Name[uk]=Закодовано КД +Name[zh_CN]=CD 已编码 +Name[zh_HK]=已編碼的 CD +Name[zh_TW]=光碟已編碼 +Comment=CD finished encoding +Comment[bg]=Завършване на кодиране на аудио диск +Comment[bn]=সিডি এনকোডিং করা শেষ +Comment[bs]=Završeno kodiranje CDa +Comment[ca]=Ha acabat la codificació del CD +Comment[cs]=Převod CD dokončen +Comment[cy]=Wedi gorffen amgodio'r CD +Comment[da]=Cd færdig med at blive indkodet +Comment[de]=Die CD ist fertig kodiert. +Comment[el]=Τέλος κωδικοποίησης CD +Comment[es]=Finalizó la codificación del CD +Comment[et]=CD kodeerimine lõpetatud +Comment[eu]=CD-aren kodetzea amaituta +Comment[fa]=دیسک فشرده به کدبندی پایان داد +Comment[fi]=CD:n koodaaminen valmis +Comment[fr]=Encodage du CD terminé +Comment[gl]=Rematou a codificación do CD +Comment[he]=קידוד תקליטור הסתיים +Comment[hu]=A CD kódolása befejeződött +Comment[is]=Kóðun disks lauk +Comment[it]=Codifica CD terminata +Comment[ja]=CD のエンコードが終了しました +Comment[kk]=CD қалыптастыру аяқталды +Comment[km]=បានបញ្ចប់ការអ៊ិនកូដស៊ីឌី +Comment[ko]=CD 인코딩 완료됨 +Comment[lt]=CD įkodavimas baigtas +Comment[mk]=Заврши кодирањето на CD-то +Comment[nb]=CD ferdig koda +Comment[nds]=De CD wöör kodeert +Comment[ne]=CD सङ्केतन समाप्त भयो +Comment[nl]=Klaar met coderen van cd +Comment[nn]=CD ferdig koda +Comment[pa]=CD ਮੁਕਮੰਲ ਇੰਕੋਡਿੰਗ +Comment[pl]=Zakończono kodowanie CD +Comment[pt]=O CD foi codificado +Comment[pt_BR]=Finalização da codificação do CD +Comment[ru]=Преобразование диска завершено +Comment[sk]=Dokončené kódovanie CD +Comment[sl]=Kodiranje CD-ja končano +Comment[sr]=Кодирање CD-а је завршено +Comment[sr@Latn]=Kodiranje CD-a je završeno +Comment[sv]=Cd:n har kodats klart +Comment[ta]=CD மறையாக்கத்தை முடித்தது. +Comment[th]=ซีดีที่ทำการเข้ารหัสเสร็จแล้ว +Comment[tr]=CD çözümleyici sonlandırıldı +Comment[uk]=Кодування КД закінчено +Comment[zh_CN]=CD 编码完成 +Comment[zh_HK]=已完成編碼的 CD +Comment[zh_TW]=光碟已完成編碼 +default_presentation=17 +default_sound=KDE_Beep_ClockChime.wav diff --git a/kaudiocreator/general.ui b/kaudiocreator/general.ui new file mode 100644 index 00000000..f20fea5b --- /dev/null +++ b/kaudiocreator/general.ui @@ -0,0 +1,285 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>General</class> +<widget class="QWidget"> + <property name="name"> + <cstring>General</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>442</width> + <height>473</height> + </rect> + </property> + <property name="caption"> + <string>General</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_removeCompletedJobs</cstring> + </property> + <property name="text"> + <string>&Automatically remove jobs when finished</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_promptIfIncompleteInfo</cstring> + </property> + <property name="text"> + <string>Prompt if information is not complete</string> + </property> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox2</cstring> + </property> + <property name="title"> + <string>File Regular Expression Replacement</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>Selection:</string> + </property> + </widget> + <widget class="QLabel" row="0" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Regular expression used on all file names. For example using selection " " and replace with "_" would replace all the spaces with underlines. +</string> + </property> + <property name="alignment"> + <set>WordBreak|AlignVCenter</set> + </property> + </widget> + <widget class="QLabel" row="5" column="0"> + <property name="name"> + <cstring>inputlabel</cstring> + </property> + <property name="text"> + <string>Input:</string> + </property> + </widget> + <widget class="QLabel" row="6" column="0"> + <property name="name"> + <cstring>outputLabel</cstring> + </property> + <property name="text"> + <string>Output:</string> + </property> + </widget> + <widget class="QLabel" row="4" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>exampleLabel</cstring> + </property> + <property name="text"> + <string>Example</string> + </property> + </widget> + <widget class="QLabel" row="6" column="1" rowspan="1" colspan="2"> + <property name="name"> + <cstring>exampleOutput</cstring> + </property> + <property name="text"> + <string>Cool artist - example audio file.wav</string> + </property> + </widget> + <widget class="QLineEdit" row="5" column="1" rowspan="1" colspan="2"> + <property name="name"> + <cstring>example</cstring> + </property> + <property name="text"> + <string>Cool artist - example audio file.wav</string> + </property> + </widget> + <widget class="QLineEdit" row="2" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>kcfg_replaceInput</cstring> + </property> + </widget> + <widget class="QLineEdit" row="2" column="2"> + <property name="name"> + <cstring>kcfg_replaceOutput</cstring> + </property> + </widget> + <widget class="QLabel" row="1" column="2"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="text"> + <string>Replace with:</string> + </property> + </widget> + <widget class="Line" row="3" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>line1</cstring> + </property> + <property name="frameShape"> + <enum>HLine</enum> + </property> + <property name="frameShadow"> + <enum>Sunken</enum> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + </widget> + </grid> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>kcfg_seperateMultiArtist</cstring> + </property> + <property name="title"> + <string>Automatically Separate Multi-Artist CDDB Entries</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QButtonGroup"> + <property name="name"> + <cstring>buttonGroup2</cstring> + </property> + <property name="title"> + <string>Format</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QRadioButton"> + <property name="name"> + <cstring>kcfg_format_titleArtist</cstring> + </property> + <property name="text"> + <string>Title - Artist</string> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>kcfg_format_artistTitle</cstring> + </property> + <property name="text"> + <string>Artist - Title</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </vbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout1</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>delimiterLabel</cstring> + </property> + <property name="text"> + <string>Delimiter:</string> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>genArtistLabel</cstring> + </property> + <property name="text"> + <string>Generic artist:</string> + </property> + </widget> + <widget class="QLineEdit" row="1" column="1"> + <property name="name"> + <cstring>kcfg_delimiter</cstring> + </property> + </widget> + <widget class="QLineEdit" row="0" column="1"> + <property name="name"> + <cstring>kcfg_genericArtist</cstring> + </property> + </widget> + </grid> + </widget> + </hbox> + </widget> + <spacer> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>16</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<connections> + <connection> + <sender>kcfg_replaceInput</sender> + <signal>textChanged(const QString&)</signal> + <receiver>General</receiver> + <slot>updateExample()</slot> + </connection> + <connection> + <sender>kcfg_replaceOutput</sender> + <signal>textChanged(const QString&)</signal> + <receiver>General</receiver> + <slot>updateExample()</slot> + </connection> + <connection> + <sender>example</sender> + <signal>textChanged(const QString&)</signal> + <receiver>General</receiver> + <slot>updateExample()</slot> + </connection> +</connections> +<tabstops> + <tabstop>kcfg_replaceInput</tabstop> + <tabstop>kcfg_replaceOutput</tabstop> + <tabstop>example</tabstop> + <tabstop>kcfg_removeCompletedJobs</tabstop> +</tabstops> +<includes> + <include location="local" impldecl="in implementation">general.ui.h</include> +</includes> +<slots> + <slot access="protected" specifier="non virtual">updateExample()</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/kaudiocreator/general.ui.h b/kaudiocreator/general.ui.h new file mode 100644 index 00000000..c54af842 --- /dev/null +++ b/kaudiocreator/general.ui.h @@ -0,0 +1,19 @@ +/**************************************************************************** +** ui.h extension file, included from the uic-generated form implementation. +** +** If you wish to add, delete or rename functions or slots use +** Qt Designer which will update this file, preserving your code. Create an +** init() function in place of a constructor, and a destroy() function in +** place of a destructor. +*****************************************************************************/ + +#include <qregexp.h> +#include <qlineedit.h> +#include <qlabel.h> + +void General::updateExample() +{ + QString text = example->text(); + text.replace( QRegExp(kcfg_replaceInput->text()), kcfg_replaceOutput->text() ); + exampleOutput->setText(text); +} diff --git a/kaudiocreator/hi16-app-kaudiocreator.png b/kaudiocreator/hi16-app-kaudiocreator.png Binary files differnew file mode 100644 index 00000000..8b65f1b1 --- /dev/null +++ b/kaudiocreator/hi16-app-kaudiocreator.png diff --git a/kaudiocreator/hi32-app-kaudiocreator.png b/kaudiocreator/hi32-app-kaudiocreator.png Binary files differnew file mode 100644 index 00000000..ed12f257 --- /dev/null +++ b/kaudiocreator/hi32-app-kaudiocreator.png diff --git a/kaudiocreator/icons/Makefile.am b/kaudiocreator/icons/Makefile.am new file mode 100644 index 00000000..8ac79054 --- /dev/null +++ b/kaudiocreator/icons/Makefile.am @@ -0,0 +1,4 @@ + +icondir = $(kde_datadir)/kaudiocreator/pics +icon_DATA = check.png + diff --git a/kaudiocreator/icons/check.png b/kaudiocreator/icons/check.png Binary files differnew file mode 100644 index 00000000..2890a7a4 --- /dev/null +++ b/kaudiocreator/icons/check.png diff --git a/kaudiocreator/infodialog.ui b/kaudiocreator/infodialog.ui new file mode 100644 index 00000000..a488e3dc --- /dev/null +++ b/kaudiocreator/infodialog.ui @@ -0,0 +1,297 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>AlbumEditor</class> +<widget class="QDialog"> + <property name="name"> + <cstring>AlbumEditor</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>423</width> + <height>365</height> + </rect> + </property> + <property name="caption"> + <string>Album Editor</string> + </property> + <property name="sizeGripEnabled"> + <bool>true</bool> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox2</cstring> + </property> + <property name="title"> + <string>Current Track</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="2" column="0" rowspan="2" colspan="1"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>Comment:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLineEdit" row="3" column="1"> + <property name="name"> + <cstring>track_comment</cstring> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>trackLabel</cstring> + </property> + <property name="text"> + <string>Title:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + <property name="hAlign" stdset="0"> + </property> + </widget> + <widget class="QLineEdit" row="1" column="1" rowspan="2" colspan="1"> + <property name="name"> + <cstring>track_title</cstring> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="text"> + <string>Artist:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLineEdit" row="0" column="1"> + <property name="name"> + <cstring>track_artist</cstring> + </property> + </widget> + </grid> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox1</cstring> + </property> + <property name="title"> + <string>Album</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLineEdit" row="1" column="1"> + <property name="name"> + <cstring>artist</cstring> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>TextLabel5</cstring> + </property> + <property name="text"> + <string>Artist:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + <property name="hAlign" stdset="0"> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>TextLabel6</cstring> + </property> + <property name="text"> + <string>Album:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + <property name="hAlign" stdset="0"> + </property> + </widget> + <widget class="QLineEdit" row="2" column="1"> + <property name="name"> + <cstring>album</cstring> + </property> + </widget> + <widget class="QSpinBox" row="3" column="1"> + <property name="name"> + <cstring>year</cstring> + </property> + <property name="maxValue"> + <number>99999</number> + </property> + </widget> + <widget class="QLabel" row="3" column="0"> + <property name="name"> + <cstring>TextLabel7</cstring> + </property> + <property name="text"> + <string>Year:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + <property name="hAlign" stdset="0"> + </property> + </widget> + <widget class="QLabel" row="4" column="0"> + <property name="name"> + <cstring>TextLabel1</cstring> + </property> + <property name="text"> + <string>Genre:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + <property name="hAlign" stdset="0"> + </property> + </widget> + <widget class="QComboBox" row="4" column="1"> + <property name="name"> + <cstring>genre</cstring> + </property> + </widget> + <widget class="QLabel" row="5" column="0"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Comment:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLineEdit" row="5" column="1"> + <property name="name"> + <cstring>comment</cstring> + </property> + </widget> + </grid> + </widget> + <spacer> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>100</height> + </size> + </property> + </spacer> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout2</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QPushButton"> + <property name="name"> + <cstring>buttonPrevious</cstring> + </property> + <property name="text"> + <string>&Previous Track</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>buttonNext</cstring> + </property> + <property name="text"> + <string>&Next Track</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>buttonOk</cstring> + </property> + <property name="text"> + <string>&OK</string> + </property> + <property name="autoDefault"> + <bool>true</bool> + </property> + <property name="default"> + <bool>true</bool> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>buttonCancel</cstring> + </property> + <property name="text"> + <string>&Cancel</string> + </property> + <property name="autoDefault"> + <bool>true</bool> + </property> + </widget> + </hbox> + </widget> + </vbox> +</widget> +<connections> + <connection> + <sender>buttonOk</sender> + <signal>clicked()</signal> + <receiver>AlbumEditor</receiver> + <slot>accept()</slot> + </connection> + <connection> + <sender>buttonCancel</sender> + <signal>clicked()</signal> + <receiver>AlbumEditor</receiver> + <slot>reject()</slot> + </connection> +</connections> +<tabstops> + <tabstop>track_artist</tabstop> + <tabstop>track_title</tabstop> + <tabstop>track_comment</tabstop> + <tabstop>artist</tabstop> + <tabstop>album</tabstop> + <tabstop>year</tabstop> + <tabstop>genre</tabstop> + <tabstop>comment</tabstop> + <tabstop>buttonPrevious</tabstop> + <tabstop>buttonNext</tabstop> + <tabstop>buttonOk</tabstop> + <tabstop>buttonCancel</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/kaudiocreator/job.cpp b/kaudiocreator/job.cpp new file mode 100644 index 00000000..159b6ebb --- /dev/null +++ b/kaudiocreator/job.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2003 Waldo Bastian <bastian@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + **/ + +#include "job.h" +#include <kmacroexpander.h> +#include <qregexp.h> + +/** + * A helper function to replace %X with the stuff in the album. + * if quote is true then put "" around the %X + */ +QString Job::replaceSpecialChars(const QString &string, bool quote, QMap<QString, QString> _map){ + QMap<QString,QString> map = _map; + + map.insert("title", track_title); + map.insert("artist", track_artist); + map.insert("number", QString().sprintf("%02d", track)); + map.insert("comment", track_comment); + map.insert("year", QString::number(year)); + map.insert("genre", genre); + + map.insert("albumtitle", album); + map.insert("albumcomment", comment); + map.insert("albumartist", group); + + if (quote) + return (KMacroExpander::expandMacrosShellQuote(string, map)); + else + return (KMacroExpander::expandMacros(string, map)); +} + +void Job::fix(const QString &in, const QString &out){ + track_title.replace( QRegExp(in), out ); + track_artist.replace( QRegExp(in), out ); + track_comment.replace( QRegExp(in), out ); + // year + // track + genre.replace( QRegExp(in), out ); + album.replace( QRegExp(in), out ); + comment.replace( QRegExp(in), out ); + group.replace( QRegExp(in), out ); +} + diff --git a/kaudiocreator/job.h b/kaudiocreator/job.h new file mode 100644 index 00000000..e0a4d577 --- /dev/null +++ b/kaudiocreator/job.h @@ -0,0 +1,78 @@ +/** + * This file is part of the KAudioCreator package + * Copyright (C) 2003 Benjamin C Meyer (ben+kaudiocreator at meyerhome dot net) + * + * 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 library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef JOB_H +#define JOB_H + +#include <qmap.h> +#include <klocale.h> + +/** + * The job class is what is passed around the system. All of the data about + * the file being ripped and encoded is stored in here. + */ +class Job{ + +public: + inline Job():id(-1),track_title(""),track_artist(""), track(-1),track_comment(""), year(-1), genre(i18n("Other")), group(""), album(""), comment(""), lastSongInAlbum(false), removeTempFile(true), encoder(-1) {}; + + QString replaceSpecialChars(const QString &string, bool quote, QMap<QString,QString> map); + + void fix( const QString &in, const QString &out ); + + // The device to obtain the file such as /dev/cdrom/ (Used when ripping and ejecting) + QString device; + int id; + + QString track_title; + QString track_artist; + int track; + QString track_comment; + int year; + QString genre; + + QString group; + QString album; + QString comment; + + // Currently location of file X + QString location; + + // New location of a file after current opertation is complete (rip/encode). + QString newLocation; + + // What was just attempted to do via this job and is spit out in the event + // of an error. + QString errorString; + + // If this is the last track to be ripped then value is true. + bool lastSongInAlbum; + + // If the file should be removed when finished encoding + bool removeTempFile; + + // output from the processing. + QString output; + + int encoder; +}; + +#endif // JOB_H + diff --git a/kaudiocreator/jobque.ui b/kaudiocreator/jobque.ui new file mode 100644 index 00000000..137ed6df --- /dev/null +++ b/kaudiocreator/jobque.ui @@ -0,0 +1,132 @@ +<!DOCTYPE UI><UI version="3.1" stdsetdef="1"> +<class>JobQue</class> +<widget class="QWidget"> + <property name="name"> + <cstring>JobQue</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>629</width> + <height>513</height> + </rect> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QPushButton" row="2" column="2"> + <property name="name"> + <cstring>removeAll</cstring> + </property> + <property name="text"> + <string>Remove All Jobs</string> + </property> + </widget> + <widget class="QPushButton" row="2" column="3"> + <property name="name"> + <cstring>removeSelected</cstring> + </property> + <property name="text"> + <string>Remove Selected Jobs</string> + </property> + </widget> + <spacer row="2" column="0"> + <property name="name"> + <cstring>Spacer2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>16</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QListView" row="1" column="0" rowspan="1" colspan="4"> + <column> + <property name="text"> + <string>Job</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Progress</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Description</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <property name="name"> + <cstring>todoQue</cstring> + </property> + <property name="selectionMode"> + <enum>Multi</enum> + </property> + <property name="allColumnsShowFocus"> + <bool>true</bool> + </property> + <property name="resizeMode"> + <enum>LastColumn</enum> + </property> + </widget> + <widget class="QLabel" row="0" column="0" rowspan="1" colspan="4"> + <property name="name"> + <cstring>queLabel</cstring> + </property> + <property name="text"> + <string>No jobs are in the queue</string> + </property> + <property name="alignment"> + <set>AlignCenter</set> + </property> + <property name="hAlign" stdset="0"> + </property> + </widget> + <widget class="QPushButton" row="2" column="1"> + <property name="name"> + <cstring>removeDoneJobs</cstring> + </property> + <property name="text"> + <string>Remove Completed Jobs</string> + </property> + </widget> + </grid> +</widget> +<tabstops> + <tabstop>todoQue</tabstop> + <tabstop>removeDoneJobs</tabstop> + <tabstop>removeAll</tabstop> + <tabstop>removeSelected</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/kaudiocreator/jobqueimp.cpp b/kaudiocreator/jobqueimp.cpp new file mode 100644 index 00000000..e9d8fa5a --- /dev/null +++ b/kaudiocreator/jobqueimp.cpp @@ -0,0 +1,310 @@ +/** + * This file is part of the KAudioCreator package + * Copyright (C) 2003 Benjamin C Meyer (ben+kaudiocreator at meyerhome dot net) + * + * 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 library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "jobqueimp.h" +#include "job.h" +#include "prefs.h" +#include <qpushbutton.h> +#include <qlabel.h> +#include <qpainter.h> +#include <kconfig.h> +#include <kglobal.h> +#include <kdebug.h> +#include <kiconloader.h> +#include <kmessagebox.h> +#include <kurl.h> +#include <qfile.h> +#include <qregexp.h> +#include <qfileinfo.h> +#include <kstandarddirs.h> +#include <knotifyclient.h> +#include <qdir.h> + +#define HEADER_JOB 0 +#define HEADER_PROGRESS 1 +#define HEADER_DESCRIPTION 2 +#define ICON_LOC HEADER_DESCRIPTION + +#define DEFAULT_HIGHEST_NUMBER 9 + +/** + * Constructor, set up signals. + * @param parent - parent widget + * @param name - widget name + */ +JobQueImp::JobQueImp( QWidget* parent, const char* name) : + JobQue(parent,name),highestNumber(DEFAULT_HIGHEST_NUMBER), currentId(0){ + connect(removeSelected,SIGNAL(clicked()), this, SLOT( removeSelectedJob())); + connect(removeAll, SIGNAL(clicked()), this, SLOT(removeAllJobs())); + connect(removeDoneJobs, SIGNAL(clicked()), this, SLOT(clearDoneJobs())); +} + +/** + * Return a buffer of "000" so that new, updated jobs strings will be able to + * sort via the columns. + * Based upon a highest number that is kept. + * @param number the number to fill out. + */ +QString JobQueImp::getStringFromNumber(int number){ + if(number > highestNumber){ + int diff = QString("%1").arg(number).length() - QString("%1").arg(highestNumber).length(); + highestNumber = number; + if(diff > 0){ + // We have to update all of the cells. + QueListViewItem * currentItem = (QueListViewItem*)todoQue->firstChild(); + while( currentItem != NULL ){ + currentItem->setText(HEADER_JOB, "0" + currentItem->text(HEADER_JOB)); + currentItem = (QueListViewItem*)currentItem->itemBelow(); + } + } + } + + QString buffer = ""; + uint newLength = QString("%1").arg(highestNumber).length() - QString("%1").arg(number).length(); + for(uint i=0; i < newLength; i++) + buffer += "0"; + return buffer; +} + +/** + * Add a new job to the que + * @param id the id of the job. + * @param name the name of the job. + */ +void JobQueImp::addJob(Job*job, const QString &name ){ + if(!job) + return; + job->id = ++currentId; + QueListViewItem *currentItem = new QueListViewItem(todoQue, QString("%1%2").arg(getStringFromNumber(currentId)).arg(currentId), "0", name); + currentItem->setPixmap(ICON_LOC, SmallIcon("player_pause", currentItem->height()-2)); + queLabel->setText(i18n("Number of jobs in the queue: %1").arg(todoQue->childCount())); +} + +/** + * Locate the job and update the progress. + * @param id the id of the job to update + * @param progress the new progress of the job. + */ +void JobQueImp::updateProgress(int id, int progress){ + int currentJobCount = numberOfJobsNotFinished(); + QueListViewItem * currentItem = (QueListViewItem*)todoQue->firstChild(); + QString buffer = getStringFromNumber(id); + buffer += QString("%1").arg(id); + + // Find the current item + while( currentItem != NULL ){ + if(currentItem->text(HEADER_JOB) == buffer) + break; + currentItem = (QueListViewItem*)currentItem->nextSibling(); + } + if( !currentItem ){ + kdDebug(60002) << "JobQueImp::updateProgress An update was received about a job, but the job couldn't be found: " << id << endl; + return; + } + + // Only update the % if it changed. + if(currentItem->percentDone == progress) + return; + + currentItem->percentDone = progress; + currentItem->repaint(); + + // Update the icon if needed + if(progress > 0 && progress < 100 && !currentItem->progressing ){ + currentItem->setPixmap(ICON_LOC, SmallIcon("gear", currentItem->height()-2)); + currentItem->progressing = true; + } + else if(progress == -1){ + currentItem->setPixmap(ICON_LOC, SmallIcon("button_cancel", currentItem->height()-2)); + } + else if(progress == 100){ + // Remove the job if requested. + if(Prefs::removeCompletedJobs()){ + removeJob(currentItem, false); + return; + } + currentItem->setPixmap(ICON_LOC, SmallIcon("button_ok", currentItem->height())); + } + if(currentJobCount > 0 && numberOfJobsNotFinished() == 0) + KNotifyClient::event("no jobs left"); +} + +/** + * Remove job listed in item + * @param item to remove. Note that it WILL be deleted and set to NULL. + * @param kill kill the actual job/process. A bool here because this CAN cause + * a race condition when the encoder is 100%, but hasn't exited. + * @param prompt the user if the job isn't finished + * @return bool if remove was successfull or not. + */ +bool JobQueImp::removeJob(QueListViewItem *item, bool kill, bool prompt){ + if(!item) + return false; + + if(item->percentDone < 100 && item->percentDone > -1 && (prompt && KMessageBox::questionYesNo(this, i18n("KAudioCreator has not finished %1. Remove anyway?").arg(item->text(HEADER_DESCRIPTION)), i18n("Unfinished Job in Queue"), KStdGuiItem::del(), i18n("Keep")) + == KMessageBox::No )) + return false; + + // "Thread" safe + if(!item) + return false; + + if(kill) + emit (removeJob(item->text(HEADER_JOB).toInt())); + + todoQue->takeItem(item); + delete(item); + item = NULL; + + // See if the Que needs to be updated... + if(todoQue->childCount() == 0){ + queLabel->setText(i18n("No jobs are in the queue")); + highestNumber = DEFAULT_HIGHEST_NUMBER; + currentId = 0; + } + else + queLabel->setText(i18n("Number of jobs in the queue: %1").arg(todoQue->childCount())); + return true; +} + +/** + * Remove the currently selected Job + */ +void JobQueImp::removeSelectedJob(){ + QueListViewItem * currentItem = (QueListViewItem*)todoQue->firstChild(); + while(currentItem != NULL){ + if(currentItem->isSelected()){ + QueListViewItem *t = currentItem; + currentItem = (QueListViewItem*)currentItem->nextSibling(); + removeJob(t); + } + else + currentItem = (QueListViewItem*)currentItem->nextSibling(); + } +} + +/** + * Remove all of the jobs in the list. + */ +void JobQueImp::removeAllJobs(){ + // First determine if there are jobs not finished and prompt once here + bool finished=true; + QueListViewItem * item = (QueListViewItem*)todoQue->firstChild(); + while( item != NULL ){ + if(item && item->percentDone < 100 && item->percentDone > -1) + finished = false; + item = (QueListViewItem*)item->nextSibling(); + } + if(!finished){ + if(KMessageBox::questionYesNo(this, i18n("KAudioCreator has not finished all of the jobs. Remove them anyway?"), i18n("Unfinished Job in Queue"), KStdGuiItem::del(), i18n("Keep")) + == KMessageBox::No ) + return; + } + + QueListViewItem * currentItem = (QueListViewItem*)todoQue->firstChild(); + while( currentItem != NULL ){ + QueListViewItem *next = (QueListViewItem*)currentItem->nextSibling(); + removeJob(currentItem, true, false); + currentItem = next; + } +} + +/** + * Remove any jobs that are in the list that are done. + */ +void JobQueImp::clearDoneJobs(){ + QueListViewItem * currentItem = (QueListViewItem*)todoQue->firstChild(); + while( currentItem != NULL ){ + QueListViewItem *itemToRemove = NULL; + if( currentItem->percentDone == 100 ){ + itemToRemove = currentItem; + } + currentItem = (QueListViewItem*)currentItem->itemBelow(); + if(itemToRemove){ + emit (removeJob(itemToRemove->text(HEADER_JOB).toInt())); + todoQue->takeItem(itemToRemove); + } + } + if(todoQue->childCount() == 0){ + queLabel->setText(i18n("No jobs are in the queue")); + highestNumber = DEFAULT_HIGHEST_NUMBER; + currentId = 0; + } + else + queLabel->setText(i18n("Number of jobs in the queue: %1").arg(todoQue->childCount())); +} + +/** + * Return the number of jobs in the que that don't have 100% or Error in the + * Progress column + * @return the number of jobs that are in the que that haven't been finished. + */ +int JobQueImp::numberOfJobsNotFinished(){ + int totalJobsToDo = 0; + QueListViewItem * currentItem = (QueListViewItem*)todoQue->firstChild(); + while( currentItem != NULL ){ + if( currentItem->percentDone == 100 || currentItem->percentDone == -1 ){ + } + else + totalJobsToDo++; + currentItem = (QueListViewItem*)currentItem->itemBelow(); + } + return totalJobsToDo; +} + +/** + * The repaint function overloaded so that we can have a built in progressbar. + */ +void QueListViewItem::paintCell (QPainter * p,const QColorGroup &cg,int column, + int width,int align){ + if(column != HEADER_PROGRESS){ + QListViewItem::paintCell(p,cg,column,width,align); + return; + } + + p->setPen(cg.base()); + p->drawRect(0,0,width,height()); + if(isSelected()) + p->fillRect(1,1,width-2,height()-2,cg.highlight()); + else + p->fillRect(1,1,width-2,height()-2,cg.base()); + + int percent = (int)(((double)(width-2)) * (percentDone/100)); + + p->fillRect(1,1,percent,height()-2,cg.mid()); + + // show the text + p->setPen(cg.text()); + if(isSelected()) + p->setPen(cg.highlightedText()); + if(percentDone != -1) + p->drawText(0,0,width-1,height()-1,AlignCenter,QString().setNum((int)percentDone) + "%"); + else + p->drawText(0,0,width-1,height()-1,AlignCenter,i18n("Error")); +} + +/** + * Header for built in treelist item so we can have a progress bar in them. + */ +QueListViewItem::QueListViewItem(QListView *parent, const QString id, const QString p , const QString name, const QString d, const QString e) : QListViewItem(parent, id, p, name,d,e), percentDone(0), progressing(false) { +} + +#include "jobqueimp.moc" + diff --git a/kaudiocreator/jobqueimp.h b/kaudiocreator/jobqueimp.h new file mode 100644 index 00000000..a797f22c --- /dev/null +++ b/kaudiocreator/jobqueimp.h @@ -0,0 +1,80 @@ +/** + * This file is part of the KAudioCreator package + * Copyright (C) 2003 Benjamin C Meyer (ben+kaudiocreator at meyerhome dot net) + * + * 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 library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef JOBQUEIMP_H +#define JOBQUEIMP_H + +#include "jobque.h" +#include <qstring.h> +#include <qlistview.h> + +class Job; +class QPainter; +class QColorGroup; +class QListView; + +/** + * Helper class to allow for progress bars in list view items. + */ +class QueListViewItem : public QListViewItem { + +public: + QueListViewItem (QListView * p = NULL, const QString a=0, const QString b=0, const QString c=0, const QString d=0, const QString e=0); + virtual void paintCell (QPainter * p,const QColorGroup &cg,int column, + int width,int align); + double percentDone; + // Has the percentDone gone beyond 0 + // Here because percentDone might go 1,2,3,4 or it could go 1,20,21,78 or ... + bool progressing; +}; + + +class JobQueImp : public JobQue { + +Q_OBJECT + +signals: + void removeJob( int idNumber ); + +public: + JobQueImp( QWidget* parent = 0, const char* name = 0 ); + int numberOfJobsNotFinished(); + +public slots: + void updateProgress( int id, int progress ); + void addJob( Job* job, const QString &name ); + + // Toolbar Button + void clearDoneJobs(); + +private slots: + void removeSelectedJob(); + void removeAllJobs(); + +private: + bool removeJob( QueListViewItem *item, bool kill=true, bool prompt=true ); + QString getStringFromNumber( int number ); + int highestNumber; + + int currentId; +}; + +#endif + diff --git a/kaudiocreator/kaudiocreator-libkcddb.upd b/kaudiocreator/kaudiocreator-libkcddb.upd new file mode 100644 index 00000000..f878b1f6 --- /dev/null +++ b/kaudiocreator/kaudiocreator-libkcddb.upd @@ -0,0 +1,6 @@ +Id=kaudiocreator-libkcddb + +File=kaudiocreatorrc,kcmcddbrc +Group=cdconfig,Lookup +Key=databasePort,port +Key=databaseServer,hostname diff --git a/kaudiocreator/kaudiocreator-meta.upd b/kaudiocreator/kaudiocreator-meta.upd new file mode 100644 index 00000000..223f6e62 --- /dev/null +++ b/kaudiocreator/kaudiocreator-meta.upd @@ -0,0 +1,3 @@ +Id=3 +File=kaudiocreatorrc +Script=upgrade-kaudiocreator-metadata.sh,bash diff --git a/kaudiocreator/kaudiocreator.cpp b/kaudiocreator/kaudiocreator.cpp new file mode 100644 index 00000000..12267ed0 --- /dev/null +++ b/kaudiocreator/kaudiocreator.cpp @@ -0,0 +1,305 @@ +/** + * This file is part of the KAudioCreator package + * Copyright (C) 2003 Benjamin C Meyer (ben+kaudiocreator at meyerhome dot net) + * + * 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 library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "kaudiocreator.h" + +#include <qvbox.h> +#include <kiconloader.h> + +#include <kmessagebox.h> +#include <kpopupmenu.h> +#include <kaction.h> +#include <kstatusbar.h> +#include <knotifydialog.h> +#include <kcombobox.h> + +#include "tracksimp.h" +#include "jobqueimp.h" +#include "ripper.h" +#include "encoder.h" +#include "prefs.h" +#include "encodefileimp.h" +#include "job.h" + +// Settings +#include "ripconfig.h" +#include "cdconfig.h" +#include "encoderconfigimp.h" +#include "general.h" +#include <kcmoduleloader.h> +#include <kurlrequester.h> + +/** + * Constructor. Connect all of the object and the job control. + */ +KAudioCreator::KAudioCreator( QWidget* parent, const char* name) : + KMainWindow(parent, name) +{ + janusWidget = new KJanusWidget(this, name, KJanusWidget::Tabbed); + setCentralWidget(janusWidget); + + QVBox *frame = janusWidget->addVBoxPage(i18n("&CD Tracks"), QString::null, SmallIcon("cdaudio_unmount", 32)); + tracks = new TracksImp(frame, "Tracks"); + + ripper = new Ripper ( frame, "Rip" ); + encoder = new Encoder( frame, "Encoder" ); + + frame = janusWidget->addVBoxPage( i18n("&Jobs"), QString::null, SmallIcon( "run", 32 ) ); + jobQue = new JobQueImp( frame, "Que" ); + + resize(500, 440); + + /*KAction *eject = */new KAction( i18n("&Eject CD"), 0, tracks, + SLOT( eject() ), actionCollection(), "eject" ); + + (void)new KAction( i18n("&Configure KAudioCreator..."), 0, this, + SLOT( showSettings() ), actionCollection(), "configure_kaudiocreator" ); + + KAction *selectAll = new KAction( i18n( "Select &All Tracks"), 0, tracks, + SLOT( selectAllTracks() ), actionCollection(), "select_all" ) ; + KAction *deselectAll = new KAction( i18n( "Deselect &All Tracks"), 0, tracks, + SLOT( deselectAllTracks() ), actionCollection(), "deselect_all" ); + selectAll->setEnabled( false ); + deselectAll->setEnabled( false ); + + KActionMenu *actActionMenu = new KActionMenu( i18n("Rip &Selection"), "rip", actionCollection(), "rip" ); + actActionMenu->setDelayed(true); //needed for checking "all accounts" + actActionMenu->setEnabled( false ); + connect( actActionMenu, SIGNAL( activated() ), tracks, SLOT( startSession() ) ); + + ripMenu = actActionMenu->popupMenu(); + connect( ripMenu, SIGNAL( activated(int) ), this, SLOT( slotRipSelection(int)) ); + connect( ripMenu, SIGNAL( aboutToShow() ), this, SLOT( getRipMenu()) ); + + KAction *rip = new KAction( i18n( "Rip &Selection" ), 0, tracks, + SLOT( startSession() ), actionCollection(), "rip_selected" ); + rip->setEnabled( false ); + + connect( jobQue, SIGNAL( removeJob(int) ), this, SLOT( updateStatus() ) ); + connect( jobQue, SIGNAL( removeJob(int) ), ripper, SLOT( removeJob(int) ) ); + connect( jobQue, SIGNAL( removeJob(int) ), encoder, SLOT( removeJob(int)) ); + + connect( ripper, SIGNAL( updateProgress(int, int) ) , jobQue, SLOT( updateProgress(int,int) ) ); + connect( ripper, SIGNAL( addJob(Job*, const QString &) ), jobQue, SLOT( addJob(Job*, const QString &)) ); + connect( ripper, SIGNAL( eject(const QString &) ) , tracks, SLOT( ejectDevice(const QString &)) ); + connect( ripper, SIGNAL( encodeWav(Job *) ) , encoder, SLOT( encodeWav(Job *)) ); + connect( ripper, SIGNAL( jobsChanged() ) , this, SLOT( updateStatus() ) ); + + connect( encoder, SIGNAL( updateProgress(int, int) ) , jobQue, SLOT( updateProgress(int,int)) ); + connect( encoder, SIGNAL( addJob(Job*, const QString&)), jobQue, SLOT( addJob(Job*, const QString &)) ); + connect( encoder, SIGNAL( jobsChanged() ) , this, SLOT( updateStatus() ) ); + + connect( tracks, SIGNAL( hasCD(bool) ) , this, SLOT( hasCD(bool) ) ); + connect( tracks, SIGNAL( ripTrack(Job *) ), ripper, SLOT( ripTrack(Job *)) ); + connect( tracks, SIGNAL( hasTracks(bool) ), rip, SLOT( setEnabled(bool)) ); + connect( tracks, SIGNAL( hasTracks(bool) ), actActionMenu, SLOT( setEnabled(bool)) ); + connect( tracks, SIGNAL( hasTracks(bool) ), deselectAll, SLOT( setEnabled(bool)) ); + connect( tracks, SIGNAL( hasTracks(bool) ), selectAll, SLOT( setEnabled(bool)) ); + + (void)new KAction(i18n("Remove &Completed Jobs"), 0, jobQue, + SLOT(clearDoneJobs()), actionCollection(), "clear_done_jobs" ); + + KAction *edit = new KAction(i18n("&Edit Album..."), 0, tracks, + SLOT(editInformation()), actionCollection(), "edit_cd"); + connect(tracks, SIGNAL(hasCD(bool)), edit, SLOT(setEnabled(bool))); + edit->setEnabled( false ); + + (void)new KAction(i18n("Encode &File..."), 0, this, + SLOT(encodeFile()), actionCollection(), "encode_file"); + + KAction *cddb = new KAction(i18n("&CDDB Lookup"), 0, tracks, + SLOT(performCDDB()), actionCollection(), "cddb_now"); + connect(tracks, SIGNAL(hasCD(bool)), cddb, SLOT(setEnabled(bool))); + cddb->setEnabled( false ); + + KStdAction::configureNotifications(this, SLOT(configureNotifications()), + actionCollection()); + KStdAction::quit( this, SLOT(close()), actionCollection(), "quit" ); + + // Init statusbar + statusBar()->insertItem(i18n("No Audio CD detected"), 0 ); + hasCD(tracks->hasCD()); + + setupGUI(); +} + +void KAudioCreator::setDevice( const QString &device ) +{ + tracks->deviceCombo->setCurrentText( device ); +} + +void KAudioCreator::slotRipSelection(int selection){ + tracks->startSession( selection ); +} + +void KAudioCreator::getRipMenu(){ + ripMenu->clear(); + + int i=0; + QString currentGroup = QString("Encoder_%1").arg(i); + while(EncoderPrefs::hasPrefs(currentGroup)){ + ripMenu->insertItem(EncoderPrefs::prefs(currentGroup)->encoderName(), i); + currentGroup = QString("Encoder_%1").arg(++i); + } +} + +/** + * Changes the status bar to let the user no if a cd was not detected or inserted. + */ +void KAudioCreator::hasCD(bool cd){ + if(cd) + statusBar()->changeItem(i18n("CD Inserted"), 0 ); + else + statusBar()->changeItem(i18n("No Audio CD detected"), 0 ); +} + +void KAudioCreator::updateStatus() { + QString status = i18n("Idle."); + QString rippingStatus; + QString encodingStatus; + int activeRippingJobs = ripper->activeJobCount(); + int pendingRippingJobs = ripper->pendingJobCount(); + int activeEncodingJobs = encoder->activeJobCount(); + int pendingEncodingJobs = encoder->pendingJobCount(); + + if ( activeRippingJobs ) { + rippingStatus = i18n("Ripping (%1 active, %2 queued)").arg( activeRippingJobs ).arg( pendingRippingJobs ); + status = rippingStatus; + } + if ( activeEncodingJobs ) { + encodingStatus = i18n("Encoding (%1 active, %2 queued)").arg( activeEncodingJobs ).arg( pendingEncodingJobs ); + + if ( activeRippingJobs ) { + status.append(" : "); + status.append( encodingStatus ); + } + else { + status = encodingStatus; + } + } + + statusBar()->changeItem( status, 0 ); +} + +/** + * Ask the user if they really want to quit if there are open jobs. + */ +bool KAudioCreator::queryClose() { + if(jobQue->numberOfJobsNotFinished() > 0 && + (KMessageBox::warningContinueCancel(this, i18n("There are unfinished jobs in the queue. Would you like to quit anyway?"), i18n("Unfinished Jobs in Queue"),KStdGuiItem::quit()) + == KMessageBox::Cancel )) + return false; + return true; +} + +void KAudioCreator::configureNotifications() { + KNotifyDialog *dialog = new KNotifyDialog(this, "KNotifyDialog", false); + dialog->show(); +} + +void KAudioCreator::encodeFile(){ + EncodeFileImp *file = new EncodeFileImp(this, "EncodeFile"); + connect(file, SIGNAL(startJob(Job*)),encoder, SLOT(encodeWav(Job*))); + file->show(); +} + +/** + * Show Settings dialog. + */ +void KAudioCreator::showSettings(){ + if(KConfigDialog::showDialog("settings")) + return; + + SettingsDialog *dialog = new SettingsDialog(this, "settings", Prefs::self()); + connect(dialog, SIGNAL(settingsChanged()), ripper, SLOT(loadSettings())); + connect(dialog, SIGNAL(settingsChanged()), encoder, SLOT(loadSettings())); + connect(dialog, SIGNAL(settingsChanged()), tracks, SLOT(loadSettings())); + connect(dialog->encoderConfigImp, SIGNAL(encoderUpdated()), encoder, SLOT(loadSettings())); + dialog->show(); +} + +SettingsDialog::SettingsDialog(QWidget *parent, const char *name,KConfigSkeleton *config) + : KConfigDialog(parent, name, config), + cddb(0), cddbChanged(false) +{ + addPage(new General(0, "General"), i18n("General"), "package_settings", + i18n("General Configuration")); + addPage(new CdConfig(0, "CD"), i18n("CD"), "package_system", + i18n("CD Configuration")); + + // Because WE don't segfault on our users... + KService::Ptr libkcddb = KService::serviceByDesktopName("libkcddb"); + if (libkcddb && libkcddb->isValid()) + { + cddb = KCModuleLoader::loadModule(QString("libkcddb"), KCModuleLoader::Inline); + if (cddb) + { + cddb->load(); + addPage(cddb, i18n("CDDB"), "cdaudio_mount", i18n("CDDB Configuration"), false); + connect(cddb, SIGNAL(changed(bool)), this, SLOT(slotCddbChanged(bool))); + } + } + RipConfig *rip = new RipConfig(0, "Ripper"); + rip->kcfg_tempDir->setMode(KFile::Directory); + addPage(rip, i18n("Ripper"), "gear", i18n("Ripper Configuration") ); + + encoderConfigImp = new EncoderConfigImp(0, "Encoder"); + addPage(encoderConfigImp, i18n("Encoder"), "filter", i18n("Encoder Configuration") ); +} + +void SettingsDialog::updateSettings() +{ + if (cddb) + cddb->save(); +} + +void SettingsDialog::updateWidgets() +{ + if (cddb) + cddb->load(); + cddbChanged = false; +} + +void SettingsDialog::updateWidgetsDefault() +{ + if (cddb) + cddb->defaults(); +} + +bool SettingsDialog::hasChanged() +{ + return cddbChanged; +} + +bool SettingsDialog::isDefault() +{ + if (cddb) + return false; + return true; +} + +void SettingsDialog::slotCddbChanged(bool changed) +{ + cddbChanged = changed; + updateButtons(); +} + +#include "kaudiocreator.moc" + diff --git a/kaudiocreator/kaudiocreator.desktop b/kaudiocreator/kaudiocreator.desktop new file mode 100644 index 00000000..585e4918 --- /dev/null +++ b/kaudiocreator/kaudiocreator.desktop @@ -0,0 +1,137 @@ +[Desktop Entry] +Comment=Frontend for audio file creation +Comment[af]=Voorprogram vir audio lêer skep +Comment[bg]=Инструмент за кодиране на аудио файлове +Comment[bn]=অডিও ফাইল তৈরি করার জন্য ফ্রন্ট-এন্ড +Comment[bs]=Interfejs za pravljenje audio datoteka +Comment[ca]=Interfície per la creació de fitxers àudio +Comment[cs]=Rozhraní pro tvorbu zvukových souborů +Comment[cy]=Blaen i greu ffeiliau sain +Comment[da]=Grænseflade til at lave lydfiler +Comment[de]=Oberfläche zur Erstellung von Audio-Dateien +Comment[el]=Σύστημα υποστήριξης χρήστη για δημιουργία αρχείου ήχου +Comment[eo]=Fasado por kreado de sonordosieroj +Comment[es]=Una interfaz para la creación de archivos audio +Comment[et]=Rippimisprogrammide kasutajaliides +Comment[eu]=Audio fitxategiak sortzeko interfazea +Comment[fa]=پایانه برای ایجاد پروندۀ صوتی +Comment[fi]=Käyttöliittymä äänitiedostojen luontiin +Comment[fr]=Une interface pour la création de fichiers sons +Comment[gl]=Interface para a creación de ficheiros de son +Comment[he]=ממשק ליצירת קבצי שמע +Comment[hi]=ऑडियो फ़ाइल बनाने के लिए फ्रन्टएण्ड +Comment[hr]=Sučelje za rađenje audio datoteka +Comment[hu]=Grafikus előtétprogram hangfájlok létrehozásához +Comment[is]=Andlit á tól sem búa til hljóðskrár +Comment[it]=Interfaccia per la creazione dei file audio +Comment[ja]=オーディオファイル作成のフロントエンド +Comment[kk]=Аудиофайл құру интерфейсі +Comment[km]=កម្មវិធីសម្រាប់បង្កើតឯកសារអូឌីយ៉ូ +Comment[ko]=오디오 파일 생성 프론트엔드 +Comment[lt]=Išorinė audio bylų kūrimo programa +Comment[lv]=Frontends audio failu veidošanai +Comment[mk]=Алатка за правење на аудио датотеки +Comment[ms]=Bahagian hadapan untuk penciptaan fail audio +Comment[nb]=Program for å lage av lydfiler +Comment[nds]=Böversiet för't Opstellen vun Klangdateien +Comment[ne]=अडियो फाइल सर्जकका लागि सुरुआत +Comment[nl]=Grafische schil voor aanmaken van geluidsbestanden +Comment[nn]=Grensesnitt for oppretting av lydfiler +Comment[pa]=ਆਡੀਓ ਫਾਇਲਾਂ ਬਣਾਉਣ ਲਈ ਮੁੱਖ +Comment[pl]=Środowisko do tworzenia plików audio +Comment[pt]=Uma interface para a criação de ficheiros de áudio +Comment[pt_BR]=Uma interface para a criação de arquivos de áudio +Comment[ro]=Interfaţă pentru crearea de fişiere audio +Comment[ru]=Интерфейс для создания аудиофайлов +Comment[se]=Lakta jietnafiillaid ráhkadeapmái +Comment[sk]=Rozhranie pre tvorbu zvukových súborov +Comment[sl]=Vmesnik za ustvarjanje zvočnih datotek +Comment[sr]=Интерфејс за прављење аудио фајлова +Comment[sr@Latn]=Interfejs za pravljenje audio fajlova +Comment[sv]=Gränssnitt för att skapa ljudfiler +Comment[ta]=கேட்பொலி கோப்பு உருவாக்குவதற்கான முன்னிலை +Comment[tg]=Пешохир барои офарандаи файлҳои садо +Comment[th]=ฟรอนต์เอนด์สำหรับการสร้างแฟ้มเสียง +Comment[tr]=Ses dosyası oluşturmak için bir önyüz +Comment[uk]=Зовнішній інтерфейс створення аудіофайлів +Comment[ven]=Zwo vhewa phanda uitela nyito ya faela ya zwipfiwa +Comment[zh_CN]=音频文件创建前端 +Comment[zh_HK]=製作音訊檔案的前端 +Comment[zh_TW]=製作聲音檔案的前端 +Comment[zu]=Isiqalo sesiphelo sokuzwakalayo kwefayela lokludala +Name=KAudioCreator +Name[bn]=কে-অডিও-ক্রিয়েটার +Name[cy]=KCreuwrSain +Name[eo]=Sonorkreilo +Name[hi]=के-ऑडियो-क्रिएटर +Name[mk]=KАудиоКреатор +Name[ne]=केडीई अडियो सर्जक +Name[pa]=ਕੇ-ਆਡੀਓ ਨਿਰਮਾਤਾ +Name[pt_BR]=Criação de Áudio +Name[sv]=Kaudiocreator +Name[ta]=கேஒலிஉருவாக்கி +Name[tg]=KОфарандаи Садо +Name[tr]=Kaudiocreator +Name[ven]=MuitiwazwamibvumoyaK +Name[zh_TW]=KAudioCreator 聲音製作 +GenericName=CD Ripper +GenericName[bg]=Кодиране на аудио дискове +GenericName[bn]=সিডি রিপার +GenericName[br]=Un eztenner CD +GenericName[ca]=Extractor de CD +GenericName[cs]=CD ripper +GenericName[cy]=Rhwygydd CD +GenericName[da]=Cd-Ripper +GenericName[de]=CD-Ripper +GenericName[el]=Εξαγωγέας CD +GenericName[eo]=Ellegilo por muzikaj lumdiskoj +GenericName[es]=Extractor de audio de CDs +GenericName[et]=CD rippija +GenericName[eu]=CD erauzlea +GenericName[fa]=شکافندۀ دیسک فشرده +GenericName[fi]=CD-kaappaaja +GenericName[fr]=Extracteur de CD audio +GenericName[gl]=Extractor de CD +GenericName[he]=קורע תקליטורים +GenericName[hi]=सीडी रिप्पर +GenericName[hu]=CD-másoló +GenericName[is]=CD afritunartól +GenericName[it]=Estrattore di CD +GenericName[ja]=CD リッパー +GenericName[kk]=CD риппері +GenericName[km]=កម្មវិធីច្រៀកស៊ីឌី +GenericName[ko]=CD 추출기 +GenericName[lt]=CD grotuvas/nurašymo priemonė +GenericName[mk]=Спуштач на CD +GenericName[nb]=CD-opptaker +GenericName[nds]=CD-Utleser +GenericName[ne]=CD काट्ने +GenericName[nl]=CD-ripper +GenericName[nn]=CD-opptakar +GenericName[pa]=CD ਰਿਪਰ +GenericName[pl]=Zgrywanie CD +GenericName[pt]=Extractor de CDs +GenericName[pt_BR]=Reprodutor de CDs/Ripar CDs +GenericName[ru]=Копирование CD +GenericName[sk]=CD získavanie +GenericName[sl]=Zajemalnik CD-jev +GenericName[sr]=CD гребач +GenericName[sr@Latn]=CD grebač +GenericName[sv]=Cd-lagring +GenericName[ta]=சிடி ரிப்பர் +GenericName[tg]=Кандакунандаи Диски Фишурда +GenericName[th]=โปรแกรมดึงข้อมูลจากซีดีบันทึกเสียง +GenericName[tr]=Cd Aktarıcı +GenericName[uk]=Видирання з КД +GenericName[uz]=Kompakt-disk ripper +GenericName[uz@cyrillic]=Компакт-диск риппер +GenericName[zh_CN]=CD 提取器 +GenericName[zh_HK]=CD 擷取器 +GenericName[zh_TW]=光碟擷取器 +MimeType= +Exec=kaudiocreator +Icon=kaudiocreator +Path= +Type=Application +Terminal=false +Categories=Qt;KDE;AudioVideo;Audio; diff --git a/kaudiocreator/kaudiocreator.h b/kaudiocreator/kaudiocreator.h new file mode 100644 index 00000000..27018908 --- /dev/null +++ b/kaudiocreator/kaudiocreator.h @@ -0,0 +1,93 @@ +/** + * This file is part of the KAudioCreator package + * Copyright (C) 2003 Benjamin C Meyer (ben+kaudiocreator at meyerhome dot net) + * + * 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 library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef KAUDIOCREATOR_H +#define KAUDIOCREATOR_H + +#include <kmainwindow.h> +#include <kconfigdialog.h> + +class KJanusWidget; +class TracksImp; +class JobQueImp; +class Ripper; +class Encoder; +class KCModule; +class EncoderConfigImp; +class KPopupMenu; + +class KAudioCreator : public KMainWindow { + +Q_OBJECT + +public: + KAudioCreator( QWidget* parent = 0, const char* name = 0); + void setDevice( const QString &device ); + +protected: + virtual bool queryClose(); + +private slots: + void showSettings(); + void updateStatus(); + + void hasCD(bool); + void configureNotifications(); + void encodeFile(); + + void slotRipSelection(int); + void getRipMenu(); + +private: + KJanusWidget *janusWidget; + TracksImp *tracks; + JobQueImp *jobQue; + Ripper *ripper; + Encoder *encoder; + KPopupMenu *ripMenu; + +}; + +class SettingsDialog: public KConfigDialog { +Q_OBJECT + +public: + SettingsDialog(QWidget *parent, const char *name,KConfigSkeleton *config); + +protected slots: + void updateSettings(); + void updateWidgets(); + void updateWidgetsDefault(); + void slotCddbChanged(bool); + +protected: + bool hasChanged(); + bool isDefault(); + +public: + EncoderConfigImp *encoderConfigImp; + +private: + KCModule *cddb; + bool cddbChanged; +}; + +#endif + diff --git a/kaudiocreator/kaudiocreator.kcfg b/kaudiocreator/kaudiocreator.kcfg new file mode 100644 index 00000000..9e8addd0 --- /dev/null +++ b/kaudiocreator/kaudiocreator.kcfg @@ -0,0 +1,107 @@ +<?xml version="1.0" encoding="UTF-8"?> +<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 + http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" > + <include>kaudiocreator_workman.h</include> + <kcfgfile name="kaudiocreatorrc"/> + <group name="CD"> + <entry name="performCDDBauto" type="Bool"> + <label>Perform automatic CDDB lookups.</label> + <default>true</default> + </entry> + <entry name="autoRip" type="Bool"> + <label>Automatically rip all tracks upon a successful CDDB retrieval</label> + <default>false</default> + </entry> + <entry name="device" type="StringList"> + <label>CD device</label> + <default code="true">DEFAULT_CD_DEVICE</default> + </entry> + <entry name="promptIfIncompleteInfo" type="Bool"> + <label>Prompt if information is not complete</label> + <default>true</default> + </entry> + </group> + <group name="General"> + <entry name="removeCompletedJobs" type="Bool"> + <label>Automatically remove jobs when finished</label> + <default>true</default> + </entry> + <entry name="replaceInput" type="String" key="selection"> + <label>Regexp to match file names with</label> + </entry> + <entry name="replaceOutput" type="String" key="replace"> + <label>String used to replace the parts that match the selection regexp</label> + </entry> + <entry name="seperateMultiArtist" type="Bool"> + <default>false</default> + </entry> + <entry name="genericArtist" type="String"> + <default>Various Artists</default> + </entry> + <entry name="delimiter" type="String"> + <default> - </default> + </entry> + <entry name="format_artistTitle" type="Bool"> + <default>true</default> + </entry> + <entry name="format_titleArtist" type="Bool"> + <default>false</default> + </entry> + </group> + <group name="Encoder"> + <entry name="currentEncoder" type="Int" key="encoderChoice"> + <label>Currently selected encoder</label> + <default>0</default> + </entry> + <entry name="lastKnownEncoder" type="Int"> + <label>Last encoder in the list</label> + <default>0</default> + </entry> + <entry name="numberOfCpus" type="Int"> + <label>Number of files to encode at a time</label> + <default>1</default> + </entry> + <entry name="fileFormat" type="String"> + <label>Location pattern for encoded files</label> + <default>~/%{extension}/%{albumartist}/%{albumtitle}/%{artist} - %{number} - %{title}.%{extension}</default> + </entry> + <entry name="NiceLevel" type="Int"> + <label>Encoder priority</label> + <default>0</default> + <min>-19</min> + <max>19</max> + </entry> + <entry name="FullDecoderDebug" type="Bool"> + <label>Enable full decoder debugging</label> + <default>false</default> + </entry> + </group> + <group name="Ripper"> + <entry name="maxWavFiles" type="Int"> + <label>Number of tracks to rip at a time</label> + <default>1</default> + </entry> + <entry name="beepAfterRip" type="Bool"> + <label>Beep after rip</label> + <default>true</default> + </entry> + <entry name="autoEjectAfterRip" type="Bool"> + <label>Eject CD after last track is ripped</label> + <default>false</default> + </entry> + <entry name="autoEjectDelay" type="Int"> + <label>Auto-eject delay</label> + <default>0</default> + </entry> + <entry name="enableTempDir" type="Bool"> + <label>Specify temporary directory</label> + <default>false</default> + </entry> + <entry name="tempDir" type="String"> + <label>Location of temporary directory to use</label> + <default></default> + </entry> + </group> +</kcfg> diff --git a/kaudiocreator/kaudiocreator_encoders.kcfg b/kaudiocreator/kaudiocreator_encoders.kcfg new file mode 100644 index 00000000..cbe9372b --- /dev/null +++ b/kaudiocreator/kaudiocreator_encoders.kcfg @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 + http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" > + <kcfgfile name="kaudiocreatorrc"> + <parameter name="encoder" /> + </kcfgfile> + + <group name="$(encoder)"> + <entry name="encoderName" type="String"> + <label>Name of the encoder</label> + <default>Unknown Encoder</default> + </entry> + <entry name="commandLine" type="Path"> + <label>Command line to invoke encoder</label> + <default>app.exe %f %o</default> + </entry> + <entry name="extension" type="String"> + <label>File extension</label> + <default>wav</default> + </entry> + <entry name="percentLength" type="Int"> + <label></label> + <default>2</default> + </entry> + </group> +</kcfg> diff --git a/kaudiocreator/kaudiocreator_workman.h b/kaudiocreator/kaudiocreator_workman.h new file mode 100644 index 00000000..268b4f90 --- /dev/null +++ b/kaudiocreator/kaudiocreator_workman.h @@ -0,0 +1,27 @@ +/** + * This file is part of the KAudioCreator package + * Copyright (C) 2003 Waldo Bastian <bastian@kde.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef KAUDIOCREATOR_WORKMAN_H +#define KAUDIOCREATOR_WORKMAN_H + +extern "C" { + #include "../kscd/libwm/include/workman.h" +} + +#endif diff --git a/kaudiocreator/kaudiocreatorui.rc b/kaudiocreator/kaudiocreatorui.rc new file mode 100644 index 00000000..597eda1d --- /dev/null +++ b/kaudiocreator/kaudiocreatorui.rc @@ -0,0 +1,41 @@ +<!DOCTYPE kpartgui> +<kpartgui name="kaudiocreator" version="3"> +<ActionProperties> + <Action name="rip_selected" icon="gear"/> + <Action name="rip" icon="gear"/> + <Action name="configure_kaudiocreator" icon="configure"/> + <Action name="clear_done_jobs" icon="edittrash"/> + <Action name="eject" icon="player_eject"/> + <Action name="edit_cd" icon="edit"/> + <Action name="cddb_now" icon="cdaudio_mount"/> +</ActionProperties> + +<MenuBar> + <Menu name="file"><Text>&Program</Text> + <Action name="eject"/> + <Action name="cddb_now"/> + <Action name="edit_cd"/> + <Action name="select_all"/> + <Action name="deselect_all"/> + <Action name="rip_selected"/> + <Action name="rip"/> + <Action name="clear_done_jobs"/> + <Separator/> + <Action name="encode_file"/> + <Separator/> + <Action name="quit"/> + </Menu> + <Menu name="settings"> + <Action name="configuretoolbars" append="configure_merge"/> + <Action name="configure_kaudiocreator" append="configure_merge"/> + </Menu> +</MenuBar> + +<ToolBar name="Main ToolBar"> + <Action name="cddb_now"/> + <Action name="edit_cd"/> + <Action name="rip"/> + <Action name="eject"/> +</ToolBar> + +</kpartgui> diff --git a/kaudiocreator/lo16-app-kaudiocreator.png b/kaudiocreator/lo16-app-kaudiocreator.png Binary files differnew file mode 100644 index 00000000..c518d066 --- /dev/null +++ b/kaudiocreator/lo16-app-kaudiocreator.png diff --git a/kaudiocreator/lo32-app-kaudiocreator.png b/kaudiocreator/lo32-app-kaudiocreator.png Binary files differnew file mode 100644 index 00000000..6f790413 --- /dev/null +++ b/kaudiocreator/lo32-app-kaudiocreator.png diff --git a/kaudiocreator/main.cpp b/kaudiocreator/main.cpp new file mode 100644 index 00000000..a8b6649f --- /dev/null +++ b/kaudiocreator/main.cpp @@ -0,0 +1,56 @@ +/** + * This file is part of the KAudioCreator package + * Copyright (C) 2003-2005 Benjamin C Meyer (ben+kaudiocreator at meyerhome dot net) + * + * 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 library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <kapplication.h> + +#include "kaudiocreator.h" +#include <kcmdlineargs.h> +#include <kaboutdata.h> + +static const KCmdLineOptions options[] = { + {"+[device]",I18N_NOOP( "CD device, can be a path or a media:/ URL" ),0}, + KCmdLineLastOption +}; + + +int main(int argc, char *argv[]){ + KAboutData aboutData("kaudiocreator", I18N_NOOP("KAudioCreator"), "1.13", + I18N_NOOP("CD ripper and audio encoder frontend"), KAboutData::License_LGPL, "(c) 2003-2005, Benjamin Meyer", + 0, "http://www.icefox.net/"); + aboutData.addAuthor("Benjamin Meyer", I18N_NOOP("Original author"), "ben+kaudiocreator@meyerhome.net", "http://www.icefox.net/"); + + // command line + KCmdLineArgs::init(argc, argv, &aboutData); + KCmdLineArgs::addCmdLineOptions( options ); + KApplication a(argc, argv); + KAudioCreator *app = new KAudioCreator(0, "MainWindow"); + + // we need some strings from libkcddb for the cddb album dialog + KGlobal::locale()->insertCatalogue("libkcddb"); + + a.setMainWidget(app); + + KCmdLineArgs* args = KCmdLineArgs::parsedArgs(); + if ( args->count()>0 ) app->setDevice( args->arg( 0 ) ); + args->clear(); + app->show(); + return a.exec(); +} + diff --git a/kaudiocreator/prefs.kcfgc b/kaudiocreator/prefs.kcfgc new file mode 100644 index 00000000..dc784e77 --- /dev/null +++ b/kaudiocreator/prefs.kcfgc @@ -0,0 +1,7 @@ +# Code generation options for kconfig_compiler +File=kaudiocreator.kcfg +#IncludeFiles=defines.h +ClassName=Prefs +Singleton=true +#CustomAdditions=true +Mutators=device,lastKnownEncoder diff --git a/kaudiocreator/ripconfig.ui b/kaudiocreator/ripconfig.ui new file mode 100644 index 00000000..4ce85f1b --- /dev/null +++ b/kaudiocreator/ripconfig.ui @@ -0,0 +1,191 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>RipConfig</class> +<widget class="QWidget"> + <property name="name"> + <cstring>RipConfig</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>525</width> + <height>526</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_beepAfterRip</cstring> + </property> + <property name="text"> + <string>&Beep after each rip is done</string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>Layout4</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>TextLabel14</cstring> + </property> + <property name="text"> + <string>&Number of tracks to rip at a time:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_maxWavFiles</cstring> + </property> + </widget> + <widget class="QSpinBox"> + <property name="name"> + <cstring>kcfg_maxWavFiles</cstring> + </property> + <property name="maxValue"> + <number>99999</number> + </property> + <property name="minValue"> + <number>1</number> + </property> + </widget> + </hbox> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_autoEjectAfterRip</cstring> + </property> + <property name="text"> + <string>&Auto-eject CD after last track is ripped</string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>Layout6</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>TextLabel15</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Auto-&eject delay:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_autoEjectDelay</cstring> + </property> + </widget> + <widget class="QSpinBox"> + <property name="name"> + <cstring>kcfg_autoEjectDelay</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="suffix"> + <string> seconds</string> + </property> + <property name="maxValue"> + <number>300</number> + </property> + </widget> + </hbox> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>kcfg_enableTempDir</cstring> + </property> + <property name="title"> + <string>Default Temporary Directory</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>false</bool> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KURLRequester"> + <property name="name"> + <cstring>kcfg_tempDir</cstring> + </property> + </widget> + </hbox> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer2</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>280</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<connections> + <connection> + <sender>kcfg_autoEjectAfterRip</sender> + <signal>toggled(bool)</signal> + <receiver>kcfg_autoEjectDelay</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>kcfg_autoEjectAfterRip</sender> + <signal>toggled(bool)</signal> + <receiver>TextLabel15</receiver> + <slot>setEnabled(bool)</slot> + </connection> +</connections> +<tabstops> + <tabstop>kcfg_beepAfterRip</tabstop> + <tabstop>kcfg_maxWavFiles</tabstop> + <tabstop>kcfg_autoEjectAfterRip</tabstop> + <tabstop>kcfg_autoEjectDelay</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kurlrequester.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> +</includehints> +</UI> diff --git a/kaudiocreator/ripper.cpp b/kaudiocreator/ripper.cpp new file mode 100644 index 00000000..2dd8795d --- /dev/null +++ b/kaudiocreator/ripper.cpp @@ -0,0 +1,263 @@ +/** + * This file is part of the KAudioCreator package + * Copyright (C) 2003 Benjamin C Meyer (ben+kaudiocreator at meyerhome dot net) + * + * 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 library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "ripper.h" +#include "prefs.h" + +#include <qfile.h> +#include <qtimer.h> +#include <ktempfile.h> +#include <kmessagebox.h> +#include <knotifyclient.h> +#include <kstandarddirs.h> +#include <kio/scheduler.h> + +/** + * Constructor, load settings. + */ +Ripper::Ripper( QObject* parent, const char* name) : QObject(parent,name) { + loadSettings(); +} + +/** + * Loads the settings + */ +void Ripper::loadSettings(){ + for(uint i=0; i<(uint)Prefs::maxWavFiles(); i++) + tendToNewJobs(); +} + +/** + * Deconstructor, remove pending jobs, remove current jobs, save settings. + */ +Ripper::~Ripper(){ + pendingJobs.clear(); + QMap<KIO::Job*, Job*>::Iterator it; + for( it = jobs.begin(); it != jobs.end(); ++it ){ + KIO::Job* ioJob = it.key(); + Job *job = it.data(); + delete job; + + if(ioJob){ + KIO::FileCopyJob *copyJob = static_cast<KIO::FileCopyJob*> (ioJob); + disconnect(copyJob, SIGNAL(result(KIO::Job*)), this, SLOT(copyJobResult(KIO::Job*))); + disconnect(copyJob, SIGNAL(percent ( KIO::Job *, unsigned long)), this, SLOT(updateProgress ( KIO::Job *, unsigned long))); + QString fileDestination = (copyJob->destURL()).path(); + copyJob->kill(); + QFile file( fileDestination ); + file.remove(); + } + } + jobs.clear(); +} + +/** + * @return The number of active jobs + */ +int Ripper::activeJobCount() { + return jobs.count(); +} + +/** + * @return The number of pending jobs + */ +int Ripper::pendingJobCount() { + return pendingJobs.count(); +} + +/** + * Cancel and remove the job with the matching id. + * Remove it from the local collection of jobs, delete the temp file if + * there is one. + * @param id the id number of the job to remove. + */ +void Ripper::removeJob(int id){ + QMap<KIO::Job*, Job*>::Iterator it; + for( it = jobs.begin(); it != jobs.end(); ++it ){ + if(it.data()->id == id){ + KIO::FileCopyJob *copyJob = dynamic_cast<KIO::FileCopyJob*> (it.key()); + if(copyJob){ + QString fileDestination = (copyJob->destURL()).path(); + copyJob->kill(); + // This here is such a hack, shouldn't kill() do this, or why isn't there a stop()? + // TODO add to copyJob a stop() function. + QFile file( fileDestination ); + if(file.exists()) + file.remove(); + else { + QFile f( fileDestination+".part" ); + f.remove(); + } + } + jobs.remove(it.key()); + break; + } + } + Job *job = pendingJobs.first(); + while(job){ + if(job->id == id) + break; + job = pendingJobs.next(); + } + if(job){ + pendingJobs.remove(job); + delete job; + } + //qDebug(QString("Done removing Job:%1").arg(id).latin1()); + tendToNewJobs(); +} + +/** + * Begin to rip the track specified in job. + * @param job the new job that this module should take over. + * @param job the new job that we need to handle. + */ +void Ripper::ripTrack(Job *job){ + if(!job) + return; + emit(addJob(job, i18n("Ripping: %1 - %2").arg(job->track_artist).arg(job->track_title))); + pendingJobs.append(job); + tendToNewJobs(); +} + +/** + * See if there are are new jobs to attend too. If we are all loaded up + * then just loop. + */ +void Ripper::tendToNewJobs(){ + if(pendingJobs.count() == 0){ + emit jobsChanged(); + return; + } + + // If we are currently ripping the max try again in a little bit. + if(jobs.count() >= (uint)Prefs::maxWavFiles()){ + emit jobsChanged(); + return; + } + + Job *job = pendingJobs.first(); + if(!job) + return; + pendingJobs.remove(job); + + QMap<QString, QString> map; + QString defaultTempDir; + if(Prefs::enableTempDir()) + defaultTempDir = Prefs::tempDir(); + else + defaultTempDir = locateLocal("tmp", ""); + // For cases like "/tmp" where there is a missing / + defaultTempDir = KURL(defaultTempDir).path(1); + KTempFile tmp( defaultTempDir, ".wav" ); + tmp.setAutoDelete(true); + + QString wavFile; + QString args = job->device; + if(!args.isEmpty()) + args = QString("?device=%1").arg(args); + args = args+"&fileNameTemplate=Track %{number}"; + if(job->track < 10) + wavFile = QString("audiocd:/Wav/Track 0%1.wav%2").arg(job->track).arg(args); + else + wavFile = QString("audiocd:/Wav/Track %1.wav%2").arg(job->track).arg(args); + + KURL source(wavFile); + KURL dest(tmp.name()); + + KIO::FileCopyJob *copyJob = new KIO::FileCopyJob(source, dest, 0644, false, true, false, false); + jobs.insert(copyJob, job); + connect(copyJob, SIGNAL(result(KIO::Job*)), this, SLOT(copyJobResult(KIO::Job*))); + connect(copyJob, SIGNAL(percent ( KIO::Job *, unsigned long)), this, SLOT(updateProgress ( KIO::Job *, unsigned long))); + + emit jobsChanged(); +} + +/** + * Copies the data from the KIO Job. Uses this data to fill in the + * information dialog. + * @param copyjob the IO job to copy from + */ +void Ripper::copyJobResult(KIO::Job *copyjob){ + if(!copyjob) + return; + KIO::FileCopyJob *copyJob = dynamic_cast<KIO::FileCopyJob*> (copyjob); + KNotifyClient::event("track ripped"); + + if(jobs.find(copyjob) == jobs.end()) + return; + Job *newJob = jobs[copyjob]; + jobs.remove(copyjob); + + if(Prefs::beepAfterRip()) + KNotifyClient::beep(); + + if ( copyJob->error() == 0 ){ + emit updateProgress(newJob->id, 100); + newJob->location = copyJob->destURL().path(); + emit( encodeWav(newJob)); + } + else{ + copyJob->showErrorDialog(0); + QFile file( (copyJob->destURL()).path()); + file.remove(); + emit updateProgress(newJob->id, -1); + delete newJob; + newJob = 0; + } + + if(newJob && newJob->lastSongInAlbum){ + if(Prefs::autoEjectAfterRip()){ + // Don't eject device if a pending job has that device + Job *job = pendingJobs.first(); + while( job ){ + if( job->device == newJob->device ) + break; + job = pendingJobs.next(); + } + if( !job ){ + deviceToEject = newJob->device; + QTimer::singleShot( Prefs::autoEjectDelay()*1000 + 500, this, SLOT(ejectNow())); + } + } + KNotifyClient::event("cd ripped"); + } + tendToNewJobs(); +} + +void Ripper::ejectNow(){ + emit eject(deviceToEject); +} + +/** + * Update the progress of the file copy. + * @param job the current ioslave job in progress + * @param percent the current percent that the ioslave has done. + */ +void Ripper::updateProgress( KIO::Job *job, unsigned long percent){ + if(job){ + Job *ripJob = (jobs[job]); + if(ripJob) + emit updateProgress(ripJob->id, percent); + } +} + +#include "ripper.moc" + diff --git a/kaudiocreator/ripper.h b/kaudiocreator/ripper.h new file mode 100644 index 00000000..7cd09522 --- /dev/null +++ b/kaudiocreator/ripper.h @@ -0,0 +1,68 @@ +/** + * This file is part of the KAudioCreator package + * Copyright (C) 2003 Benjamin C Meyer (ben+kaudiocreator at meyerhome dot net) + * + * 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 library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef RIPPER_H +#define RIPPER_H + +#include "job.h" +#include <kio/jobclasses.h> +#include <qmap.h> +#include <qptrlist.h> + +class Job; + +class Ripper : public QObject { + +Q_OBJECT + +signals: + void addJob( Job *job, const QString &name ); + void updateProgress( int id, int progress ); + void encodeWav( Job *job ); + void eject( const QString &device ); + void jobsChanged(); + +public: + Ripper( QObject* parent = 0, const char* name = 0 ); + ~Ripper(); + int activeJobCount(); + int pendingJobCount(); + +public slots: + void loadSettings(); + void ripTrack( Job * ); + void removeJob( int id ); + +private slots: + void copyJobResult( KIO::Job *job ); + void updateProgress( KIO::Job *job, unsigned long percent ); + void tendToNewJobs(); + void ejectNow(); + +private: + QString deviceToEject; + // Jobs that we are currently doing. + QMap<KIO::Job*, Job*> jobs; + // Jobs that we want to do , but haven't done yet + QPtrList<Job> pendingJobs; +}; + +#endif // RIPPER_H + diff --git a/kaudiocreator/tracks.ui b/kaudiocreator/tracks.ui new file mode 100644 index 00000000..a225f041 --- /dev/null +++ b/kaudiocreator/tracks.ui @@ -0,0 +1,225 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>Tracks</class> +<widget class="QWidget"> + <property name="name"> + <cstring>Tracks</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>501</width> + <height>377</height> + </rect> + </property> + <property name="caption"> + <string>Tracks</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>albumName</cstring> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>Plain</enum> + </property> + <property name="text"> + <string>Unknown Artist - Unknown Album</string> + </property> + <property name="alignment"> + <set>AlignCenter</set> + </property> + <property name="hAlign" stdset="0"> + </property> + </widget> + <widget class="KListView" row="2" column="0"> + <column> + <property name="text"> + <string>Rip</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Track</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Length</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Title</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <property name="name"> + <cstring>trackListing</cstring> + </property> + <property name="allColumnsShowFocus"> + <bool>true</bool> + </property> + <property name="resizeMode"> + <enum>LastColumn</enum> + </property> + </widget> + <widget class="QLayoutWidget" row="3" column="0"> + <property name="name"> + <cstring>Layout2</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <spacer> + <property name="name"> + <cstring>Spacer1</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>selectAllTracksButton</cstring> + </property> + <property name="text"> + <string>Select &All Tracks</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>deselectAllTracksButton</cstring> + </property> + <property name="text"> + <string>&Deselect All Tracks</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout6</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Device:</string> + </property> + </widget> + <widget class="KComboBox"> + <item> + <property name="text"> + <string>/dev/cdrom</string> + </property> + </item> + <property name="name"> + <cstring>deviceCombo</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="editable"> + <bool>true</bool> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer3</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>246</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + </grid> +</widget> +<tabstops> + <tabstop>deviceCombo</tabstop> + <tabstop>trackListing</tabstop> + <tabstop>selectAllTracksButton</tabstop> + <tabstop>deselectAllTracksButton</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kcombobox.h</includehint> + <includehint>klineedit.h</includehint> +</includehints> +</UI> diff --git a/kaudiocreator/tracksimp.cpp b/kaudiocreator/tracksimp.cpp new file mode 100644 index 00000000..591e7f2b --- /dev/null +++ b/kaudiocreator/tracksimp.cpp @@ -0,0 +1,578 @@ +/** + * This file is part of the KAudioCreator package + * Copyright (C) 2003 Benjamin C Meyer (ben+kaudiocreator at meyerhome dot net) + * + * 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 library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#include <dcopref.h> +#include <fixx11h.h> + +#include <kapplication.h> +#include <kconfig.h> +#include <kcombobox.h> +#include <kdebug.h> +#include <kinputdialog.h> +#include <klistview.h> +#include <kprocess.h> +#include <kmessagebox.h> +#include <kurl.h> + +#include <qfileinfo.h> +#include <qlabel.h> +#include <qptrlist.h> +#include <qpushbutton.h> +#include <qregexp.h> +#include <qspinbox.h> +#include <qtimer.h> + +#include "job.h" +#include "kcompactdisc.h" +#include "libkcddb/cdinfodialogbase.h" +#include "prefs.h" +#include "tracksimp.h" + +/** + * Constructor, connect up slots and signals. + */ +TracksImp::TracksImp( QWidget* parent, const char* name) : + Tracks(parent,name), + cddbInfo() +{ + cd = new KCompactDisc; + + connect(cd,SIGNAL(discChanged(unsigned)),this,SLOT(newDisc(unsigned))); + + connect(trackListing, SIGNAL(clicked( QListViewItem * )), this, SLOT(selectTrack(QListViewItem*))); + connect(trackListing, SIGNAL(doubleClicked(QListViewItem *)), this, SLOT(editInformation())); + connect(trackListing, SIGNAL(returnPressed(QListViewItem *)), this, SLOT(editInformation())); + connect(selectAllTracksButton, SIGNAL(clicked()), this, SLOT(selectAllTracks())); + connect(deselectAllTracksButton, SIGNAL(clicked()), this, SLOT(deselectAllTracks())); + + connect(deviceCombo, SIGNAL(textChanged(const QString &)), this, SLOT(changeDevice(const QString &))); + + selectAllTracksButton->setEnabled( false ); + deselectAllTracksButton->setEnabled( false ); + + cddb = new KCDDB::Client(); + cddb->setBlockingMode(false); + connect(cddb, SIGNAL(finished(CDDB::Result)), this, SLOT(lookupCDDBDone(CDDB::Result))); + trackListing->setSorting(-1, false); + loadSettings(); +} + +/** + * store the current device from the combo. + */ +TracksImp::~TracksImp() { + QStringList list; + if( deviceCombo->count() != 0) + list.append(deviceCombo->currentText()); + for ( int i=0; i<deviceCombo->count();i++ ) { + QString text = deviceCombo->text(i); + if( list.find(text) == list.end()) + list.append(text); + if( list.count() == 5) + break; + } + + Prefs::setDevice(list); + Prefs::writeConfig(); +} + +/** + * Load the class settings. + */ +void TracksImp::loadSettings() { + QStringList list; + + // Add the saved list, no dups + QStringList prefsList = Prefs::device(); + QStringList::Iterator it; + for ( it = prefsList.begin(); it != prefsList.end(); ++it ) { + if( list.find( *it ) == list.end()) + list.append(*it); + } + // Get current list, no dups + for ( int i=0; i<deviceCombo->count();i++ ) { + QString text = deviceCombo->text(i); + if( list.find(text) == list.end()) + list.append(text); + } + + // Set list, get top one + deviceCombo->clear(); + deviceCombo->insertStringList(list); + + changeDevice(deviceCombo->currentText()); +} + +void TracksImp::newDisc(unsigned discId) +{ + if (discId == KCompactDisc::missingDisc) + { + kdDebug() << "newDisc - No disc" << endl; + cddbInfo.clear(); + cddbInfo.title = i18n("No disc"); + newAlbum(); + emit(hasCD(false)); + + selectAllTracksButton->setEnabled( false ); + deselectAllTracksButton->setEnabled( false ); + + return; + } + + kdDebug() << "newDisc - " << discId << endl; + emit(hasCD(true)); + + selectAllTracksButton->setEnabled( true ); + deselectAllTracksButton->setEnabled( true ); + + cddbInfo.clear(); + + cddbInfo.id = QString::number(discId, 16).rightJustify(8,'0'); + cddbInfo.length = cd->discLength(); + + cddbInfo.artist = cd->discArtist(); + cddbInfo.title = cd->discTitle(); + + // If it's a sampler, we'll do artist/title. + bool isSampler = (cddbInfo.title.compare("Various") == 0); + KCDDB::TrackInfo track; + for (unsigned i = 1; i <= cd->tracks(); i++) { + if (isSampler) + track.title = cd->trackArtist(i) + " / " + cd->trackTitle(i); + else + track.title = cd->trackTitle(i); + cddbInfo.trackInfoList.append(track); + } + + newAlbum(); + + if (Prefs::performCDDBauto()) + lookupCDDB(); +} + +/** + * @return if there is a cd inserted or not. + */ +bool TracksImp::hasCD(){ + return cd->discId() != KCompactDisc::missingDisc; +} + +/** + * The device text has changed. + * @param file - the new text to check. + */ +void TracksImp::changeDevice(const QString &file ) { + QString newDevice = KCompactDisc::urlToDevice(file); + + if( newDevice == cd->device() ) { + //qDebug("Device names match, returning"); + return; + } + + QFileInfo fileInfo(newDevice); + if( !fileInfo.exists() || fileInfo.isDir()) { + //qDebug("Device file !exist or isDir or !file"); + return; + } + + if (!cd->setDevice(newDevice, 50, false)) + { + QString errstring = + i18n("CDROM read or access error (or no audio disk in drive).\n"\ + "Please make sure you have access permissions to:\n%1") + .arg(file); + KMessageBox::error(this, errstring, i18n("Error")); + } +} + +/** + * Helper function (toolbar button) for users. + **/ +void TracksImp::performCDDB() { + if (!hasCD()) { + KMessageBox::sorry(this, i18n("Please insert a disk."), + i18n("CDDB Failed")); + return; + } + + lookupCDDB(); +} + +/** + * See if we can't get the cddb value for this cd. + */ +void TracksImp::lookupCDDB() { + cddb->config().reparse(); + cddb->lookup(cd->discSignature()); +} + +/** + * The non blocking CDDB function calling has finished. Report an error or + * continue. + * @param result the success or failure of the cddb retrieval. + */ +void TracksImp::lookupCDDBDone(CDDB::Result result ) { + if ((result != KCDDB::CDDB::Success) && + (result != KCDDB::CDDB::MultipleRecordFound)) + { + KMessageBox::sorry(this, i18n("Unable to retrieve CDDB information."), i18n("CDDB Failed")); + return; + } + + // Choose the cddb entry + KCDDB::CDInfo info = cddb->bestLookupResponse(); + // TODO Why doesn't libcddb not return MultipleRecordFound? + //if( result == KCDDB::CDDB::MultipleRecordFound ) { + if( Prefs::promptIfIncompleteInfo() && cddb->lookupResponse().count() > 1 ) { + QString searchedCDId = cddbInfo.id; + CDInfoList cddb_info = cddb->lookupResponse(); + CDInfoList::iterator it; + QStringList list; + for ( it = cddb_info.begin(); it != cddb_info.end(); ++it ) { + list.append( QString("%1, %2, %3").arg((*it).artist).arg((*it).title) + .arg((*it).genre)); + } + + bool ok(false); + QString res = KInputDialog::getItem( + i18n("Select CDDB entry"), + i18n("Select a CDDB entry:"), list, 0, false, &ok, + this ); + if ( ok ) { + // The user selected and item and pressed OK + uint c = 0; + for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { + if( *it == res) break; + c++; + } + if( c < cddb_info.size() ) + info = cddb_info[c]; + } else { + return; + // user pressed Cancel + } + // Check that the CD we looked up is the one now loaded. + // The user might have ejected the CD while we were in the + // KInputDialog event loop, and replaced it with another one. + if ( searchedCDId != cddbInfo.id ) + return; + } + + // Some sanity provisions to ensure that the number of records matches what + // the CD actually contains. + while (info.trackInfoList.count() < cddbInfo.trackInfoList.count()) + { + info.trackInfoList.append(KCDDB::TrackInfo()); + } + while (info.trackInfoList.count() > cddbInfo.trackInfoList.count()) + { + info.trackInfoList.pop_back(); + } + cddbInfo = info; + newAlbum(); + + // See if the user wishes to automaticly rip after successfully retrieving + if( Prefs::autoRip()) + ripWholeAlbum(); +} + +/** + * Bring up the dialog to edit the information about this album. + * If there is not currently selected track return. + * If ok is pressed then store the information and update track name. + */ +void TracksImp::editInformation( ) +{ + if( !hasCD() ) return; + // Create dialog. + KDialogBase *dialog = new KDialogBase( this, "name", false, i18n( "CD Editor" ), + KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok, true ); + CDInfoDialogBase *base = new CDInfoDialogBase(dialog, "Album info editor dialog"); + // Workaround the fact that CDInfoDialogBase doesn't take + // a const TrackOffsetList + QValueList<unsigned> discSig = cd->discSignature(); + base->setInfo(cddbInfo, discSig); + dialog->setMainWidget(base); + + // Show dialog->and save results. + bool okClicked = dialog->exec(); + if( okClicked ) { + cddbInfo = base->info(); + newAlbum(); + KCDDB::Cache::store(cddbInfo); + } + delete dialog; +} + +QString TracksImp::formatTime(unsigned ms) +{ + QTime time; + + time = time.addMSecs((int)ms); + + // Use ".zzz" for milliseconds... + QString temp2; + if (time.hour() > 0) + temp2 = time.toString("hh:mm:ss"); + else + temp2 = time.toString("mm:ss"); + return temp2; +} + +/** + * Helper function. + * Selects all tracks and then calls startSession to rip them all. + */ +void TracksImp::ripWholeAlbum() { + selectAllTracks(); + startSession(); +} + +/** + * Start of the "ripping session" by emiting signals to rip the selected tracks. + * If any album information is not set, notify the user first. + */ +void TracksImp::startSession( int encoder ) +{ + QPtrList<TracksItem> selected = selectedTracks(); + + if( selected.isEmpty() ) + { + int i = KMessageBox::questionYesNo( this, i18n("No tracks have been selected. Would you like to rip the entire CD?"), + i18n("No Tracks Selected"), i18n("Rip CD"), KStdGuiItem::cancel() ); + if( i == KMessageBox::No ) + return; + + selectAllTracks(); + selected = selectedTracks(); + } + + QStringList list; + if( cddbInfo.genre == "Unknown" ) + list += "Genre"; + if( cddbInfo.year == 0 ) + list += "Year"; + if( cddbInfo.artist == "Unknown Artist") + list += "Artist"; + if( cddbInfo.title == "Unknown Album") + list += "Album"; + + if( Prefs::promptIfIncompleteInfo() && list.count() > 0 ) + { + int r = KMessageBox::questionYesNo( this, + i18n( "Part of the album is not set: %1.\n (To change album information click the \"Edit Information\" button.)\n Would you like to rip the selected tracks anyway?").arg(list.join(", ")), i18n("Album Information Incomplete"), i18n("Rip"), KStdGuiItem::cancel() ); + + if( r == KMessageBox::No ) + return; + } + + if ( encoder == -1 ) + encoder = Prefs::currentEncoder(); + + Job *lastJob = 0; + TracksItem *item = selected.first(); + + for( ; item ; item = selected.next() ) + { + Job *newJob = new Job(); + newJob->encoder = encoder; + newJob->device = cd->device(); + newJob->album = cddbInfo.title; + newJob->genre = cddbInfo.genre; + if( newJob->genre.isEmpty() ) + newJob->genre = "Pop"; + + newJob->group = cddbInfo.artist; + newJob->comment = cddbInfo.extd; + newJob->year = cddbInfo.year; + newJob->track = item->track(); + +// newJob->track_title = item->title(); + newJob->track_title = item->text( HEADER_TRACK_NAME ); + newJob->track_artist = item->artist(); + newJob->track_comment = item->comment(); + lastJob = newJob; + emit( ripTrack(newJob) ); + } + if( lastJob) + lastJob->lastSongInAlbum = true; + + KMessageBox::information(this, + i18n("%1 Job(s) have been started. You can watch their progress in the " + "jobs section.").arg( selected.count() ), + i18n("Jobs have started"), i18n("Jobs have started")); +} + +/** + * Selects and unselects the tracks. + * @param currentItem the track to swich the selection choice. + */ +void TracksImp::selectTrack( QListViewItem *item ) +{ + if( !item ) + return; + +#define item static_cast<TracksItem*>(item) + item->setChecked( !item->checked() ); +#undef item +} + +QPtrList<TracksItem> TracksImp::selectedTracks() +{ + QPtrList<TracksItem> selected; + TracksItem *item = static_cast<TracksItem*>(trackListing->firstChild()); + + while( item ) + { + if( item->checked() ) + selected.append( item ); + item = static_cast<TracksItem*>(item->nextSibling()); + } + return selected; +} + +/** + * Turn on all of the tracks. + */ +void TracksImp::selectAllTracks() +{ + TracksItem *currentItem = static_cast<TracksItem*>(trackListing->firstChild()); + while( currentItem ) + { + currentItem->setChecked( true ); + currentItem = static_cast<TracksItem*>(currentItem->nextSibling()); + } +} + +/** + * Turn off all of the tracks. + */ +void TracksImp::deselectAllTracks() +{ + TracksItem *currentItem = static_cast<TracksItem*>(trackListing->firstChild()); + while( currentItem ) + { + currentItem->setChecked( false ); + currentItem = static_cast<TracksItem*>(currentItem->nextSibling()); + } +} + +/** + * Set the current stats for the new album being displayed. + */ +void TracksImp::newAlbum() +{ + QString albumText = cddbInfo.title; + if( !cddbInfo.artist.isEmpty() ) + albumText = cddbInfo.artist + i18n( " - " ) + albumText; + + albumName->setText( albumText ); + trackListing->clear(); + selectAllTracksButton->setEnabled(false); + deselectAllTracksButton->setEnabled(false); + + emit( hasTracks(false) ); + + KCDDB::TrackInfoList t = cddbInfo.trackInfoList; + + bool isSampler = true; + for( unsigned i = 0; i < t.count(); i++ ) + { + if (t[i].title.find(" / ") == -1) + { + isSampler = false; + break; + } + } + + TracksItem *last = 0; + for( unsigned i = 0; i < t.count(); i++ ) + { + QString trackArtist; + QString title; + + if( isSampler ) + { + // Support for multiple artists stripping. + int delimiter = t[i].title.find(" / "); + Q_ASSERT( delimiter != -1 ); + trackArtist = t[i].title.left(delimiter); + title = t[i].title.mid(delimiter + 3); + } + else { + trackArtist = cddbInfo.artist; + title = t[i].title; + } + + // There is a new track for this title. Add it to the list of tracks. + QString trackLength = formatTime(cd->trackLength(i+1)); + last = new TracksItem( trackListing, last, title, trackArtist, i+1, trackLength, t[i].extt ); + } + + if( t.count() ) + { + // Set the current selected track to the first one. + trackListing->setCurrentItem(trackListing->firstChild()); + selectAllTracksButton->setEnabled(true); + deselectAllTracksButton->setEnabled(true); + emit(hasTracks(true)); + } +} + + +/** + * If the user presses the F2 key, trigger renaming of the title. + * @param event the QKeyEvent passed to this event handler. + */ +void TracksImp::keyPressEvent(QKeyEvent *event) +{ + QListViewItem *item = trackListing->selectedItem(); + if( !item ) return; + + if( event->key() == Qt::Key_F2 ) + { + item->setRenameEnabled( HEADER_TRACK_NAME, true ); + item->startRename( HEADER_TRACK_NAME ); + event->accept(); + } + else + Tracks::keyPressEvent(event); +} + +/** + * Eject the current cd device + */ +void TracksImp::eject() { + ejectDevice(cd->device()); +} + +/** + * Eject a device + * @param deviceToEject the device to eject. + */ +void TracksImp::ejectDevice(const QString &deviceToEject) { + changeDevice(deviceToEject); + + cd->eject(); +} + +#include "tracksimp.moc" + diff --git a/kaudiocreator/tracksimp.h b/kaudiocreator/tracksimp.h new file mode 100644 index 00000000..f193ac3a --- /dev/null +++ b/kaudiocreator/tracksimp.h @@ -0,0 +1,136 @@ +/** + * This file is part of the KAudioCreator package + * Copyright (C) 2003 Benjamin C Meyer (ben+kaudiocreator at meyerhome dot net) + * + * 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 library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef TRACKSIMP_H +#define TRACKSIMP_H + +#include "tracks.h" +#include <kiconloader.h> +#include <klistview.h> +#include <klocale.h> + +// CDDB support via libkcddb +#include <libkcddb/client.h> + +#define HEADER_RIP 0 +#define HEADER_TRACK 1 +#define HEADER_LENGTH 2 +#define HEADER_TRACK_NAME 3 +#define HEADER_TRACK_ARTIST 4 +#define HEADER_TRACK_COMMENT 5 + +using namespace KCDDB; +class Job; +class KProcess; +class KCompactDisc; + +class TracksItem : public KListViewItem +{ +public: + TracksItem( KListView *parent, KListViewItem *after, QString t, QString a, int tr, QString l, QString c ) + : KListViewItem( parent, after, QString::null/*rip*/, QString::number(tr), l, t ) + { + m_title = t; + m_artist = a; + m_length = l; + m_track = tr; + m_comment = c; + m_checked = false; + } + + QString title() const { return m_title; } + QString artist() const { return m_artist; } + int track() const { return m_track; } + QString length() const { return m_length; } + bool checked() const { return m_checked; } + QString comment() const { return m_comment; } + #include <kdebug.h> + void setTitle( const QString &t ) { m_title = t; kdDebug() << "title: " << m_title << endl; } + void setChecked( const bool &b ) { + m_checked = b; + b ? setPixmap( HEADER_RIP, SmallIcon( "apply", height()-2 ) ) : + setPixmap( HEADER_RIP, 0 ); + } + +private: + QString m_title; + QString m_artist; + int m_track; + QString m_length; + QString m_comment; + bool m_checked; // marked for ripping +}; + + + +/** + * This class handles the display of the tracks. It also starts off the job que. + */ +class TracksImp : public Tracks { + +Q_OBJECT + +signals: + void ripTrack(Job *job); + void hasCD(bool); + void hasTracks(bool); + +public: + TracksImp( QWidget* parent = 0, const char* name = 0); + ~TracksImp(); + + bool hasCD(); + +public slots: + void loadSettings(); + + // Toolbar Buttons + void startSession( int encoder = -1 ); + void editInformation(); + void performCDDB(); + void ejectDevice(const QString &deviceToEject); + void eject(); + void selectAllTracks(); + void deselectAllTracks(); + +private slots: + void changeDevice(const QString &file); + void keyPressEvent(QKeyEvent *event); + void lookupCDDBDone(CDDB::Result result); + void newDisc(unsigned discId); + void selectTrack(QListViewItem *); + +private: + void lookupDevice(); + void lookupCDDB(); + void newAlbum(); + void ripWholeAlbum(); + QPtrList<TracksItem> selectedTracks(); + + QString formatTime(unsigned ms); + + KCDDB::Client *cddb; + KCompactDisc *cd; + + // Current album + KCDDB::CDInfo cddbInfo; +}; + +#endif // TRACKSIMP_H diff --git a/kaudiocreator/upgrade-kaudiocreator-metadata.sh b/kaudiocreator/upgrade-kaudiocreator-metadata.sh new file mode 100755 index 00000000..a288c411 --- /dev/null +++ b/kaudiocreator/upgrade-kaudiocreator-metadata.sh @@ -0,0 +1,77 @@ +#! /usr/bin/env bash + +while read; do + if [ "${REPLY#\[}" != "$REPLY" ] ; then # group name + GROUP="${REPLY:1:${#REPLY}-2}" + continue; + fi + # normal key=value pair: + KEY="${REPLY%%=*}" + VALUE="${REPLY#*=}" + + case "$GROUP/$KEY" in + encoderconfig/fileFormat) + VALUE=`echo $VALUE | sed -e s/%album/%{albumtitle}/g`; + VALUE=`echo $VALUE | sed -e s/%artist/%{albumartist}/g`; + VALUE=`echo $VALUE | sed -e s/%song/%{title}/g`; + VALUE=`echo $VALUE | sed -e s/%track/%{number}/g`; + VALUE=`echo $VALUE | sed -e s/%genre/%{genre}/g`; + VALUE=`echo $VALUE | sed -e s/%extension/%{extension}/g`; + VALUE=`echo $VALUE | sed -e s/%year/%{year}/g`; + echo "[encoderconfig]"; + echo "fileFormat=$VALUE" + echo "# DELETE [encoderconfig]fileFormat" + ;; + + Encoder_0/commandLine) + VALUE=`echo $VALUE | sed -e s/%album/%{albumtitle}/g`; + VALUE=`echo $VALUE | sed -e s/%artist/%{albumartist}/g`; + VALUE=`echo $VALUE | sed -e s/%song/%{title}/g`; + VALUE=`echo $VALUE | sed -e s/%track/%{number}/g`; + VALUE=`echo $VALUE | sed -e s/%genre/%{genre}/g`; + VALUE=`echo $VALUE | sed -e s/%extension/%{extension}/g`; + VALUE=`echo $VALUE | sed -e s/%year/%{year}/g`; + echo "[Encoder_0]"; + echo "commandLine=$VALUE" + echo "# DELETE [Encoder_0]commandLine" + ;; + + Encoder_1/commandLine) + VALUE=`echo $VALUE | sed -e s/%album/%{albumtitle}/g`; + VALUE=`echo $VALUE | sed -e s/%artist/%{albumartist}/g`; + VALUE=`echo $VALUE | sed -e s/%song/%{title}/g`; + VALUE=`echo $VALUE | sed -e s/%track/%{number}/g`; + VALUE=`echo $VALUE | sed -e s/%genre/%{genre}/g`; + VALUE=`echo $VALUE | sed -e s/%extension/%{extension}/g`; + VALUE=`echo $VALUE | sed -e s/%year/%{year}/g`; + echo "[Encoder_1]"; + echo "commandLine=$VALUE" + echo "# DELETE [Encoder_1]commandLine" + ;; + + Encoder_2/commandLine) + VALUE=`echo $VALUE | sed -e s/%album/%{albumtitle}/g`; + VALUE=`echo $VALUE | sed -e s/%artist/%{albumartist}/g`; + VALUE=`echo $VALUE | sed -e s/%song/%{title}/g`; + VALUE=`echo $VALUE | sed -e s/%track/%{number}/g`; + VALUE=`echo $VALUE | sed -e s/%genre/%{genre}/g`; + VALUE=`echo $VALUE | sed -e s/%extension/%{extension}/g`; + VALUE=`echo $VALUE | sed -e s/%year/%{year}/g`; + echo "[Encoder_2]"; + echo "commandLine=$VALUE" + echo "# DELETE [Encoder_2]commandLine" + ;; + Encoder_3/commandLine) + VALUE=`echo $VALUE | sed -e s/%album/%{albumtitle}/g`; + VALUE=`echo $VALUE | sed -e s/%artist/%{albumartist}/g`; + VALUE=`echo $VALUE | sed -e s/%song/%{title}/g`; + VALUE=`echo $VALUE | sed -e s/%track/%{number}/g`; + VALUE=`echo $VALUE | sed -e s/%genre/%{genre}/g`; + VALUE=`echo $VALUE | sed -e s/%extension/%{extension}/g`; + VALUE=`echo $VALUE | sed -e s/%year/%{year}/g`; + echo "[Encoder_3]"; + echo "commandLine=$VALUE" + echo "# DELETE [Encoder_3]commandLine" + ;; + esac +done diff --git a/kaudiocreator/wizard.ui b/kaudiocreator/wizard.ui new file mode 100644 index 00000000..7658557b --- /dev/null +++ b/kaudiocreator/wizard.ui @@ -0,0 +1,410 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>fileWizard</class> +<widget class="QDialog"> + <property name="name"> + <cstring>fileWizard</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>582</width> + <height>456</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>1</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="caption"> + <string>File Location Wizard</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>TextLabel8</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>3</hsizetype> + <vsizetype>3</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>When files have finished being processed, they are saved based upon the <i>File Location</i>. Information about the track should be used within that text. There are eleven special words starting with a % that will be replaced with the corresponding track's information. Each of the buttons below will insert its replacement word into the <i>File Location</i> where the cursor is. Use at least one replacement string to make sure that the <i>File Location</i> is unique.</string> + </property> + <property name="textFormat"> + <enum>RichText</enum> + </property> + <property name="alignment"> + <set>WordBreak|AlignTop|AlignLeft</set> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer6</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>16</height> + </size> + </property> + </spacer> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>Layout8</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>TextLabel9</cstring> + </property> + <property name="text"> + <string>&File location:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>playlistFormat</cstring> + </property> + </widget> + <widget class="QLineEdit"> + <property name="name"> + <cstring>fileFormat</cstring> + </property> + <property name="text"> + <string>~/%{extension}/%{artist}/%{album}/%{artist} - %{album}.m3u</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>exampleLabel</cstring> + </property> + <property name="text"> + <string>Example: ~/mp3/Staind/Lost Love/Staind - Lost Love.m3u</string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout15</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QPushButton" row="0" column="1"> + <property name="name"> + <cstring>artistButton</cstring> + </property> + <property name="text"> + <string>&Artist</string> + </property> + </widget> + <widget class="QPushButton" row="2" column="2"> + <property name="name"> + <cstring>homeDirButton</cstring> + </property> + <property name="text"> + <string>&Home Folder</string> + </property> + </widget> + <widget class="QPushButton" row="1" column="3"> + <property name="name"> + <cstring>trackNumberButton</cstring> + </property> + <property name="text"> + <string>&Track Number</string> + </property> + </widget> + <widget class="QPushButton" row="2" column="1"> + <property name="name"> + <cstring>extensionButton</cstring> + </property> + <property name="text"> + <string>&Extension</string> + </property> + </widget> + <widget class="QPushButton" row="1" column="0"> + <property name="name"> + <cstring>trackTitleButton</cstring> + </property> + <property name="text"> + <string>Track T&itle</string> + </property> + </widget> + <widget class="QPushButton" row="1" column="2"> + <property name="name"> + <cstring>trackCommentButton</cstring> + </property> + <property name="text"> + <string>T&rack Comment</string> + </property> + </widget> + <widget class="QPushButton" row="2" column="0"> + <property name="name"> + <cstring>genreButton</cstring> + </property> + <property name="text"> + <string>&Genre</string> + </property> + </widget> + <widget class="QPushButton" row="0" column="3"> + <property name="name"> + <cstring>yearButton</cstring> + </property> + <property name="text"> + <string>&Year</string> + </property> + </widget> + <widget class="QPushButton" row="0" column="0"> + <property name="name"> + <cstring>albumButton</cstring> + </property> + <property name="text"> + <string>Al&bum</string> + </property> + </widget> + <widget class="QPushButton" row="1" column="1"> + <property name="name"> + <cstring>trackArtistButton</cstring> + </property> + <property name="text"> + <string>Trac&k Artist</string> + </property> + </widget> + <widget class="QPushButton" row="0" column="2"> + <property name="name"> + <cstring>commentButton</cstring> + </property> + <property name="text"> + <string>Co&mment</string> + </property> + </widget> + </grid> + </widget> + <widget class="Line"> + <property name="name"> + <cstring>Line2</cstring> + </property> + <property name="frameShape"> + <enum>HLine</enum> + </property> + <property name="frameShadow"> + <enum>Sunken</enum> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>Layout1</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <spacer> + <property name="name"> + <cstring>Horizontal Spacing2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>buttonOk</cstring> + </property> + <property name="text"> + <string>&OK</string> + </property> + <property name="autoDefault"> + <bool>true</bool> + </property> + <property name="default"> + <bool>true</bool> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>buttonCancel</cstring> + </property> + <property name="text"> + <string>&Cancel</string> + </property> + <property name="autoDefault"> + <bool>true</bool> + </property> + </widget> + </hbox> + </widget> + </vbox> +</widget> +<connections> + <connection> + <sender>buttonOk</sender> + <signal>clicked()</signal> + <receiver>fileWizard</receiver> + <slot>accept()</slot> + </connection> + <connection> + <sender>buttonCancel</sender> + <signal>clicked()</signal> + <receiver>fileWizard</receiver> + <slot>reject()</slot> + </connection> + <connection> + <sender>homeDirButton</sender> + <signal>clicked()</signal> + <receiver>fileWizard</receiver> + <slot>homePressed()</slot> + </connection> + <connection> + <sender>artistButton</sender> + <signal>clicked()</signal> + <receiver>fileWizard</receiver> + <slot>artistPressed()</slot> + </connection> + <connection> + <sender>trackNumberButton</sender> + <signal>clicked()</signal> + <receiver>fileWizard</receiver> + <slot>trackNumberPressed()</slot> + </connection> + <connection> + <sender>yearButton</sender> + <signal>clicked()</signal> + <receiver>fileWizard</receiver> + <slot>yearPressed()</slot> + </connection> + <connection> + <sender>extensionButton</sender> + <signal>clicked()</signal> + <receiver>fileWizard</receiver> + <slot>extensionPressed()</slot> + </connection> + <connection> + <sender>albumButton</sender> + <signal>clicked()</signal> + <receiver>fileWizard</receiver> + <slot>albumPressed()</slot> + </connection> + <connection> + <sender>trackTitleButton</sender> + <signal>clicked()</signal> + <receiver>fileWizard</receiver> + <slot>trackTitlePressed()</slot> + </connection> + <connection> + <sender>genreButton</sender> + <signal>clicked()</signal> + <receiver>fileWizard</receiver> + <slot>genrePressed()</slot> + </connection> + <connection> + <sender>fileFormat</sender> + <signal>textChanged(const QString&)</signal> + <receiver>fileWizard</receiver> + <slot>fileFormatTextChanged(const QString&)</slot> + </connection> + <connection> + <sender>trackArtistButton</sender> + <signal>clicked()</signal> + <receiver>fileWizard</receiver> + <slot>trackArtistPressed()</slot> + </connection> + <connection> + <sender>trackCommentButton</sender> + <signal>clicked()</signal> + <receiver>fileWizard</receiver> + <slot>trackCommentPressed()</slot> + </connection> + <connection> + <sender>commentButton</sender> + <signal>clicked()</signal> + <receiver>fileWizard</receiver> + <slot>commentPressed()</slot> + </connection> +</connections> +<tabstops> + <tabstop>fileFormat</tabstop> + <tabstop>albumButton</tabstop> + <tabstop>artistButton</tabstop> + <tabstop>commentButton</tabstop> + <tabstop>yearButton</tabstop> + <tabstop>trackNumberButton</tabstop> + <tabstop>trackArtistButton</tabstop> + <tabstop>trackCommentButton</tabstop> + <tabstop>trackTitleButton</tabstop> + <tabstop>genreButton</tabstop> + <tabstop>extensionButton</tabstop> + <tabstop>homeDirButton</tabstop> + <tabstop>buttonOk</tabstop> + <tabstop>buttonCancel</tabstop> +</tabstops> +<includes> + <include location="local" impldecl="in implementation">wizard.ui.h</include> +</includes> +<slots> + <slot access="private">homePressed()</slot> + <slot>extensionPressed()</slot> + <slot access="private">trackTitlePressed()</slot> + <slot>trackArtistPressed()</slot> + <slot access="private">trackNumberPressed()</slot> + <slot>trackCommentPressed()</slot> + <slot access="private">yearPressed()</slot> + <slot>genrePressed()</slot> + <slot>albumPressed()</slot> + <slot>artistPressed()</slot> + <slot>commentPressed()</slot> + <slot>fileFormatTextChanged( const QString & text )</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/kaudiocreator/wizard.ui.h b/kaudiocreator/wizard.ui.h new file mode 100644 index 00000000..95b26b7b --- /dev/null +++ b/kaudiocreator/wizard.ui.h @@ -0,0 +1,110 @@ +/** + * This file is part of the KAudioCreator package + * Copyright (C) 2003 Benjamin C Meyer (ben+kaudiocreator at meyerhome dot net) + * + * 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 library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/**************************************************************************** +** ui.h extension file, included from the uic-generated form implementation. +** +** If you wish to add, delete or rename slots use Qt Designer which will +** update this file, preserving your code. Create an init() slot in place of +** a constructor, and a destroy() slot in place of a destructor. +*****************************************************************************/ + +#include <qstring.h> +#include <qregexp.h> +#include <qmap.h> +#include <klocale.h> +#include "job.h" + +void fileWizard::homePressed() +{ + fileFormat->insert("~"); +} + +void fileWizard::extensionPressed() +{ + fileFormat->insert("%{extension}"); +} + +void fileWizard::trackTitlePressed() +{ + fileFormat->insert("%{title}"); +} + +void fileWizard::trackArtistPressed() +{ + fileFormat->insert("%{artist}"); +} + +void fileWizard::trackNumberPressed() +{ + fileFormat->insert("%{number}"); +} + +void fileWizard::trackCommentPressed() +{ + fileFormat->insert("%{comment}"); +} + +void fileWizard::yearPressed() +{ + fileFormat->insert("%{year}"); +} + +void fileWizard::genrePressed() +{ + fileFormat->insert("%{genre}"); +} + +void fileWizard::albumPressed() +{ + fileFormat->insert("%{albumtitle}"); +} + +void fileWizard::artistPressed() +{ + fileFormat->insert("%{albumartist}"); +} + +void fileWizard::commentPressed() +{ + fileFormat->insert("%{albumcomment}"); +} + +void fileWizard::fileFormatTextChanged(const QString& text) +{ + QString string = text; + string.replace(QRegExp("~"), "/home/foo"); + Job job; + job.genre = "Rock"; + job.group = "J Rocker"; + job.album = "Why Rain"; + job.year = 2002; + job.track = 9; + job.comment = "This Album rocks!"; + + job.track_title = "Time"; + job.track_artist = "John Rocker"; + job.track_comment = "This Song Rocks!"; + QMap<QString,QString> map; + map.insert("extension", "mp3"); + string = job.replaceSpecialChars(string, false, map); + exampleLabel->setText(i18n("Example: %1").arg(string)); +} + |