Ticket #7416: mediaplayer2.diff

File mediaplayer2.diff, 21.2 KB (added by shinta, 13 years ago)
  • 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
     
    668692}
    669693
    670694
     695// _BindExtraMedia() searches additional videos and audios
     696// and addes them as extra medias.
     697/*static*/ void
     698Playlist::_BindExtraMedia(PlaylistItem* item)
     699{
     700    FilePlaylistItem* fileItem = dynamic_cast<FilePlaylistItem*>(item);
     701    if (!item)
     702        return;
     703   
     704    // If the media file is foo.mp3, _BindExtraMedia() searches foo.avi.
     705    BPath mediaFilePath(&fileItem->Ref());
     706    BString mediaFilePathString = mediaFilePath.Path();
     707    BPath dirPath;
     708    mediaFilePath.GetParent(&dirPath);
     709    BDirectory dir(dirPath.Path());
     710    if (dir.InitCheck() != B_OK)
     711        return;
     712   
     713    BEntry entry;
     714    BString entryPathString;
     715    while (dir.GetNextEntry(&entry, true) == B_OK) {
     716        if (!entry.IsFile())
     717            continue;
     718        entryPathString = BPath(&entry).Path();
     719        if (entryPathString != mediaFilePathString
     720                && _GetExceptExtension(entryPathString) == _GetExceptExtension(mediaFilePathString)) {
     721            _BindExtraMedia(fileItem, entry);
     722        }
     723    }
     724}
     725
     726
     727/*static*/ void
     728Playlist::_BindExtraMedia(FilePlaylistItem* fileItem, const BEntry& entry)
     729{
     730    entry_ref ref;
     731    entry.GetRef(&ref);
     732    BString mimeString = _MIMEString(&ref);
     733    if (_IsMediaFile(mimeString)) {
     734        fileItem->AddRef(ref);
     735    }
     736}
     737
     738
     739/*static*/ BString
     740Playlist::_GetExceptExtension(const BString& path)
     741{
     742    int32 periodPos = path.FindLast('.');
     743    if (periodPos <= path.FindLast('/'))
     744        return path;
     745    return BString(path.String(), periodPos);
     746}
     747
     748
    671749// #pragma mark - notifications
    672750
    673751
  • 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, PlaylistItem* item);
     118    static  bool                ExtraMediaExists(Playlist* playlist, const entry_ref& ref);
     119
    116120private:
    117121                                Playlist(const Playlist& other);
    118122            Playlist&           operator=(const Playlist& other);
     
    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

     
    1818#include "MediaFileTrackSupplier.h"
    1919#include "SubTitlesSRT.h"
    2020
    21 
    2221static const char* kPathKey = "path";
    2322
    24 
    2523FilePlaylistItem::FilePlaylistItem(const entry_ref& ref)
    26     :
    27     fRef(ref),
    28     fNameInTrash("")
    2924{
     25    fRefs.push_back(ref);
     26    fNamesInTrash.push_back("");
    3027}
    3128
    3229
    3330FilePlaylistItem::FilePlaylistItem(const FilePlaylistItem& other)
    3431    :
    35     fRef(other.fRef),
    36     fNameInTrash(other.fNameInTrash)
     32    fRefs(other.fRefs),
     33    fNamesInTrash(other.fNamesInTrash)
    3734{
    3835}
    3936
    4037
    4138FilePlaylistItem::FilePlaylistItem(const BMessage* archive)
    42     :
    43     fRef(),
    44     fNameInTrash("")
    4539{
    4640    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();
     41    entry_ref   ref;
     42    if (archive != NULL) {
     43        int32 i = 0;
     44        while (archive->FindString(kPathKey, i, &path) == B_OK) {
     45            if (get_ref_for_path(path, &ref) == B_OK) {
     46                fRefs.push_back(ref);
     47            }
     48            i++;
     49        }
    5050    }
     51    if (fRefs.empty()) {
     52        fRefs.push_back(entry_ref());
     53    }
     54    for (vector<entry_ref>::size_type i = 0; i < fRefs.size(); i++) {
     55        fNamesInTrash.push_back("");
     56    }
    5157}
    5258
    5359
     
    8288    status_t ret = BArchivable::Archive(into, deep);
    8389    if (ret != B_OK)
    8490        return ret;
    85     BPath path(&fRef);
    86     ret = path.InitCheck();
    87     if (ret == B_OK)
     91    for (vector<entry_ref>::size_type i = 0; i < fRefs.size(); i++) {
     92        BPath path(&fRefs[i]);
     93        ret = path.InitCheck();
     94        if (ret != B_OK)
     95            return ret;
    8896        ret = into->AddString(kPathKey, path.Path());
    89     return ret;
     97        if (ret != B_OK)
     98            return ret;
     99    }
     100    return B_OK;
    90101}
    91102
    92103
     
    97108    switch (attribute) {
    98109        case ATTR_STRING_NAME:
    99110        {
    100             BEntry entry(&fRef, false);
     111            BEntry entry(&fRefs[0], false);
    101112            return entry.Rename(string.String(), false);
    102113        }
    103114   
     
    135146    BString& string) const
    136147{
    137148    if (attribute == ATTR_STRING_NAME) {
    138         string = fRef.name;
     149        string = fRefs[0].name;
    139150        return B_OK;
    140151    }
    141152
     
    194205BString
    195206FilePlaylistItem::LocationURI() const
    196207{
    197     BPath path(&fRef);
     208    BPath path(&fRefs[0]);
    198209    BString locationURI("file://");
    199210    locationURI << path.Path();
    200211    return locationURI;
     
    204215status_t
    205216FilePlaylistItem::GetIcon(BBitmap* bitmap, icon_size iconSize) const
    206217{
    207     BNode node(&fRef);
     218    BNode node(&fRefs[0]);
    208219    BNodeInfo info(&node);
    209220    return info.GetTrackerIcon(bitmap, iconSize);
    210221}
     
    213224status_t
    214225FilePlaylistItem::MoveIntoTrash()
    215226{
    216     if (fNameInTrash.Length() != 0) {
     227    if (fNamesInTrash[0].Length() != 0) {
    217228        // Already in the trash!
    218229        return B_ERROR;
    219230    }
    220231
    221232    char trashPath[B_PATH_NAME_LENGTH];
    222     status_t err = find_directory(B_TRASH_DIRECTORY, fRef.device,
     233    status_t err = find_directory(B_TRASH_DIRECTORY, fRefs[0].device,
    223234        true /*create it*/, trashPath, B_PATH_NAME_LENGTH);
    224235    if (err != B_OK) {
    225236        fprintf(stderr, "failed to find Trash: %s\n", strerror(err));
    226237        return err;
    227238    }
    228239
    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));
    234         return err;
    235     }
    236240    BDirectory trashDir(trashPath);
    237241    if (err != B_OK) {
    238242        fprintf(stderr, "failed to init BDirectory for %s: %s\n",
     
    240244        return err;
    241245    }
    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++;
     247    for (vector<entry_ref>::size_type i = 0; i < fRefs.size(); i++) {
     248        BEntry entry(&fRefs[i]);
     249        err = entry.InitCheck();
     250        if (err != B_OK) {
     251            fprintf(stderr, "failed to init BEntry for %s: %s\n",
     252                fRefs[i].name, strerror(err));
     253            return err;
     254        }
     255   
     256        // Find a unique name for the entry in the trash
     257        fNamesInTrash[i] = fRefs[i].name;
     258        int32 uniqueNameIndex = 1;
     259        while (true) {
     260            BEntry test(&trashDir, fNamesInTrash[i].String());
     261            if (!test.Exists())
     262                break;
     263            fNamesInTrash[i] = fRefs[i].name;
     264            fNamesInTrash[i] << ' ' << uniqueNameIndex;
     265            uniqueNameIndex++;
     266        }
     267   
     268        // Remember the original path
     269        BPath originalPath;
     270        entry.GetPath(&originalPath);
     271   
     272        // Finally, move the entry into the trash
     273        err = entry.MoveTo(&trashDir, fNamesInTrash[i].String());
     274        if (err != B_OK) {
     275            fprintf(stderr, "failed to move entry into trash %s: %s\n",
     276                trashPath, strerror(err));
     277            return err;
     278        }
     279   
     280        // Allow Tracker to restore this entry
     281        BNode node(&entry);
     282        BString originalPathString(originalPath.Path());
     283        node.WriteAttrString("_trk/original_path", &originalPathString);
    253284    }
    254285
    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;
     286    return B_OK;
    273287}
    274288
    275289
    276 
    277290status_t
    278291FilePlaylistItem::RestoreFromTrash()
    279292{
    280     if (fNameInTrash.Length() <= 0) {
     293    if (fNamesInTrash[0].Length() <= 0) {
    281294        // Not in the trash!
    282295        return B_ERROR;
    283296    }
    284297
    285298    char trashPath[B_PATH_NAME_LENGTH];
    286     status_t err = find_directory(B_TRASH_DIRECTORY, fRef.device,
     299    status_t err = find_directory(B_TRASH_DIRECTORY, fRefs[0].device,
    287300        false /*create it*/, trashPath, B_PATH_NAME_LENGTH);
    288301    if (err != B_OK) {
    289302        fprintf(stderr, "failed to find Trash: %s\n", strerror(err));
    290303        return err;
    291304    }
    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;
     305   
     306    for (vector<entry_ref>::size_type i = 0; i < fRefs.size(); i++) {
     307        // construct the entry to the file in the trash
     308        // TODO: BEntry(const BDirectory* directory, const char* path) is broken!
     309        //  BEntry entry(trashPath, fNamesInTrash[i].String());
     310        BPath path(trashPath, fNamesInTrash[i].String());
     311        BEntry entry(path.Path());
     312        err = entry.InitCheck();
     313        if (err != B_OK) {
     314            fprintf(stderr, "failed to init BEntry for %s: %s\n",
     315                fNamesInTrash[i].String(), strerror(err));
     316            return err;
     317        }
     318        //entry.GetPath(&path);
     319        //printf("moving '%s'\n", path.Path());
     320   
     321        // construct the folder of the original entry_ref
     322        node_ref nodeRef;
     323        nodeRef.device = fRefs[i].device;
     324        nodeRef.node = fRefs[i].directory;
     325        BDirectory originalDir(&nodeRef);
     326        err = originalDir.InitCheck();
     327        if (err != B_OK) {
     328            fprintf(stderr, "failed to init original BDirectory for "
     329                "%s: %s\n", fRefs[i].name, strerror(err));
     330            return err;
     331        }
     332   
     333        //path.SetTo(&originalDir, fItems[i].name);
     334        //printf("as '%s'\n", path.Path());
     335   
     336        // Reset the name here, the user may have already moved the entry
     337        // out of the trash via Tracker for example.
     338        fNamesInTrash[i] = "";
     339   
     340        // Finally, move the entry back into the original folder
     341        err = entry.MoveTo(&originalDir, fRefs[i].name);
     342        if (err != B_OK) {
     343            fprintf(stderr, "failed to restore entry from trash "
     344                "%s: %s\n", fRefs[i].name, strerror(err));
     345            return err;
     346        }
     347   
     348        // Remove the attribute that helps Tracker restore the entry.
     349        BNode node(&entry);
     350        node.RemoveAttr("_trk/original_path");
    302351    }
    303 //entry.GetPath(&path);
    304 //printf("moving '%s'\n", path.Path());
    305352
    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));
    315         return err;
    316     }
    317 
    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;
     353    return B_OK;
    338354}
    339355
    340356
    341357// #pragma mark -
    342358
    343 
    344359TrackSupplier*
    345360FilePlaylistItem::CreateTrackSupplier() const
    346361{
    347     BMediaFile* mediaFile = new(std::nothrow) BMediaFile(&fRef);
    348     if (mediaFile == NULL)
    349         return NULL;
    350362    MediaFileTrackSupplier* supplier
    351         = new(std::nothrow) MediaFileTrackSupplier(mediaFile);
    352     if (supplier == NULL) {
    353         delete mediaFile;
     363        = new(std::nothrow) MediaFileTrackSupplier();
     364    if (supplier == NULL)
    354365        return NULL;
     366
     367    for (vector<entry_ref>::size_type i = 0; i < fRefs.size(); i++) {
     368        BMediaFile* mediaFile = new(std::nothrow) BMediaFile(&fRefs[i]);
     369        if (mediaFile == NULL) {
     370            delete supplier;
     371            return NULL;
     372        }
     373        if (supplier->AddMediaFile(mediaFile) != B_OK)
     374            delete mediaFile;
    355375    }
    356376
    357377    // Search for subtitle files in the same folder
    358378    // TODO: Error checking
    359     BEntry entry(&fRef, true);
     379    BEntry entry(&fRefs[0], true);
    360380
    361381    char originalName[B_FILE_NAME_LENGTH];
    362382    entry.GetName(originalName);
     
    411431
    412432
    413433status_t
     434FilePlaylistItem::AddRef(const entry_ref& ref)
     435{
     436    fRefs.push_back(ref);
     437    fNamesInTrash.push_back("");
     438    return B_OK;
     439}
     440
     441
     442status_t
    414443FilePlaylistItem::_SetAttribute(const char* attrName, type_code type,
    415444    const void* data, size_t size)
    416445{
    417     BEntry entry(&fRef, true);
     446    BEntry entry(&fRefs[0], true);
    418447    BNode node(&entry);
    419448    if (node.InitCheck() != B_OK)
    420449        return node.InitCheck();
     
    433462FilePlaylistItem::_GetAttribute(const char* attrName, type_code type,
    434463    void* data, size_t size)
    435464{
    436     BEntry entry(&fRef, true);
     465    BEntry entry(&fRefs[0], true);
    437466    BNode node(&entry);
    438467    if (node.InitCheck() != B_OK)
    439468        return node.InitCheck();
  • 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);
    5456
     57            const entry_ref&    Ref() const { return fRefs[0]; }
     58
    5559private:
    5660            status_t            _SetAttribute(const char* attrName,
    5761                                    type_code type, const void* data,
     
    6165                                    size_t size);
    6266
    6367private:
    64             entry_ref           fRef;
    65             BString             fNameInTrash;
     68    // always fRefs.size() == fNamesInTrash.size()
     69            vector<entry_ref>   fRefs;
     70            vector<BString>     fNamesInTrash;
    6671};
    6772
    6873#endif // FILE_PLAYLIST_ITEM_H
  • supplier/MediaFileTrackSupplier.cpp

     
    1919#include "MediaTrackVideoSupplier.h"
    2020
    2121
    22 MediaFileTrackSupplier::MediaFileTrackSupplier(BMediaFile* mediaFile)
     22MediaFileTrackSupplier::MediaFileTrackSupplier()
    2323    :
    24     TrackSupplier(),
    25     fMediaFile(mediaFile)
     24    TrackSupplier()
    2625{
    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     }
    6526}
    6627
    6728
    6829MediaFileTrackSupplier::~MediaFileTrackSupplier()
    6930{
    70     delete fMediaFile;
     31    for (vector<BMediaFile*>::size_type i = fMediaFiles.size() - 1; static_cast<int32>(i) >= 0; i--)
     32        delete fMediaFiles[i];
    7133        // BMediaFile destructor will call ReleaseAllTracks()
    7234    for (int32 i = fSubTitleTracks.CountItems() - 1; i >= 0; i--)
    7335        delete reinterpret_cast<SubTitles*>(fSubTitleTracks.ItemAtFast(i));
     
    7739status_t
    7840MediaFileTrackSupplier::InitCheck()
    7941{
    80     return fMediaFile->InitCheck();
     42    if (fMediaFiles.empty())
     43        return B_ERROR;
     44   
     45    return fMediaFiles[0]->InitCheck();
    8146}
    8247
    8348
    8449status_t
    8550MediaFileTrackSupplier::GetFileFormatInfo(media_file_format* fileFormat)
    8651{
    87     return fMediaFile->GetFileFormatInfo(fileFormat);
     52    if (fMediaFiles.empty())
     53        return B_ERROR;
     54
     55    return fMediaFiles[0]->GetFileFormatInfo(fileFormat);
    8856}
    8957
    9058
    9159status_t
    9260MediaFileTrackSupplier::GetCopyright(BString* copyright)
    9361{
    94     *copyright = fMediaFile->Copyright();
     62    if (fMediaFiles.empty())
     63        return B_ERROR;
     64
     65    *copyright = fMediaFiles[0]->Copyright();
    9566    return B_OK;
    9667}
    9768
     
    9970status_t
    10071MediaFileTrackSupplier::GetMetaData(BMessage* metaData)
    10172{
    102     return fMediaFile->GetMetaData(metaData);
     73    if (fMediaFiles.empty())
     74        return B_ERROR;
     75
     76    return fMediaFiles[0]->GetMetaData(metaData);
    10377}
    10478
    10579
     
    189163    return fSubTitleTracks.AddItem(subTitles);
    190164}
    191165
     166
     167status_t
     168MediaFileTrackSupplier::AddMediaFile(BMediaFile* mediaFile)
     169{
     170    if (mediaFile->InitCheck() != B_OK)
     171        return B_ERROR;
     172    int trackCount = mediaFile->CountTracks();
     173    if (trackCount <= 0)
     174        return B_ERROR;
     175
     176    status_t    funcStatus = B_ERROR;
     177    for (int i = 0; i < trackCount; i++) {
     178        BMediaTrack* track = mediaFile->TrackAt(i);
     179        media_format format;
     180        status_t status = track->EncodedFormat(&format);
     181        if (status != B_OK) {
     182            fprintf(stderr, "MediaFileTrackSupplier: EncodedFormat failed for "
     183                "track index %d, error: %s\n", i, strerror(status));
     184            mediaFile->ReleaseTrack(track);
     185            continue;
     186        }
     187
     188        if (track->Duration() <= 0) {
     189            fprintf(stderr, "MediaFileTrackSupplier: warning! track index %d "
     190                "has no duration\n", i);
     191        }
     192
     193        if (format.IsAudio()) {
     194            if (fAudioTracks.AddItem(track)) {
     195                funcStatus = B_OK;
     196            } else {
     197                mediaFile->ReleaseTrack(track);
     198            }
     199        } else if (format.IsVideo()) {
     200            if (fVideoTracks.AddItem(track)) {
     201                funcStatus = B_OK;
     202            } else {
     203                mediaFile->ReleaseTrack(track);
     204            }
     205        } else {
     206            printf("MediaFileTrackSupplier: track index %d has unknown "
     207                "type\n", i);
     208            mediaFile->ReleaseTrack(track);
     209        }
     210    }
     211    if (funcStatus == B_OK)
     212        fMediaFiles.push_back(mediaFile);
     213    return funcStatus;
     214}
     215
     216
  • supplier/MediaFileTrackSupplier.h

     
    1010
    1111#include "TrackSupplier.h"
    1212
     13#include <vector>
    1314
    1415class BMediaFile;
    1516
    1617
    1718class MediaFileTrackSupplier : public TrackSupplier {
    1819public:
    19                                 MediaFileTrackSupplier(BMediaFile* mediaFile);
     20                                MediaFileTrackSupplier();
    2021    virtual                     ~MediaFileTrackSupplier();
    2122
    2223    virtual status_t            InitCheck();
     
    4142
    4243            bool                AddSubTitles(SubTitles* subTitles);
    4344
     45            status_t            AddMediaFile(BMediaFile* mediaFile);
     46
    4447private:
    45             BMediaFile*         fMediaFile;
     48            vector<BMediaFile*> fMediaFiles;
    4649            BList               fAudioTracks;
    4750            BList               fVideoTracks;
    4851            BList               fSubTitleTracks;