MediaPlayer: Show total playlist length
Signed-off-by: Dario Casalinuovo <[email protected]>
This commit is contained in:
committed by
Dario Casalinuovo
parent
beddc8eefa
commit
1c68b67a36
@@ -190,7 +190,13 @@ status_t
|
|||||||
FilePlaylistItem::SetAttribute(const Attribute& attribute,
|
FilePlaylistItem::SetAttribute(const Attribute& attribute,
|
||||||
const int64& value)
|
const int64& value)
|
||||||
{
|
{
|
||||||
return B_NOT_SUPPORTED;
|
switch (attribute) {
|
||||||
|
case ATTR_INT64_DURATION:
|
||||||
|
return _SetAttribute("Media:Length", B_INT64_TYPE, &value,
|
||||||
|
sizeof(int64));
|
||||||
|
default:
|
||||||
|
return B_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -198,7 +204,13 @@ status_t
|
|||||||
FilePlaylistItem::GetAttribute(const Attribute& attribute,
|
FilePlaylistItem::GetAttribute(const Attribute& attribute,
|
||||||
int64& value) const
|
int64& value) const
|
||||||
{
|
{
|
||||||
return B_NOT_SUPPORTED;
|
switch (attribute) {
|
||||||
|
case ATTR_INT64_DURATION:
|
||||||
|
return _GetAttribute("Media:Length", B_INT64_TYPE, &value,
|
||||||
|
sizeof(int64));
|
||||||
|
default:
|
||||||
|
return B_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -407,7 +419,7 @@ FilePlaylistItem::_SetAttribute(const char* attrName, type_code type,
|
|||||||
|
|
||||||
status_t
|
status_t
|
||||||
FilePlaylistItem::_GetAttribute(const char* attrName, type_code type,
|
FilePlaylistItem::_GetAttribute(const char* attrName, type_code type,
|
||||||
void* data, size_t size)
|
void* data, size_t size) const
|
||||||
{
|
{
|
||||||
BEntry entry(&fRefs[0], true);
|
BEntry entry(&fRefs[0], true);
|
||||||
BNode node(&entry);
|
BNode node(&entry);
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ private:
|
|||||||
size_t size);
|
size_t size);
|
||||||
status_t _GetAttribute(const char* attrName,
|
status_t _GetAttribute(const char* attrName,
|
||||||
type_code type, void* data,
|
type_code type, void* data,
|
||||||
size_t size);
|
size_t size) const;
|
||||||
status_t _MoveIntoTrash(vector<entry_ref>* refs,
|
status_t _MoveIntoTrash(vector<entry_ref>* refs,
|
||||||
vector<BString>* namesInTrash);
|
vector<BString>* namesInTrash);
|
||||||
status_t _RestoreFromTrash(vector<entry_ref>* refs,
|
status_t _RestoreFromTrash(vector<entry_ref>* refs,
|
||||||
|
|||||||
@@ -49,11 +49,12 @@ public:
|
|||||||
ATTR_STRING_TITLE = 'titl',
|
ATTR_STRING_TITLE = 'titl',
|
||||||
ATTR_STRING_AUDIO_BITRATE = 'abtr',
|
ATTR_STRING_AUDIO_BITRATE = 'abtr',
|
||||||
ATTR_STRING_VIDEO_BITRATE = 'vbtr',
|
ATTR_STRING_VIDEO_BITRATE = 'vbtr',
|
||||||
ATTR_STRING_DURATION = 'drtn',
|
|
||||||
|
|
||||||
ATTR_INT32_TRACK = 'trck',
|
ATTR_INT32_TRACK = 'trck',
|
||||||
ATTR_INT32_YEAR = 'year',
|
ATTR_INT32_YEAR = 'year',
|
||||||
ATTR_INT32_RATING = 'rtng'
|
ATTR_INT32_RATING = 'rtng',
|
||||||
|
|
||||||
|
ATTR_INT64_DURATION = 'drtn'
|
||||||
} Attribute;
|
} Attribute;
|
||||||
|
|
||||||
virtual status_t SetAttribute(const Attribute& attribute,
|
virtual status_t SetAttribute(const Attribute& attribute,
|
||||||
|
|||||||
@@ -22,6 +22,8 @@
|
|||||||
#include <File.h>
|
#include <File.h>
|
||||||
#include <FilePanel.h>
|
#include <FilePanel.h>
|
||||||
#include <Locale.h>
|
#include <Locale.h>
|
||||||
|
#include <MediaFile.h>
|
||||||
|
#include <MediaTrack.h>
|
||||||
#include <Menu.h>
|
#include <Menu.h>
|
||||||
#include <MenuBar.h>
|
#include <MenuBar.h>
|
||||||
#include <MenuItem.h>
|
#include <MenuItem.h>
|
||||||
@@ -31,12 +33,16 @@
|
|||||||
#include <ScrollBar.h>
|
#include <ScrollBar.h>
|
||||||
#include <ScrollView.h>
|
#include <ScrollView.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
#include <StringView.h>
|
||||||
|
|
||||||
|
#include "AudioTrackSupplier.h"
|
||||||
#include "CommandStack.h"
|
#include "CommandStack.h"
|
||||||
|
#include "DurationToString.h"
|
||||||
#include "MainApp.h"
|
#include "MainApp.h"
|
||||||
#include "PlaylistListView.h"
|
#include "PlaylistListView.h"
|
||||||
#include "RWLocker.h"
|
#include "RWLocker.h"
|
||||||
|
#include "TrackSupplier.h"
|
||||||
|
#include "VideoTrackSupplier.h"
|
||||||
|
|
||||||
#undef B_TRANSLATION_CONTEXT
|
#undef B_TRANSLATION_CONTEXT
|
||||||
#define B_TRANSLATION_CONTEXT "MediaPlayer-PlaylistWindow"
|
#define B_TRANSLATION_CONTEXT "MediaPlayer-PlaylistWindow"
|
||||||
@@ -82,7 +88,8 @@ PlaylistWindow::PlaylistWindow(BRect frame, Playlist* playlist,
|
|||||||
fPlaylist(playlist),
|
fPlaylist(playlist),
|
||||||
fLocker(new RWLocker("command stack lock")),
|
fLocker(new RWLocker("command stack lock")),
|
||||||
fCommandStack(new CommandStack(fLocker)),
|
fCommandStack(new CommandStack(fLocker)),
|
||||||
fCommandStackListener(this)
|
fCommandStackListener(this),
|
||||||
|
fDurationListener(new DurationListener(*this))
|
||||||
{
|
{
|
||||||
frame = Bounds();
|
frame = Bounds();
|
||||||
|
|
||||||
@@ -90,6 +97,7 @@ PlaylistWindow::PlaylistWindow(BRect frame, Playlist* playlist,
|
|||||||
// will adjust frame to account for menubar
|
// will adjust frame to account for menubar
|
||||||
|
|
||||||
frame.right -= B_V_SCROLL_BAR_WIDTH;
|
frame.right -= B_V_SCROLL_BAR_WIDTH;
|
||||||
|
frame.bottom -= B_H_SCROLL_BAR_HEIGHT;
|
||||||
fListView = new PlaylistListView(frame, playlist, controller,
|
fListView = new PlaylistListView(frame, playlist, controller,
|
||||||
fCommandStack);
|
fCommandStack);
|
||||||
|
|
||||||
@@ -104,7 +112,23 @@ PlaylistWindow::PlaylistWindow(BRect frame, Playlist* playlist,
|
|||||||
// make it so the frame of the menubar is also the frame of
|
// make it so the frame of the menubar is also the frame of
|
||||||
// the scroll bar (appears to be)
|
// the scroll bar (appears to be)
|
||||||
scrollBar->MoveBy(0, -1);
|
scrollBar->MoveBy(0, -1);
|
||||||
scrollBar->ResizeBy(0, -(B_H_SCROLL_BAR_HEIGHT - 2));
|
scrollBar->ResizeBy(0, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
frame.top += frame.Height();
|
||||||
|
frame.bottom += B_H_SCROLL_BAR_HEIGHT;
|
||||||
|
|
||||||
|
fTotalDuration = new BStringView(frame, "fDuration", "",
|
||||||
|
B_FOLLOW_BOTTOM | B_FOLLOW_LEFT_RIGHT);
|
||||||
|
AddChild(fTotalDuration);
|
||||||
|
|
||||||
|
_UpdateTotalDuration(0);
|
||||||
|
|
||||||
|
{
|
||||||
|
BAutolock _(fPlaylist);
|
||||||
|
|
||||||
|
_QueryInitialDurations();
|
||||||
|
fPlaylist->AddListener(fDurationListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
fCommandStack->AddListener(&fCommandStackListener);
|
fCommandStack->AddListener(&fCommandStackListener);
|
||||||
@@ -121,6 +145,9 @@ PlaylistWindow::~PlaylistWindow()
|
|||||||
fCommandStack->RemoveListener(&fCommandStackListener);
|
fCommandStack->RemoveListener(&fCommandStackListener);
|
||||||
delete fCommandStack;
|
delete fCommandStack;
|
||||||
delete fLocker;
|
delete fLocker;
|
||||||
|
|
||||||
|
fPlaylist->RemoveListener(fDurationListener);
|
||||||
|
BMessenger(fDurationListener).SendMessage(B_QUIT_REQUESTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -422,3 +449,157 @@ PlaylistWindow::_SavePlaylist(BEntry& origEntry, BEntry& tempEntry,
|
|||||||
info.SetType("application/x-vnd.haiku-playlist");
|
info.SetType("application/x-vnd.haiku-playlist");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PlaylistWindow::_QueryInitialDurations()
|
||||||
|
{
|
||||||
|
BAutolock lock(fPlaylist);
|
||||||
|
|
||||||
|
BMessage addMessage(MSG_PLAYLIST_ITEM_ADDED);
|
||||||
|
for (int32 i = 0; i < fPlaylist->CountItems(); i++) {
|
||||||
|
addMessage.AddPointer("item", fPlaylist->ItemAt(i));
|
||||||
|
addMessage.AddInt32("index", i);
|
||||||
|
}
|
||||||
|
|
||||||
|
BMessenger(fDurationListener).SendMessage(&addMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PlaylistWindow::_UpdateTotalDuration(bigtime_t duration)
|
||||||
|
{
|
||||||
|
BAutolock lock(this);
|
||||||
|
|
||||||
|
char buffer[64];
|
||||||
|
duration /= 1000000;
|
||||||
|
duration_to_string(duration, buffer, sizeof(buffer));
|
||||||
|
|
||||||
|
BString text;
|
||||||
|
text.SetToFormat(B_TRANSLATE("Total duration : %s"), buffer);
|
||||||
|
|
||||||
|
fTotalDuration->SetText(text.String());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
PlaylistWindow::DurationListener::DurationListener(PlaylistWindow& parent)
|
||||||
|
:
|
||||||
|
PlaylistObserver(this),
|
||||||
|
fKnown(20, true),
|
||||||
|
fTotalDuration(0),
|
||||||
|
fParent(parent)
|
||||||
|
{
|
||||||
|
Run();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PlaylistWindow::DurationListener::~DurationListener()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PlaylistWindow::DurationListener::MessageReceived(BMessage* message)
|
||||||
|
{
|
||||||
|
switch (message->what) {
|
||||||
|
case MSG_PLAYLIST_ITEM_ADDED:
|
||||||
|
{
|
||||||
|
void* item;
|
||||||
|
int32 index;
|
||||||
|
|
||||||
|
int32 currentItem = 0;
|
||||||
|
while (message->FindPointer("item", currentItem, &item) == B_OK
|
||||||
|
&& message->FindInt32("index", currentItem, &index) == B_OK) {
|
||||||
|
_HandleItemAdded(static_cast<PlaylistItem*>(item), index);
|
||||||
|
++currentItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MSG_PLAYLIST_ITEM_REMOVED:
|
||||||
|
{
|
||||||
|
int32 index;
|
||||||
|
|
||||||
|
if (message->FindInt32("index", &index) == B_OK) {
|
||||||
|
_HandleItemRemoved(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
BLooper::MessageReceived(message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bigtime_t
|
||||||
|
PlaylistWindow::DurationListener::TotalDuration()
|
||||||
|
{
|
||||||
|
return fTotalDuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PlaylistWindow::DurationListener::_HandleItemAdded(PlaylistItem* item,
|
||||||
|
int32 index)
|
||||||
|
{
|
||||||
|
bigtime_t duration = _DetermineItemDuration(item);
|
||||||
|
fTotalDuration += duration;
|
||||||
|
fParent._UpdateTotalDuration(fTotalDuration);
|
||||||
|
fKnown.AddItem(new bigtime_t(duration), index);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PlaylistWindow::DurationListener::_HandleItemRemoved(int32 index)
|
||||||
|
{
|
||||||
|
bigtime_t* deleted = fKnown.RemoveItemAt(index);
|
||||||
|
fTotalDuration -= *deleted;
|
||||||
|
fParent._UpdateTotalDuration(fTotalDuration);
|
||||||
|
|
||||||
|
delete deleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bigtime_t
|
||||||
|
PlaylistWindow::DurationListener::_DetermineItemDuration(PlaylistItem* item)
|
||||||
|
{
|
||||||
|
bigtime_t duration;
|
||||||
|
if (item->GetAttribute(PlaylistItem::ATTR_INT64_DURATION, duration) == B_OK)
|
||||||
|
return duration;
|
||||||
|
|
||||||
|
// We have to find out the duration ourselves
|
||||||
|
if (FilePlaylistItem* file = dynamic_cast<FilePlaylistItem*>(item)) {
|
||||||
|
// We are dealing with a file
|
||||||
|
BMediaFile mediaFile(&file->Ref());
|
||||||
|
|
||||||
|
if (mediaFile.InitCheck() != B_OK || mediaFile.CountTracks() < 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
duration = mediaFile.TrackAt(0)->Duration();
|
||||||
|
} else {
|
||||||
|
// Not a file, so fall back to the generic TrackSupplier solution
|
||||||
|
TrackSupplier* supplier = item->CreateTrackSupplier();
|
||||||
|
|
||||||
|
AudioTrackSupplier* au = supplier->CreateAudioTrackForIndex(0);
|
||||||
|
VideoTrackSupplier* vi = supplier->CreateVideoTrackForIndex(0);
|
||||||
|
|
||||||
|
duration = max_c(au == NULL ? 0 : au->Duration(),
|
||||||
|
vi == NULL ? 0 : vi->Duration());
|
||||||
|
|
||||||
|
delete vi;
|
||||||
|
delete au;
|
||||||
|
delete supplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store the duration for later use
|
||||||
|
item->SetAttribute(PlaylistItem::ATTR_INT64_DURATION, duration);
|
||||||
|
|
||||||
|
return duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,8 +11,10 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <Entry.h>
|
#include <Entry.h>
|
||||||
|
#include <ObjectList.h>
|
||||||
#include <Window.h>
|
#include <Window.h>
|
||||||
|
|
||||||
|
#include "PlaylistObserver.h"
|
||||||
#include "ListenerAdapter.h"
|
#include "ListenerAdapter.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -21,11 +23,11 @@ class BMenuItem;
|
|||||||
class CommandStack;
|
class CommandStack;
|
||||||
class Controller;
|
class Controller;
|
||||||
class Notifier;
|
class Notifier;
|
||||||
class Playlist;
|
|
||||||
class PlaylistListView;
|
class PlaylistListView;
|
||||||
class RWLocker;
|
class RWLocker;
|
||||||
class BButton;
|
class BButton;
|
||||||
class BFilePanel;
|
class BFilePanel;
|
||||||
|
class BStringView;
|
||||||
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -53,12 +55,39 @@ public:
|
|||||||
virtual void MessageReceived(BMessage* message);
|
virtual void MessageReceived(BMessage* message);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
class DurationListener : public PlaylistObserver, public BLooper {
|
||||||
|
public:
|
||||||
|
|
||||||
|
DurationListener(PlaylistWindow& parent);
|
||||||
|
~DurationListener();
|
||||||
|
|
||||||
|
void MessageReceived(BMessage* message);
|
||||||
|
|
||||||
|
bigtime_t TotalDuration();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _HandleItemAdded(PlaylistItem* item,
|
||||||
|
int32 index);
|
||||||
|
void _HandleItemRemoved(int32 index);
|
||||||
|
bigtime_t _DetermineItemDuration(PlaylistItem* item);
|
||||||
|
|
||||||
|
BObjectList<bigtime_t>
|
||||||
|
fKnown;
|
||||||
|
bigtime_t fTotalDuration;
|
||||||
|
PlaylistWindow& fParent;
|
||||||
|
};
|
||||||
|
|
||||||
|
friend class DurationListener;
|
||||||
|
|
||||||
void _CreateMenu(BRect& frame);
|
void _CreateMenu(BRect& frame);
|
||||||
void _ObjectChanged(const Notifier* object);
|
void _ObjectChanged(const Notifier* object);
|
||||||
void _SavePlaylist(const BMessage* filePanelMessage);
|
void _SavePlaylist(const BMessage* filePanelMessage);
|
||||||
void _SavePlaylist(const entry_ref& ref);
|
void _SavePlaylist(const entry_ref& ref);
|
||||||
void _SavePlaylist(BEntry& origEntry,
|
void _SavePlaylist(BEntry& origEntry,
|
||||||
BEntry& tempEntry, const char* finalName);
|
BEntry& tempEntry, const char* finalName);
|
||||||
|
void _QueryInitialDurations();
|
||||||
|
void _UpdateTotalDuration(bigtime_t duration);
|
||||||
|
|
||||||
Playlist* fPlaylist;
|
Playlist* fPlaylist;
|
||||||
PlaylistListView* fListView;
|
PlaylistListView* fListView;
|
||||||
@@ -72,6 +101,9 @@ private:
|
|||||||
ListenerAdapter fCommandStackListener;
|
ListenerAdapter fCommandStackListener;
|
||||||
|
|
||||||
entry_ref fSavedPlaylistRef;
|
entry_ref fSavedPlaylistRef;
|
||||||
|
|
||||||
|
DurationListener* fDurationListener;
|
||||||
|
BStringView* fTotalDuration;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user