Commit 1a0287f7 authored by Matěj Laitl's avatar Matěj Laitl
Browse files

Rework transcoding: remember encoder, transcode on move, cleaner code

This is a major rework of transcoding feature that brings following
user-visible changes to Amarok:
 * Amarok can remember preferred transcoding configuration per each
   collection that supports transcoding. Therefore, the "Use default
   configuration" work-around can go away and the "Transcode or copy?"
   dialog can (and is) be one-step now. This preference can be changed
   in configuration.
 * Transcoding is now supported even during the move operation. No
   worries, only successfully transcoded tracks are removed from their
   original location.
 * Only formats playable on the target collection are offered. Already
   used & tested in yet-to-be-merged iPod collection rewrite.
 * The "Organize Tracks" dialog title and progress bar operation name
   now more verbosely describe actual operation to prevent user
   mistakes.
 * Double-transcode when ripping audio CDs that caused failures is
   avoided. (ChangeLog entry for this was miscredited to my earilier
   commit)

Technically, following changes are made:
 * many methods that accepted optional TranscodingConfiguration now
   either have it mandatory or not at all.
 * TranscodingConfiguration's NULL_CODEC was splitted to JUST_COPY and
   INVALID along with convenience methods isValid() and isJustCopy().
   This simplifies logic in many methods.
 * CollectionLocation::prepare{Copy,Move}() now don't have optional
   TranscodingConfiguration parameter. Depending on target collection,
   CollectionLocation determines it automatically or asks user in
   showSourceDialog() (overridable). AudioCdCollectionLocation already
   overrides it.
 * Collections that support transcoding now should expose
   TranscodeCapability which is used to a) indicate that transcoding
   is supported; b) query which file formats are playable on target
   collection; c) read & save & unset preferred transcoding parameters.

Why the hell the new Capability?
================================

Many Amarok devs dislike the concept of capabilities[1]. Why the hell I
introduced the new one? In ideal world Amarok would be able to transcode
everything regardless of the target collection. This is however not
doable witch current copyUrlToCollection() design - target collection
needs to do non-trivial things such as re-reading file tags, accounting
for different file name and space requirements etc. See my comments in
[1]. We therefore need a way for target collection to indicate it
supports transcoding (in order not to fool user). Some collection
locations such as TrashCollectionLocation should even intentionally
disallow transcoding. Additionally, we want to be able to query
supported destination file formats, to save preferred transcoding
paremeters etc.

I simply didn't want to pollute already over-crowded CollectionLocation
with three more methods used by only a few subclasses. On the other
hand, TranscodeCapability is not the central idea of this patch and I
can factor it into CollectionLocation should there be a voice supporting
it.

v2 patch version: gui string changes as suggested by Bart & Teo

[1] https://git.reviewboard.kde.org/r/103752/

FEATURE: 280526
FEATURE: 264681
CCBUG: 291722
BUG: 263775
FIXED-IN: 2.6
REVIEW: 104213
DIGEST: Feature: much improved transcoding
parent e9362ca7
......@@ -4,6 +4,8 @@ Amarok ChangeLog
Version 2.6-Beta 1
FEATURES:
* Amarok can now remember whether and how to transcode tracks when
transferring them to a particular collection. (BR 264681)
* "Crop playlist" functionality implemented using drag & drop. (BR 267729, 211811)
* Added keyboard shortcut for "Edit Track Information..." (BR 173814)
Patch by Jasneet Bhatti.
......@@ -26,6 +28,7 @@ Version 2.6-Beta 1
vice versa. (BR 142579)
CHANGES:
* It is now possible to transcode tracks when moving them. (BR 280526)
* Drag & drop of tracks and playlists to Saved Playlists works in all cases.
* Don't show unmounted USB Mass Storage devices and make it clear when
the device is not "activated" yet.
......@@ -42,6 +45,7 @@ Version 2.6-Beta 1
"1.2 GB free" is shown instead of "85% used"; thicker capacity bar.
BUGFIXES:
* Do not double-transcode tracks when importing from an audio CD. (BR 263775)
* Playlists with a dot in name can now be saved to Playlist Files on Disk. (BR 290318)
* iPod playlists now appear even when plugged in while Amarok is running. (BR 289303)
* Show in Media Sources actions no longer reset the collection sorting to artist/album. (BR 231858)
......@@ -53,7 +57,6 @@ Version 2.6-Beta 1
* Remove empty folders when deleting tracks from USB Mass Storage collection.
* Don't copy tracks to USB Mass Storage collection in move operation.
* Fix defunct aborting of transfers to USB Mass Storage collection. (BR 290448)
* Do not double-transcode tracks when importing from an audio CD. (BR 263775)
* Allow ripping of CD tracks with special characters in name tranks to
Björn Steinbrink. (BR 224437)
* Don't allow tracks to be dropped to their own collection and to
......
......@@ -891,6 +891,7 @@ qt4_add_dbus_adaptor(
set( amaroklib_DEPENDS "amarokpud" )
set( amaroklib_DEPENDS "amarokcore" )
set( amaroklib_DEPENDS "amarok-transcoding" ) # depends on generated ui_*.h file
kde4_add_kcfg_files(amaroklib_LIB_SRCS amarokconfig.kcfgc)
add_custom_target(amarokconfig_h DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/amarokconfig.h)
......
......@@ -44,7 +44,6 @@
#include "core/collections/QueryMaker.h"
#include "SvgHandler.h"
#include "TagDialog.h"
#include "transcoding/TranscodingAssistantDialog.h"
#include <KAction>
#include <KGlobalSettings>
......@@ -750,7 +749,7 @@ CollectionTreeView::organizeTracks( const QSet<CollectionTreeItem*> &items ) con
void
CollectionTreeView::copyTracks( const QSet<CollectionTreeItem*> &items, Collections::Collection *destination,
bool removeSources, Transcoding::Configuration configuration ) const
bool removeSources ) const
{
DEBUG_BLOCK
if( !destination || !destination->isWritable() )
......@@ -798,7 +797,7 @@ CollectionTreeView::copyTracks( const QSet<CollectionTreeItem*> &items, Collecti
else
{
debug() << "starting source->prepareCopy";
source->prepareCopy( qm, dest, configuration );
source->prepareCopy( qm, dest );
}
}
......@@ -1175,40 +1174,18 @@ void CollectionTreeView::slotEditTracks()
void CollectionTreeView::slotCopyTracks()
{
if( sender() )
{
if( QAction * action = dynamic_cast<QAction *>( sender() ) )
{
Transcoding::Configuration configuration = Transcoding::Configuration();
Collections::Collection *destCollection = m_currentCopyDestination[ action ];
if( destCollection->uidUrlProtocol() == "amarok-sqltrackuid" ) //we can only transcode to a SqlCollection for now
{
if( !Amarok::Components::transcodingController()->availableFormats().isEmpty() )
{
Transcoding::AssistantDialog dialog( this );
if( dialog.exec() )
configuration = dialog.configuration();
}
else
debug() << "FFmpeg is not installed or does not support any of the required formats.";
}
else
debug() << "The destination collection does not support transcoding.";
copyTracks( m_currentItems, destCollection, false, configuration );
}
}
if( !sender() )
return;
if( QAction *action = dynamic_cast<QAction *>( sender() ) )
copyTracks( m_currentItems, m_currentCopyDestination[ action ], false );
}
void CollectionTreeView::slotMoveTracks()
{
if( sender() )
{
if ( QAction * action = dynamic_cast<QAction *>( sender() ) )
copyTracks( m_currentItems, m_currentMoveDestination[ action ], true );
}
if( !sender() )
return;
if ( QAction *action = dynamic_cast<QAction *>( sender() ) )
copyTracks( m_currentItems, m_currentMoveDestination[ action ], true );
}
void
......
......@@ -21,7 +21,6 @@
#include "core/meta/Meta.h"
#include "playlist/PlaylistController.h"
#include "core/transcoding/TranscodingController.h"
#include <QModelIndex>
#include <QMutex>
......@@ -99,7 +98,7 @@ class CollectionTreeView: public Amarok::PrettyTreeView
void editTracks( const QSet<CollectionTreeItem*> &items ) const;
void organizeTracks( const QSet<CollectionTreeItem*> &items ) const;
void copyTracks( const QSet<CollectionTreeItem*> &items, Collections::Collection *destination,
bool removeSources, Transcoding::Configuration configuration = Transcoding::Configuration() ) const;
bool removeSources) const;
void removeTracks( const QSet<CollectionTreeItem*> &items, bool useTrash ) const;
// creates different actions from the different objects.
......
......@@ -35,11 +35,7 @@
#include "PaletteHandler.h"
#include "playlist/PlaylistController.h"
#include "PopupDropperFactory.h"
#include "SvgHandler.h"
#include "src/transcoding/TranscodingJob.h"
#include "src/transcoding/TranscodingAssistantDialog.h"
#include "src/core/transcoding/TranscodingController.h"
#include <KAction>
#include <KIO/CopyJob>
......@@ -141,10 +137,6 @@ FileView::contextMenuEvent( QContextMenuEvent *e )
}
menu->addMenu( copyMenu );
}
KAction *transcodeAction = new KAction( "Transcode here", this );
connect( transcodeAction, SIGNAL( triggered() ), this, SLOT( slotPrepareTranscodeTracks() ) );
menu->addAction( transcodeAction );
transcodeAction->setVisible( false ); //This is just used for debugging, hide it!
menu->exec( e->globalPos() );
}
......@@ -240,29 +232,6 @@ FileView::slotEditTracks()
}
}
void
FileView::slotPrepareTranscodeTracks()
{
DEBUG_BLOCK
KAction *action = qobject_cast< KAction * >( sender() );
if( !action )
return;
const KFileItemList list = selectedItems();
if( list.isEmpty() )
return;
if( !Amarok::Components::transcodingController()->availableFormats().isEmpty() )
{
Transcoding::AssistantDialog *d = new Transcoding::AssistantDialog( this );
d->show();
}
else
{
debug() << "FFmpeg is not installed or does not support any of the required formats.";
}
}
void
FileView::slotPrepareMoveTracks()
{
......@@ -335,13 +304,7 @@ FileView::slotCopyTracks( const Meta::TrackList& tracks )
source = new Collections::FileCollectionLocation();
}
Collections::CollectionLocation *destination = m_copyAction->collection()->location();
Transcoding::AssistantDialog dialog( this );
Transcoding::Configuration configuration = Transcoding::Configuration();
if( dialog.exec() )
{
configuration = dialog.configuration();
source->prepareCopy( tracks, destination, configuration );
}
source->prepareCopy( tracks, destination );
}
else
{
......
......@@ -67,7 +67,6 @@ protected slots:
void slotEditTracks();
void slotPrepareMoveTracks();
void slotPrepareCopyTracks();
void slotPrepareTranscodeTracks();
void slotMoveTracks( const Meta::TrackList &tracks );
void slotCopyTracks( const Meta::TrackList &tracks );
void slotDelete( Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers );
......
......@@ -17,6 +17,7 @@
#include "CollectionConfig.h"
#include "core/support/Amarok.h"
#include "core-impl/collections/db/sql/SqlCollection.h"
#include "CollectionSetup.h"
#include "amarokconfig.h"
#include <config-amarok.h>
......@@ -33,6 +34,10 @@ CollectionConfig::CollectionConfig( QWidget* parent )
QVBoxLayout *layout = new QVBoxLayout();
layout->addWidget( m_collectionSetup );
collectionFoldersBox->setLayout( layout );
KConfigGroup transcodeGroup = Amarok::config( Collections::SQL_TRANSCODING_GROUP_NAME );
transcodingConfig->fillInChoices( Transcoding::Configuration::fromConfigGroup( transcodeGroup ) );
connect( transcodingConfig, SIGNAL(currentIndexChanged(int)), parent, SLOT(updateButtons()) );
}
CollectionConfig::~CollectionConfig()
......@@ -48,7 +53,9 @@ CollectionConfig::hasChanged()
{
DEBUG_BLOCK
return m_collectionSetup->hasChanged();
return m_collectionSetup->hasChanged()
|| transcodingConfig->currentChoice() != Transcoding::SelectConfigWidget::DontChange;
}
bool
......@@ -61,8 +68,19 @@ void
CollectionConfig::updateSettings()
{
m_collectionSetup->writeConfig();
KConfigGroup transcodeGroup = Amarok::config( Collections::SQL_TRANSCODING_GROUP_NAME );
switch( transcodingConfig->currentChoice() )
{
case Transcoding::SelectConfigWidget::DontChange:
break;
case Transcoding::SelectConfigWidget::JustCopy:
Transcoding::Configuration( Transcoding::JUST_COPY ).saveToConfigGroup( transcodeGroup );
break;
case Transcoding::SelectConfigWidget::Forget:
Transcoding::Configuration( Transcoding::INVALID ).saveToConfigGroup( transcodeGroup );
break;
}
}
#include "CollectionConfig.moc"
......@@ -21,8 +21,41 @@
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="importingBox">
<property name="title">
<string>Importing Music</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="transcodeLabel">
<property name="toolTip">
<string>Whether Amarok should transcode tracks when they are copied or moved to Local Collection.</string>
</property>
<property name="text">
<string>Transcode tracks:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="Transcoding::SelectConfigWidget" name="transcodingConfig">
<property name="toolTip">
<string>Whether Amarok should transcode tracks when they are copied or moved to Local Collection.</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Transcoding::SelectConfigWidget</class>
<extends>QComboBox</extends>
<header>transcoding/TranscodingSelectConfigWidget.h</header>
</customwidget>
</customwidgets>
<includes>
<include location="local">klineedit.h</include>
<include location="local">kpushbutton.h</include>
......
......@@ -23,6 +23,7 @@
#include "CapabilityDelegateImpl.h"
#include "DatabaseUpdater.h"
#include "core/support/Debug.h"
#include "core/capabilities/TranscodeCapability.h"
#include "core/transcoding/TranscodingController.h"
#include "core-impl/collections/db/ScanManager.h"
#include "MountPointManager.h"
......@@ -65,10 +66,10 @@ public:
virtual void setTracks( const Meta::TrackList &tracks ) { m_tracks = tracks; }
virtual void setFolders( const QStringList &folders ) { m_folders = folders; }
virtual void setIsOrganizing( bool organizing ) { m_organizing = organizing; }
virtual void setTranscodingConfiguration( const Transcoding::Configuration &configuration
= Transcoding::Configuration() )
virtual void setTranscodingConfiguration( const Transcoding::Configuration &configuration )
{ m_targetFileExtension =
Amarok::Components::transcodingController()->format( configuration.encoder() )->fileExtension(); }
virtual void setCaption( const QString &caption ) { m_caption = caption; }
virtual void show()
{
......@@ -78,7 +79,7 @@ public:
The::mainWindow(), //parent
"", //name is unused
true, //modal
i18n( "Organize Files" ) //caption
m_caption //caption
);
connect( m_dialog, SIGNAL( accepted() ), SIGNAL( accepted() ) );
......@@ -95,6 +96,7 @@ private:
OrganizeCollectionDialog *m_dialog;
bool m_organizing;
QString m_targetFileExtension;
QString m_caption;
};
......@@ -480,19 +482,34 @@ SqlCollection::slotDeviceRemoved( int id )
bool
SqlCollection::hasCapabilityInterface( Capabilities::Capability::Type type ) const
{
return ( type == Capabilities::Capability::CollectionScan && m_scanManager ) ||
( type == Capabilities::Capability::CollectionImport && m_scanManager );
switch( type )
{
case Capabilities::Capability::CollectionImport:
case Capabilities::Capability::CollectionScan:
return (bool) m_scanManager;
case Capabilities::Capability::Transcode:
return true;
default:
break;
}
return false;
}
Capabilities::Capability*
SqlCollection::createCapabilityInterface( Capabilities::Capability::Type type )
{
if( type == Capabilities::Capability::CollectionScan && m_scanManager )
return new SqlCollectionScanCapability( m_scanManager );
else if( type == Capabilities::Capability::CollectionImport && m_scanManager )
return new SqlCollectionImportCapability( m_scanManager );
else
return 0;
switch( type )
{
case Capabilities::Capability::CollectionImport:
return m_scanManager ? new SqlCollectionImportCapability( m_scanManager ) : 0;
case Capabilities::Capability::CollectionScan:
return m_scanManager ? new SqlCollectionScanCapability( m_scanManager ) : 0;
case Capabilities::Capability::Transcode:
return new SqlCollectionTranscodeCapability();
default:
break;
}
return 0;
}
void
......@@ -586,5 +603,24 @@ SqlCollectionImportCapability::import( QIODevice *input, QObject *listener )
}
}
#include "SqlCollection.moc"
SqlCollectionTranscodeCapability::~SqlCollectionTranscodeCapability()
{
// nothing to do
}
Transcoding::Configuration
SqlCollectionTranscodeCapability::savedConfiguration()
{
KConfigGroup transcodeGroup = Amarok::config( SQL_TRANSCODING_GROUP_NAME );
return Transcoding::Configuration::fromConfigGroup( transcodeGroup );
}
void
SqlCollectionTranscodeCapability::setSavedConfiguration( const Transcoding::Configuration &configuration )
{
KConfigGroup transcodeGroup = Amarok::config( SQL_TRANSCODING_GROUP_NAME );
configuration.saveToConfigGroup( transcodeGroup );
transcodeGroup.sync();
}
#include "SqlCollection.moc"
......@@ -21,6 +21,7 @@
#include "amarok_sqlcollection_export.h"
#include "core/capabilities/CollectionScanCapability.h"
#include "core/capabilities/CollectionImportCapability.h"
#include "core/capabilities/TranscodeCapability.h"
#include "core/collections/Collection.h"
#include "core-impl/collections/db/DatabaseCollection.h"
#include "core-impl/collections/support/CollectionManager.h"
......@@ -46,6 +47,9 @@ class CollectionLocation;
class SqlCollectionLocationFactory;
class SqlQueryMakerFactory;
/// Configuration group name in amarokrc for preferred transcoding configuration for SqlCollection
static const QString SQL_TRANSCODING_GROUP_NAME = "Collection Transcoding Preference";
class AMAROK_SQLCOLLECTION_EXPORT SqlCollection : public Collections::DatabaseCollection
{
Q_OBJECT
......@@ -204,8 +208,17 @@ class SqlCollectionImportCapability : public Capabilities::CollectionImportCapab
ScanManager *m_scanManager;
};
class AMAROK_SQLCOLLECTION_EXPORT SqlCollectionTranscodeCapability : public Capabilities::TranscodeCapability
{
Q_OBJECT
public:
virtual ~SqlCollectionTranscodeCapability();
virtual Transcoding::Configuration savedConfiguration();
virtual void setSavedConfiguration( const Transcoding::Configuration &configuration );
};
}
#endif /* AMAROK_COLLECTION_SQLCOLLECTION_H */
......@@ -351,6 +351,7 @@ SqlCollectionLocation::showDestinationDialog( const Meta::TrackList &tracks,
delegate->setFolders( available_folders );
delegate->setIsOrganizing( ( collection() == source()->collection() ) );
delegate->setTranscodingConfiguration( configuration );
delegate->setCaption( operationText( configuration, false /* continuousSuffix */ ) );
connect( delegate, SIGNAL( accepted() ), SLOT( slotDialogAccepted() ) );
connect( delegate, SIGNAL( rejected() ), SLOT( slotDialogRejected() ) );
......@@ -491,20 +492,7 @@ SqlCollectionLocation::copyUrlsToCollection( const QMap<Meta::TrackPtr, KUrl> &s
m_sources = sources;
QString statusBarTxt;
if( destination() == source() )
statusBarTxt = i18n( "Organizing tracks" );
else if ( isGoingToRemoveSources() )
statusBarTxt = i18n( "Moving tracks" );
else
{
if( configuration.encoder() == Transcoding::NULL_CODEC )
statusBarTxt = i18n( "Copying tracks" );
else
statusBarTxt = i18n( "Transcoding tracks" );
}
QString statusBarTxt = operationText( configuration, true /* continuousSuffix */ );
m_transferjob = new TransferJob( this, configuration );
Amarok::Components::logger()->newProgressOperation( m_transferjob, statusBarTxt, this,
SLOT(slotTransferJobAborted()) );
......@@ -548,7 +536,7 @@ bool SqlCollectionLocation::startNextJob( const Transcoding::Configuration confi
bool hasMoodFile = QFile::exists( moodFile( src ).toLocalFile() );
if( configuration.encoder() == Transcoding::NULL_CODEC )
if( configuration.isJustCopy() )
debug() << "copying from " << src << " to " << dest;
else
debug() << "transcoding from " << src << " to " << dest;
......@@ -566,7 +554,7 @@ bool SqlCollectionLocation::startNextJob( const Transcoding::Configuration confi
}
KIO::JobFlags flags;
if( configuration.encoder() == Transcoding::NULL_CODEC )
if( configuration.isJustCopy() )
{
flags = KIO::HideProgressInfo;
if( m_overwriteFiles )
......@@ -600,7 +588,7 @@ bool SqlCollectionLocation::startNextJob( const Transcoding::Configuration confi
else
{
//later on in the case that remove is called, the file will be deleted because we didn't apply moveByDestination to the track
if( configuration.encoder() == Transcoding::NULL_CODEC )
if( configuration.isJustCopy() )
job = KIO::file_copy( src, dest, -1, flags );
else
{
......@@ -636,7 +624,7 @@ bool SqlCollectionLocation::startNextJob( const Transcoding::Configuration confi
if( track->artist() )
name = QString( "%1 - %2" ).arg( track->artist()->name(), track->prettyName() );
if( configuration.encoder() == Transcoding::NULL_CODEC )
if( configuration.isJustCopy() )
m_transferjob->emitInfo( i18n( "Transferring: %1", name ) );
else
m_transferjob->emitInfo( i18n( "Transcoding: %1", name ) );
......@@ -700,6 +688,39 @@ SqlCollectionLocation::moodFile( const KUrl &track ) const
return moodPath;
}
QString
SqlCollectionLocation::operationText( const Transcoding::Configuration &configuration, bool continuousSuffix )
{
if( source()->collection() == collection() )
{
if( configuration.isJustCopy() )
// in this case it is really about the files, not "tracks".
return continuousSuffix ? i18n( "Organizing files" )
: i18n( "Organize files" );
else
return continuousSuffix ? i18n( "Transcoding and organizing tracks" )
: i18n( "Transcode and organize tracks" );
}
if( isGoingToRemoveSources() )
{
if( configuration.isJustCopy() )
return continuousSuffix ? i18n( "Moving tracks" )
: i18n( "Move tracks" );
else
return continuousSuffix ? i18n( "Transcoding and moving tracks" )
: i18n( "Transcode and move tracks" );
}
else
{
if( configuration.isJustCopy() )
return continuousSuffix ? i18n( "Copying tracks" )
: i18n( "Copy tracks" );
else
return continuousSuffix ? i18n( "Transcoding and copying tracks" )
: i18n( "Transcode and copy tracks" );
}
}
TransferJob::TransferJob( SqlCollectionLocation * location, const Transcoding::Configuration & configuration )
: KCompositeJob( 0 )
, m_location( location )
......
......@@ -100,7 +100,7 @@ class AMAROK_SQLCOLLECTION_EXPORT_TESTS SqlCollectionLocation : public Collectio
bool removeSources,
const Transcoding::Configuration &configuration );
virtual void copyUrlsToCollection( const QMap<Meta::TrackPtr, KUrl> &sources,
const Transcoding::Configuration & configuration = Transcoding::Configuration() );
const Transcoding::Configuration & configuration );
virtual void removeUrlsFromCollection( const Meta::TrackList &sources );
private slots:
......@@ -116,6 +116,7 @@ class AMAROK_SQLCOLLECTION_EXPORT_TESTS SqlCollectionLocation : public Collectio
void migrateLabels( const QMap<Meta::TrackPtr, QString> &trackMap );
bool startNextJob( const Transcoding::Configuration configuration );
bool startNextRemoveJob();
QString operationText( const Transcoding::Configuration &configuration, bool continuousSuffix );
Collections::SqlCollection *m_collection;
OrganizeCollectionDelegateFactory *m_delegateFactory;
......@@ -150,6 +151,7 @@ public:
virtual void setFolders( const QStringList &folders ) = 0;
virtual void setIsOrganizing( bool organizing ) = 0;
virtual void setTranscodingConfiguration( const Transcoding::Configuration &configuration ) = 0;
virtual void setCaption( const QString &caption ) = 0;
virtual void show() = 0;
......
......@@ -47,7 +47,7 @@ class MEDIADEVICECOLLECTION_EXPORT MediaDeviceCollectionLocation : public Collec
/// Copies these tracks to the Collection using the Handler
virtual void copyUrlsToCollection( const QMap<Meta::TrackPtr, KUrl> &sources,
const Transcoding::Configuration &configuration = Transcoding::Configuration() );
const Transcoding::Configuration &configuration );
virtual void removeUrlsFromCollection( const Meta::TrackList &sources );
......
......@@ -21,6 +21,7 @@
#include "core/interfaces/Logger.h"
#include "core/collections/CollectionLocation.h"
#include "core/support/Components.h"
#include "transcoding/TranscodingAssistantDialog.h"
#include <KLocale>
#include <KMessageBox>
......@@ -98,6 +99,22 @@ CollectionLocationDelegateImpl::deleteEmptyDirs( CollectionLocation *loc ) const
return result == KMessageBox::Yes;
}
Transcoding::Configuration
CollectionLocationDelegateImpl::transcode( const QStringList &playableFileTypes,
bool *remember, OperationType operation,
const QString &destCollectionName ) const
{