mtpmediadevice.cpp

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

CPP
1,669
字号
/*************************************************************************** * 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.                                   * *                                                                         * ***************************************************************************/ /**  *  Based on njb mediadevice with some code hints from the libmtp  *  example tools  */ /**  *  MTP media device  *  @author Andy Kelk <andy@mopoke.co.uk>  *  @see http://libmtp.sourceforge.net/  */#define DEBUG_PREFIX "MtpMediaDevice"#include <config.h>#include "mtpmediadevice.h"AMAROK_EXPORT_PLUGIN( MtpMediaDevice )// Amarok#include <debug.h>#include <metabundle.h>#include <statusbar/statusbar.h>#include <statusbar/popupMessage.h>#include <collectionbrowser.h>// KDE#include <kapplication.h>#include <kiconloader.h>#include <kpopupmenu.h>#include <kmessagebox.h>#include <ktoolbarbutton.h>#include <ktempdir.h>// Qt#include <qdir.h>#include <qlistview.h>#include <qtooltip.h>#include <qlineedit.h>#include <qregexp.h>#include <qbuffer.h>#include <qmap.h>/** * MtpMediaDevice Class */MtpMediaDevice::MtpMediaDevice() : MediaDevice(){    m_name = i18n("MTP Media Device");    m_device = 0;    m_folders = 0;    m_playlistItem = 0;    setDisconnected();    m_hasMountPoint = false;    m_syncStats = false;    m_transcode = false;    m_transcodeAlways = false;    m_transcodeRemove = false;    m_configure = false;    m_customButton = true;    m_transfer = true;    KToolBarButton *customButton = MediaBrowser::instance()->getToolBar()->getButton( MediaBrowser::CUSTOM );    customButton->setText( i18n("Special device functions") );    QToolTip::remove( customButton );    QToolTip::add( customButton, i18n( "Special functions of your device" ) );    mtpFileTypes[LIBMTP_FILETYPE_WAV] = "wav";    mtpFileTypes[LIBMTP_FILETYPE_MP3] = "mp3";    mtpFileTypes[LIBMTP_FILETYPE_WMA] = "wma";    mtpFileTypes[LIBMTP_FILETYPE_OGG] = "ogg";    mtpFileTypes[LIBMTP_FILETYPE_AUDIBLE] = "aa"; // audible    mtpFileTypes[LIBMTP_FILETYPE_MP4] = "mp4";    mtpFileTypes[LIBMTP_FILETYPE_UNDEF_AUDIO] = "undef-audio";    mtpFileTypes[LIBMTP_FILETYPE_WMV] = "wmv";    mtpFileTypes[LIBMTP_FILETYPE_AVI] = "avi";    mtpFileTypes[LIBMTP_FILETYPE_MPEG] = "mpg";    mtpFileTypes[LIBMTP_FILETYPE_ASF] = "asf";    mtpFileTypes[LIBMTP_FILETYPE_QT] = "mov";    mtpFileTypes[LIBMTP_FILETYPE_UNDEF_VIDEO] = "undef-video";    mtpFileTypes[LIBMTP_FILETYPE_JPEG] = "jpg";    mtpFileTypes[LIBMTP_FILETYPE_JFIF] = "jpg";    mtpFileTypes[LIBMTP_FILETYPE_TIFF] = "tiff";    mtpFileTypes[LIBMTP_FILETYPE_BMP] = "bmp";    mtpFileTypes[LIBMTP_FILETYPE_GIF] = "gif";    mtpFileTypes[LIBMTP_FILETYPE_PICT] = "pict";    mtpFileTypes[LIBMTP_FILETYPE_PNG] = "png";    mtpFileTypes[LIBMTP_FILETYPE_VCALENDAR1] = "vcs"; // vcal1    mtpFileTypes[LIBMTP_FILETYPE_VCALENDAR2] = "vcs"; // vcal2    mtpFileTypes[LIBMTP_FILETYPE_VCARD2] = "vcf"; // vcard2    mtpFileTypes[LIBMTP_FILETYPE_VCARD3] = "vcf"; // vcard3    mtpFileTypes[LIBMTP_FILETYPE_WINDOWSIMAGEFORMAT] = "wim"; // windows image format    mtpFileTypes[LIBMTP_FILETYPE_WINEXEC] = "exe";    mtpFileTypes[LIBMTP_FILETYPE_TEXT] = "txt";    mtpFileTypes[LIBMTP_FILETYPE_HTML] = "html";    mtpFileTypes[LIBMTP_FILETYPE_UNKNOWN] = "unknown";    m_newTracks = new QPtrList<MediaItem>;}voidMtpMediaDevice::init( MediaBrowser *parent ){    MediaDevice::init( parent );}boolMtpMediaDevice::isConnected(){    return !( m_device == 0 );}/** * File types that we support */QStringListMtpMediaDevice::supportedFiletypes(){    return m_supportedFiles;}intMtpMediaDevice::progressCallback( uint64_t const sent, uint64_t const total, void const * const data ){    Q_UNUSED( sent );    Q_UNUSED( total );    kapp->processEvents( 100 );    MtpMediaDevice *dev = (MtpMediaDevice*)(data);    if( dev->isCanceled() )    {        debug() << "Canceling transfer operation" << endl;        dev->setCanceled( true );        return 1;    }    return 0;}/** * Copy a track to the device */MediaItem*MtpMediaDevice::copyTrackToDevice( const MetaBundle &bundle ){    DEBUG_BLOCK    QString genericError = i18n( "Could not send track" );    LIBMTP_track_t *trackmeta = LIBMTP_new_track_t();    trackmeta->item_id = 0;    debug() << "filetype : " << bundle.fileType() << endl;    if( bundle.fileType() == MetaBundle::mp3 )    {        trackmeta->filetype = LIBMTP_FILETYPE_MP3;    }    else if( bundle.fileType() == MetaBundle::ogg )    {        trackmeta->filetype = LIBMTP_FILETYPE_OGG;    }    else if( bundle.fileType() == MetaBundle::wma )    {        trackmeta->filetype = LIBMTP_FILETYPE_WMA;    }    else if( bundle.fileType() == MetaBundle::mp4 )    {        trackmeta->filetype = LIBMTP_FILETYPE_MP4;    }    else    {        // Couldn't recognise an Amarok filetype.        // fallback to checking the extension (e.g. .wma, .ogg, etc)        debug() << "No filetype found by Amarok filetype" << endl;        const QString extension = bundle.url().path().section( ".", -1 ).lower();        int libmtp_type = m_supportedFiles.findIndex( extension );        if( libmtp_type >= 0 )        {            int keyIndex = mtpFileTypes.values().findIndex( extension );            libmtp_type = mtpFileTypes.keys()[keyIndex];            trackmeta->filetype = (LIBMTP_filetype_t) libmtp_type;            debug() << "set filetype to " << libmtp_type << " based on extension of ." << extension << endl;        }        else        {            debug() << "We don't support the extension ." << extension << endl;            Amarok::StatusBar::instance()->shortLongMessage(                genericError,                i18n( "Cannot determine a valid file type" ),                KDE::StatusBar::Error            );            return 0;        }    }    if( bundle.title().isEmpty() )    {        trackmeta->title = qstrdup( i18n( "Unknown title" ).utf8() );    }    else    {        trackmeta->title = qstrdup( bundle.title().utf8() );    }    if( bundle.album().isEmpty() )    {        trackmeta->album = qstrdup( i18n( "Unknown album" ).utf8() );    }    else    {        trackmeta->album = qstrdup( bundle.album().string().utf8() );    }    if( bundle.artist().isEmpty() )    {        trackmeta->artist = qstrdup( i18n( "Unknown artist" ).utf8() );    }    else    {        trackmeta->artist = qstrdup( bundle.artist().string().utf8() );    }    if( bundle.genre().isEmpty() )    {        trackmeta->genre = qstrdup( i18n( "Unknown genre" ).utf8() );    }    else    {        trackmeta->genre = qstrdup( bundle.genre().string().utf8() );    }    if( bundle.year() > 0 )    {        QString date;        QTextOStream( &date ) << bundle.year() << "0101T0000.0";        trackmeta->date = qstrdup( date.utf8() );    }    else    {        trackmeta->date = qstrdup( "00010101T0000.0" );    }    if( bundle.track() > 0 )    {        trackmeta->tracknumber = bundle.track();    }    if( bundle.length() > 0 )    {        // Multiply by 1000 since this is in milliseconds        trackmeta->duration = bundle.length() * 1000;    }    if( !bundle.filename().isEmpty() )    {        trackmeta->filename = qstrdup( bundle.filename().utf8() );    }    trackmeta->filesize = bundle.filesize();    // try and create the requested folder structure    uint32_t parent_id = 0;    if( !m_folderStructure.isEmpty() )    {        parent_id = checkFolderStructure( bundle );        if( parent_id == 0 )        {            debug() << "Couldn't create new parent (" << m_folderStructure << ")" << endl;            Amarok::StatusBar::instance()->shortLongMessage(                genericError,                i18n( "Cannot create parent folder. Check your structure." ),                KDE::StatusBar::Error            );            return 0;        }    }    else    {        parent_id = getDefaultParentId();    }    debug() << "Parent id : " << parent_id << endl;    m_critical_mutex.lock();    debug() << "Sending track... " << bundle.url().path().utf8() << endl;    int ret = LIBMTP_Send_Track_From_File(        m_device, bundle.url().path().utf8(), trackmeta,        progressCallback, this, parent_id    );    m_critical_mutex.unlock();    if( ret < 0 )    {        debug() << "Could not write file " << ret << endl;        Amarok::StatusBar::instance()->shortLongMessage(            genericError,            i18n( "File write failed" ),            KDE::StatusBar::Error        );        return 0;    }    MetaBundle temp( bundle );    MtpTrack *taggedTrack = new MtpTrack( trackmeta );    taggedTrack->setBundle( temp );    taggedTrack->setFolderId( parent_id );    LIBMTP_destroy_track_t( trackmeta );    kapp->processEvents( 100 );    // add track to view and to new tracks list    MediaItem *newItem = addTrackToView( taggedTrack );    m_newTracks->append( newItem );    return newItem;}/** * Get the cover image for a track, convert it to a format supported on the * device and set it as the cover art. */voidMtpMediaDevice::sendAlbumArt( QPtrList<MediaItem> *items ){    QString image;    image = CollectionDB::instance()->albumImage(items->first()->bundle()->artist(), items->first()->bundle()->album(), false, 100);    if( ! image.endsWith( "@nocover.png" ) )    {        debug() << "image " << image << " found for " << items->first()->bundle()->album() << endl;        QByteArray *imagedata = getSupportedImage( image );        if( imagedata == 0 )        {            debug() << "Cannot generate a supported image format" << endl;            return;        }        if( imagedata->size() )        {            m_critical_mutex.lock();            LIBMTP_album_t *album_object = getOrCreateAlbum( items );            if( album_object )            {                LIBMTP_filesampledata_t *imagefile = LIBMTP_new_filesampledata_t();                imagefile->data = (char *) imagedata->data();                imagefile->size = imagedata->size();                imagefile->filetype = LIBMTP_FILETYPE_JPEG;                int ret = LIBMTP_Send_Representative_Sample( m_device, album_object->album_id, imagefile );                if( ret != 0 )                {                    debug() << "image send failed : " << ret << endl;                }            }            m_critical_mutex.unlock();        }    }}uint32_tMtpMediaDevice::getDefaultParentId( void ){    // Decide which folder to send it to:    // If the device gave us a parent_folder setting, we use it    uint32_t parent_id = 0;    if( m_default_parent_folder )    {        parent_id = m_default_parent_folder;    }    // Otherwise look for a folder called "Music"    else if( m_folders != 0 )    {        parent_id = folderNameToID( "Music", m_folders );        if( !parent_id )        {            debug() << "Parent folder could not be found. Going to use top level." << endl;        }    }    // Give up and don't set a parent folder, let the device deal with it    else    {        debug() << "No folders found. Going to use top level." << endl;    }    return parent_id;}/** * Takes path to an existing cover image and converts it to a format * supported on the device */QByteArray*MtpMediaDevice::getSupportedImage( QString path ){    if( m_format == 0 )        return 0;    debug() << "Will convert image to " << m_format << endl;    // open image    const QImage original( path );    // save as new image    QImage newformat( original );    QByteArray *newimage = new QByteArray();    QBuffer buffer( *newimage );    buffer.open( IO_WriteOnly );    if( newformat.save( &buffer, m_format.ascii() ) )    {

⌨️ 快捷键说明

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