[haiku-commits] r41271 - in haiku/trunk/src/apps/mediaplayer: . playlist supplier

  • From: philippe.houdoin@xxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Wed, 20 Apr 2011 19:58:09 +0200 (CEST)

Author: phoudoin
Date: 2011-04-20 19:58:07 +0200 (Wed, 20 Apr 2011)
New Revision: 41271
Changeset: https://dev.haiku-os.org/changeset/41271
Ticket: https://dev.haiku-os.org/ticket/7430

Added:
   haiku/trunk/src/apps/mediaplayer/supplier/ImageTrackVideoSupplier.cpp
   haiku/trunk/src/apps/mediaplayer/supplier/ImageTrackVideoSupplier.h
Modified:
   haiku/trunk/src/apps/mediaplayer/Jamfile
   haiku/trunk/src/apps/mediaplayer/playlist/FilePlaylistItem.cpp
   haiku/trunk/src/apps/mediaplayer/playlist/FilePlaylistItem.h
   haiku/trunk/src/apps/mediaplayer/playlist/ImportPLItemsCommand.cpp
   haiku/trunk/src/apps/mediaplayer/playlist/Playlist.cpp
   haiku/trunk/src/apps/mediaplayer/playlist/Playlist.h
   haiku/trunk/src/apps/mediaplayer/supplier/MediaFileTrackSupplier.cpp
   haiku/trunk/src/apps/mediaplayer/supplier/MediaFileTrackSupplier.h
Log:
Patch by SHINTA: add MediaPlayer cover image/artwork support.
This implemented #7430 enhancement.
Arigato gozaimasu!


Modified: haiku/trunk/src/apps/mediaplayer/Jamfile
===================================================================
--- haiku/trunk/src/apps/mediaplayer/Jamfile    2011-04-19 21:25:00 UTC (rev 
41270)
+++ haiku/trunk/src/apps/mediaplayer/Jamfile    2011-04-20 17:58:07 UTC (rev 
41271)
@@ -77,6 +77,7 @@
 
        # supplier
        AudioTrackSupplier.cpp
+       ImageTrackVideoSupplier.cpp
        MediaFileTrackSupplier.cpp
        MediaTrackAudioSupplier.cpp
        MediaTrackVideoSupplier.cpp

Modified: haiku/trunk/src/apps/mediaplayer/playlist/FilePlaylistItem.cpp
===================================================================
--- haiku/trunk/src/apps/mediaplayer/playlist/FilePlaylistItem.cpp      
2011-04-19 21:25:00 UTC (rev 41270)
+++ haiku/trunk/src/apps/mediaplayer/playlist/FilePlaylistItem.cpp      
2011-04-20 17:58:07 UTC (rev 41271)
@@ -14,40 +14,49 @@
 #include <FindDirectory.h>
 #include <MediaFile.h>
 #include <Path.h>
+#include <TranslationUtils.h>
 
 #include "MediaFileTrackSupplier.h"
 #include "SubTitlesSRT.h"
 
-
 static const char* kPathKey = "path";
 
-
 FilePlaylistItem::FilePlaylistItem(const entry_ref& ref)
-       :
-       fRef(ref),
-       fNameInTrash("")
 {
+       fRefs.push_back(ref);
+       fNamesInTrash.push_back("");
 }
 
 
 FilePlaylistItem::FilePlaylistItem(const FilePlaylistItem& other)
        :
-       fRef(other.fRef),
-       fNameInTrash(other.fNameInTrash)
+       fRefs(other.fRefs),
+       fNamesInTrash(other.fNamesInTrash),
+       fImageRefs(other.fImageRefs),
+       fImageNamesInTrash(other.fImageNamesInTrash)
 {
 }
 
 
 FilePlaylistItem::FilePlaylistItem(const BMessage* archive)
-       :
-       fRef(),
-       fNameInTrash("")
 {
        const char* path;
-       if (archive != NULL && archive->FindString(kPathKey, &path) == B_OK) {
-               if (get_ref_for_path(path, &fRef) != B_OK)
-                       fRef = entry_ref();
+       entry_ref       ref;
+       if (archive != NULL) {
+               int32 i = 0;
+               while (archive->FindString(kPathKey, i, &path) == B_OK) {
+                       if (get_ref_for_path(path, &ref) == B_OK) {
+                               fRefs.push_back(ref);
+                       }
+                       i++;
+               }
        }
+       if (fRefs.empty()) {
+               fRefs.push_back(entry_ref());
+       }
+       for (vector<entry_ref>::size_type i = 0; i < fRefs.size(); i++) {
+               fNamesInTrash.push_back("");
+       }
 }
 
 
@@ -82,11 +91,16 @@
        status_t ret = BArchivable::Archive(into, deep);
        if (ret != B_OK)
                return ret;
-       BPath path(&fRef);
-       ret = path.InitCheck();
-       if (ret == B_OK)
+       for (vector<entry_ref>::size_type i = 0; i < fRefs.size(); i++) {
+               BPath path(&fRefs[i]);
+               ret = path.InitCheck();
+               if (ret != B_OK)
+                       return ret;
                ret = into->AddString(kPathKey, path.Path());
-       return ret;
+               if (ret != B_OK)
+                       return ret;
+       }
+       return B_OK;
 }
 
 
@@ -97,7 +111,7 @@
        switch (attribute) {
                case ATTR_STRING_NAME:
                {
-                       BEntry entry(&fRef, false);
+                       BEntry entry(&fRefs[0], false);
                        return entry.Rename(string.String(), false);
                }
        
@@ -135,7 +149,7 @@
        BString& string) const
 {
        if (attribute == ATTR_STRING_NAME) {
-               string = fRef.name;
+               string = fRefs[0].name;
                return B_OK;
        }
 
@@ -194,7 +208,7 @@
 BString
 FilePlaylistItem::LocationURI() const
 {
-       BPath path(&fRef);
+       BPath path(&fRefs[0]);
        BString locationURI("file://");
        locationURI << path.Path();
        return locationURI;
@@ -204,7 +218,7 @@
 status_t
 FilePlaylistItem::GetIcon(BBitmap* bitmap, icon_size iconSize) const
 {
-       BNode node(&fRef);
+       BNode node(&fRefs[0]);
        BNodeInfo info(&node);
        return info.GetTrackerIcon(bitmap, iconSize);
 }
@@ -213,150 +227,82 @@
 status_t
 FilePlaylistItem::MoveIntoTrash()
 {
-       if (fNameInTrash.Length() != 0) {
+       if (fNamesInTrash[0].Length() != 0) {
                // Already in the trash!
                return B_ERROR;
        }
 
-       char trashPath[B_PATH_NAME_LENGTH];
-       status_t err = find_directory(B_TRASH_DIRECTORY, fRef.device,
-               true /*create it*/, trashPath, B_PATH_NAME_LENGTH);
-       if (err != B_OK) {
-               fprintf(stderr, "failed to find Trash: %s\n", strerror(err));
+       status_t err;
+       err = _MoveIntoTrash(&fRefs, &fNamesInTrash);
+       if (err != B_OK)
                return err;
-       }
+       
+       if (fImageRefs.empty())
+               return B_OK;
 
-       BEntry entry(&fRef);
-       err = entry.InitCheck();
-       if (err != B_OK) {
-               fprintf(stderr, "failed to init BEntry for %s: %s\n",
-                       fRef.name, strerror(err));
+       err = _MoveIntoTrash(&fImageRefs, &fImageNamesInTrash);
+       if (err != B_OK)
                return err;
-       }
-       BDirectory trashDir(trashPath);
-       if (err != B_OK) {
-               fprintf(stderr, "failed to init BDirectory for %s: %s\n",
-                       trashPath, strerror(err));
-               return err;
-       }
 
-       // Find a unique name for the entry in the trash
-       fNameInTrash = fRef.name;
-       int32 uniqueNameIndex = 1;
-       while (true) {
-               BEntry test(&trashDir, fNameInTrash.String());
-               if (!test.Exists())
-                       break;
-               fNameInTrash = fRef.name;
-               fNameInTrash << ' ' << uniqueNameIndex;
-               uniqueNameIndex++;
-       }
-
-       // Remember the original path
-       BPath originalPath;
-       entry.GetPath(&originalPath);
-
-       // Finally, move the entry into the trash
-       err = entry.MoveTo(&trashDir, fNameInTrash.String());
-       if (err != B_OK) {
-               fprintf(stderr, "failed to move entry into trash %s: %s\n",
-                       trashPath, strerror(err));
-               return err;
-       }
-
-       // Allow Tracker to restore this entry
-       BNode node(&entry);
-       BString originalPathString(originalPath.Path());
-       node.WriteAttrString("_trk/original_path", &originalPathString);
-
-       return err;
+       return B_OK;
 }
 
 
-
 status_t
 FilePlaylistItem::RestoreFromTrash()
 {
-       if (fNameInTrash.Length() <= 0) {
+       if (fNamesInTrash[0].Length() <= 0) {
                // Not in the trash!
                return B_ERROR;
        }
 
-       char trashPath[B_PATH_NAME_LENGTH];
-       status_t err = find_directory(B_TRASH_DIRECTORY, fRef.device,
-               false /*create it*/, trashPath, B_PATH_NAME_LENGTH);
-       if (err != B_OK) {
-               fprintf(stderr, "failed to find Trash: %s\n", strerror(err));
+       status_t err;
+       err = _RestoreFromTrash(&fRefs, &fNamesInTrash);
+       if (err != B_OK)
                return err;
-       }
-       // construct the entry to the file in the trash
-// TODO: BEntry(const BDirectory* directory, const char* path) is broken!
-//     BEntry entry(trashPath, fNamesInTrash[i].String());
-BPath path(trashPath, fNameInTrash.String());
-BEntry entry(path.Path());
-       err = entry.InitCheck();
-       if (err != B_OK) {
-               fprintf(stderr, "failed to init BEntry for %s: %s\n",
-                       fNameInTrash.String(), strerror(err));
-               return err;
-       }
-//entry.GetPath(&path);
-//printf("moving '%s'\n", path.Path());
+       
+       if (fImageRefs.empty())
+               return B_OK;
 
-       // construct the folder of the original entry_ref
-       node_ref nodeRef;
-       nodeRef.device = fRef.device;
-       nodeRef.node = fRef.directory;
-       BDirectory originalDir(&nodeRef);
-       err = originalDir.InitCheck();
-       if (err != B_OK) {
-               fprintf(stderr, "failed to init original BDirectory for "
-                       "%s: %s\n", fRef.name, strerror(err));
+       err = _RestoreFromTrash(&fImageRefs, &fImageNamesInTrash);
+       if (err != B_OK)
                return err;
-       }
 
-//path.SetTo(&originalDir, fItems[i].name);
-//printf("as '%s'\n", path.Path());
-
-       // Reset the name here, the user may have already moved the entry
-       // out of the trash via Tracker for example.
-       fNameInTrash = "";
-
-       // Finally, move the entry back into the original folder
-       err = entry.MoveTo(&originalDir, fRef.name);
-       if (err != B_OK) {
-               fprintf(stderr, "failed to restore entry from trash "
-                       "%s: %s\n", fRef.name, strerror(err));
-               return err;
-       }
-
-       // Remove the attribute that helps Tracker restore the entry.
-       BNode node(&entry);
-       node.RemoveAttr("_trk/original_path");
-
-       return err;
+       return B_OK;
 }
 
 
 // #pragma mark -
 
-
 TrackSupplier*
 FilePlaylistItem::CreateTrackSupplier() const
 {
-       BMediaFile* mediaFile = new(std::nothrow) BMediaFile(&fRef);
-       if (mediaFile == NULL)
-               return NULL;
        MediaFileTrackSupplier* supplier
-               = new(std::nothrow) MediaFileTrackSupplier(mediaFile);
-       if (supplier == NULL) {
-               delete mediaFile;
+               = new(std::nothrow) MediaFileTrackSupplier();
+       if (supplier == NULL)
                return NULL;
+
+       for (vector<entry_ref>::size_type i = 0; i < fRefs.size(); i++) {
+               BMediaFile* mediaFile = new(std::nothrow) BMediaFile(&fRefs[i]);
+               if (mediaFile == NULL) {
+                       delete supplier;
+                       return NULL;
+               }
+               if (supplier->AddMediaFile(mediaFile) != B_OK)
+                       delete mediaFile;
        }
 
+       for (vector<entry_ref>::size_type i = 0; i < fImageRefs.size(); i++) {
+               BBitmap* bitmap = BTranslationUtils::GetBitmap(&fImageRefs[i]);
+               if (bitmap == NULL)
+                       continue;
+               if (supplier->AddBitmap(bitmap) != B_OK)
+                       delete bitmap;
+       }
+
        // Search for subtitle files in the same folder
        // TODO: Error checking
-       BEntry entry(&fRef, true);
+       BEntry entry(&fRefs[0], true);
 
        char originalName[B_FILE_NAME_LENGTH];
        entry.GetName(originalName);
@@ -411,10 +357,40 @@
 
 
 status_t
+FilePlaylistItem::AddRef(const entry_ref& ref)
+{
+       fRefs.push_back(ref);
+       fNamesInTrash.push_back("");
+       return B_OK;
+}
+
+
+status_t
+FilePlaylistItem::AddImageRef(const entry_ref& ref)
+{
+       fImageRefs.push_back(ref);
+       fImageNamesInTrash.push_back("");
+       return B_OK;
+}
+
+
+const entry_ref&
+FilePlaylistItem::ImageRef() const
+{
+       static entry_ref ref;
+
+       if (fImageRefs.empty())
+               return ref;
+       
+       return fImageRefs[0];
+}
+
+
+status_t
 FilePlaylistItem::_SetAttribute(const char* attrName, type_code type,
        const void* data, size_t size)
 {
-       BEntry entry(&fRef, true);
+       BEntry entry(&fRefs[0], true);
        BNode node(&entry);
        if (node.InitCheck() != B_OK)
                return node.InitCheck();
@@ -433,7 +409,7 @@
 FilePlaylistItem::_GetAttribute(const char* attrName, type_code type,
        void* data, size_t size)
 {
-       BEntry entry(&fRef, true);
+       BEntry entry(&fRefs[0], true);
        BNode node(&entry);
        if (node.InitCheck() != B_OK)
                return node.InitCheck();
@@ -447,3 +423,128 @@
        return B_OK;
 }
 
+
+status_t
+FilePlaylistItem::_MoveIntoTrash(vector<entry_ref>* refs,
+       vector<BString>* namesInTrash)
+{
+       char trashPath[B_PATH_NAME_LENGTH];
+       status_t err = find_directory(B_TRASH_DIRECTORY, (*refs)[0].device,
+               true /*create it*/, trashPath, B_PATH_NAME_LENGTH);
+       if (err != B_OK) {
+               fprintf(stderr, "failed to find Trash: %s\n", strerror(err));
+               return err;
+       }
+
+       BDirectory trashDir(trashPath);
+       if (err != B_OK) {
+               fprintf(stderr, "failed to init BDirectory for %s: %s\n",
+                       trashPath, strerror(err));
+               return err;
+       }
+
+       for (vector<entry_ref>::size_type i = 0; i < refs->size(); i++) {
+               BEntry entry(&(*refs)[i]);
+               err = entry.InitCheck();
+               if (err != B_OK) {
+                       fprintf(stderr, "failed to init BEntry for %s: %s\n",
+                               (*refs)[i].name, strerror(err));
+                       return err;
+               }
+       
+               // Find a unique name for the entry in the trash
+               (*namesInTrash)[i] = (*refs)[i].name;
+               int32 uniqueNameIndex = 1;
+               while (true) {
+                       BEntry test(&trashDir, (*namesInTrash)[i].String());
+                       if (!test.Exists())
+                               break;
+                       (*namesInTrash)[i] = (*refs)[i].name;
+                       (*namesInTrash)[i] << ' ' << uniqueNameIndex;
+                       uniqueNameIndex++;
+               }
+       
+               // Remember the original path
+               BPath originalPath;
+               entry.GetPath(&originalPath);
+       
+               // Finally, move the entry into the trash
+               err = entry.MoveTo(&trashDir, (*namesInTrash)[i].String());
+               if (err != B_OK) {
+                       fprintf(stderr, "failed to move entry into trash %s: 
%s\n",
+                               trashPath, strerror(err));
+                       return err;
+               }
+       
+               // Allow Tracker to restore this entry
+               BNode node(&entry);
+               BString originalPathString(originalPath.Path());
+               node.WriteAttrString("_trk/original_path", &originalPathString);
+       }
+
+       return B_OK;
+}
+
+
+status_t
+FilePlaylistItem::_RestoreFromTrash(vector<entry_ref>* refs,
+       vector<BString>* namesInTrash)
+{
+       char trashPath[B_PATH_NAME_LENGTH];
+       status_t err = find_directory(B_TRASH_DIRECTORY, (*refs)[0].device,
+               false /*create it*/, trashPath, B_PATH_NAME_LENGTH);
+       if (err != B_OK) {
+               fprintf(stderr, "failed to find Trash: %s\n", strerror(err));
+               return err;
+       }
+       
+       for (vector<entry_ref>::size_type i = 0; i < refs->size(); i++) {
+               // construct the entry to the file in the trash
+               // TODO: BEntry(const BDirectory* directory, const char* path) 
is broken!
+               //      BEntry entry(trashPath, (*namesInTrash)[i].String());
+               BPath path(trashPath, (*namesInTrash)[i].String());
+               BEntry entry(path.Path());
+               err = entry.InitCheck();
+               if (err != B_OK) {
+                       fprintf(stderr, "failed to init BEntry for %s: %s\n",
+                               (*namesInTrash)[i].String(), strerror(err));
+                       return err;
+               }
+               //entry.GetPath(&path);
+               //printf("moving '%s'\n", path.Path());
+       
+               // construct the folder of the original entry_ref
+               node_ref nodeRef;
+               nodeRef.device = (*refs)[i].device;
+               nodeRef.node = (*refs)[i].directory;
+               BDirectory originalDir(&nodeRef);
+               err = originalDir.InitCheck();
+               if (err != B_OK) {
+                       fprintf(stderr, "failed to init original BDirectory for 
"
+                               "%s: %s\n", (*refs)[i].name, strerror(err));
+                       return err;
+               }
+       
+               //path.SetTo(&originalDir, fItems[i].name);
+               //printf("as '%s'\n", path.Path());
+       
+               // Reset the name here, the user may have already moved the 
entry
+               // out of the trash via Tracker for example.
+               (*namesInTrash)[i] = "";
+       
+               // Finally, move the entry back into the original folder
+               err = entry.MoveTo(&originalDir, (*refs)[i].name);
+               if (err != B_OK) {
+                       fprintf(stderr, "failed to restore entry from trash "
+                               "%s: %s\n", (*refs)[i].name, strerror(err));
+                       return err;
+               }
+       
+               // Remove the attribute that helps Tracker restore the entry.
+               BNode node(&entry);
+               node.RemoveAttr("_trk/original_path");
+       }
+
+       return B_OK;
+}
+

Modified: haiku/trunk/src/apps/mediaplayer/playlist/FilePlaylistItem.h
===================================================================
--- haiku/trunk/src/apps/mediaplayer/playlist/FilePlaylistItem.h        
2011-04-19 21:25:00 UTC (rev 41270)
+++ haiku/trunk/src/apps/mediaplayer/playlist/FilePlaylistItem.h        
2011-04-20 17:58:07 UTC (rev 41271)
@@ -7,8 +7,13 @@
 
 #include "PlaylistItem.h"
 
+#include <vector>
+
 #include <Entry.h>
 
+using std::vector;
+
+
 class FilePlaylistItem : public PlaylistItem {
 public:
                                                                
FilePlaylistItem(const entry_ref& ref);
@@ -50,8 +55,12 @@
        // playback
        virtual TrackSupplier*          CreateTrackSupplier() const;
 
-                       const entry_ref&        Ref() const { return fRef; }
+                       status_t                        AddRef(const entry_ref& 
ref);
+                       const entry_ref&        Ref() const { return fRefs[0]; }
 
+                       status_t                        AddImageRef(const 
entry_ref& ref);
+                       const entry_ref&        ImageRef() const;
+
 private:
                        status_t                        _SetAttribute(const 
char* attrName,
                                                                        
type_code type, const void* data,
@@ -59,10 +68,18 @@
                        status_t                        _GetAttribute(const 
char* attrName,
                                                                        
type_code type, void* data,
                                                                        size_t 
size);
+                       status_t                        
_MoveIntoTrash(vector<entry_ref>* refs,
+                                                                       
vector<BString>* namesInTrash);
+                       status_t                        
_RestoreFromTrash(vector<entry_ref>* refs,
+                                                                       
vector<BString>* namesInTrash);
 
 private:
-                       entry_ref                       fRef;
-                       BString                         fNameInTrash;
+       // always fRefs.size() == fNamesInTrash.size()
+                       vector<entry_ref>       fRefs;
+                       vector<BString>         fNamesInTrash;
+       // always fImageRefs.size() == fImageNamesInTrash.size()
+                       vector<entry_ref>       fImageRefs;
+                       vector<BString>         fImageNamesInTrash;
 };
 
 #endif // FILE_PLAYLIST_ITEM_H

Modified: haiku/trunk/src/apps/mediaplayer/playlist/ImportPLItemsCommand.cpp
===================================================================
--- haiku/trunk/src/apps/mediaplayer/playlist/ImportPLItemsCommand.cpp  
2011-04-19 21:25:00 UTC (rev 41270)
+++ haiku/trunk/src/apps/mediaplayer/playlist/ImportPLItemsCommand.cpp  
2011-04-20 17:58:07 UTC (rev 41271)
@@ -57,14 +57,20 @@
        memset(fNewItems, 0, fNewCount * sizeof(PlaylistItem*));
 
        // init new entries
+       int32 added = 0;
        for (int32 i = 0; i < fNewCount; i++) {
-               fNewItems[i] = temp.ItemAtFast(i)->Clone();
-               if (fNewItems[i] == NULL) {
-                       // indicate bad object init
-                       _CleanUp(fNewItems, fNewCount, true);
-                       return;
+               FilePlaylistItem* fileItem = 
dynamic_cast<FilePlaylistItem*>(temp.ItemAtFast(i));
+               if (fileItem && !Playlist::ExtraMediaExists(playlist, 
fileItem->Ref())) {
+                       fNewItems[added] = temp.ItemAtFast(i)->Clone();
+                       if (fNewItems[added] == NULL) {
+                               // indicate bad object init
+                               _CleanUp(fNewItems, fNewCount, true);
+                               return;
+                       }
+                       added++;
                }
        }
+       fNewCount = added;
 
        fPlaylingIndex = fPlaylist->CurrentItemIndex();
 

Modified: haiku/trunk/src/apps/mediaplayer/playlist/Playlist.cpp
===================================================================
--- haiku/trunk/src/apps/mediaplayer/playlist/Playlist.cpp      2011-04-19 
21:25:00 UTC (rev 41270)
+++ haiku/trunk/src/apps/mediaplayer/playlist/Playlist.cpp      2011-04-20 
17:58:07 UTC (rev 41271)
@@ -456,8 +456,11 @@
                } else {
                        if (_IsQuery(type))
                                AppendQueryToPlaylist(ref, &subPlaylist);
-                       else
-                               AppendToPlaylistRecursive(ref, &subPlaylist);
+                       else {
+                               if ( !ExtraMediaExists(this, ref) ) {
+                                       AppendToPlaylistRecursive(ref, 
&subPlaylist);
+                               }
+                       }
 
                        // At least sort this subsection of the playlist
                        // if the whole playlist is not sorted anymore.
@@ -510,7 +513,11 @@
                BString mimeString = _MIMEString(&ref);
                if (_IsMediaFile(mimeString)) {
                        PlaylistItem* item = new (std::nothrow) 
FilePlaylistItem(ref);
-                       if (item != NULL && !playlist->AddItem(item))
+                       if (!ExtraMediaExists(playlist, ref)) {
+                               _BindExtraMedia(item);
+                               if (item != NULL && !playlist->AddItem(item))
+                                       delete item;
+                       } else
                                delete item;
                } else
                        printf("MIME Type = %s\n", mimeString.String());
@@ -584,10 +591,43 @@
 }
 
 
+/*static*/ bool
+Playlist::ExtraMediaExists(Playlist* playlist, const entry_ref& ref)
+{
+       BString exceptExtension = _GetExceptExtension(BPath(&ref).Path());
+       
+       for (int32 i = 0; i < playlist->CountItems(); i++) {
+               FilePlaylistItem* compare = 
dynamic_cast<FilePlaylistItem*>(playlist->ItemAt(i));
+               if (compare == NULL)
+                       continue;
+               if (compare->Ref() != ref
+                               && 
_GetExceptExtension(BPath(&compare->Ref()).Path()) == exceptExtension )
+                       return true;
+       }
+       return false;
+}
+
+
 // #pragma mark - private
 
 
 /*static*/ bool
+Playlist::_IsImageFile(const BString& mimeString)
+{
+       BMimeType superType;
+       BMimeType fileType(mimeString.String());
+
+       if (fileType.GetSupertype(&superType) != B_OK)
+               return false;
+
+       if (superType == "image")
+               return true;
+
+       return false;
+}
+
+
+/*static*/ bool
 Playlist::_IsMediaFile(const BString& mimeString)
 {
        BMimeType superType;
@@ -668,6 +708,62 @@
 }
 
 
+// _BindExtraMedia() searches additional videos and audios
+// and addes them as extra medias.
+/*static*/ void
+Playlist::_BindExtraMedia(PlaylistItem* item)
+{
+       FilePlaylistItem* fileItem = dynamic_cast<FilePlaylistItem*>(item);
+       if (!item)
+               return;
+       
+       // If the media file is foo.mp3, _BindExtraMedia() searches foo.avi.
+       BPath mediaFilePath(&fileItem->Ref());
+       BString mediaFilePathString = mediaFilePath.Path();
+       BPath dirPath;
+       mediaFilePath.GetParent(&dirPath);
+       BDirectory dir(dirPath.Path());
+       if (dir.InitCheck() != B_OK)
+               return;
+       
+       BEntry entry;
+       BString entryPathString;
+       while (dir.GetNextEntry(&entry, true) == B_OK) {
+               if (!entry.IsFile())
+                       continue;
+               entryPathString = BPath(&entry).Path();
+               if (entryPathString != mediaFilePathString
+                               && _GetExceptExtension(entryPathString) == 
_GetExceptExtension(mediaFilePathString)) {
+                       _BindExtraMedia(fileItem, entry);
+               }
+       }
+}
+
+
+/*static*/ void
+Playlist::_BindExtraMedia(FilePlaylistItem* fileItem, const BEntry& entry)
+{
+       entry_ref ref;
+       entry.GetRef(&ref);
+       BString mimeString = _MIMEString(&ref);
+       if (_IsMediaFile(mimeString)) {
+               fileItem->AddRef(ref);
+       } else if (_IsImageFile(mimeString)) {
+               fileItem->AddImageRef(ref);
+       }
+}
+
+
+/*static*/ BString
+Playlist::_GetExceptExtension(const BString& path)
+{
+       int32 periodPos = path.FindLast('.');
+       if (periodPos <= path.FindLast('/'))
+               return path;
+       return BString(path.String(), periodPos);
+}
+
+
 // #pragma mark - notifications
 
 

Modified: haiku/trunk/src/apps/mediaplayer/playlist/Playlist.h
===================================================================
--- haiku/trunk/src/apps/mediaplayer/playlist/Playlist.h        2011-04-19 
21:25:00 UTC (rev 41270)
+++ haiku/trunk/src/apps/mediaplayer/playlist/Playlist.h        2011-04-20 
17:58:07 UTC (rev 41271)
@@ -25,6 +25,7 @@
 #include <List.h>
 #include <Locker.h>
 
+#include "FilePlaylistItem.h"
 #include "PlaylistItem.h"
 
 class BDataIO;
@@ -113,17 +114,23 @@
 
                        void                            NotifyImportFailed();
 
+       static  bool                            ExtraMediaExists(Playlist* 
playlist, const entry_ref& ref);
+
 private:
                                                                Playlist(const 
Playlist& other);
                        Playlist&                       operator=(const 
Playlist& other);
                                                                        // 
unimplemented
 
+       static  bool                            _IsImageFile(const BString& 
mimeString);
        static  bool                            _IsMediaFile(const BString& 
mimeString);
        static  bool                            _IsTextPlaylist(const BString& 
mimeString);
        static  bool                            _IsBinaryPlaylist(const 
BString& mimeString);
        static  bool                            _IsPlaylist(const BString& 
mimeString);
        static  bool                            _IsQuery(const BString& 
mimeString);
        static  BString                         _MIMEString(const entry_ref* 
ref);
+       static  void                            _BindExtraMedia(PlaylistItem* 
item);
+       static  void                            
_BindExtraMedia(FilePlaylistItem* fileItem, const BEntry& entry);
+       static  BString                         _GetExceptExtension(const 
BString& path);
 
                        void                            
_NotifyItemAdded(PlaylistItem*,
                                                                        int32 
index) const;

Added: haiku/trunk/src/apps/mediaplayer/supplier/ImageTrackVideoSupplier.cpp
===================================================================
--- haiku/trunk/src/apps/mediaplayer/supplier/ImageTrackVideoSupplier.cpp       
                        (rev 0)
+++ haiku/trunk/src/apps/mediaplayer/supplier/ImageTrackVideoSupplier.cpp       
2011-04-20 17:58:07 UTC (rev 41271)
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2011, Haiku Inc. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             SHINTA
+ */
+#include "ImageTrackVideoSupplier.h"
+
+#include <string.h>
+
+
+ImageTrackVideoSupplier::ImageTrackVideoSupplier(BBitmap* bitmap,
+               int32 trackIndex, status_t& initStatus)
+       :
+       VideoTrackSupplier(),
+       fPerformanceTime(0),
+       fDuration(0),
+       fCurrentFrame(0),
+       fBitmap(bitmap),
+       fTrackIndex(trackIndex)
+{
+       fFormat.type = B_MEDIA_ENCODED_VIDEO;
+       fFormat.u.encoded_video.output.field_rate = 0.0;
+       fFormat.u.encoded_video.output.interlace = 1;
+       fFormat.u.encoded_video.output.first_active = 0;
+       fFormat.u.encoded_video.output.orientation = B_VIDEO_TOP_LEFT_RIGHT;
+       fFormat.u.encoded_video.output.display.format = B_RGB32;
+       fFormat.u.encoded_video.output.pixel_width_aspect
+               = fFormat.u.raw_video.display.line_width
+               = static_cast<int32>(fBitmap->Bounds().right) + 1;
+       fFormat.u.encoded_video.output.pixel_height_aspect
+               = fFormat.u.raw_video.display.line_count
+               = static_cast<int32>(fBitmap->Bounds().bottom) + 1;
+       fFormat.u.encoded_video.output.display.bytes_per_row
+               = fFormat.u.raw_video.display.line_width * sizeof(int32);
+       fFormat.u.encoded_video.output.display.pixel_offset = 0;
+       fFormat.u.encoded_video.output.display.line_offset = 0;
+       fFormat.u.encoded_video.output.display.flags = 0;
+       fFormat.u.encoded_video.output.last_active
+               = fFormat.u.raw_video.display.line_count - 1;
+       fFormat.u.encoded_video.avg_bit_rate = 0.0;
+       fFormat.u.encoded_video.max_bit_rate = 0.0;
+       fFormat.u.encoded_video.encoding = media_encoded_video_format::B_ANY;
+       fFormat.u.encoded_video.frame_size
+               = fFormat.u.encoded_video.output.display.bytes_per_row *
+               fFormat.u.raw_video.display.line_count;
+       fFormat.u.encoded_video.forward_history = 0;
+       fFormat.u.encoded_video.backward_history = 0;
+
+       initStatus = B_OK;
+}
+
+
+ImageTrackVideoSupplier::~ImageTrackVideoSupplier()
+{
+}
+
+
+const media_format&
+ImageTrackVideoSupplier::Format() const
+{
+       return fFormat;
+}
+
+
+status_t
+ImageTrackVideoSupplier::GetEncodedFormat(media_format* format) const
+{
+       *format = fFormat;
+       return B_OK;
+}
+
+
+status_t
+ImageTrackVideoSupplier::GetCodecInfo(media_codec_info* info) const
+{
+       strlcpy(info->pretty_name, "Artwork (static image)",
+               sizeof(info->pretty_name));
+       strlcpy(info->short_name, "Artwork", sizeof(info->short_name));
+       info->id = info->sub_id = 0;
+
+       return B_OK;
+}
+
+
+status_t
+ImageTrackVideoSupplier::ReadFrame(void* buffer, bigtime_t* performanceTime,
+       const media_raw_video_format& format, bool& wasCached)
+{
+       uint32  size = format.display.bytes_per_row * format.display.line_count;
+       memcpy(buffer, fBitmap->Bits(), size);
+       return B_OK;
+}
+
+
+status_t
+ImageTrackVideoSupplier::FindKeyFrameForFrame(int64* frame)
+{
+       return B_OK;
+}
+
+
+status_t
+ImageTrackVideoSupplier::SeekToTime(bigtime_t* performanceTime)
+{
+       return B_OK;
+}
+
+
+status_t
+ImageTrackVideoSupplier::SeekToFrame(int64* frame)
+{
+       return B_OK;
+}
+
+

Added: haiku/trunk/src/apps/mediaplayer/supplier/ImageTrackVideoSupplier.h
===================================================================
--- haiku/trunk/src/apps/mediaplayer/supplier/ImageTrackVideoSupplier.h         
                (rev 0)
+++ haiku/trunk/src/apps/mediaplayer/supplier/ImageTrackVideoSupplier.h 
2011-04-20 17:58:07 UTC (rev 41271)
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2011, Haiku. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             SHINTA
+ */
+#ifndef IMAGE_TRACK_VIDEO_SUPPLIER_H
+#define IMAGE_TRACK_VIDEO_SUPPLIER_H
+
+#include <Bitmap.h>
+#include <MediaFormats.h>
+
+#include "VideoTrackSupplier.h"
+
+
+class ImageTrackVideoSupplier : public VideoTrackSupplier {
+public:
+                                                               
ImageTrackVideoSupplier(BBitmap* bitmap,
+                                                                       int32 
trackIndex, status_t& initStatus);
+       virtual                                         
~ImageTrackVideoSupplier();
+
+       virtual const media_format&     Format() const;
+       virtual status_t                        GetEncodedFormat(media_format* 
format) const;
+       virtual status_t                        GetCodecInfo(media_codec_info* 
info) const;
+
+       virtual status_t                        ReadFrame(void* buffer,
+                                                                       
bigtime_t* performanceTime,
+                                                                       const 
media_raw_video_format& format,
+                                                                       bool& 
wasCached);
+       virtual status_t                        FindKeyFrameForFrame(int64* 
frame);
+       virtual status_t                        SeekToTime(bigtime_t* 
performanceTime);
+       virtual status_t                        SeekToFrame(int64* frame);
+
+       virtual bigtime_t                       Position() const
+                                                                       { 
return fPerformanceTime; }
+       virtual bigtime_t                       Duration() const
+                                                                       { 
return fDuration; }
+       virtual int64                           CurrentFrame() const
+                                                                       { 
return fCurrentFrame; }
+
+#if 0
+       virtual BRect                           Bounds() const;
+       virtual color_space                     ColorSpace() const;
+       virtual uint32                          BytesPerRow() const;
+#endif
+
+       virtual int32                           TrackIndex() const
+                                                                       { 
return fTrackIndex; }
+
+private:
+                       media_format            fFormat;
+
+                       bigtime_t                       fPerformanceTime;
+                       bigtime_t                       fDuration;
+                       int64                           fCurrentFrame;
+
+                       BBitmap*                        fBitmap;
+                       int32                           fTrackIndex;
+};
+
+
+#endif // IMAGE_TRACK_VIDEO_SUPPLIER_H

Modified: haiku/trunk/src/apps/mediaplayer/supplier/MediaFileTrackSupplier.cpp
===================================================================
--- haiku/trunk/src/apps/mediaplayer/supplier/MediaFileTrackSupplier.cpp        
2011-04-19 21:25:00 UTC (rev 41270)
+++ haiku/trunk/src/apps/mediaplayer/supplier/MediaFileTrackSupplier.cpp        
2011-04-20 17:58:07 UTC (rev 41271)
@@ -1,9 +1,11 @@
 /*
- * Copyright 2010, Stephan Aßmus <superstippi@xxxxxx>. All rights reserved.
+ * Copyright 2010-2011, Haiku Inc. All rights reserved.
  * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Stephan Aßmus <superstippi@xxxxxx>
+ *             SHINTA
  */
-
-
 #include "MediaFileTrackSupplier.h"
 
 #include <new>
@@ -17,58 +19,29 @@
 
 #include "MediaTrackAudioSupplier.h"
 #include "MediaTrackVideoSupplier.h"
+#include "ImageTrackVideoSupplier.h"
 
 
-MediaFileTrackSupplier::MediaFileTrackSupplier(BMediaFile* mediaFile)
+MediaFileTrackSupplier::MediaFileTrackSupplier()
        :
-       TrackSupplier(),
-       fMediaFile(mediaFile)
+       TrackSupplier()
 {
-       if (fMediaFile->InitCheck() != B_OK)
-               return;
-       int trackCount = fMediaFile->CountTracks();
-       if (trackCount <= 0)
-               return;

[... truncated: 249 lines follow ...]

Other related posts:

  • » [haiku-commits] r41271 - in haiku/trunk/src/apps/mediaplayer: . playlist supplier - philippe . houdoin