Ticket #7430: mediaplayer_artwork.diff

File mediaplayer_artwork.diff, 26.2 KB (added by shinta, 13 years ago)

This is the patch to implement artwork feature.

  • playlist/Playlist.cpp

     
    456456        } else {
    457457            if (_IsQuery(type))
    458458                AppendQueryToPlaylist(ref, &subPlaylist);
    459             else
    460                 AppendToPlaylistRecursive(ref, &subPlaylist);
     459            else {
     460                if ( !ExtraMediaExists(this, ref) ) {
     461                    AppendToPlaylistRecursive(ref, &subPlaylist);
     462                }
     463            }
    461464
    462465            // At least sort this subsection of the playlist
    463466            // if the whole playlist is not sorted anymore.
     
    510513        BString mimeString = _MIMEString(&ref);
    511514        if (_IsMediaFile(mimeString)) {
    512515            PlaylistItem* item = new (std::nothrow) FilePlaylistItem(ref);
    513             if (item != NULL && !playlist->AddItem(item))
     516            if (!ExtraMediaExists(playlist, ref)) {
     517                _BindExtraMedia(item);
     518                if (item != NULL && !playlist->AddItem(item))
     519                    delete item;
     520            } else
    514521                delete item;
    515522        } else
    516523            printf("MIME Type = %s\n", mimeString.String());
     
    584591}
    585592
    586593
     594/*static*/ bool
     595Playlist::ExtraMediaExists(Playlist* playlist, const entry_ref& ref)
     596{
     597    BString exceptExtension = _GetExceptExtension(BPath(&ref).Path());
     598   
     599    for (int32 i = 0; i < playlist->CountItems(); i++) {
     600        FilePlaylistItem* compare = dynamic_cast<FilePlaylistItem*>(playlist->ItemAt(i));
     601        if (compare == NULL)
     602            continue;
     603        if (compare->Ref() != ref
     604                && _GetExceptExtension(BPath(&compare->Ref()).Path()) == exceptExtension )
     605            return true;
     606    }
     607    return false;
     608}
     609
     610
    587611// #pragma mark - private
    588612
    589613
    590614/*static*/ bool
     615Playlist::_IsImageFile(const BString& mimeString)
     616{
     617    BMimeType superType;
     618    BMimeType fileType(mimeString.String());
     619
     620    if (fileType.GetSupertype(&superType) != B_OK)
     621        return false;
     622
     623    if (superType == "image")
     624        return true;
     625
     626    return false;
     627}
     628
     629
     630/*static*/ bool
    591631Playlist::_IsMediaFile(const BString& mimeString)
    592632{
    593633    BMimeType superType;
     
    668708}
    669709
    670710
     711// _BindExtraMedia() searches additional videos and audios
     712// and addes them as extra medias.
     713/*static*/ void
     714Playlist::_BindExtraMedia(PlaylistItem* item)
     715{
     716    FilePlaylistItem* fileItem = dynamic_cast<FilePlaylistItem*>(item);
     717    if (!item)
     718        return;
     719   
     720    // If the media file is foo.mp3, _BindExtraMedia() searches foo.avi.
     721    BPath mediaFilePath(&fileItem->Ref());
     722    BString mediaFilePathString = mediaFilePath.Path();
     723    BPath dirPath;
     724    mediaFilePath.GetParent(&dirPath);
     725    BDirectory dir(dirPath.Path());
     726    if (dir.InitCheck() != B_OK)
     727        return;
     728   
     729    BEntry entry;
     730    BString entryPathString;
     731    while (dir.GetNextEntry(&entry, true) == B_OK) {
     732        if (!entry.IsFile())
     733            continue;
     734        entryPathString = BPath(&entry).Path();
     735        if (entryPathString != mediaFilePathString
     736                && _GetExceptExtension(entryPathString) == _GetExceptExtension(mediaFilePathString)) {
     737            _BindExtraMedia(fileItem, entry);
     738        }
     739    }
     740}
     741
     742
     743/*static*/ void
     744Playlist::_BindExtraMedia(FilePlaylistItem* fileItem, const BEntry& entry)
     745{
     746    entry_ref ref;
     747    entry.GetRef(&ref);
     748    BString mimeString = _MIMEString(&ref);
     749    if (_IsMediaFile(mimeString)) {
     750        fileItem->AddRef(ref);
     751    } else if (_IsImageFile(mimeString)) {
     752        fileItem->AddImageRef(ref);
     753    }
     754}
     755
     756
     757/*static*/ BString
     758Playlist::_GetExceptExtension(const BString& path)
     759{
     760    int32 periodPos = path.FindLast('.');
     761    if (periodPos <= path.FindLast('/'))
     762        return path;
     763    return BString(path.String(), periodPos);
     764}
     765
     766
    671767// #pragma mark - notifications
    672768
    673769
  • playlist/Playlist.h

     
    2525#include <List.h>
    2626#include <Locker.h>
    2727
     28#include "FilePlaylistItem.h"
    2829#include "PlaylistItem.h"
    2930
    3031class BDataIO;
     
    113114
    114115            void                NotifyImportFailed();
    115116
     117    static  bool                ExtraMediaExists(Playlist* playlist, const entry_ref& ref);
     118
    116119private:
    117120                                Playlist(const Playlist& other);
    118121            Playlist&           operator=(const Playlist& other);
    119122                                    // unimplemented
    120123
     124    static  bool                _IsImageFile(const BString& mimeString);
    121125    static  bool                _IsMediaFile(const BString& mimeString);
    122126    static  bool                _IsTextPlaylist(const BString& mimeString);
    123127    static  bool                _IsBinaryPlaylist(const BString& mimeString);
    124128    static  bool                _IsPlaylist(const BString& mimeString);
    125129    static  bool                _IsQuery(const BString& mimeString);
    126130    static  BString             _MIMEString(const entry_ref* ref);
     131    static  void                _BindExtraMedia(PlaylistItem* item);
     132    static  void                _BindExtraMedia(FilePlaylistItem* fileItem, const BEntry& entry);
     133    static  BString             _GetExceptExtension(const BString& path);
    127134
    128135            void                _NotifyItemAdded(PlaylistItem*,
    129136                                    int32 index) const;
  • playlist/ImportPLItemsCommand.cpp

     
    5757    memset(fNewItems, 0, fNewCount * sizeof(PlaylistItem*));
    5858
    5959    // init new entries
     60    int32 added = 0;
    6061    for (int32 i = 0; i < fNewCount; i++) {
    61         fNewItems[i] = temp.ItemAtFast(i)->Clone();
    62         if (fNewItems[i] == NULL) {
    63             // indicate bad object init
    64             _CleanUp(fNewItems, fNewCount, true);
    65             return;
     62        FilePlaylistItem* fileItem = dynamic_cast<FilePlaylistItem*>(temp.ItemAtFast(i));
     63        if (fileItem && !Playlist::ExtraMediaExists(playlist, fileItem->Ref())) {
     64            fNewItems[added] = temp.ItemAtFast(i)->Clone();
     65            if (fNewItems[added] == NULL) {
     66                // indicate bad object init
     67                _CleanUp(fNewItems, fNewCount, true);
     68                return;
     69            }
     70            added++;
    6671        }
    6772    }
     73    fNewCount = added;
    6874
    6975    fPlaylingIndex = fPlaylist->CurrentItemIndex();
    7076
  • playlist/FilePlaylistItem.cpp

     
    1414#include <FindDirectory.h>
    1515#include <MediaFile.h>
    1616#include <Path.h>
     17#include <TranslationUtils.h>
    1718
    1819#include "MediaFileTrackSupplier.h"
    1920#include "SubTitlesSRT.h"
    2021
    21 
    2222static const char* kPathKey = "path";
    2323
    24 
    2524FilePlaylistItem::FilePlaylistItem(const entry_ref& ref)
    26     :
    27     fRef(ref),
    28     fNameInTrash("")
    2925{
     26    fRefs.push_back(ref);
     27    fNamesInTrash.push_back("");
    3028}
    3129
    3230
    3331FilePlaylistItem::FilePlaylistItem(const FilePlaylistItem& other)
    3432    :
    35     fRef(other.fRef),
    36     fNameInTrash(other.fNameInTrash)
     33    fRefs(other.fRefs),
     34    fNamesInTrash(other.fNamesInTrash),
     35    fImageRefs(other.fImageRefs),
     36    fImageNamesInTrash(other.fImageNamesInTrash)
    3737{
    3838}
    3939
    4040
    4141FilePlaylistItem::FilePlaylistItem(const BMessage* archive)
    42     :
    43     fRef(),
    44     fNameInTrash("")
    4542{
    4643    const char* path;
    47     if (archive != NULL && archive->FindString(kPathKey, &path) == B_OK) {
    48         if (get_ref_for_path(path, &fRef) != B_OK)
    49             fRef = entry_ref();
     44    entry_ref   ref;
     45    if (archive != NULL) {
     46        int32 i = 0;
     47        while (archive->FindString(kPathKey, i, &path) == B_OK) {
     48            if (get_ref_for_path(path, &ref) == B_OK) {
     49                fRefs.push_back(ref);
     50            }
     51            i++;
     52        }
    5053    }
     54    if (fRefs.empty()) {
     55        fRefs.push_back(entry_ref());
     56    }
     57    for (vector<entry_ref>::size_type i = 0; i < fRefs.size(); i++) {
     58        fNamesInTrash.push_back("");
     59    }
    5160}
    5261
    5362
     
    8291    status_t ret = BArchivable::Archive(into, deep);
    8392    if (ret != B_OK)
    8493        return ret;
    85     BPath path(&fRef);
    86     ret = path.InitCheck();
    87     if (ret == B_OK)
     94    for (vector<entry_ref>::size_type i = 0; i < fRefs.size(); i++) {
     95        BPath path(&fRefs[i]);
     96        ret = path.InitCheck();
     97        if (ret != B_OK)
     98            return ret;
    8899        ret = into->AddString(kPathKey, path.Path());
    89     return ret;
     100        if (ret != B_OK)
     101            return ret;
     102    }
     103    return B_OK;
    90104}
    91105
    92106
     
    97111    switch (attribute) {
    98112        case ATTR_STRING_NAME:
    99113        {
    100             BEntry entry(&fRef, false);
     114            BEntry entry(&fRefs[0], false);
    101115            return entry.Rename(string.String(), false);
    102116        }
    103117   
     
    135149    BString& string) const
    136150{
    137151    if (attribute == ATTR_STRING_NAME) {
    138         string = fRef.name;
     152        string = fRefs[0].name;
    139153        return B_OK;
    140154    }
    141155
     
    194208BString
    195209FilePlaylistItem::LocationURI() const
    196210{
    197     BPath path(&fRef);
     211    BPath path(&fRefs[0]);
    198212    BString locationURI("file://");
    199213    locationURI << path.Path();
    200214    return locationURI;
     
    204218status_t
    205219FilePlaylistItem::GetIcon(BBitmap* bitmap, icon_size iconSize) const
    206220{
    207     BNode node(&fRef);
     221    BNode node(&fRefs[0]);
    208222    BNodeInfo info(&node);
    209223    return info.GetTrackerIcon(bitmap, iconSize);
    210224}
     
    213227status_t
    214228FilePlaylistItem::MoveIntoTrash()
    215229{
    216     if (fNameInTrash.Length() != 0) {
     230    if (fNamesInTrash[0].Length() != 0) {
    217231        // Already in the trash!
    218232        return B_ERROR;
    219233    }
    220234
    221     char trashPath[B_PATH_NAME_LENGTH];
    222     status_t err = find_directory(B_TRASH_DIRECTORY, fRef.device,
    223         true /*create it*/, trashPath, B_PATH_NAME_LENGTH);
    224     if (err != B_OK) {
    225         fprintf(stderr, "failed to find Trash: %s\n", strerror(err));
     235    status_t err;
     236    err = _MoveIntoTrash(&fRefs, &fNamesInTrash);
     237    if (err != B_OK)
    226238        return err;
    227     }
     239   
     240    if (fImageRefs.empty())
     241        return B_OK;
    228242
    229     BEntry entry(&fRef);
    230     err = entry.InitCheck();
    231     if (err != B_OK) {
    232         fprintf(stderr, "failed to init BEntry for %s: %s\n",
    233             fRef.name, strerror(err));
     243    err = _MoveIntoTrash(&fImageRefs, &fImageNamesInTrash);
     244    if (err != B_OK)
    234245        return err;
    235     }
    236     BDirectory trashDir(trashPath);
    237     if (err != B_OK) {
    238         fprintf(stderr, "failed to init BDirectory for %s: %s\n",
    239             trashPath, strerror(err));
    240         return err;
    241     }
    242246
    243     // Find a unique name for the entry in the trash
    244     fNameInTrash = fRef.name;
    245     int32 uniqueNameIndex = 1;
    246     while (true) {
    247         BEntry test(&trashDir, fNameInTrash.String());
    248         if (!test.Exists())
    249             break;
    250         fNameInTrash = fRef.name;
    251         fNameInTrash << ' ' << uniqueNameIndex;
    252         uniqueNameIndex++;
    253     }
    254 
    255     // Remember the original path
    256     BPath originalPath;
    257     entry.GetPath(&originalPath);
    258 
    259     // Finally, move the entry into the trash
    260     err = entry.MoveTo(&trashDir, fNameInTrash.String());
    261     if (err != B_OK) {
    262         fprintf(stderr, "failed to move entry into trash %s: %s\n",
    263             trashPath, strerror(err));
    264         return err;
    265     }
    266 
    267     // Allow Tracker to restore this entry
    268     BNode node(&entry);
    269     BString originalPathString(originalPath.Path());
    270     node.WriteAttrString("_trk/original_path", &originalPathString);
    271 
    272     return err;
     247    return B_OK;
    273248}
    274249
    275250
    276 
    277251status_t
    278252FilePlaylistItem::RestoreFromTrash()
    279253{
    280     if (fNameInTrash.Length() <= 0) {
     254    if (fNamesInTrash[0].Length() <= 0) {
    281255        // Not in the trash!
    282256        return B_ERROR;
    283257    }
    284258
    285     char trashPath[B_PATH_NAME_LENGTH];
    286     status_t err = find_directory(B_TRASH_DIRECTORY, fRef.device,
    287         false /*create it*/, trashPath, B_PATH_NAME_LENGTH);
    288     if (err != B_OK) {
    289         fprintf(stderr, "failed to find Trash: %s\n", strerror(err));
     259    status_t err;
     260    err = _RestoreFromTrash(&fRefs, &fNamesInTrash);
     261    if (err != B_OK)
    290262        return err;
    291     }
    292     // construct the entry to the file in the trash
    293 // TODO: BEntry(const BDirectory* directory, const char* path) is broken!
    294 //  BEntry entry(trashPath, fNamesInTrash[i].String());
    295 BPath path(trashPath, fNameInTrash.String());
    296 BEntry entry(path.Path());
    297     err = entry.InitCheck();
    298     if (err != B_OK) {
    299         fprintf(stderr, "failed to init BEntry for %s: %s\n",
    300             fNameInTrash.String(), strerror(err));
    301         return err;
    302     }
    303 //entry.GetPath(&path);
    304 //printf("moving '%s'\n", path.Path());
     263   
     264    if (fImageRefs.empty())
     265        return B_OK;
    305266
    306     // construct the folder of the original entry_ref
    307     node_ref nodeRef;
    308     nodeRef.device = fRef.device;
    309     nodeRef.node = fRef.directory;
    310     BDirectory originalDir(&nodeRef);
    311     err = originalDir.InitCheck();
    312     if (err != B_OK) {
    313         fprintf(stderr, "failed to init original BDirectory for "
    314             "%s: %s\n", fRef.name, strerror(err));
     267    err = _RestoreFromTrash(&fImageRefs, &fImageNamesInTrash);
     268    if (err != B_OK)
    315269        return err;
    316     }
    317270
    318 //path.SetTo(&originalDir, fItems[i].name);
    319 //printf("as '%s'\n", path.Path());
    320 
    321     // Reset the name here, the user may have already moved the entry
    322     // out of the trash via Tracker for example.
    323     fNameInTrash = "";
    324 
    325     // Finally, move the entry back into the original folder
    326     err = entry.MoveTo(&originalDir, fRef.name);
    327     if (err != B_OK) {
    328         fprintf(stderr, "failed to restore entry from trash "
    329             "%s: %s\n", fRef.name, strerror(err));
    330         return err;
    331     }
    332 
    333     // Remove the attribute that helps Tracker restore the entry.
    334     BNode node(&entry);
    335     node.RemoveAttr("_trk/original_path");
    336 
    337     return err;
     271    return B_OK;
    338272}
    339273
    340274
    341275// #pragma mark -
    342276
    343 
    344277TrackSupplier*
    345278FilePlaylistItem::CreateTrackSupplier() const
    346279{
    347     BMediaFile* mediaFile = new(std::nothrow) BMediaFile(&fRef);
    348     if (mediaFile == NULL)
    349         return NULL;
    350280    MediaFileTrackSupplier* supplier
    351         = new(std::nothrow) MediaFileTrackSupplier(mediaFile);
    352     if (supplier == NULL) {
    353         delete mediaFile;
     281        = new(std::nothrow) MediaFileTrackSupplier();
     282    if (supplier == NULL)
    354283        return NULL;
     284
     285    for (vector<entry_ref>::size_type i = 0; i < fRefs.size(); i++) {
     286        BMediaFile* mediaFile = new(std::nothrow) BMediaFile(&fRefs[i]);
     287        if (mediaFile == NULL) {
     288            delete supplier;
     289            return NULL;
     290        }
     291        if (supplier->AddMediaFile(mediaFile) != B_OK)
     292            delete mediaFile;
    355293    }
    356294
     295    for (vector<entry_ref>::size_type i = 0; i < fImageRefs.size(); i++) {
     296        BBitmap* bitmap = BTranslationUtils::GetBitmap(&fImageRefs[i]);
     297        if (bitmap == NULL)
     298            continue;
     299        if (supplier->AddBitmap(bitmap) != B_OK)
     300            delete bitmap;
     301    }
     302
    357303    // Search for subtitle files in the same folder
    358304    // TODO: Error checking
    359     BEntry entry(&fRef, true);
     305    BEntry entry(&fRefs[0], true);
    360306
    361307    char originalName[B_FILE_NAME_LENGTH];
    362308    entry.GetName(originalName);
     
    411357
    412358
    413359status_t
     360FilePlaylistItem::AddRef(const entry_ref& ref)
     361{
     362    fRefs.push_back(ref);
     363    fNamesInTrash.push_back("");
     364    return B_OK;
     365}
     366
     367
     368status_t
     369FilePlaylistItem::AddImageRef(const entry_ref& ref)
     370{
     371    fImageRefs.push_back(ref);
     372    fImageNamesInTrash.push_back("");
     373    return B_OK;
     374}
     375
     376
     377const entry_ref&
     378FilePlaylistItem::ImageRef() const
     379{
     380    static entry_ref ref;
     381
     382    if (fImageRefs.empty())
     383        return ref;
     384   
     385    return fImageRefs[0];
     386}
     387
     388
     389status_t
    414390FilePlaylistItem::_SetAttribute(const char* attrName, type_code type,
    415391    const void* data, size_t size)
    416392{
    417     BEntry entry(&fRef, true);
     393    BEntry entry(&fRefs[0], true);
    418394    BNode node(&entry);
    419395    if (node.InitCheck() != B_OK)
    420396        return node.InitCheck();
     
    433409FilePlaylistItem::_GetAttribute(const char* attrName, type_code type,
    434410    void* data, size_t size)
    435411{
    436     BEntry entry(&fRef, true);
     412    BEntry entry(&fRefs[0], true);
    437413    BNode node(&entry);
    438414    if (node.InitCheck() != B_OK)
    439415        return node.InitCheck();
     
    447423    return B_OK;
    448424}
    449425
     426
     427status_t
     428FilePlaylistItem::_MoveIntoTrash(vector<entry_ref>* refs,
     429    vector<BString>* namesInTrash)
     430{
     431    char trashPath[B_PATH_NAME_LENGTH];
     432    status_t err = find_directory(B_TRASH_DIRECTORY, (*refs)[0].device,
     433        true /*create it*/, trashPath, B_PATH_NAME_LENGTH);
     434    if (err != B_OK) {
     435        fprintf(stderr, "failed to find Trash: %s\n", strerror(err));
     436        return err;
     437    }
     438
     439    BDirectory trashDir(trashPath);
     440    if (err != B_OK) {
     441        fprintf(stderr, "failed to init BDirectory for %s: %s\n",
     442            trashPath, strerror(err));
     443        return err;
     444    }
     445
     446    for (vector<entry_ref>::size_type i = 0; i < refs->size(); i++) {
     447        BEntry entry(&(*refs)[i]);
     448        err = entry.InitCheck();
     449        if (err != B_OK) {
     450            fprintf(stderr, "failed to init BEntry for %s: %s\n",
     451                (*refs)[i].name, strerror(err));
     452            return err;
     453        }
     454   
     455        // Find a unique name for the entry in the trash
     456        (*namesInTrash)[i] = (*refs)[i].name;
     457        int32 uniqueNameIndex = 1;
     458        while (true) {
     459            BEntry test(&trashDir, (*namesInTrash)[i].String());
     460            if (!test.Exists())
     461                break;
     462            (*namesInTrash)[i] = (*refs)[i].name;
     463            (*namesInTrash)[i] << ' ' << uniqueNameIndex;
     464            uniqueNameIndex++;
     465        }
     466   
     467        // Remember the original path
     468        BPath originalPath;
     469        entry.GetPath(&originalPath);
     470   
     471        // Finally, move the entry into the trash
     472        err = entry.MoveTo(&trashDir, (*namesInTrash)[i].String());
     473        if (err != B_OK) {
     474            fprintf(stderr, "failed to move entry into trash %s: %s\n",
     475                trashPath, strerror(err));
     476            return err;
     477        }
     478   
     479        // Allow Tracker to restore this entry
     480        BNode node(&entry);
     481        BString originalPathString(originalPath.Path());
     482        node.WriteAttrString("_trk/original_path", &originalPathString);
     483    }
     484
     485    return B_OK;
     486}
     487
     488
     489status_t
     490FilePlaylistItem::_RestoreFromTrash(vector<entry_ref>* refs,
     491    vector<BString>* namesInTrash)
     492{
     493    char trashPath[B_PATH_NAME_LENGTH];
     494    status_t err = find_directory(B_TRASH_DIRECTORY, (*refs)[0].device,
     495        false /*create it*/, trashPath, B_PATH_NAME_LENGTH);
     496    if (err != B_OK) {
     497        fprintf(stderr, "failed to find Trash: %s\n", strerror(err));
     498        return err;
     499    }
     500   
     501    for (vector<entry_ref>::size_type i = 0; i < refs->size(); i++) {
     502        // construct the entry to the file in the trash
     503        // TODO: BEntry(const BDirectory* directory, const char* path) is broken!
     504        //  BEntry entry(trashPath, (*namesInTrash)[i].String());
     505        BPath path(trashPath, (*namesInTrash)[i].String());
     506        BEntry entry(path.Path());
     507        err = entry.InitCheck();
     508        if (err != B_OK) {
     509            fprintf(stderr, "failed to init BEntry for %s: %s\n",
     510                (*namesInTrash)[i].String(), strerror(err));
     511            return err;
     512        }
     513        //entry.GetPath(&path);
     514        //printf("moving '%s'\n", path.Path());
     515   
     516        // construct the folder of the original entry_ref
     517        node_ref nodeRef;
     518        nodeRef.device = (*refs)[i].device;
     519        nodeRef.node = (*refs)[i].directory;
     520        BDirectory originalDir(&nodeRef);
     521        err = originalDir.InitCheck();
     522        if (err != B_OK) {
     523            fprintf(stderr, "failed to init original BDirectory for "
     524                "%s: %s\n", (*refs)[i].name, strerror(err));
     525            return err;
     526        }
     527   
     528        //path.SetTo(&originalDir, fItems[i].name);
     529        //printf("as '%s'\n", path.Path());
     530   
     531        // Reset the name here, the user may have already moved the entry
     532        // out of the trash via Tracker for example.
     533        (*namesInTrash)[i] = "";
     534   
     535        // Finally, move the entry back into the original folder
     536        err = entry.MoveTo(&originalDir, (*refs)[i].name);
     537        if (err != B_OK) {
     538            fprintf(stderr, "failed to restore entry from trash "
     539                "%s: %s\n", (*refs)[i].name, strerror(err));
     540            return err;
     541        }
     542   
     543        // Remove the attribute that helps Tracker restore the entry.
     544        BNode node(&entry);
     545        node.RemoveAttr("_trk/original_path");
     546    }
     547
     548    return B_OK;
     549}
     550
  • playlist/FilePlaylistItem.h

     
    99
    1010#include <Entry.h>
    1111
     12#include <vector>
     13
    1214class FilePlaylistItem : public PlaylistItem {
    1315public:
    1416                                FilePlaylistItem(const entry_ref& ref);
     
    5052    // playback
    5153    virtual TrackSupplier*      CreateTrackSupplier() const;
    5254
    53             const entry_ref&    Ref() const { return fRef; }
     55            status_t            AddRef(const entry_ref& ref);
     56            const entry_ref&    Ref() const { return fRefs[0]; }
    5457
     58            status_t            AddImageRef(const entry_ref& ref);
     59            const entry_ref&    ImageRef() const;
     60
    5561private:
    5662            status_t            _SetAttribute(const char* attrName,
    5763                                    type_code type, const void* data,
     
    5965            status_t            _GetAttribute(const char* attrName,
    6066                                    type_code type, void* data,
    6167                                    size_t size);
     68            status_t            _MoveIntoTrash(vector<entry_ref>* refs,
     69                                    vector<BString>* namesInTrash);
     70            status_t            _RestoreFromTrash(vector<entry_ref>* refs,
     71                                    vector<BString>* namesInTrash);
    6272
    6373private:
    64             entry_ref           fRef;
    65             BString             fNameInTrash;
     74    // always fRefs.size() == fNamesInTrash.size()
     75            vector<entry_ref>   fRefs;
     76            vector<BString>     fNamesInTrash;
     77    // always fImageRefs.size() == fImageNamesInTrash.size()
     78            vector<entry_ref>   fImageRefs;
     79            vector<BString>     fImageNamesInTrash;
    6680};
    6781
    6882#endif // FILE_PLAYLIST_ITEM_H
  • supplier/MediaFileTrackSupplier.cpp

     
    1717
    1818#include "MediaTrackAudioSupplier.h"
    1919#include "MediaTrackVideoSupplier.h"
     20#include "ImageTrackVideoSupplier.h"
    2021
    2122
    22 MediaFileTrackSupplier::MediaFileTrackSupplier(BMediaFile* mediaFile)
     23MediaFileTrackSupplier::MediaFileTrackSupplier()
    2324    :
    24     TrackSupplier(),
    25     fMediaFile(mediaFile)
     25    TrackSupplier()
    2626{
    27     if (fMediaFile->InitCheck() != B_OK)
    28         return;
    29     int trackCount = fMediaFile->CountTracks();
    30     if (trackCount <= 0)
    31         return;
    32 
    33     for (int i = 0; i < trackCount; i++) {
    34         BMediaTrack* track = fMediaFile->TrackAt(i);
    35         media_format format;
    36         status_t status = track->EncodedFormat(&format);
    37         if (status != B_OK) {
    38             fprintf(stderr, "MediaFileTrackSupplier: EncodedFormat failed for "
    39                 "track index %d, error: %s\n", i, strerror(status));
    40             fMediaFile->ReleaseTrack(track);
    41             continue;
    42         }
    43 
    44         if (track->Duration() <= 0) {
    45             fprintf(stderr, "MediaFileTrackSupplier: warning! track index %d "
    46                 "has no duration\n", i);
    47         }
    48 
    49         if (format.IsAudio()) {
    50             if (!fAudioTracks.AddItem(track)) {
    51                 fMediaFile->ReleaseTrack(track);
    52                 return;
    53             }
    54         } else if (format.IsVideo()) {
    55             if (!fVideoTracks.AddItem(track)) {
    56                 fMediaFile->ReleaseTrack(track);
    57                 return;
    58             }
    59         } else {
    60             printf("MediaFileTrackSupplier: track index %d has unknown "
    61                 "type\n", i);
    62             fMediaFile->ReleaseTrack(track);
    63         }
    64     }
    6527}
    6628
    6729
    6830MediaFileTrackSupplier::~MediaFileTrackSupplier()
    6931{
    70     delete fMediaFile;
     32    for (vector<BMediaFile*>::size_type i = fMediaFiles.size() - 1; static_cast<int32>(i) >= 0; i--)
     33        delete fMediaFiles[i];
    7134        // BMediaFile destructor will call ReleaseAllTracks()
     35    for (vector<BBitmap*>::size_type i = fBitmaps.size() - 1; static_cast<int32>(i) >= 0; i--)
     36        delete fBitmaps[i];
    7237    for (int32 i = fSubTitleTracks.CountItems() - 1; i >= 0; i--)
    7338        delete reinterpret_cast<SubTitles*>(fSubTitleTracks.ItemAtFast(i));
    7439 }
     
    7742status_t
    7843MediaFileTrackSupplier::InitCheck()
    7944{
    80     return fMediaFile->InitCheck();
     45    if (fMediaFiles.empty())
     46        return B_ERROR;
     47   
     48    return fMediaFiles[0]->InitCheck();
    8149}
    8250
    8351
    8452status_t
    8553MediaFileTrackSupplier::GetFileFormatInfo(media_file_format* fileFormat)
    8654{
    87     return fMediaFile->GetFileFormatInfo(fileFormat);
     55    if (fMediaFiles.empty())
     56        return B_ERROR;
     57
     58    return fMediaFiles[0]->GetFileFormatInfo(fileFormat);
    8859}
    8960
    9061
    9162status_t
    9263MediaFileTrackSupplier::GetCopyright(BString* copyright)
    9364{
    94     *copyright = fMediaFile->Copyright();
     65    if (fMediaFiles.empty())
     66        return B_ERROR;
     67
     68    *copyright = fMediaFiles[0]->Copyright();
    9569    return B_OK;
    9670}
    9771
     
    9973status_t
    10074MediaFileTrackSupplier::GetMetaData(BMessage* metaData)
    10175{
    102     return fMediaFile->GetMetaData(metaData);
     76    if (fMediaFiles.empty())
     77        return B_ERROR;
     78
     79    return fMediaFiles[0]->GetMetaData(metaData);
    10380}
    10481
    10582
     
    11390int32
    11491MediaFileTrackSupplier::CountVideoTracks()
    11592{
    116     return fVideoTracks.CountItems();
     93    return fVideoTracks.CountItems() + fBitmaps.size();
    11794}
    11895
    11996
     
    160137VideoTrackSupplier*
    161138MediaFileTrackSupplier::CreateVideoTrackForIndex(int32 index)
    162139{
    163     BMediaTrack* track = (BMediaTrack*)fVideoTracks.ItemAt(index);
    164     if (track == NULL)
    165         return NULL;
     140    VideoTrackSupplier* supplier;
     141    status_t initStatus;
    166142
    167     status_t initStatus;
    168     MediaTrackVideoSupplier* supplier
    169         = new(std::nothrow) MediaTrackVideoSupplier(track, index, initStatus);
     143    if (fVideoTracks.CountItems() <= index
     144            && index < fVideoTracks.CountItems() + static_cast<int32>(fBitmaps.size())) {
     145        supplier = new(std::nothrow) ImageTrackVideoSupplier(fBitmaps[index-fVideoTracks.CountItems()], index, initStatus);
     146    } else {
     147        BMediaTrack* track = (BMediaTrack*)fVideoTracks.ItemAt(index);
     148        if (track == NULL)
     149            return NULL;
     150   
     151        supplier = new(std::nothrow) MediaTrackVideoSupplier(track, index, initStatus);
     152    }
     153
    170154    if (initStatus != B_OK) {
    171155        delete supplier;
    172156        return NULL;
    173157    }
    174 
    175158    return supplier;
    176159}
    177160
     
    189172    return fSubTitleTracks.AddItem(subTitles);
    190173}
    191174
     175
     176status_t
     177MediaFileTrackSupplier::AddMediaFile(BMediaFile* mediaFile)
     178{
     179    if (mediaFile->InitCheck() != B_OK)
     180        return B_ERROR;
     181    int trackCount = mediaFile->CountTracks();
     182    if (trackCount <= 0)
     183        return B_ERROR;
     184
     185    status_t    funcStatus = B_ERROR;
     186    for (int i = 0; i < trackCount; i++) {
     187        BMediaTrack* track = mediaFile->TrackAt(i);
     188        media_format format;
     189        status_t status = track->EncodedFormat(&format);
     190        if (status != B_OK) {
     191            fprintf(stderr, "MediaFileTrackSupplier: EncodedFormat failed for "
     192                "track index %d, error: %s\n", i, strerror(status));
     193            mediaFile->ReleaseTrack(track);
     194            continue;
     195        }
     196
     197        if (track->Duration() <= 0) {
     198            fprintf(stderr, "MediaFileTrackSupplier: warning! track index %d "
     199                "has no duration\n", i);
     200        }
     201
     202        if (format.IsAudio()) {
     203            if (fAudioTracks.AddItem(track)) {
     204                funcStatus = B_OK;
     205            } else {
     206                mediaFile->ReleaseTrack(track);
     207            }
     208        } else if (format.IsVideo()) {
     209            if (fVideoTracks.AddItem(track)) {
     210                funcStatus = B_OK;
     211            } else {
     212                mediaFile->ReleaseTrack(track);
     213            }
     214        } else {
     215            printf("MediaFileTrackSupplier: track index %d has unknown "
     216                "type\n", i);
     217            mediaFile->ReleaseTrack(track);
     218        }
     219    }
     220    if (funcStatus == B_OK)
     221        fMediaFiles.push_back(mediaFile);
     222    return funcStatus;
     223}
     224
     225
     226status_t
     227MediaFileTrackSupplier::AddBitmap(BBitmap* bitmap)
     228{
     229    fBitmaps.push_back(bitmap);
     230    return B_OK;
     231}
     232
     233
  • supplier/MediaFileTrackSupplier.h

     
    66#define MEDIA_FILE_TRACK_SUPPLIER_H
    77
    88
     9#include <Bitmap.h>
    910#include <List.h>
    1011
    1112#include "TrackSupplier.h"
    1213
     14#include <vector>
    1315
    1416class BMediaFile;
    1517
    1618
    1719class MediaFileTrackSupplier : public TrackSupplier {
    1820public:
    19                                 MediaFileTrackSupplier(BMediaFile* mediaFile);
     21                                MediaFileTrackSupplier();
    2022    virtual                     ~MediaFileTrackSupplier();
    2123
    2224    virtual status_t            InitCheck();
     
    4143
    4244            bool                AddSubTitles(SubTitles* subTitles);
    4345
     46            status_t            AddMediaFile(BMediaFile* mediaFile);
     47
     48            status_t            AddBitmap(BBitmap* bitmap);
     49
    4450private:
    45             BMediaFile*         fMediaFile;
     51            vector<BMediaFile*> fMediaFiles;
     52            vector<BBitmap*>    fBitmaps;
    4653            BList               fAudioTracks;
    4754            BList               fVideoTracks;
    4855            BList               fSubTitleTracks;
  • Jamfile

     
    7777
    7878    # supplier
    7979    AudioTrackSupplier.cpp
     80    ImageTrackVideoSupplier.cpp
    8081    MediaFileTrackSupplier.cpp
    8182    MediaTrackAudioSupplier.cpp
    8283    MediaTrackVideoSupplier.cpp