/**************************************************************************** * copyright :(C) 2006 Roel Meeuws * * (C) 2005 Seb Ruiz * * * * With some code helpers from TDEIO_VFAT * * (c) 2004 Thomas Loeber * ***************************************************************************/ /*************************************************************************** * * * 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. * * * ***************************************************************************/ #define DEBUG_PREFIX "GenericMediaDevice" #include "genericmediadevice.h" AMAROK_EXPORT_PLUGIN( GenericMediaDevice ) #include "amarok.h" #include "debug.h" #include "medium.h" #include "metabundle.h" #include "collectiondb.h" #include "collectionbrowser.h" #include "k3bexporter.h" #include "playlist.h" #include "podcastbundle.h" #include "statusbar/statusbar.h" #include "transferdialog.h" #include "genericmediadeviceconfigdialog.h" #include #include //download saveLocation #include #include //smallIcon #include #include #include #include #include #include #include //downloadSelectedItems() #include //downloadSelectedItems() #include #include //usleep() #include #include #include #include #include #include #include typedef TQPtrList MediaFileList; typedef TQPtrListIterator MediaFileListIterator; /** * GenericMediaItem Class */ class GenericMediaItem : public MediaItem { public: GenericMediaItem( TQListView *parent, TQListViewItem *after = 0 ) : MediaItem( parent, after ) { } GenericMediaItem( TQListViewItem *parent, TQListViewItem *after = 0 ) : MediaItem( parent, after ) { } // List directories first, always int compare( TQListViewItem *i, int col, bool ascending ) const { #define i static_cast(i) switch( type() ) { case MediaItem::DIRECTORY: if( i->type() == MediaItem::DIRECTORY ) break; return -1; default: if( i->type() == MediaItem::DIRECTORY ) return 1; } #undef i return MediaItem::compare(i, col, ascending); } private: bool m_dir; }; class GenericMediaFile { public: GenericMediaFile( GenericMediaFile *parent, TQString basename, GenericMediaDevice *device ) : m_parent( parent ) , m_device( device ) { m_listed = false; m_children = new MediaFileList(); if( m_parent ) { if( m_parent == m_device->getInitialFile() ) m_viewItem = new GenericMediaItem( m_device->view() ); else m_viewItem = new GenericMediaItem( m_parent->getViewItem() ); setNamesFromBase( basename ); m_viewItem->setText( 0, m_baseName ); m_parent->getChildren()->append( this ); } else { m_viewItem = 0; setNamesFromBase( basename ); } m_device->getItemMap()[m_viewItem] = this; if( m_device->getFileMap()[m_fullName] ) { debug() << "Trying to create two GenericMediaFile items with same fullName!" << endl; debug() << "name already existing: " << m_device->getFileMap()[m_fullName]->getFullName() << endl; delete this; } else { m_device->getFileMap()[m_fullName] = this; } } ~GenericMediaFile() { if( m_parent ) m_parent->removeChild( this ); m_device->getItemMap().erase( m_viewItem ); m_device->getFileMap().erase( m_fullName ); if ( m_children ) delete m_children; if ( m_viewItem ) delete m_viewItem; } GenericMediaFile* getParent() { return m_parent; } void setParent( GenericMediaFile* parent ) { m_device->getFileMap().erase( m_fullName ); m_parent->getChildren()->remove( this ); m_parent = parent; if( m_parent ) m_parent->getChildren()->append( this ); setNamesFromBase( m_baseName ); m_device->getFileMap()[m_fullName] = this; } void removeChild( GenericMediaFile* childToDelete ) { m_children->remove( childToDelete ); } GenericMediaItem* getViewItem() { return m_viewItem; } bool getListed() { return m_listed; } void setListed( bool listed ) { m_listed = listed; } TQString getFullName() { return m_fullName; } TQString getBaseName() { return m_baseName; } //always follow this function with setNamesFromBase() void setBaseName( TQString &name ) { m_baseName = name; } void setNamesFromBase( const TQString &name = TQString() ) { if( name != TQString() ) m_baseName = name; if( m_parent ) m_fullName = m_parent->getFullName() + '/' + m_baseName; else m_fullName = m_baseName; if( m_viewItem ) m_viewItem->setBundle( new MetaBundle( KURL::fromPathOrURL( m_fullName ), true, TagLib::AudioProperties::Fast ) ); } MediaFileList* getChildren() { return m_children; } void deleteAll( bool onlyChildren ) { GenericMediaFile *vmf; if( m_children && !m_children->isEmpty() ) { MediaFileListIterator it( *m_children ); while( ( vmf = it.current() ) != 0 ) { ++it; vmf->deleteAll( true ); } } if( onlyChildren ) delete this; } void renameAllChildren() { GenericMediaFile *vmf; if( m_children && !m_children->isEmpty() ) { for( vmf = m_children->first(); vmf; vmf = m_children->next() ) vmf->renameAllChildren(); } setNamesFromBase(); } private: TQString m_fullName; TQString m_baseName; GenericMediaFile *m_parent; MediaFileList *m_children; GenericMediaItem *m_viewItem; GenericMediaDevice* m_device; bool m_listed; }; TQString GenericMediaDevice::fileName( const MetaBundle &bundle ) { TQString result = cleanPath( bundle.artist() ); if( !result.isEmpty() ) { if( m_spacesToUnderscores ) result += "_-_"; else result += " - "; } if( bundle.track() ) { result.sprintf( "%02d", bundle.track() ); if( m_spacesToUnderscores ) result += '_'; else result += ' '; } result += cleanPath( bundle.title() + '.' + bundle.type() ); return result; } /** * GenericMediaDevice Class */ GenericMediaDevice::GenericMediaDevice() : MediaDevice() , m_kBSize( 0 ) , m_kBAvail( 0 ) , m_connected( false ) { DEBUG_BLOCK m_name = i18n("Generic Audio Player"); m_dirLister = new KDirLister(); m_dirLister->setNameFilter( "*.mp3 *.wav *.asf *.flac *.wma *.ogg *.aac *.m4a *.mp4 *.mp2 *.ac3" ); m_dirLister->setAutoUpdate( false ); m_spacesToUnderscores = false; m_ignoreThePrefix = false; m_asciiTextOnly = false; m_songLocation = TQString(); m_podcastLocation = TQString(); m_supportedFileTypes.clear(); m_configDialog = 0; connect( m_dirLister, TQT_SIGNAL( newItems(const KFileItemList &) ), this, TQT_SLOT( newItems(const KFileItemList &) ) ); connect( m_dirLister, TQT_SIGNAL( completed() ), this, TQT_SLOT( dirListerCompleted() ) ); connect( m_dirLister, TQT_SIGNAL( clear() ), this, TQT_SLOT( dirListerClear() ) ); connect( m_dirLister, TQT_SIGNAL( clear(const KURL &) ), this, TQT_SLOT( dirListerClear(const KURL &) ) ); connect( m_dirLister, TQT_SIGNAL( deleteItem(KFileItem *) ), this, TQT_SLOT( dirListerDeleteItem(KFileItem *) ) ); } void GenericMediaDevice::init( MediaBrowser* parent ) { MediaDevice::init( parent ); } GenericMediaDevice::~GenericMediaDevice() { closeDevice(); } void GenericMediaDevice::applyConfig() { if( m_configDialog != 0) { m_supportedFileTypes.clear(); for( uint i = 0; i < m_configDialog->m_supportedListBox->count(); i++ ) { TQString currentText = m_configDialog->m_supportedListBox->item( i )->text(); if( currentText == m_configDialog->m_convertComboBox->currentText() ) m_supportedFileTypes.prepend( currentText ); else m_supportedFileTypes.append( currentText ); } m_spacesToUnderscores = m_configDialog->m_spaceCheck->isChecked(); m_asciiTextOnly = m_configDialog->m_asciiCheck->isChecked(); m_vfatTextOnly = m_configDialog->m_vfatCheck->isChecked(); m_ignoreThePrefix = m_configDialog->m_ignoreTheCheck->isChecked(); m_songLocation = m_configDialog->m_songLocationBox->text(); m_podcastLocation = m_configDialog->m_podcastLocationBox->text(); } setConfigString( "songLocation" , m_songLocation ); setConfigString( "podcastLocation" , m_podcastLocation ); setConfigBool( "spacesToUnderscores", m_spacesToUnderscores ); setConfigBool( "ignoreThePrefix" , m_ignoreThePrefix ); setConfigBool( "asciiTextOnly" , m_asciiTextOnly ); setConfigBool( "vfatTextOnly" , m_vfatTextOnly ); setConfigString( "supportedFiletypes" , m_supportedFileTypes.join( ", " ) ); } void GenericMediaDevice::loadConfig() { MediaDevice::loadConfig(); m_spacesToUnderscores = configBool( "spacesToUnderscores", false ); m_ignoreThePrefix = configBool( "ignoreThePrefix", false); m_asciiTextOnly = configBool( "asciiTextOnly", false ); m_vfatTextOnly = configBool( "vfatTextOnly", false ); m_songLocation = configString( "songLocation", "/%artist/%album/%title.%filetype" ); m_podcastLocation = configString( "podcastLocation", "/podcasts/" ); m_supportedFileTypes = TQStringList::split( ", ", configString( "supportedFiletypes", "mp3"), true); } bool GenericMediaDevice::openDevice( bool /*silent*/ ) { DEBUG_BLOCK if( !m_medium.mountPoint() ) { Amarok::StatusBar::instance()->longMessage( i18n( "Devices handled by this plugin must be mounted first.\n" "Please mount the device and click \"Connect\" again." ), KDE::StatusBar::Sorry ); return false; } KMountPoint::List currentmountpoints = KMountPoint::currentMountPoints(); KMountPoint::List::Iterator mountiter = currentmountpoints.begin(); for(; mountiter != currentmountpoints.end(); ++mountiter) { if( m_medium.mountPoint() == (*mountiter)->mountPoint() ) m_medium.setFsType( (*mountiter)->mountType() ); } m_actuallyVfat = (m_medium.fsType() == "vfat" || m_medium.fsType() == "msdosfs") ? true : false; m_connected = true; KURL tempurl = KURL::fromPathOrURL( m_medium.mountPoint() ); TQString newMountPoint = tempurl.isLocalFile() ? tempurl.path( -1 ) : tempurl.prettyURL( -1 ); //no trailing slash m_transferDir = newMountPoint; m_initialFile = new GenericMediaFile( 0, newMountPoint, this ); listDir( newMountPoint ); connect( this, TQT_SIGNAL( startTransfer() ), MediaBrowser::instance(), TQT_SLOT( transferClicked() ) ); return true; } bool GenericMediaDevice::closeDevice() //SLOT { if( m_connected ) { m_initialFile->deleteAll( true ); m_view->clear(); m_connected = false; } //delete these? m_mfm.clear(); m_mim.clear(); return true; } /// Renaming void GenericMediaDevice::renameItem( TQListViewItem *item ) // SLOT { if( !item ) return; #define item static_cast(item) TQString src = m_mim[item]->getFullName(); TQString dst = m_mim[item]->getParent()->getFullName() + '/' + item->text(0); debug() << "Renaming: " << src << " to: " << dst << endl; //do we want a progress dialog? If so, set last false to true if( TDEIO::NetAccess::file_move( KURL::fromPathOrURL(src), KURL::fromPathOrURL(dst), -1, false, false, 0 ) ) { m_mfm.erase( m_mim[item]->getFullName() ); m_mim[item]->setNamesFromBase( item->text(0) ); m_mfm[m_mim[item]->getFullName()] = m_mim[item]; } else { debug() << "Renaming FAILED!" << endl; //failed, so set the item's text back to how it should be item->setText( 0, m_mim[item]->getBaseName() ); } refreshDir( m_mim[item]->getParent()->getFullName() ); m_mim[item]->renameAllChildren(); #undef item } /// Creating a directory MediaItem * GenericMediaDevice::newDirectory( const TQString &name, MediaItem *parent ) { if( !m_connected || name.isEmpty() ) return 0; #define parent static_cast(parent) TQString fullName = m_mim[parent]->getFullName(); TQString cleanedName = cleanPath( name ); TQString fullPath = fullName + '/' + cleanedName; debug() << "Creating directory: " << fullPath << endl; const KURL url( fullPath ); if( !TDEIO::NetAccess::mkdir( url, m_parent ) ) //failed { debug() << "Failed to create directory " << fullPath << endl; return 0; } refreshDir( m_mim[parent]->getFullName() ); #undef parent return 0; } void GenericMediaDevice::addToDirectory( MediaItem *directory, TQPtrList items ) { if( items.isEmpty() ) return; GenericMediaFile *dropDir; if( !directory ) dropDir = m_initialFile; else { if( directory->type() == MediaItem::TRACK ) #define directory static_cast(directory) dropDir = m_mim[directory]->getParent(); else dropDir = m_mim[directory]; } for( TQPtrListIterator it(items); *it; ++it ) { GenericMediaItem *currItem = static_cast(*it); TQString src = m_mim[currItem]->getFullName(); TQString dst = dropDir->getFullName() + '/' + currItem->text(0); debug() << "Moving: " << src << " to: " << dst << endl; const KURL srcurl(src); const KURL dsturl(dst); if ( !TDEIO::NetAccess::file_move( srcurl, dsturl, -1, false, false, m_parent ) ) debug() << "Failed moving " << src << " to " << dst << endl; else { refreshDir( m_mim[currItem]->getParent()->getFullName() ); refreshDir( dropDir->getFullName() ); //smb: urls don't seem to refresh correctly, but this seems to be a samba issue? } } #undef directory } /// Uploading TQString GenericMediaDevice::buildDestination( const TQString &format, const MetaBundle &mb ) { bool isCompilation = mb.compilation() == MetaBundle::CompilationYes; TQMap args; TQString artist = mb.artist(); TQString albumartist = artist; if( isCompilation ) albumartist = i18n( "Various Artists" ); args["theartist"] = cleanPath( artist ); args["thealbumartist"] = cleanPath( albumartist ); if( m_ignoreThePrefix && artist.startsWith( "The " ) ) CollectionView::instance()->manipulateThe( artist, true ); artist = cleanPath( artist ); if( m_ignoreThePrefix && albumartist.startsWith( "The " ) ) CollectionView::instance()->manipulateThe( albumartist, true ); albumartist = cleanPath( albumartist ); for( int i = 0; i < MetaBundle::NUM_COLUMNS; i++ ) { if( i == MetaBundle::Score || i == MetaBundle::PlayCount || i == MetaBundle::LastPlayed ) continue; args[mb.exactColumnName( i ).lower()] = cleanPath( mb.prettyText( i ) ); } args["artist"] = artist; args["albumartist"] = albumartist; args["initial"] = albumartist.mid( 0, 1 ).upper(); args["filetype"] = TQString(mb.url().pathOrURL().section( ".", -1 )).lower(); TQString track; if ( mb.track() ) track.sprintf( "%02d", mb.track() ); args["track"] = track; Amarok::QStringx formatx( format ); TQString result = formatx.namedOptArgs( args ); if( !result.startsWith( "/" ) ) result.prepend( "/" ); return result.replace( TQRegExp( "/\\.*" ), "/" ); } void GenericMediaDevice::checkAndBuildLocation( const TQString& location ) { // check for every directory from the mount point to the location // whether they exist or not. int mountPointDepth = m_medium.mountPoint().contains( '/', false ); int locationDepth = location.contains( '/', false ); if( m_medium.mountPoint().endsWith( "/" ) ) mountPointDepth--; if( location.endsWith( "/") ) locationDepth--; // the locationDepth indicates the filename, in the following loop // however, we only look at the direcories. hence i < locationDepth // instead of '<=' for( int i = mountPointDepth; i < locationDepth; i++ ) { TQString firstpart = location.section( '/', 0, i-1 ); TQString secondpart = cleanPath( location.section( '/', i, i ) ); KURL url = KURL::fromPathOrURL( firstpart + '/' + secondpart ); if( !TDEIO::NetAccess::exists( url, false, m_parent ) ) { debug() << "directory does not exist, creating..." << url << endl; if( !TDEIO::NetAccess::mkdir(url, m_view ) ) //failed { debug() << "Failed to create directory " << url << endl; return; } } } } TQString GenericMediaDevice::buildPodcastDestination( const PodcastEpisodeBundle *bundle ) { TQString location = m_podcastLocation.endsWith("/") ? m_podcastLocation : m_podcastLocation + '/'; // get info about the PodcastChannel TQString parentUrl = bundle->parent().url(); TQString sql = "SELECT title,parent FROM podcastchannels WHERE url='" + CollectionDB::instance()->escapeString( parentUrl ) + "';"; TQStringList values = CollectionDB::instance()->query( sql ); TQString channelTitle; int parent = 0; channelTitle = values.first(); parent = values.last().toInt(); // Put the file in a directory tree like in the playlistbrowser sql = "SELECT name,parent FROM podcastfolders WHERE id=%1;"; TQString name; while ( parent > 0 ) { values = CollectionDB::instance()->query( sql.arg( parent ) ); name = values.first(); parent = values.last().toInt(); location += cleanPath( name ) + '/'; } location += cleanPath( channelTitle ) + '/' + cleanPath( bundle->localUrl().filename() ); return location; } MediaItem * GenericMediaDevice::copyTrackToDevice( const MetaBundle& bundle ) { if( !m_connected ) return 0; // use different naming schemes for differen kinds of tracks TQString path = m_transferDir; debug() << "bundle exists: " << bundle.podcastBundle() << endl; if( bundle.podcastBundle() ) path += buildPodcastDestination( bundle.podcastBundle() ); else path += buildDestination( m_songLocation, bundle ); checkAndBuildLocation( path ); const KURL desturl = KURL::fromPathOrURL( path ); //kapp->processEvents( 100 ); if( !kioCopyTrack( bundle.url(), desturl ) ) { debug() << "Failed to copy track: " << bundle.url().pathOrURL() << " to " << desturl.pathOrURL() << endl; return 0; } refreshDir( m_transferDir ); //the return value just can't be null, as nothing is done with it //other than to see if it is NULL or not //if we're here the transfer shouldn't have failed, so we shouldn't get into a loop by waiting... while( !m_view->firstChild() ) kapp->processEvents( 100 ); return static_cast(m_view->firstChild()); } //Somewhat related... MediaItem * GenericMediaDevice::trackExists( const MetaBundle& bundle ) { TQString key; TQString path = buildDestination( m_songLocation, bundle); KURL url( path ); TQStringList directories = TQStringList::split( "/", url.directory(1,1), false ); TQListViewItem *it = view()->firstChild(); for( TQStringList::Iterator directory = directories.begin(); directory != directories.end(); directory++ ) { key = *directory; while( it && it->text( 0 ) != key ) it = it->nextSibling(); if( !it ) return 0; if( !it->childCount() ) expandItem( it ); it = it->firstChild(); } key = url.fileName( true ); key = key.isEmpty() ? fileName( bundle ) : key; while( it && it->text( 0 ) != key ) it = it->nextSibling(); return dynamic_cast( it ); } /// File transfer methods void GenericMediaDevice::downloadSelectedItems() { KURL::List urls = getSelectedItems(); CollectionView::instance()->organizeFiles( urls, i18n("Copy Files to Collection"), true ); hideProgress(); } KURL::List GenericMediaDevice::getSelectedItems() { return m_view->nodeBuildDragList( static_cast(m_view->firstChild()), true ); } /// Deleting int GenericMediaDevice::deleteItemFromDevice( MediaItem *item, int /*flags*/ ) { if( !item || !m_connected ) return -1; #define item static_cast(item) TQString path = m_mim[item]->getFullName(); debug() << "Deleting path: " << path << endl; if ( !TDEIO::NetAccess::del( KURL::fromPathOrURL(path), m_view )) { debug() << "Could not delete!" << endl; return -1; } if( m_mim[item] == m_initialFile ) { m_mim[item]->deleteAll( false ); debug() << "Not deleting root directory of mount!" << endl; path = m_initialFile->getFullName(); } else { path = m_mim[item]->getParent()->getFullName(); m_mim[item]->deleteAll( true ); } refreshDir( path ); setProgress( progress() + 1 ); #undef item return 1; } /// Directory Reading void GenericMediaDevice::expandItem( TQListViewItem *item ) // SLOT { if( !item || !item->isExpandable() ) return; #define item static_cast(item) m_dirListerComplete = false; listDir( m_mim[item]->getFullName() ); #undef item while( !m_dirListerComplete ) { kapp->processEvents( 100 ); usleep(10000); } } void GenericMediaDevice::listDir( const TQString &dir ) { m_dirListerComplete = false; if( m_mfm[dir]->getListed() ) m_dirLister->updateDirectory( KURL::fromPathOrURL(dir) ); else { m_dirLister->openURL( KURL::fromPathOrURL(dir), true, true ); m_mfm[dir]->setListed( true ); } } void GenericMediaDevice::refreshDir( const TQString &dir ) { m_dirListerComplete = false; m_dirLister->updateDirectory( KURL::fromPathOrURL(dir) ); } void GenericMediaDevice::newItems( const KFileItemList &items ) { TQPtrListIterator it( items ); KFileItem *kfi; while ( (kfi = it.current()) != 0 ) { ++it; addTrackToList( kfi->isFile() ? MediaItem::TRACK : MediaItem::DIRECTORY, kfi->url(), 0 ); } } void GenericMediaDevice::dirListerCompleted() { m_dirListerComplete = true; } void GenericMediaDevice::dirListerClear() { m_initialFile->deleteAll( true ); m_view->clear(); m_mfm.clear(); m_mim.clear(); KURL tempurl = KURL::fromPathOrURL( m_medium.mountPoint() ); TQString newMountPoint = tempurl.isLocalFile() ? tempurl.path( -1 ) : tempurl.prettyURL( -1 ); //no trailing slash m_initialFile = new GenericMediaFile( 0, newMountPoint, this ); } void GenericMediaDevice::dirListerClear( const KURL &url ) { TQString directory = url.pathOrURL(); GenericMediaFile *vmf = m_mfm[directory]; if( vmf ) vmf->deleteAll( false ); } void GenericMediaDevice::dirListerDeleteItem( KFileItem *fileitem ) { TQString filename = fileitem->url().pathOrURL(); GenericMediaFile *vmf = m_mfm[filename]; if( vmf ) vmf->deleteAll( true ); } int GenericMediaDevice::addTrackToList( int type, KURL url, int /*size*/ ) { TQString path = url.isLocalFile() ? url.path( -1 ) : url.prettyURL( -1 ); //no trailing slash int index = path.findRev( '/', -1 ); TQString baseName = path.right( path.length() - index - 1 ); TQString parentName = path.left( index ); GenericMediaFile* parent = m_mfm[parentName]; GenericMediaFile* newItem = new GenericMediaFile( parent, baseName, this ); if( type == MediaItem::DIRECTORY ) //directory newItem->getViewItem()->setType( MediaItem::DIRECTORY ); //TODO: this logic could maybe be taken out later...or the dirlister shouldn't //filter, one or the other...depends if we want to allow viewing any files //or just update the list in the plugin as appropriate else if( type == MediaItem::TRACK ) //file { if( baseName.endsWith( "mp3", false ) || baseName.endsWith( "wma", false ) || baseName.endsWith( "wav", false ) || baseName.endsWith( "ogg", false ) || baseName.endsWith( "asf", false ) || baseName.endsWith( "flac", false ) || baseName.endsWith( "aac", false ) || baseName.endsWith( "m4a", false ) ) newItem->getViewItem()->setType( MediaItem::TRACK ); else newItem->getViewItem()->setType( MediaItem::UNKNOWN ); } refreshDir( parent->getFullName() ); return 0; } /// Capacity, in kB bool GenericMediaDevice::getCapacity( TDEIO::filesize_t *total, TDEIO::filesize_t *available ) { if( !m_connected || !KURL::fromPathOrURL( m_medium.mountPoint() ).isLocalFile() ) return false; KDiskFreeSp* kdf = new KDiskFreeSp( TQT_TQOBJECT(m_parent), "generic_kdf" ); kdf->readDF( m_medium.mountPoint() ); connect(kdf, TQT_SIGNAL(foundMountPoint( const TQString &, unsigned long, unsigned long, unsigned long )), TQT_SLOT(foundMountPoint( const TQString &, unsigned long, unsigned long, unsigned long ))); int count = 0; while( m_kBSize == 0 && m_kBAvail == 0){ usleep( 10000 ); kapp->processEvents( 100 ); count++; if (count > 120){ debug() << "KDiskFreeSp taking too long. Returning false from getCapacity()" << endl; return false; } } *total = m_kBSize*1024; *available = m_kBAvail*1024; unsigned long localsize = m_kBSize; m_kBSize = 0; m_kBAvail = 0; return localsize > 0; } void GenericMediaDevice::foundMountPoint( const TQString & mountPoint, unsigned long kBSize, unsigned long /*kBUsed*/, unsigned long kBAvail ) { if ( mountPoint == m_medium.mountPoint() ){ m_kBSize = kBSize; m_kBAvail = kBAvail; } } /// Helper functions void GenericMediaDevice::rmbPressed( TQListViewItem* qitem, const TQPoint& point, int ) { enum Actions { APPEND, LOAD, QUEUE, DOWNLOAD, BURN_DATACD, BURN_AUDIOCD, DIRECTORY, RENAME, DELETE, TRANSFER_HERE }; MediaItem *item = static_cast(qitem); if ( item ) { TDEPopupMenu menu( m_view ); menu.insertItem( SmallIconSet( Amarok::icon( "playlist" ) ), i18n( "&Load" ), LOAD ); menu.insertItem( SmallIconSet( Amarok::icon( "1downarrow" ) ), i18n( "&Append to Playlist" ), APPEND ); menu.insertItem( SmallIconSet( Amarok::icon( "fastforward" ) ), i18n( "&Queue Tracks" ), QUEUE ); menu.insertSeparator(); menu.insertItem( SmallIconSet( Amarok::icon( "collection" ) ), i18n( "&Copy Files to Collection..." ), DOWNLOAD ); menu.insertItem( SmallIconSet( Amarok::icon( "media-optical-cdrom" ) ), i18n( "Burn to CD as Data" ), BURN_DATACD ); menu.setItemEnabled( BURN_DATACD, K3bExporter::isAvailable() ); menu.insertItem( SmallIconSet( Amarok::icon( "media-optical-cdaudio" ) ), i18n( "Burn to CD as Audio" ), BURN_AUDIOCD ); menu.setItemEnabled( BURN_AUDIOCD, K3bExporter::isAvailable() ); menu.insertSeparator(); menu.insertItem( SmallIconSet( Amarok::icon( "folder" ) ), i18n( "Add Directory" ), DIRECTORY ); menu.insertItem( SmallIconSet( Amarok::icon( "edit" ) ), i18n( "Rename" ), RENAME ); menu.insertItem( SmallIconSet( Amarok::icon( "remove" ) ), i18n( "Delete" ), DELETE ); menu.insertSeparator(); // NOTE: need better icon menu.insertItem( SmallIconSet( Amarok::icon( "add_playlist" ) ), i18n( "Transfer Queue to Here..." ), TRANSFER_HERE ); menu.setItemEnabled( TRANSFER_HERE, MediaBrowser::queue()->childCount() ); int id = menu.exec( point ); switch( id ) { case LOAD: Playlist::instance()->insertMedia( getSelectedItems(), Playlist::Replace ); break; case APPEND: Playlist::instance()->insertMedia( getSelectedItems(), Playlist::Append ); break; case QUEUE: Playlist::instance()->insertMedia( getSelectedItems(), Playlist::Queue ); break; case DOWNLOAD: downloadSelectedItems(); break; case BURN_DATACD: K3bExporter::instance()->exportTracks( getSelectedItems(), K3bExporter::DataCD ); break; case BURN_AUDIOCD: K3bExporter::instance()->exportTracks( getSelectedItems(), K3bExporter::AudioCD ); break; case DIRECTORY: if( item->type() == MediaItem::DIRECTORY ) m_view->newDirectory( static_cast(item) ); else m_view->newDirectory( static_cast(item->parent()) ); break; case RENAME: m_view->rename( item, 0 ); break; case DELETE: deleteFromDevice(); break; case TRANSFER_HERE: #define item static_cast(item) if( item->type() == MediaItem::DIRECTORY ) m_transferDir = m_mim[item]->getFullName(); else m_transferDir = m_mim[item]->getParent()->getFullName(); #undef item emit startTransfer(); break; } return; } if( isConnected() ) { TDEPopupMenu menu( m_view ); menu.insertItem( SmallIconSet( Amarok::icon( "folder" ) ), i18n("Add Directory" ), DIRECTORY ); if ( MediaBrowser::queue()->childCount()) { menu.insertSeparator(); menu.insertItem( SmallIconSet( Amarok::icon( "add_playlist" ) ), i18n(" Transfer queue to here..." ), TRANSFER_HERE ); } int id = menu.exec( point ); switch( id ) { case DIRECTORY: m_view->newDirectory( 0 ); break; case TRANSFER_HERE: m_transferDir = m_medium.mountPoint(); emit startTransfer(); break; } } } TQString GenericMediaDevice::cleanPath( const TQString &component ) { TQString result = Amarok::cleanPath( component ); if( m_asciiTextOnly ) result = Amarok::asciiPath( result ); result.simplifyWhiteSpace(); if( m_spacesToUnderscores ) result.replace( TQRegExp( "\\s" ), "_" ); if( m_actuallyVfat || m_vfatTextOnly ) result = Amarok::vfatPath( result ); result.replace( "/", "-" ); return result; } /// File Information functions bool GenericMediaDevice::isPlayable( const MetaBundle& bundle ) { for( TQStringList::Iterator it = m_supportedFileTypes.begin(); it != m_supportedFileTypes.end() ; it++ ) { if( bundle.type().lower() == (*it).lower() ) return true; } return false; } bool GenericMediaDevice::isPreferredFormat( const MetaBundle &bundle ) { return m_supportedFileTypes.first().lower() == bundle.type().lower(); } /// Configuration Dialog Extension void GenericMediaDevice::addConfigElements( TQWidget * parent ) { m_configDialog = new GenericMediaDeviceConfigDialog( parent ); m_configDialog->setDevice( this ); } void GenericMediaDevice::removeConfigElements( TQWidget * /* parent */ ) { if( m_configDialog != 0 ) delete m_configDialog; m_configDialog = 0; } #include "genericmediadevice.moc"