diff --git a/src/apps/mediaplayer/Controller.cpp b/src/apps/mediaplayer/Controller.cpp index 511dd25c4e..4237f9fa30 100644 --- a/src/apps/mediaplayer/Controller.cpp +++ b/src/apps/mediaplayer/Controller.cpp @@ -125,6 +125,10 @@ Controller::~Controller() int64 Controller::Duration() { + // TODO: It is not so nice that the MediaPlayer still measures + // in video frames if only playing audio. Here for example, it will + // return a duration of 0 if the audio clip happens to be shorter than + // one video frame at 25 fps. return (int64)((double)fDuration * fVideoFrameRate / 1000000.0); } @@ -195,7 +199,7 @@ Controller::SetTo(const entry_ref &ref) status_t err; - BMediaFile *mf = new BMediaFile(&ref); + BMediaFile* mf = new BMediaFile(&ref); ObjectDeleter mediaFileDeleter(mf); err = mf->InitCheck(); @@ -213,19 +217,21 @@ Controller::SetTo(const entry_ref &ref) } for (int i = 0; i < trackcount; i++) { - BMediaTrack *t = mf->TrackAt(i); + BMediaTrack* t = mf->TrackAt(i); media_format f; err = t->EncodedFormat(&f); - if (err != B_OK) { + if (err != B_OK || t->Duration() <= 0) { printf("Controller::SetTo: EncodedFormat failed for track index %d, error 0x%08lx (%s)\n", i, err, strerror(err)); mf->ReleaseTrack(t); continue; } if (f.IsAudio()) { - fAudioTrackList.AddItem(t); + if (!fAudioTrackList.AddItem(t)) + return B_NO_MEMORY; } else if (f.IsVideo()) { - fVideoTrackList.AddItem(t); + if (!fVideoTrackList.AddItem(t)) + return B_NO_MEMORY; } else { printf("Controller::SetTo: track index %d has unknown type\n", i); mf->ReleaseTrack(t); @@ -326,7 +332,7 @@ Controller::SelectAudioTrack(int n) return B_ERROR; ObjectDeleter deleter(fAudioTrackSupplier); - fAudioTrackSupplier = new MediaTrackAudioSupplier(track); + fAudioTrackSupplier = new MediaTrackAudioSupplier(track, n); bigtime_t a = fAudioTrackSupplier->Duration(); bigtime_t v = fVideoTrackSupplier ? fVideoTrackSupplier->Duration() : 0;; @@ -334,10 +340,6 @@ Controller::SelectAudioTrack(int n) DurationChanged(); // TODO: notify duration changed! - // TODO: Not good, because the ProxyAudioSupplier currently - // uses the supplier without locking the Controller! - // This is only a problem when selecting a different audio track - // from the interface menu. fAudioSupplier->SetSupplier(fAudioTrackSupplier, fVideoFrameRate); _NotifyAudioTrackChanged(n); @@ -345,6 +347,18 @@ Controller::SelectAudioTrack(int n) } +int +Controller::CurrentAudioTrack() +{ + BAutolock _(this); + + if (fAudioTrackSupplier == NULL) + return -1; + + return fAudioTrackSupplier->TrackIndex(); +} + + status_t Controller::SelectVideoTrack(int n) { @@ -356,7 +370,7 @@ Controller::SelectVideoTrack(int n) status_t initStatus; ObjectDeleter deleter(fVideoTrackSupplier); - fVideoTrackSupplier = new MediaTrackVideoSupplier(track, initStatus); + fVideoTrackSupplier = new MediaTrackVideoSupplier(track, n, initStatus); if (initStatus < B_OK) { delete fVideoTrackSupplier; fVideoTrackSupplier = NULL; @@ -383,6 +397,18 @@ Controller::SelectVideoTrack(int n) } +int +Controller::CurrentVideoTrack() +{ + BAutolock _(this); + + if (fVideoTrackSupplier == NULL) + return -1; + + return fVideoTrackSupplier->TrackIndex(); +} + + // #pragma mark - diff --git a/src/apps/mediaplayer/Controller.h b/src/apps/mediaplayer/Controller.h index d2dc289798..0ae23c2738 100644 --- a/src/apps/mediaplayer/Controller.h +++ b/src/apps/mediaplayer/Controller.h @@ -83,7 +83,9 @@ public: int VideoTrackCount(); status_t SelectAudioTrack(int n); + int CurrentAudioTrack(); status_t SelectVideoTrack(int n); + int CurrentVideoTrack(); void Stop(); void Play(); diff --git a/src/apps/mediaplayer/MainWin.cpp b/src/apps/mediaplayer/MainWin.cpp index 7126243719..c8aaaa284a 100644 --- a/src/apps/mediaplayer/MainWin.cpp +++ b/src/apps/mediaplayer/MainWin.cpp @@ -709,10 +709,21 @@ MainWin::OpenFile(const entry_ref &ref) if (err != B_OK) { if (fPlaylist->CountItems() == 1) { // display error if this is the only file we're supposed to play - char s[300]; - sprintf(s, "Can't open file\n\n%s\n\nError 0x%08lx\n(%s)\n", - ref.name, err, strerror(err)); - (new BAlert("error", s, "OK"))->Go(); + BString message; + message << "The file '"; + message << ref.name; + message << "' could not be opened.\n\n"; + + if (err == B_MEDIA_NO_HANDLER) { + // give a more detailed message for the most likely of all + // errors + message << "There is no decoder installed to handle the " + "file format, or the decoder has trouble with the specific " + "version of the format."; + } else { + message << "Error: " << strerror(err); + } + (new BAlert("error", message.String(), "OK"))->Go(); } else { // just go to the next file and don't bother user fPlaylist->SetCurrentRefIndex(fPlaylist->CurrentRefIndex() + 1); @@ -828,9 +839,6 @@ MainWin::_SetupWindow() // Enable both if a file was loaded fAudioTrackMenu->SetEnabled(fHasFile); fVideoTrackMenu->SetEnabled(fHasFile); - // Select first track (might be "none") in both - fAudioTrackMenu->ItemAt(0)->SetMarked(true); - fVideoTrackMenu->ItemAt(0)->SetMarked(true); fVideoMenu->SetEnabled(fHasVideo); fAudioMenu->SetEnabled(fHasAudio); @@ -847,6 +855,8 @@ MainWin::_SetupWindow() } _UpdateControlsEnabledStatus(); + // TODO: Don't if the video size did not change! Also don't + // exit full screen mode. _ResizeWindow(100); fVideoView->MakeFocus(); @@ -958,26 +968,36 @@ MainWin::_SetupTrackMenus() fAudioTrackMenu->RemoveItems(0, fAudioTrackMenu->CountItems(), true); fVideoTrackMenu->RemoveItems(0, fVideoTrackMenu->CountItems(), true); - int c, i; char s[100]; - c = fController->AudioTrackCount(); - for (i = 0; i < c; i++) { + int count = fController->AudioTrackCount(); + int current = fController->CurrentAudioTrack(); + for (int i = 0; i < count; i++) { sprintf(s, "Track %d", i + 1); - fAudioTrackMenu->AddItem(new BMenuItem(s, - new BMessage(M_SELECT_AUDIO_TRACK + i))); + BMenuItem* item = new BMenuItem(s, + new BMessage(M_SELECT_AUDIO_TRACK + i)); + item->SetMarked(i == current); + fAudioTrackMenu->AddItem(item); } - if (!c) + if (!count) { fAudioTrackMenu->AddItem(new BMenuItem("none", new BMessage(M_DUMMY))); - - c = fController->VideoTrackCount(); - for (i = 0; i < c; i++) { - sprintf(s, "Track %d", i + 1); - fVideoTrackMenu->AddItem(new BMenuItem(s, - new BMessage(M_SELECT_VIDEO_TRACK + i))); + fAudioTrackMenu->ItemAt(0)->SetMarked(true); } - if (!c) + + + count = fController->VideoTrackCount(); + current = fController->CurrentVideoTrack(); + for (int i = 0; i < count; i++) { + sprintf(s, "Track %d", i + 1); + BMenuItem* item = new BMenuItem(s, + new BMessage(M_SELECT_VIDEO_TRACK + i)); + item->SetMarked(i == current); + fVideoTrackMenu->AddItem(item); + } + if (!count) { fVideoTrackMenu->AddItem(new BMenuItem("none", new BMessage(M_DUMMY))); + fVideoTrackMenu->ItemAt(0)->SetMarked(true); + } } diff --git a/src/apps/mediaplayer/supplier/AudioTrackSupplier.h b/src/apps/mediaplayer/supplier/AudioTrackSupplier.h index 0e5001ac3c..8e2bce22ba 100644 --- a/src/apps/mediaplayer/supplier/AudioTrackSupplier.h +++ b/src/apps/mediaplayer/supplier/AudioTrackSupplier.h @@ -23,6 +23,8 @@ class AudioTrackSupplier : public AudioReader { const = 0; virtual status_t GetCodecInfo(media_codec_info* info) const = 0; virtual bigtime_t Duration() const = 0; + + virtual int32 TrackIndex() const = 0; }; #endif // AUDIO_TRACK_SUPPLIER_H diff --git a/src/apps/mediaplayer/supplier/MediaTrackAudioSupplier.cpp b/src/apps/mediaplayer/supplier/MediaTrackAudioSupplier.cpp index 77b93c1cc6..a702d1eca7 100644 --- a/src/apps/mediaplayer/supplier/MediaTrackAudioSupplier.cpp +++ b/src/apps/mediaplayer/supplier/MediaTrackAudioSupplier.cpp @@ -54,7 +54,8 @@ MediaTrackAudioSupplier::Buffer::CompareOffset(const void* a, const void* b) // #pragma mark - MediaTrackAudioSupplier -MediaTrackAudioSupplier::MediaTrackAudioSupplier(BMediaTrack* mediaTrack) +MediaTrackAudioSupplier::MediaTrackAudioSupplier(BMediaTrack* mediaTrack, + int32 trackIndex) : AudioTrackSupplier(), fMediaTrack(mediaTrack), fBuffer(NULL), @@ -63,7 +64,8 @@ MediaTrackAudioSupplier::MediaTrackAudioSupplier(BMediaTrack* mediaTrack) fBuffers(10), fHasKeyFrames(false), fCountFrames(0), - fReportSeekError(true) + fReportSeekError(true), + fTrackIndex(trackIndex) { _InitFromTrack(); } @@ -104,6 +106,7 @@ MediaTrackAudioSupplier::GetCodecInfo(media_codec_info* info) const bigtime_t MediaTrackAudioSupplier::Duration() const { + fMediaTrack, fMediaTrack ? fMediaTrack->Duration() : 0LL, fCountFrames); if (!fMediaTrack) return 0; @@ -199,6 +202,9 @@ MediaTrackAudioSupplier::_InitFromTrack() // get the length of the track fCountFrames = fMediaTrack->CountFrames(); + + TRACE("MediaTrackAudioSupplier: keyframes: %d, frame count: %lld\n", + fHasKeyFrames, fCountFrames); } else fMediaTrack = NULL; } diff --git a/src/apps/mediaplayer/supplier/MediaTrackAudioSupplier.h b/src/apps/mediaplayer/supplier/MediaTrackAudioSupplier.h index 51c2fa9494..abb76d4331 100644 --- a/src/apps/mediaplayer/supplier/MediaTrackAudioSupplier.h +++ b/src/apps/mediaplayer/supplier/MediaTrackAudioSupplier.h @@ -16,7 +16,8 @@ struct media_format; class MediaTrackAudioSupplier : public AudioTrackSupplier { public: - MediaTrackAudioSupplier(BMediaTrack* track); + MediaTrackAudioSupplier(BMediaTrack* track, + int32 trackIndex); virtual ~MediaTrackAudioSupplier(); virtual const media_format& Format() const; @@ -30,6 +31,9 @@ class MediaTrackAudioSupplier : public AudioTrackSupplier { virtual status_t InitCheck() const; + virtual int32 TrackIndex() const + { return fTrackIndex; } + private: struct Buffer; void _InitFromTrack(); @@ -84,6 +88,7 @@ class MediaTrackAudioSupplier : public AudioTrackSupplier { bool fHasKeyFrames; int64 fCountFrames; bool fReportSeekError; + int32 fTrackIndex; }; #endif // MEDIA_TRACK_AUDIO_SUPPLIER_H diff --git a/src/apps/mediaplayer/supplier/MediaTrackVideoSupplier.cpp b/src/apps/mediaplayer/supplier/MediaTrackVideoSupplier.cpp index 6c6e09a60d..7c56f3fc99 100644 --- a/src/apps/mediaplayer/supplier/MediaTrackVideoSupplier.cpp +++ b/src/apps/mediaplayer/supplier/MediaTrackVideoSupplier.cpp @@ -24,13 +24,15 @@ using std::nothrow; // constructor MediaTrackVideoSupplier::MediaTrackVideoSupplier(BMediaTrack* track, - status_t& initStatus) + int32 trackIndex, status_t& initStatus) : VideoTrackSupplier() , fVideoTrack(track) , fPerformanceTime(0) , fDuration(0) , fCurrentFrame(0) + + , fTrackIndex(trackIndex) { if (!fVideoTrack) { printf("MediaTrackVideoSupplier() - no video track\n"); diff --git a/src/apps/mediaplayer/supplier/MediaTrackVideoSupplier.h b/src/apps/mediaplayer/supplier/MediaTrackVideoSupplier.h index f00f9901c1..93613358b9 100644 --- a/src/apps/mediaplayer/supplier/MediaTrackVideoSupplier.h +++ b/src/apps/mediaplayer/supplier/MediaTrackVideoSupplier.h @@ -17,7 +17,7 @@ class BMediaTrack; class MediaTrackVideoSupplier : public VideoTrackSupplier { public: MediaTrackVideoSupplier(BMediaTrack* track, - status_t& initStatus); + int32 trackIndex, status_t& initStatus); virtual ~MediaTrackVideoSupplier(); virtual const media_format& Format() const; @@ -42,6 +42,9 @@ class MediaTrackVideoSupplier : public VideoTrackSupplier { virtual color_space ColorSpace() const; virtual uint32 BytesPerRow() const; + virtual int32 TrackIndex() const + { return fTrackIndex; } + private: status_t _SwitchFormat(color_space format, uint32 bytesPerRow); @@ -55,6 +58,8 @@ class MediaTrackVideoSupplier : public VideoTrackSupplier { bigtime_t fPerformanceTime; bigtime_t fDuration; int64 fCurrentFrame; + + int32 fTrackIndex; }; #endif // MEDIA_TRACK_VIDEO_SUPPLIER_H diff --git a/src/apps/mediaplayer/supplier/VideoTrackSupplier.h b/src/apps/mediaplayer/supplier/VideoTrackSupplier.h index 383ee4a3dc..c6e5a7490b 100644 --- a/src/apps/mediaplayer/supplier/VideoTrackSupplier.h +++ b/src/apps/mediaplayer/supplier/VideoTrackSupplier.h @@ -31,6 +31,8 @@ class VideoTrackSupplier { virtual bigtime_t Position() const = 0; virtual bigtime_t Duration() const = 0; virtual int64 CurrentFrame() const = 0; + + virtual int32 TrackIndex() const = 0; }; #endif // VIDEO_TRACK_SUPPLIER_H