riokarmamediadevice.cpp

来自「Amarok是一款在LINUX或其他类UNIX操作系统中运行的音频播放器软件。 」· C++ 代码 · 共 611 行

CPP
611
字号
/*************************************************************************** * copyright            : (C) 2006 Andy Kelk <andy@mopoke.co.uk>           * ***************************************************************************//*************************************************************************** *                                                                         * *   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.                                   * *                                                                         * ***************************************************************************/ /**  *  Rio Karma media device  *  @author Andy Kelk <andy@mopoke.co.uk>  *  @see http://linux-karma.sourceforge.net/  */#define DEBUG_PREFIX "RioKarmaMediaDevice"#include <config.h>#include "riokarmamediadevice.h"AMAROK_EXPORT_PLUGIN( RioKarmaMediaDevice )// Amarok#include <debug.h>#include <metabundle.h>#include <statusbar/statusbar.h>#include <statusbar/popupMessage.h>// KDE#include <kapplication.h>#include <kiconloader.h>#include <kpopupmenu.h>// Qt#include <qdir.h>#include <qlistview.h>#include <qmap.h>/** * RioKarmaMediaDevice Class */RioKarmaMediaDevice::RioKarmaMediaDevice() : MediaDevice(){    m_name = "Rio Karma";    setDisconnected();    m_hasMountPoint = true;    m_syncStats = false;    m_transcode = false;    m_transcodeAlways = false;    m_transcodeRemove = false;    m_configure = false;    m_customButton = false;    m_transfer = true;}voidRioKarmaMediaDevice::init( MediaBrowser *parent ){    MediaDevice::init( parent );}boolRioKarmaMediaDevice::isConnected(){    return m_rio >= 0 ? true : false;}/** * File types that we support */QStringListRioKarmaMediaDevice::supportedFiletypes(){    QStringList supportedFiles;    supportedFiles << "mp3";    supportedFiles << "ogg";    supportedFiles << "wma";    supportedFiles << "flac";    return supportedFiles;}/** * Copy a track to the device */MediaItem*RioKarmaMediaDevice::copyTrackToDevice( const MetaBundle &bundle ){    DEBUG_BLOCK    QString genericError = i18n( "Could not send track" );    if( m_fileNameToItem[ bundle.filename() ] != 0 )    {        // track already exists. don't do anything (for now).        debug() << "Track already exists on device." << endl;        Amarok::StatusBar::instance()->shortLongMessage(            genericError,            i18n( "Track already exists on device" ),            KDE::StatusBar::Error        );        return 0;    }    int fid = lk_rio_write( m_rio, bundle.url().path().utf8() );    if( fid < 0 )    {        debug() << "Could not write file" << fid << endl;        return 0;    }    MetaBundle temp( bundle );    RioKarmaTrack *taggedTrack = new RioKarmaTrack( fid );    taggedTrack->setBundle( temp );    // cache the track    updateRootItems();    return addTrackToView( taggedTrack );}/** * Write any pending changes to the device, such as database changes */voidRioKarmaMediaDevice::synchronizeDevice(){    DEBUG_BLOCK    int ret;    ret = lk_karma_write_smalldb();    if( ret )        debug() << "error writing smalldb file" << endl;}/** * Find an existing track */MediaItem*RioKarmaMediaDevice::trackExists( const MetaBundle &bundle ){    MediaItem *artist = dynamic_cast<MediaItem *>( m_view->findItem( bundle.artist(), 0 ) );    if( artist )    {        MediaItem *album = dynamic_cast<MediaItem *>( artist->findItem( bundle.album() ) );        if( album )        {            MediaItem *track =  dynamic_cast<MediaItem *>( album->findItem( bundle.title() ) );            if( track )            {                if( track->bundle()->track() == bundle.track() )                    return track;            }        }    }    return 0;}/** * Create a new playlist * @note Playlists not implemented yet... :-) */RioKarmaMediaItem*RioKarmaMediaDevice::newPlaylist( const QString &name, MediaItem *parent, QPtrList<MediaItem> items ){    Q_UNUSED( name );    Q_UNUSED( parent );    Q_UNUSED( items );    return 0;}/** * Add an item to a playlist * @note Playlists not implemented yet... :-) */voidRioKarmaMediaDevice::addToPlaylist( MediaItem *mlist, MediaItem *after, QPtrList<MediaItem> items ){    Q_UNUSED( mlist );    Q_UNUSED( after );    Q_UNUSED( items );}/** * Recursively remove MediaItem from the device */intRioKarmaMediaDevice::deleteItemFromDevice(MediaItem* item, int flags ){    int result = 0;    if( isCanceled() )    {        return -1;    }    MediaItem *next = 0;    switch( item->type() )    {        case MediaItem::TRACK:            if( isCanceled() )                break;            if( item )            {                int res = deleteRioTrack( dynamic_cast<RioKarmaMediaItem *> ( item ) );                if( res >=0 && result >= 0 )                    result += res;                else                    result = -1;            }            break;        case MediaItem::ALBUM:        case MediaItem::ARTIST:            // Recurse through the lists            next = 0;            if( isCanceled() )                break;            for( MediaItem *it = dynamic_cast<MediaItem *>( item->firstChild() ); it ; it = next )            {                next = dynamic_cast<MediaItem *>( it->nextSibling() );                int res = deleteItemFromDevice( it, flags );                if( res >= 0 && result >= 0 )                    result += res;                else                    result = -1;            }            if( item )                delete dynamic_cast<MediaItem *>( item );            break;        default:            result = 0;    }    return result;}/** * Actually delete a track from the Rio */intRioKarmaMediaDevice::deleteRioTrack( RioKarmaMediaItem *trackItem ){    DEBUG_BLOCK    debug() << "delete this fid : " << trackItem->track()->id() << endl;    // delete the file    int status = lk_karma_delete_file( m_rio, trackItem->track()->id() );    if( status < 0 ) {        debug() << "delete track failed" << endl;        return -1;    }    debug() << "track deleted" << endl;    // delete the properties (db entry)    status = lk_properties_del_property( trackItem->track()->id() );    if( status < 0 ) {        debug() << "delete property failed" << endl;        return -1;    }    debug() << "property deleted" << endl;    // remove from the listview    delete trackItem;    kapp->processEvents( 100 );    return 1;}/** * Connect to device, and populate m_view with MediaItems */boolRioKarmaMediaDevice::openDevice( bool silent ){    DEBUG_BLOCK    Q_UNUSED( silent );    QDir dir( mountPoint() );    if( !dir.exists() )    {        Amarok::StatusBar::instance()->longMessage(                i18n( "Media device: Mount point %1 does not exist" ).arg( mountPoint() ),                KDE::StatusBar::Error );        return false;    }    if( m_rio >= 0 )        return true;    QString genericError = i18n( "Could not connect to Rio Karma" );    char *mount = qstrdup( mountPoint().utf8() );    m_rio = lk_karma_connect( mount );    debug() << "Rio karma : " << m_rio << endl;    if( m_rio < 0 )    {        debug()<< "Error connecting" << endl;        Amarok::StatusBar::instance()->shortLongMessage( genericError, i18n( "Rio Karma could not be opened" ), KDE::StatusBar::Error );        setDisconnected();        return false;    }    lk_karma_use_smalldb();    lk_karma_write_dupes( 1 );    RioKarmaMediaDevice::readKarmaMusic();    return true;}/** * Wrap up any loose ends and close the device */boolRioKarmaMediaDevice::closeDevice(){    DEBUG_BLOCK    clearItems();    setDisconnected();    return true;}/** * Get the capacity and freespace available on the device, in KB */boolRioKarmaMediaDevice::getCapacity( KIO::filesize_t *total, KIO::filesize_t *available ){    if( !isConnected() )        return false;    uint32_t numfiles;    uint64_t disksize;    uint64_t freespace;    uint32_t maxfileid;    if( lk_karma_get_storage_details( m_rio, 0, &numfiles, &disksize, &freespace, &maxfileid ) == 0 )    {        *total = disksize;        *available = freespace;        return true;    }    else    {        return false;    }}/** * Current device ID (usually starts at 0) */intRioKarmaMediaDevice::current_id(){    return m_rio;}/** * We use -1 device ID to show a disconnected device. * This just sets the device ID to that. */voidRioKarmaMediaDevice::setDisconnected(){    m_rio = -1;}/** * Handle clicking of the right mouse button */voidRioKarmaMediaDevice::rmbPressed( QListViewItem *qitem, const QPoint &point, int ){    enum Actions {DELETE};    RioKarmaMediaItem *item = static_cast<RioKarmaMediaItem *>( qitem );    if( item )    {        KPopupMenu menu( m_view );        menu.insertItem( SmallIconSet( Amarok::icon( "remove" ) ), i18n( "Delete from device" ), DELETE );        int id =  menu.exec( point );        switch( id )        {        case DELETE:            MediaDevice::deleteFromDevice();            break;        }        return;    }}/** * Add a track to the current list view */RioKarmaMediaItem*RioKarmaMediaDevice::addTrackToView( RioKarmaTrack *track, RioKarmaMediaItem *item ){    QString artistName = track->bundle()->artist();    RioKarmaMediaItem *artist = dynamic_cast<RioKarmaMediaItem *>( m_view->findItem( artistName, 0 ) );    if( !artist )    {        artist = new RioKarmaMediaItem( m_view );        artist->m_device = this;        artist->setText( 0, artistName );        artist->setType( MediaItem::ARTIST );    }    QString albumName = track->bundle()->album();    RioKarmaMediaItem *album = dynamic_cast<RioKarmaMediaItem *>( artist->findItem( albumName ) );    if( !album )    {        album = new RioKarmaMediaItem( artist );        album->setText( 0, albumName );        album->setType( MediaItem::ALBUM );        album->m_device = this;    }    if( item )        album->insertItem( item );    else    {        item = new RioKarmaMediaItem( album );        item->m_device = this;        QString titleName = track->bundle()->title();        item->setTrack( track );        item->m_order = track->bundle()->track();        item->setText( 0, titleName );        item->setType( MediaItem::TRACK );        item->setBundle( track->bundle() );        item->track()->setId( track->id() );        m_fileNameToItem[ track->bundle()->filename() ] = item;    }    return item;}/** * Get karma tracks and add them to the listview */intRioKarmaMediaDevice::readKarmaMusic(){    DEBUG_BLOCK    clearItems();    QString genericError = i18n( "Could not get music from Rio Karma" );    int total = 100;    int progress = 0;    setProgress( progress, total ); // we don't know how many tracks. fake progress bar.    kapp->processEvents( 100 );    lk_karma_load_database( m_rio );    int i;    uint32_t *ret;    kapp->processEvents( 100 );    ret = lk_properties_andOrSearch( 0, 0, "fid", "" );    if( ret == 0 )    {        debug()<< "Error reading tracks. NULL returned." << endl;        Amarok::StatusBar::instance()->shortLongMessage( genericError, i18n( "Could not read Rio Karma tracks" ), KDE::StatusBar::Error );        setDisconnected();        hideProgress();        return -1;    }    total = 0;    // spin through once to determine size of the list    for( i=0; ret[i] != 0; i++ )    {        total++;    }    setProgress( progress, total );    // now process the tracks    for( i=0; ret[i] != 0; i++ )    {        // check playlist        if( qstrcmp( "playlist", lk_properties_get_property( ret[i], "type" ) ) == 0 )        {            // nothing for now...            debug() << "Found a playlist at fid " << ret[i] << ". Skipping." << endl;        }        else        {            RioKarmaTrack *track = new RioKarmaTrack( ret[i] );            track->readMetaData();            addTrackToView( track );        }        progress++;        setProgress( progress );        if( progress % 50 == 0 )            kapp->processEvents( 100 );    }    setProgress( total );    hideProgress();    return 0;}/** * Clear the current listview */voidRioKarmaMediaDevice::clearItems(){    m_view->clear();}/** * RioKarmaTrack Class */RioKarmaTrack::RioKarmaTrack( int Fid ){    m_id = Fid;}RioKarmaTrack::~RioKarmaTrack(){    m_itemList.setAutoDelete( true );    while( m_itemList.count() > 0 )    {        delete m_itemList.first();    }}/** * Read track properties from the Karma and set it on the track */voidRioKarmaTrack::readMetaData(){    MetaBundle *bundle = new MetaBundle();    bundle->setGenre( AtomicString( QString::fromUtf8( lk_properties_get_property( m_id, "genre" ) ) ) );    bundle->setArtist( AtomicString( QString::fromUtf8( lk_properties_get_property( m_id, "artist" ) ) ) );    bundle->setAlbum( AtomicString( QString::fromUtf8( lk_properties_get_property( m_id, "source" ) ) ) );    bundle->setTitle( AtomicString( QString::fromUtf8( lk_properties_get_property( m_id, "title" ) ) ) );    // translate codecs to file types    QString codec = QCString( lk_properties_get_property( m_id, "codec" ) );    if( codec == "mp3" )        bundle->setFileType( MetaBundle::mp3 );    else if( codec == "wma" )        bundle->setFileType( MetaBundle::wma );    else if( codec == "flac" )        bundle->setFileType( MetaBundle::flac );    else if( codec == "vorbis" )        bundle->setFileType( MetaBundle::ogg );    else        bundle->setFileType( MetaBundle::other );    bundle->setYear( QString( lk_properties_get_property( m_id, "year" ) ).toUInt() );    bundle->setTrack( QString( lk_properties_get_property( m_id, "tracknr" ) ).toUInt() );    bundle->setLength( QString( lk_properties_get_property( m_id, "duration" ) ).toUInt() );    this->setBundle( *bundle );}/** * Set this track's metabundle */voidRioKarmaTrack::setBundle( MetaBundle &bundle ){    m_bundle = bundle;}/** * Add a child item */voidRioKarmaTrack::addItem( const RioKarmaMediaItem *item ){    m_itemList.append( item );}/** * Remove a child item */boolRioKarmaTrack::removeItem( const RioKarmaMediaItem *item ){    m_itemList.remove( item );    return m_itemList.isEmpty();}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?