summaryrefslogtreecommitdiffstats
path: root/kaudiocreator
diff options
context:
space:
mode:
Diffstat (limited to 'kaudiocreator')
-rw-r--r--kaudiocreator/Makefile.am44
-rw-r--r--kaudiocreator/TODO19
-rw-r--r--kaudiocreator/audiocd_extract.desktop54
-rw-r--r--kaudiocreator/cdconfig.ui61
-rw-r--r--kaudiocreator/configure.in.in0
-rw-r--r--kaudiocreator/encodefile.ui345
-rw-r--r--kaudiocreator/encodefileimp.cpp82
-rw-r--r--kaudiocreator/encodefileimp.h57
-rw-r--r--kaudiocreator/encoder.cpp331
-rw-r--r--kaudiocreator/encoder.h68
-rw-r--r--kaudiocreator/encoder_prefs.kcfgc7
-rw-r--r--kaudiocreator/encoder_prefs_addons.h8
-rw-r--r--kaudiocreator/encoderconfig.ui293
-rw-r--r--kaudiocreator/encoderconfig.ui.h25
-rw-r--r--kaudiocreator/encoderconfigimp.cpp289
-rw-r--r--kaudiocreator/encoderconfigimp.h57
-rw-r--r--kaudiocreator/encoderedit.ui98
-rw-r--r--kaudiocreator/encoderoutput.ui103
-rw-r--r--kaudiocreator/eventsrc528
-rw-r--r--kaudiocreator/general.ui285
-rw-r--r--kaudiocreator/general.ui.h19
-rw-r--r--kaudiocreator/hi16-app-kaudiocreator.pngbin0 -> 971 bytes
-rw-r--r--kaudiocreator/hi32-app-kaudiocreator.pngbin0 -> 2596 bytes
-rw-r--r--kaudiocreator/icons/Makefile.am4
-rw-r--r--kaudiocreator/icons/check.pngbin0 -> 130 bytes
-rw-r--r--kaudiocreator/infodialog.ui297
-rw-r--r--kaudiocreator/job.cpp58
-rw-r--r--kaudiocreator/job.h78
-rw-r--r--kaudiocreator/jobque.ui132
-rw-r--r--kaudiocreator/jobqueimp.cpp310
-rw-r--r--kaudiocreator/jobqueimp.h80
-rw-r--r--kaudiocreator/kaudiocreator-libkcddb.upd6
-rw-r--r--kaudiocreator/kaudiocreator-meta.upd3
-rw-r--r--kaudiocreator/kaudiocreator.cpp305
-rw-r--r--kaudiocreator/kaudiocreator.desktop137
-rw-r--r--kaudiocreator/kaudiocreator.h93
-rw-r--r--kaudiocreator/kaudiocreator.kcfg107
-rw-r--r--kaudiocreator/kaudiocreator_encoders.kcfg28
-rw-r--r--kaudiocreator/kaudiocreator_workman.h27
-rw-r--r--kaudiocreator/kaudiocreatorui.rc41
-rw-r--r--kaudiocreator/lo16-app-kaudiocreator.pngbin0 -> 313 bytes
-rw-r--r--kaudiocreator/lo32-app-kaudiocreator.pngbin0 -> 539 bytes
-rw-r--r--kaudiocreator/main.cpp56
-rw-r--r--kaudiocreator/prefs.kcfgc7
-rw-r--r--kaudiocreator/ripconfig.ui191
-rw-r--r--kaudiocreator/ripper.cpp263
-rw-r--r--kaudiocreator/ripper.h68
-rw-r--r--kaudiocreator/tracks.ui225
-rw-r--r--kaudiocreator/tracksimp.cpp578
-rw-r--r--kaudiocreator/tracksimp.h136
-rwxr-xr-xkaudiocreator/upgrade-kaudiocreator-metadata.sh77
-rw-r--r--kaudiocreator/wizard.ui410
-rw-r--r--kaudiocreator/wizard.ui.h110
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>&amp;Perform CDDB lookup automatically</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>kcfg_autoRip</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;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>&amp;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>&amp;Encode File</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>closeButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;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>&amp;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>&amp;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>&amp;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>&amp;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>&amp;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&amp;)</signal>
+ <receiver>currentEncoderName</receiver>
+ <slot>setText(const QString&amp;)</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>&amp;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>&amp;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&amp;)</signal>
+ <receiver>General</receiver>
+ <slot>updateExample()</slot>
+ </connection>
+ <connection>
+ <sender>kcfg_replaceOutput</sender>
+ <signal>textChanged(const QString&amp;)</signal>
+ <receiver>General</receiver>
+ <slot>updateExample()</slot>
+ </connection>
+ <connection>
+ <sender>example</sender>
+ <signal>textChanged(const QString&amp;)</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
new file mode 100644
index 00000000..8b65f1b1
--- /dev/null
+++ b/kaudiocreator/hi16-app-kaudiocreator.png
Binary files differ
diff --git a/kaudiocreator/hi32-app-kaudiocreator.png b/kaudiocreator/hi32-app-kaudiocreator.png
new file mode 100644
index 00000000..ed12f257
--- /dev/null
+++ b/kaudiocreator/hi32-app-kaudiocreator.png
Binary files differ
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
new file mode 100644
index 00000000..2890a7a4
--- /dev/null
+++ b/kaudiocreator/icons/check.png
Binary files differ
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>&amp;Previous Track</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>buttonNext</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Next Track</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>buttonOk</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;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>&amp;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>&amp;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
new file mode 100644
index 00000000..c518d066
--- /dev/null
+++ b/kaudiocreator/lo16-app-kaudiocreator.png
Binary files differ
diff --git a/kaudiocreator/lo32-app-kaudiocreator.png b/kaudiocreator/lo32-app-kaudiocreator.png
new file mode 100644
index 00000000..6f790413
--- /dev/null
+++ b/kaudiocreator/lo32-app-kaudiocreator.png
Binary files differ
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>&amp;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>&amp;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>&amp;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-&amp;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 &amp;All Tracks</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>deselectAllTracksButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;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 &lt;i&gt;File Location&lt;/i&gt;. 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 &lt;i&gt;File Location&lt;/i&gt; where the cursor is. Use at least one replacement string to make sure that the &lt;i&gt;File Location&lt;/i&gt; 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>&amp;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>&amp;Artist</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="2" column="2">
+ <property name="name">
+ <cstring>homeDirButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Home Folder</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="1" column="3">
+ <property name="name">
+ <cstring>trackNumberButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Track Number</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="2" column="1">
+ <property name="name">
+ <cstring>extensionButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Extension</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="1" column="0">
+ <property name="name">
+ <cstring>trackTitleButton</cstring>
+ </property>
+ <property name="text">
+ <string>Track T&amp;itle</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="1" column="2">
+ <property name="name">
+ <cstring>trackCommentButton</cstring>
+ </property>
+ <property name="text">
+ <string>T&amp;rack Comment</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="2" column="0">
+ <property name="name">
+ <cstring>genreButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Genre</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="0" column="3">
+ <property name="name">
+ <cstring>yearButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Year</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="0" column="0">
+ <property name="name">
+ <cstring>albumButton</cstring>
+ </property>
+ <property name="text">
+ <string>Al&amp;bum</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="1" column="1">
+ <property name="name">
+ <cstring>trackArtistButton</cstring>
+ </property>
+ <property name="text">
+ <string>Trac&amp;k Artist</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="0" column="2">
+ <property name="name">
+ <cstring>commentButton</cstring>
+ </property>
+ <property name="text">
+ <string>Co&amp;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>&amp;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>&amp;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&amp;)</signal>
+ <receiver>fileWizard</receiver>
+ <slot>fileFormatTextChanged(const QString&amp;)</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 &amp; 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));
+}
+