* extraced PlaylistListView into it's own files
* lots of changes, besically these make the Playlist window usable
- drag sorting works (hold shift to copy instead of move items)
- removing items with the delete key works
- dragging files/folders from Tracker works (hold shift to insert
them in the existing playlist, othewise the new files replace
the playlist)
* some refactoring and bug fixes in previously unused functionality
* Playlist can now be locked (needed to be), and is in ControllerView,
MainWin and PlaylistListView
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21305 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -23,11 +23,10 @@
|
||||
#include <new>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <Debug.h>
|
||||
#include <Entry.h>
|
||||
#include <Window.h>
|
||||
#include <Bitmap.h>
|
||||
|
||||
#include <Autolock.h>
|
||||
#include <Bitmap.h>
|
||||
#include <Debug.h>
|
||||
#include <MediaFile.h>
|
||||
#include <MediaTrack.h>
|
||||
|
||||
@@ -87,6 +86,7 @@ Controller::Controller()
|
||||
, fStopped(true)
|
||||
, fVolume(1.0)
|
||||
|
||||
, fRef()
|
||||
, fMediaFile(0)
|
||||
// TODO: remove, InfoWin depends on it but should be fixed
|
||||
,fAudioTrack(0)
|
||||
@@ -201,6 +201,11 @@ Controller::SetTo(const entry_ref &ref)
|
||||
BAutolock al(fVideoSupplierLock);
|
||||
BAutolock vl(fAudioSupplierLock);
|
||||
|
||||
if (fRef == ref)
|
||||
return B_OK;
|
||||
|
||||
fRef = ref;
|
||||
|
||||
fAudioTrackList->MakeEmpty();
|
||||
fVideoTrackList->MakeEmpty();
|
||||
if (fMediaFile)
|
||||
@@ -466,6 +471,18 @@ Controller::Pause()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Controller::TogglePlaying()
|
||||
{
|
||||
BAutolock _(fDataLock);
|
||||
|
||||
if (IsPaused() || IsStopped())
|
||||
Play();
|
||||
else
|
||||
Pause();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Controller::IsPaused() const
|
||||
{
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#ifndef __CONTROLLER_H
|
||||
#define __CONTROLLER_H
|
||||
|
||||
#include <Entry.h>
|
||||
#include <MediaDefs.h>
|
||||
#include <MediaNode.h>
|
||||
#include <List.h>
|
||||
@@ -76,6 +77,7 @@ public:
|
||||
void Stop();
|
||||
void Play();
|
||||
void Pause();
|
||||
void TogglePlaying();
|
||||
|
||||
bool IsPaused() const;
|
||||
bool IsStopped() const;
|
||||
@@ -158,6 +160,7 @@ private:
|
||||
volatile bool fStopped;
|
||||
float fVolume;
|
||||
|
||||
entry_ref fRef;
|
||||
BMediaFile * fMediaFile;
|
||||
BMediaTrack * fAudioTrack;
|
||||
BMediaTrack * fVideoTrack;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
*/
|
||||
#include "ControllerView.h"
|
||||
|
||||
#include <Autolock.h>
|
||||
#include <Message.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -91,18 +92,13 @@ ControllerView::EnabledButtons()
|
||||
void
|
||||
ControllerView::TogglePlaying()
|
||||
{
|
||||
printf("ControllerView::TogglePlaying()\n");
|
||||
if (fController->IsPaused() || fController->IsStopped())
|
||||
fController->Play();
|
||||
else
|
||||
fController->Pause();
|
||||
fController->TogglePlaying();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ControllerView::Stop()
|
||||
{
|
||||
printf("ControllerView::Stop()\n");
|
||||
fController->Stop();
|
||||
}
|
||||
|
||||
@@ -126,7 +122,7 @@ ControllerView::Forward()
|
||||
void
|
||||
ControllerView::SkipBackward()
|
||||
{
|
||||
printf("ControllerView::SkipBackward()\n");
|
||||
BAutolock _(fPlaylist);
|
||||
fPlaylist->SetCurrentRefIndex(fPlaylist->CurrentRefIndex() - 1);
|
||||
}
|
||||
|
||||
@@ -134,7 +130,7 @@ ControllerView::SkipBackward()
|
||||
void
|
||||
ControllerView::SkipForward()
|
||||
{
|
||||
printf("ControllerView::SkipForward()\n");
|
||||
BAutolock _(fPlaylist);
|
||||
fPlaylist->SetCurrentRefIndex(fPlaylist->CurrentRefIndex() + 1);
|
||||
}
|
||||
|
||||
@@ -142,7 +138,6 @@ ControllerView::SkipForward()
|
||||
void
|
||||
ControllerView::VolumeChanged(float value)
|
||||
{
|
||||
printf("ControllerView::VolumeChanged(%.4f)\n", value);
|
||||
fController->SetVolume(value);
|
||||
}
|
||||
|
||||
@@ -157,7 +152,6 @@ ControllerView::ToggleMute()
|
||||
void
|
||||
ControllerView::PositionChanged(float value)
|
||||
{
|
||||
printf("ControllerView::PositionChanged(%.2f)\n", value);
|
||||
// 0.0 ... 1.0
|
||||
fController->SetPosition(value);
|
||||
}
|
||||
@@ -169,6 +163,8 @@ ControllerView::PositionChanged(float value)
|
||||
void
|
||||
ControllerView::CheckSkippable()
|
||||
{
|
||||
BAutolock _(fPlaylist);
|
||||
|
||||
bool canSkipNext, canSkipPrevious;
|
||||
fPlaylist->GetSkipInfo(&canSkipPrevious, &canSkipNext);
|
||||
SetSkippable(canSkipPrevious, canSkipNext);
|
||||
|
||||
@@ -32,6 +32,7 @@ Application MediaPlayer :
|
||||
MainApp.cpp
|
||||
MainWin.cpp
|
||||
Playlist.cpp
|
||||
PlaylistListView.cpp
|
||||
PlaylistObserver.cpp
|
||||
PlaylistWindow.cpp
|
||||
SoundOutput.cpp
|
||||
|
||||
@@ -320,21 +320,20 @@ DragSortableListView::MessageReceived(BMessage* message)
|
||||
{
|
||||
if (AcceptDragMessage(message)) {
|
||||
DragSortableListView *list = NULL;
|
||||
if ( message->FindPointer( "list", (void **)&list ) == B_OK
|
||||
&& list == this ) {
|
||||
if (message->FindPointer("list", (void **)&list) == B_OK
|
||||
&& list == this) {
|
||||
int32 count = CountItems();
|
||||
if ( fDropIndex < 0 || fDropIndex > count )
|
||||
if (fDropIndex < 0 || fDropIndex > count)
|
||||
fDropIndex = count;
|
||||
BList items;
|
||||
BList indices;
|
||||
int32 index;
|
||||
for ( int32 i = 0; message->FindInt32( "index", i, &index ) == B_OK; i++ )
|
||||
if ( BListItem* item = ItemAt(index) )
|
||||
items.AddItem( (void*)item );
|
||||
if ( items.CountItems() > 0 ) {
|
||||
if ( modifiers() & B_SHIFT_KEY )
|
||||
CopyItems( items, fDropIndex );
|
||||
for (int32 i = 0; message->FindInt32("index", i, &index) == B_OK; i++)
|
||||
indices.AddItem((void*)index);
|
||||
if (indices.CountItems() > 0) {
|
||||
if (modifiers() & B_SHIFT_KEY)
|
||||
CopyItems(indices, fDropIndex);
|
||||
else
|
||||
MoveItems( items, fDropIndex );
|
||||
MoveItems(indices, fDropIndex);
|
||||
}
|
||||
fDropIndex = -1;
|
||||
}
|
||||
@@ -371,9 +370,9 @@ DragSortableListView::MessageReceived(BMessage* message)
|
||||
}
|
||||
break;
|
||||
}
|
||||
// case B_MODIFIERS_CHANGED:
|
||||
// ModifiersChanged();
|
||||
// break;
|
||||
case B_MODIFIERS_CHANGED:
|
||||
ModifiersChanged();
|
||||
break;
|
||||
case B_MOUSE_WHEEL_CHANGED: {
|
||||
BListView::MessageReceived( message );
|
||||
BPoint point;
|
||||
@@ -625,42 +624,39 @@ DragSortableListView::ScrollTo(int32 index)
|
||||
|
||||
// MoveItems
|
||||
void
|
||||
DragSortableListView::MoveItems( BList& items, int32 index )
|
||||
DragSortableListView::MoveItems(BList& indices, int32 index)
|
||||
{
|
||||
DeselectAll();
|
||||
// we remove the items while we look at them, the insertion index is decreased
|
||||
// when the items index is lower, so that we insert at the right spot after
|
||||
// removal
|
||||
BList removedItems;
|
||||
int32 count = items.CountItems();
|
||||
for ( int32 i = 0; i < count; i++ )
|
||||
{
|
||||
BListItem* item = (BListItem*)items.ItemAt( i );
|
||||
int32 removeIndex = IndexOf( item );
|
||||
if ( RemoveItem( item ) && removedItems.AddItem( (void*)item ) )
|
||||
{
|
||||
if ( removeIndex < index )
|
||||
int32 count = indices.CountItems();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
int32 removeIndex = (int32)indices.ItemAtFast(i) - i;
|
||||
BListItem* item = RemoveItem(removeIndex);
|
||||
if (item && removedItems.AddItem((void*)item)) {
|
||||
if (removeIndex < index)
|
||||
index--;
|
||||
}
|
||||
// else ??? -> blow up
|
||||
}
|
||||
for ( int32 i = 0; BListItem* item = (BListItem*)removedItems.ItemAt( i ); i++ )
|
||||
{
|
||||
if ( AddItem( item, index ) )
|
||||
{
|
||||
count = removedItems.CountItems();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
BListItem* item = (BListItem*)removedItems.ItemAtFast(i);
|
||||
if (AddItem(item, index)) {
|
||||
// after we're done, the newly inserted items will be selected
|
||||
Select( index, true );
|
||||
Select(index, true);
|
||||
// next items will be inserted after this one
|
||||
index++;
|
||||
}
|
||||
else
|
||||
} else
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
|
||||
// CopyItems
|
||||
void
|
||||
DragSortableListView::CopyItems( BList& items, int32 index )
|
||||
DragSortableListView::CopyItems(BList& indices, int32 toIndex)
|
||||
{
|
||||
DeselectAll();
|
||||
// by inserting the items after we copied all items first, we avoid
|
||||
@@ -668,37 +664,34 @@ DragSortableListView::CopyItems( BList& items, int32 index )
|
||||
// in other words, don't touch the list before we know which items
|
||||
// need to be cloned
|
||||
BList clonedItems;
|
||||
int32 count = items.CountItems();
|
||||
for ( int32 i = 0; i < count; i++ )
|
||||
{
|
||||
BListItem* item = CloneItem( IndexOf( (BListItem*)items.ItemAt( i ) ) );
|
||||
if ( item && !clonedItems.AddItem( (void*)item ) )
|
||||
int32 count = indices.CountItems();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
int32 index = (int32)indices.ItemAtFast(i);
|
||||
BListItem* item = CloneItem(index);
|
||||
if (item && !clonedItems.AddItem((void*)item))
|
||||
delete item;
|
||||
}
|
||||
for ( int32 i = 0; BListItem* item = (BListItem*)clonedItems.ItemAt( i ); i++ )
|
||||
{
|
||||
if ( AddItem( item, index ) )
|
||||
{
|
||||
count = clonedItems.CountItems();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
BListItem* item = (BListItem*)clonedItems.ItemAtFast(i);
|
||||
if (AddItem(item, toIndex)) {
|
||||
// after we're done, the newly inserted items will be selected
|
||||
Select( index, true );
|
||||
Select(toIndex, true);
|
||||
// next items will be inserted after this one
|
||||
index++;
|
||||
}
|
||||
else
|
||||
toIndex++;
|
||||
} else
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveItemList
|
||||
void
|
||||
DragSortableListView::RemoveItemList( BList& items )
|
||||
DragSortableListView::RemoveItemList(BList& indices)
|
||||
{
|
||||
int32 count = items.CountItems();
|
||||
for ( int32 i = 0; i < count; i++ )
|
||||
{
|
||||
BListItem* item = (BListItem*)items.ItemAt( i );
|
||||
if ( RemoveItem( item ) )
|
||||
delete item;
|
||||
int32 count = indices.CountItems();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
int32 index = (int32)indices.ItemAtFast(i) - i;
|
||||
delete RemoveItem(index);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -706,13 +699,19 @@ DragSortableListView::RemoveItemList( BList& items )
|
||||
void
|
||||
DragSortableListView::RemoveSelected()
|
||||
{
|
||||
// if (fFocusedIndex >= 0)
|
||||
// return;
|
||||
BList indices;
|
||||
for (int32 i = 0; true; i++) {
|
||||
int32 index = CurrentSelection(i);
|
||||
if (index < 0)
|
||||
break;
|
||||
if (!indices.AddItem((void*)index))
|
||||
break;
|
||||
}
|
||||
|
||||
BList items;
|
||||
for ( int32 i = 0; BListItem* item = ItemAt( CurrentSelection( i ) ); i++ )
|
||||
items.AddItem( (void*)item );
|
||||
RemoveItemList( items );
|
||||
DeselectAll();
|
||||
|
||||
if (indices.CountItems() > 0)
|
||||
RemoveItemList(indices);
|
||||
}
|
||||
|
||||
// CountSelectedItems
|
||||
@@ -720,7 +719,7 @@ int32
|
||||
DragSortableListView::CountSelectedItems() const
|
||||
{
|
||||
int32 count = 0;
|
||||
while ( CurrentSelection( count ) >= 0 )
|
||||
while (CurrentSelection(count) >= 0)
|
||||
count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -89,8 +89,8 @@ class DragSortableListView : public BListView {
|
||||
|
||||
bool MouseWheelChanged(float x, float y);
|
||||
|
||||
virtual void MoveItems(BList& items, int32 toIndex);
|
||||
virtual void CopyItems(BList& items, int32 toIndex);
|
||||
virtual void MoveItems(BList& indices, int32 toIndex);
|
||||
virtual void CopyItems(BList& indices, int32 toIndex);
|
||||
virtual void RemoveItemList(BList& indices);
|
||||
void RemoveSelected(); // uses RemoveItemList()
|
||||
int32 CountSelectedItems() const;
|
||||
|
||||
@@ -20,25 +20,27 @@
|
||||
*/
|
||||
#include "MainWin.h"
|
||||
|
||||
#include <View.h>
|
||||
#include <Screen.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <Alert.h>
|
||||
#include <Application.h>
|
||||
#include <Autolock.h>
|
||||
#include <Debug.h>
|
||||
#include <Menu.h>
|
||||
#include <MenuBar.h>
|
||||
#include <MenuItem.h>
|
||||
#include <Application.h>
|
||||
#include <Alert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <Messenger.h>
|
||||
#include <PopUpMenu.h>
|
||||
#include <Screen.h>
|
||||
#include <String.h>
|
||||
#include <Debug.h>
|
||||
#include <math.h>
|
||||
#include <View.h>
|
||||
|
||||
#include "ControllerObserver.h"
|
||||
#include "MainApp.h"
|
||||
#include "PlaylistObserver.h"
|
||||
#include "PlaylistWindow.h"
|
||||
#include "MainApp.h"
|
||||
|
||||
#define NAME "MediaPlayer"
|
||||
#define MIN_WIDTH 250
|
||||
@@ -317,7 +319,6 @@ MainWin::MessageReceived(BMessage *msg)
|
||||
|
||||
// PlaylistObserver messages
|
||||
case MSG_PLAYLIST_REF_ADDED: {
|
||||
printf("MSG_PLAYLIST_REF_ADDED\n");
|
||||
entry_ref ref;
|
||||
int32 index;
|
||||
if (msg->FindRef("refs", &ref) == B_OK
|
||||
@@ -327,7 +328,6 @@ printf("MSG_PLAYLIST_REF_ADDED\n");
|
||||
break;
|
||||
}
|
||||
case MSG_PLAYLIST_REF_REMOVED: {
|
||||
printf("MSG_PLAYLIST_REF_REMOVED\n");
|
||||
int32 index;
|
||||
if (msg->FindInt32("index", &index) == B_OK) {
|
||||
_RemovePlaylistItem(index);
|
||||
@@ -335,12 +335,12 @@ printf("MSG_PLAYLIST_REF_REMOVED\n");
|
||||
break;
|
||||
}
|
||||
case MSG_PLAYLIST_CURRENT_REF_CHANGED: {
|
||||
printf("MSG_PLAYLIST_CURRENT_REF_CHANGED\n");
|
||||
BAutolock _(fPlaylist);
|
||||
|
||||
int32 index;
|
||||
if (msg->FindInt32("index", &index) < B_OK
|
||||
|| index != fPlaylist->CurrentRefIndex())
|
||||
break;
|
||||
printf(" index: %ld\n", index);
|
||||
entry_ref ref;
|
||||
if (fPlaylist->GetRefAt(index, &ref) == B_OK) {
|
||||
printf("open ref: %s\n", ref.name);
|
||||
@@ -352,7 +352,6 @@ printf(" index: %ld\n", index);
|
||||
|
||||
// ControllerObserver messages
|
||||
case MSG_CONTROLLER_FILE_FINISHED:
|
||||
printf("MSG_CONTROLLER_FILE_FINISHED\n");
|
||||
fPlaylist->SetCurrentRefIndex(fPlaylist->CurrentRefIndex() + 1);
|
||||
break;
|
||||
case MSG_CONTROLLER_FILE_CHANGED:
|
||||
@@ -686,7 +685,7 @@ MainWin::ShowPlaylistWindow()
|
||||
{
|
||||
if (!fPlaylistWindow) {
|
||||
fPlaylistWindow = new PlaylistWindow(BRect(150, 150, 400, 500),
|
||||
fPlaylist);
|
||||
fPlaylist, fController);
|
||||
fPlaylistWindow->Show();
|
||||
return;
|
||||
}
|
||||
@@ -731,34 +730,13 @@ MainWin::VideoFormatChange(int width, int height, float width_scale, float heigh
|
||||
void
|
||||
MainWin::_RefsReceived(BMessage *msg)
|
||||
{
|
||||
printf("MainWin::_RefsReceived\n");
|
||||
|
||||
// the playlist ist replaced by dropped files
|
||||
// or the dropped files are appended to the end
|
||||
// of the existing playlist if <shift> is pressed
|
||||
bool add = modifiers() & B_SHIFT_KEY;
|
||||
int32 appendIndex = modifiers() & B_SHIFT_KEY ?
|
||||
fPlaylist->CountItems() : -1;
|
||||
|
||||
if (!add)
|
||||
fPlaylist->MakeEmpty();
|
||||
|
||||
bool startPlaying = fPlaylist->CountItems() == 0;
|
||||
|
||||
Playlist temporaryPlaylist;
|
||||
Playlist* playlist = add ? &temporaryPlaylist : fPlaylist;
|
||||
|
||||
entry_ref ref;
|
||||
for (int i = 0; B_OK == msg->FindRef("refs", i, &ref); i++)
|
||||
_AppendToPlaylist(ref, playlist);
|
||||
|
||||
playlist->Sort();
|
||||
|
||||
if (add)
|
||||
fPlaylist->AdoptPlaylist(temporaryPlaylist);
|
||||
|
||||
if (startPlaying) {
|
||||
// open first file
|
||||
fPlaylist->SetCurrentRefIndex(0);
|
||||
}
|
||||
fPlaylist->AppendRefs(msg, appendIndex);
|
||||
}
|
||||
|
||||
|
||||
@@ -1414,9 +1392,10 @@ MainWin::_UpdateControlsEnabledStatus()
|
||||
void
|
||||
MainWin::_UpdatePlaylistMenu()
|
||||
{
|
||||
fPlaylistMenu->RemoveItems(0, fPlaylistMenu->CountItems(), true);
|
||||
if (!fPlaylist->Lock())
|
||||
return;
|
||||
|
||||
// TODO: lock fPlaylist
|
||||
fPlaylistMenu->RemoveItems(0, fPlaylistMenu->CountItems(), true);
|
||||
|
||||
int32 count = fPlaylist->CountItems();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
@@ -1428,6 +1407,8 @@ MainWin::_UpdatePlaylistMenu()
|
||||
fPlaylistMenu->SetTargetForItems(this);
|
||||
|
||||
_MarkPlaylistItem(fPlaylist->CurrentRefIndex());
|
||||
|
||||
fPlaylist->Unlock();
|
||||
}
|
||||
|
||||
|
||||
@@ -1462,25 +1443,3 @@ MainWin::_MarkPlaylistItem(int32 index)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MainWin::_AppendToPlaylist(const entry_ref& ref, Playlist* playlist)
|
||||
{
|
||||
// recursively append the ref (dive into folders)
|
||||
BEntry entry(&ref, true);
|
||||
if (entry.InitCheck() < B_OK)
|
||||
return;
|
||||
if (!entry.Exists())
|
||||
return;
|
||||
if (entry.IsDirectory()) {
|
||||
BDirectory dir(&entry);
|
||||
if (dir.InitCheck() < B_OK)
|
||||
return;
|
||||
entry.Unset();
|
||||
entry_ref subRef;
|
||||
while (dir.GetNextRef(&subRef) == B_OK)
|
||||
_AppendToPlaylist(subRef, playlist);
|
||||
} else if (entry.IsFile()) {
|
||||
playlist->AddRef(ref);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -91,8 +91,6 @@ private:
|
||||
int32 index);
|
||||
void _RemovePlaylistItem(int32 index);
|
||||
void _MarkPlaylistItem(int32 index);
|
||||
void _AppendToPlaylist(const entry_ref& ref,
|
||||
Playlist* playlist);
|
||||
|
||||
BMenuBar* fMenuBar;
|
||||
BView* fBackground;
|
||||
|
||||
@@ -25,6 +25,9 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <Autolock.h>
|
||||
#include <Directory.h>
|
||||
#include <Message.h>
|
||||
#include <Path.h>
|
||||
|
||||
using std::nothrow;
|
||||
@@ -43,7 +46,8 @@ void Playlist::Listener::CurrentRefChanged(int32 newIndex) {}
|
||||
|
||||
|
||||
Playlist::Playlist()
|
||||
: fRefs()
|
||||
: BLocker("playlist lock")
|
||||
, fRefs()
|
||||
, fCurrentIndex(-1)
|
||||
{
|
||||
}
|
||||
@@ -104,6 +108,10 @@ Playlist::AddRef(const entry_ref &ref, int32 index)
|
||||
return false;
|
||||
}
|
||||
_NotifyRefAdded(ref, index);
|
||||
|
||||
if (index <= fCurrentIndex)
|
||||
SetCurrentRefIndex(fCurrentIndex + 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -129,6 +137,8 @@ Playlist::AdoptPlaylist(Playlist& other, int32 index)
|
||||
entry_ref* ref = (entry_ref*)fRefs.ItemAtFast(i);
|
||||
_NotifyRefAdded(*ref, i);
|
||||
}
|
||||
if (index <= fCurrentIndex)
|
||||
SetCurrentRefIndex(fCurrentIndex + count);
|
||||
// empty the other list, so that the entry_refs are no ours
|
||||
other.fRefs.MakeEmpty();
|
||||
return true;
|
||||
@@ -138,7 +148,7 @@ Playlist::AdoptPlaylist(Playlist& other, int32 index)
|
||||
|
||||
|
||||
entry_ref
|
||||
Playlist::RemoveRef(int32 index)
|
||||
Playlist::RemoveRef(int32 index, bool careAboutCurrentIndex)
|
||||
{
|
||||
entry_ref _ref;
|
||||
entry_ref* ref = (entry_ref*)fRefs.RemoveItem(index);
|
||||
@@ -147,21 +157,29 @@ Playlist::RemoveRef(int32 index)
|
||||
_NotifyRefRemoved(index);
|
||||
_ref = *ref;
|
||||
delete ref;
|
||||
|
||||
if (careAboutCurrentIndex) {
|
||||
if (index == fCurrentIndex)
|
||||
SetCurrentRefIndex(-1);
|
||||
else if (index < fCurrentIndex)
|
||||
SetCurrentRefIndex(fCurrentIndex - 1);
|
||||
}
|
||||
|
||||
return _ref;
|
||||
}
|
||||
|
||||
|
||||
//int32
|
||||
//Playlist::IndexOf(const entry_ref& _ref) const
|
||||
//{
|
||||
// int32 count = CountItems();
|
||||
// for (int32 i = 0; i < count; i++) {
|
||||
// entry_ref* ref = (entry_ref*)fRefs.ItemAtFast(i);
|
||||
// if (*ref == _ref)
|
||||
// return i;
|
||||
// }
|
||||
// return -1;
|
||||
//}
|
||||
int32
|
||||
Playlist::IndexOf(const entry_ref& _ref) const
|
||||
{
|
||||
int32 count = CountItems();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
entry_ref* ref = (entry_ref*)fRefs.ItemAtFast(i);
|
||||
if (*ref == _ref)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
@@ -223,6 +241,7 @@ Playlist::GetSkipInfo(bool* canSkipPrevious, bool* canSkipNext) const
|
||||
bool
|
||||
Playlist::AddListener(Listener* listener)
|
||||
{
|
||||
BAutolock _(this);
|
||||
if (listener && !fListeners.HasItem(listener))
|
||||
return fListeners.AddItem(listener);
|
||||
return false;
|
||||
@@ -232,6 +251,7 @@ Playlist::AddListener(Listener* listener)
|
||||
void
|
||||
Playlist::RemoveListener(Listener* listener)
|
||||
{
|
||||
BAutolock _(this);
|
||||
fListeners.RemoveItem(listener);
|
||||
}
|
||||
|
||||
@@ -239,6 +259,64 @@ Playlist::RemoveListener(Listener* listener)
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
void
|
||||
Playlist::AppendRefs(BMessage* refsReceivedMessage, int32 appendIndex)
|
||||
{
|
||||
// the playlist ist replaced by the refs in the message
|
||||
// or the refs are appended at the appendIndex
|
||||
// in the existing playlist
|
||||
bool add = appendIndex >= 0;
|
||||
|
||||
if (!add)
|
||||
MakeEmpty();
|
||||
|
||||
bool startPlaying = CountItems() == 0;
|
||||
|
||||
Playlist temporaryPlaylist;
|
||||
Playlist* playlist = add ? &temporaryPlaylist : this;
|
||||
|
||||
entry_ref ref;
|
||||
for (int i = 0; refsReceivedMessage->FindRef("refs", i, &ref) == B_OK; i++)
|
||||
AppendToPlaylistRecursive(ref, playlist);
|
||||
|
||||
playlist->Sort();
|
||||
|
||||
if (add)
|
||||
AdoptPlaylist(temporaryPlaylist, appendIndex);
|
||||
|
||||
if (startPlaying) {
|
||||
// open first file
|
||||
SetCurrentRefIndex(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*static*/ void
|
||||
Playlist::AppendToPlaylistRecursive(const entry_ref& ref, Playlist* playlist)
|
||||
{
|
||||
// recursively append the ref (dive into folders)
|
||||
BEntry entry(&ref, true);
|
||||
if (entry.InitCheck() < B_OK)
|
||||
return;
|
||||
if (!entry.Exists())
|
||||
return;
|
||||
if (entry.IsDirectory()) {
|
||||
BDirectory dir(&entry);
|
||||
if (dir.InitCheck() < B_OK)
|
||||
return;
|
||||
entry.Unset();
|
||||
entry_ref subRef;
|
||||
while (dir.GetNextRef(&subRef) == B_OK)
|
||||
AppendToPlaylistRecursive(subRef, playlist);
|
||||
} else if (entry.IsFile()) {
|
||||
playlist->AddRef(ref);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
int
|
||||
Playlist::playlist_cmp(const void *p1, const void *p2)
|
||||
{
|
||||
|
||||
@@ -23,8 +23,9 @@
|
||||
|
||||
#include <Entry.h>
|
||||
#include <List.h>
|
||||
#include <Locker.h>
|
||||
|
||||
class Playlist {
|
||||
class Playlist : public BLocker {
|
||||
public:
|
||||
class Listener {
|
||||
public:
|
||||
@@ -40,51 +41,58 @@ public:
|
||||
};
|
||||
|
||||
public:
|
||||
Playlist();
|
||||
~Playlist();
|
||||
|
||||
// list functionality
|
||||
void MakeEmpty();
|
||||
int32 CountItems() const;
|
||||
|
||||
void Sort();
|
||||
Playlist();
|
||||
~Playlist();
|
||||
|
||||
// list functionality
|
||||
void MakeEmpty();
|
||||
int32 CountItems() const;
|
||||
|
||||
void Sort();
|
||||
|
||||
bool AddRef(const entry_ref& ref);
|
||||
bool AddRef(const entry_ref& ref, int32 index);
|
||||
entry_ref RemoveRef(int32 index,
|
||||
bool careAboutCurrentIndex = true);
|
||||
|
||||
bool AdoptPlaylist(Playlist& other);
|
||||
bool AdoptPlaylist(Playlist& other, int32 index);
|
||||
|
||||
int32 IndexOf(const entry_ref& ref) const;
|
||||
status_t GetRefAt(int32 index, entry_ref* ref) const;
|
||||
// bool HasRef(const entry_ref& ref) const;
|
||||
|
||||
// navigating current ref
|
||||
void SetCurrentRefIndex(int32 index);
|
||||
int32 CurrentRefIndex() const;
|
||||
|
||||
void GetSkipInfo(bool* canSkipPrevious,
|
||||
bool* canSkipNext) const;
|
||||
|
||||
bool AddRef(const entry_ref& ref);
|
||||
bool AddRef(const entry_ref& ref, int32 index);
|
||||
entry_ref RemoveRef(int32 index);
|
||||
// listener support
|
||||
bool AddListener(Listener* listener);
|
||||
void RemoveListener(Listener* listener);
|
||||
|
||||
bool AdoptPlaylist(Playlist& other);
|
||||
bool AdoptPlaylist(Playlist& other, int32 index);
|
||||
|
||||
// int32 IndexOf(const entry_ref& ref) const;
|
||||
status_t GetRefAt(int32 index, entry_ref* ref) const;
|
||||
// bool HasRef(const entry_ref& ref) const;
|
||||
|
||||
// navigating current ref
|
||||
void SetCurrentRefIndex(int32 index);
|
||||
int32 CurrentRefIndex() const;
|
||||
|
||||
void GetSkipInfo(bool* canSkipPrevious,
|
||||
bool* canSkipNext) const;
|
||||
|
||||
// listener support
|
||||
bool AddListener(Listener* listener);
|
||||
void RemoveListener(Listener* listener);
|
||||
// support functions
|
||||
void AppendRefs(BMessage* refsReceivedMessage,
|
||||
int32 appendIndex = -1);
|
||||
static void AppendToPlaylistRecursive(const entry_ref& ref,
|
||||
Playlist* playlist);
|
||||
|
||||
private:
|
||||
static int playlist_cmp(const void* p1, const void* p2);
|
||||
static int playlist_cmp(const void* p1, const void* p2);
|
||||
|
||||
void _NotifyRefAdded(const entry_ref& ref,
|
||||
int32 index) const;
|
||||
void _NotifyRefRemoved(int32 index) const;
|
||||
void _NotifyRefsSorted() const;
|
||||
void _NotifyCurrentRefChanged(int32 newIndex) const;
|
||||
void _NotifyRefAdded(const entry_ref& ref,
|
||||
int32 index) const;
|
||||
void _NotifyRefRemoved(int32 index) const;
|
||||
void _NotifyRefsSorted() const;
|
||||
void _NotifyCurrentRefChanged(int32 newIndex) const;
|
||||
|
||||
private:
|
||||
BList fRefs;
|
||||
BList fListeners;
|
||||
BList fRefs;
|
||||
BList fListeners;
|
||||
|
||||
int32 fCurrentIndex;
|
||||
int32 fCurrentIndex;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,502 @@
|
||||
/*
|
||||
* Copyright 2007, Haiku. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
*/
|
||||
#include "PlaylistListView.h"
|
||||
|
||||
#include <new>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <Autolock.h>
|
||||
#include <Message.h>
|
||||
#include <ScrollBar.h>
|
||||
#include <ScrollView.h>
|
||||
#include <Window.h>
|
||||
|
||||
#include "Controller.h"
|
||||
#include "ControllerObserver.h"
|
||||
#include "ListViews.h"
|
||||
#include "PlaybackState.h"
|
||||
#include "Playlist.h"
|
||||
#include "PlaylistObserver.h"
|
||||
|
||||
using std::nothrow;
|
||||
|
||||
|
||||
enum {
|
||||
DISPLAY_NAME = 0,
|
||||
DISPLAY_PATH = 1
|
||||
};
|
||||
|
||||
|
||||
static float
|
||||
playback_mark_size(const font_height& fh)
|
||||
{
|
||||
return ceilf(fh.ascent * 0.7);
|
||||
}
|
||||
|
||||
|
||||
static float
|
||||
text_offset(const font_height& fh)
|
||||
{
|
||||
return ceilf(fh.ascent * 0.8);
|
||||
}
|
||||
|
||||
|
||||
class PlaylistItem : public SimpleItem {
|
||||
public:
|
||||
PlaylistItem(const entry_ref& ref);
|
||||
virtual ~PlaylistItem();
|
||||
|
||||
void Draw(BView* owner, BRect frame,
|
||||
const font_height& fh,
|
||||
bool tintedLine, uint32 mode,
|
||||
bool active,
|
||||
uint32 playbackState);
|
||||
|
||||
private:
|
||||
entry_ref fRef;
|
||||
|
||||
};
|
||||
|
||||
|
||||
PlaylistItem::PlaylistItem(const entry_ref& ref)
|
||||
: SimpleItem(ref.name),
|
||||
fRef(ref)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
PlaylistItem::~PlaylistItem()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistItem::Draw(BView* owner, BRect frame, const font_height& fh,
|
||||
bool tintedLine, uint32 mode, bool active, uint32 playbackState)
|
||||
{
|
||||
rgb_color color = (rgb_color){ 255, 255, 255, 255 };
|
||||
if (tintedLine)
|
||||
color = tint_color(color, 1.04);
|
||||
// background
|
||||
if (IsSelected())
|
||||
color = tint_color(color, B_DARKEN_2_TINT);
|
||||
owner->SetLowColor(color);
|
||||
owner->FillRect(frame, B_SOLID_LOW);
|
||||
// label
|
||||
rgb_color black = (rgb_color){ 0, 0, 0, 255 };
|
||||
owner->SetHighColor(black);
|
||||
const char* text = Text();
|
||||
switch (mode) {
|
||||
case DISPLAY_NAME:
|
||||
// TODO
|
||||
break;
|
||||
case DISPLAY_PATH:
|
||||
// TODO
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
float playbackMarkSize = playback_mark_size(fh);
|
||||
float textOffset = text_offset(fh);
|
||||
|
||||
BString truncatedString(text);
|
||||
owner->TruncateString(&truncatedString, B_TRUNCATE_MIDDLE,
|
||||
frame.Width() - playbackMarkSize - textOffset);
|
||||
owner->DrawString(truncatedString.String(),
|
||||
BPoint(frame.left + playbackMarkSize + textOffset,
|
||||
floorf(frame.top + frame.bottom + fh.ascent) / 2 - 1));
|
||||
|
||||
// playmark
|
||||
if (active) {
|
||||
rgb_color green = (rgb_color){ 0, 255, 0, 255 };
|
||||
if (playbackState != PLAYBACK_STATE_PLAYING)
|
||||
green = tint_color(color, B_DARKEN_1_TINT);
|
||||
|
||||
BRect r(0, 0, playbackMarkSize, playbackMarkSize);
|
||||
r.OffsetTo(frame.left + 4,
|
||||
ceilf((frame.top + frame.bottom) / 2) - 5);
|
||||
|
||||
BPoint arrow[3];
|
||||
arrow[0] = r.LeftTop();
|
||||
arrow[1] = r.LeftBottom();
|
||||
arrow[2].x = r.right;
|
||||
arrow[2].y = (r.top + r.bottom) / 2;
|
||||
#ifdef __HAIKU__
|
||||
owner->SetPenSize(2);
|
||||
owner->StrokePolygon(arrow, 3);
|
||||
owner->SetPenSize(1);
|
||||
#else
|
||||
rgb_color lightGreen = tint_color(green, B_LIGHTEN_2_TINT);
|
||||
rgb_color darkGreen = tint_color(green, B_DARKEN_2_TINT);
|
||||
owner->BeginLineArray( 6 );
|
||||
// black outline
|
||||
owner->AddLine(arrow[0], arrow[1], black);
|
||||
owner->AddLine(BPoint(arrow[1].x + 1.0, arrow[1].y - 1.0),
|
||||
arrow[2], black);
|
||||
owner->AddLine(arrow[0], arrow[2], black);
|
||||
// inset arrow
|
||||
arrow[0].x += 1.0;
|
||||
arrow[0].y += 2.0;
|
||||
arrow[1].x += 1.0;
|
||||
arrow[1].y -= 2.0;
|
||||
arrow[2].x -= 2.0;
|
||||
// highlights and shadow
|
||||
owner->AddLine(arrow[1], arrow[2], darkGreen);
|
||||
owner->AddLine(arrow[0], arrow[2], lightGreen);
|
||||
owner->AddLine(arrow[0], arrow[1], lightGreen);
|
||||
owner->EndLineArray();
|
||||
// fill green
|
||||
arrow[0].x += 1.0;
|
||||
arrow[0].y += 1.0;
|
||||
arrow[1].x += 1.0;
|
||||
arrow[1].y -= 1.0;
|
||||
arrow[2].x -= 2.0;
|
||||
#endif // __HAIKU__
|
||||
owner->SetLowColor(owner->HighColor());
|
||||
owner->SetHighColor(green);
|
||||
owner->FillPolygon(arrow, 3);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
PlaylistListView::PlaylistListView(BRect frame, Playlist* playlist,
|
||||
Controller* controller)
|
||||
: SimpleListView(frame, "playlist listview", NULL)
|
||||
|
||||
, fPlaylist(playlist)
|
||||
, fPlaylistObserver(new PlaylistObserver(this))
|
||||
|
||||
, fController(controller)
|
||||
, fControllerObserver(new ControllerObserver(this,
|
||||
OBSERVE_PLAYBACK_STATE_CHANGES))
|
||||
|
||||
, fCurrentPlaylistIndex(-1)
|
||||
, fPlaybackState(PLAYBACK_STATE_STOPPED)
|
||||
|
||||
, fLastClickedItem(NULL)
|
||||
{
|
||||
fPlaylist->AddListener(fPlaylistObserver);
|
||||
fController->AddListener(fControllerObserver);
|
||||
|
||||
#ifdef __HAIKU__
|
||||
SetFlags(Flags() & B_SUBPIXEL_PRECISE);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
PlaylistListView::~PlaylistListView()
|
||||
{
|
||||
fPlaylist->RemoveListener(fPlaylistObserver);
|
||||
delete fPlaylistObserver;
|
||||
fController->RemoveListener(fControllerObserver);
|
||||
delete fControllerObserver;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistListView::AttachedToWindow()
|
||||
{
|
||||
_FullSync();
|
||||
SimpleListView::AttachedToWindow();
|
||||
|
||||
GetFontHeight(&fFontHeight);
|
||||
MakeFocus(true);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistListView::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (message->what) {
|
||||
// PlaylistObserver messages
|
||||
case MSG_PLAYLIST_REF_ADDED: {
|
||||
entry_ref ref;
|
||||
int32 index;
|
||||
if (message->FindRef("refs", &ref) == B_OK
|
||||
&& message->FindInt32("index", &index) == B_OK)
|
||||
_AddItem(ref, index);
|
||||
break;
|
||||
}
|
||||
case MSG_PLAYLIST_REF_REMOVED: {
|
||||
int32 index;
|
||||
if (message->FindInt32("index", &index) == B_OK)
|
||||
_RemoveItem(index);
|
||||
break;
|
||||
}
|
||||
case MSG_PLAYLIST_REFS_SORTED:
|
||||
_FullSync();
|
||||
break;
|
||||
case MSG_PLAYLIST_CURRENT_REF_CHANGED: {
|
||||
int32 index;
|
||||
if (message->FindInt32("index", &index) == B_OK)
|
||||
_SetCurrentPlaylistIndex(index);
|
||||
break;
|
||||
}
|
||||
|
||||
// ControllerObserver messages
|
||||
case MSG_CONTROLLER_PLAYBACK_STATE_CHANGED: {
|
||||
uint32 state;
|
||||
if (message->FindInt32("state", (int32*)&state) == B_OK)
|
||||
_SetPlaybackState(state);
|
||||
break;
|
||||
}
|
||||
|
||||
case B_SIMPLE_DATA:
|
||||
if (message->HasRef("refs"))
|
||||
_RefsReceived(message, fDropIndex);
|
||||
else if (message->HasPointer("list"))
|
||||
SimpleListView::MessageReceived(message);
|
||||
break;
|
||||
case B_REFS_RECEIVED:
|
||||
_RefsReceived(message, fDropIndex);
|
||||
break;
|
||||
|
||||
default:
|
||||
SimpleListView::MessageReceived(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistListView::MouseDown(BPoint where)
|
||||
{
|
||||
if (!IsFocus())
|
||||
MakeFocus(true);
|
||||
|
||||
int32 clicks;
|
||||
if (Window()->CurrentMessage()->FindInt32("clicks", &clicks) < B_OK)
|
||||
clicks = 1;
|
||||
|
||||
bool handled = false;
|
||||
|
||||
float playbackMarkSize = playback_mark_size(fFontHeight);
|
||||
float textOffset = text_offset(fFontHeight);
|
||||
|
||||
for (int32 i = 0;
|
||||
PlaylistItem* item = dynamic_cast<PlaylistItem*>(ItemAt(i)); i++) {
|
||||
BRect r = ItemFrame(i);
|
||||
if (r.Contains(where)) {
|
||||
if (clicks == 2) {
|
||||
// only do something if user clicked the same item twice
|
||||
if (fLastClickedItem == item) {
|
||||
BAutolock _(fPlaylist);
|
||||
fPlaylist->SetCurrentRefIndex(i);
|
||||
handled = true;
|
||||
}
|
||||
} else {
|
||||
// remember last clicked item
|
||||
fLastClickedItem = item;
|
||||
if (i == fCurrentPlaylistIndex) {
|
||||
r.right = r.left + playbackMarkSize + textOffset;
|
||||
if (r.Contains (where)) {
|
||||
fController->TogglePlaying();
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!handled)
|
||||
SimpleListView::MouseDown(where);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistListView::KeyDown(const char* bytes, int32 numBytes)
|
||||
{
|
||||
if (numBytes < 1)
|
||||
return;
|
||||
|
||||
if ((bytes[0] == B_BACKSPACE) || (bytes[0] == B_DELETE))
|
||||
RemoveSelected();
|
||||
|
||||
DragSortableListView::KeyDown(bytes, numBytes);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistListView::MoveItems(BList& indices, int32 toIndex)
|
||||
{
|
||||
if (!fPlaylist->Lock())
|
||||
return;
|
||||
|
||||
entry_ref currentRef;
|
||||
bool adjustCurrentRef = fPlaylist->GetRefAt(fPlaylist->CurrentRefIndex(),
|
||||
¤tRef) == B_OK;
|
||||
|
||||
int32 count = indices.CountItems();
|
||||
entry_ref refs[count];
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
int32 index = (int32)indices.ItemAtFast(i) - i;
|
||||
// "-i" to account for items already removed in the
|
||||
// target list
|
||||
if (index < 0) {
|
||||
// asynchronous message is out of date
|
||||
return;
|
||||
}
|
||||
refs[i] = fPlaylist->RemoveRef(index, false);
|
||||
if (index < toIndex)
|
||||
toIndex --;
|
||||
}
|
||||
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
fPlaylist->AddRef(refs[i], toIndex++);
|
||||
}
|
||||
|
||||
if (adjustCurrentRef)
|
||||
fPlaylist->SetCurrentRefIndex(fPlaylist->IndexOf(currentRef));
|
||||
|
||||
fPlaylist->Unlock();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistListView::CopyItems(BList& indices, int32 toIndex)
|
||||
{
|
||||
if (!fPlaylist->Lock())
|
||||
return;
|
||||
|
||||
int32 count = indices.CountItems();
|
||||
entry_ref refs[count];
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
int32 index = (int32)indices.ItemAtFast(i);
|
||||
if (index < 0) {
|
||||
// asynchronous message is out of date
|
||||
return;
|
||||
}
|
||||
if (fPlaylist->GetRefAt(index, &refs[i]) < B_OK)
|
||||
return;
|
||||
}
|
||||
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
fPlaylist->AddRef(refs[i], toIndex++);
|
||||
}
|
||||
|
||||
fPlaylist->Unlock();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistListView::RemoveItemList(BList& indices)
|
||||
{
|
||||
if (!fPlaylist->Lock())
|
||||
return;
|
||||
|
||||
int32 count = indices.CountItems();
|
||||
int32 lastRemovedIndex = -1;
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
lastRemovedIndex = (int32)indices.ItemAtFast(i) - i;
|
||||
// "-i" to account for items already removed in the
|
||||
// target list
|
||||
fPlaylist->RemoveRef(lastRemovedIndex);
|
||||
}
|
||||
|
||||
// in case we removed the currently playing file
|
||||
if (fPlaylist->CurrentRefIndex() == -1)
|
||||
fPlaylist->SetCurrentRefIndex(lastRemovedIndex);
|
||||
|
||||
fPlaylist->Unlock();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistListView::DrawListItem(BView* owner, int32 index, BRect frame) const
|
||||
{
|
||||
if (PlaylistItem* item = dynamic_cast<PlaylistItem*>(ItemAt(index))) {
|
||||
item->Draw(owner, frame, fFontHeight, index % 2,
|
||||
DISPLAY_NAME, index == fCurrentPlaylistIndex, fPlaybackState);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
void
|
||||
PlaylistListView::_FullSync()
|
||||
{
|
||||
if (!fPlaylist->Lock())
|
||||
return;
|
||||
|
||||
// TODO: detach scrollbar, and this will be quick...
|
||||
// BScrollBar* scrollBar = ScrollBar(B_VERTICAL);
|
||||
// SetScrollBar();
|
||||
//
|
||||
MakeEmpty();
|
||||
|
||||
int32 count = fPlaylist->CountItems();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
entry_ref ref;
|
||||
if (fPlaylist->GetRefAt(i, &ref) == B_OK)
|
||||
_AddItem(ref, i);
|
||||
}
|
||||
|
||||
_SetCurrentPlaylistIndex(fPlaylist->CurrentRefIndex());
|
||||
_SetPlaybackState(fController->PlaybackState());
|
||||
|
||||
fPlaylist->Unlock();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistListView::_AddItem(const entry_ref& ref, int32 index)
|
||||
{
|
||||
PlaylistItem* item = new (nothrow) PlaylistItem(ref);
|
||||
if (item)
|
||||
AddItem(item, index);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistListView::_RemoveItem(int32 index)
|
||||
{
|
||||
delete RemoveItem(index);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistListView::_SetCurrentPlaylistIndex(int32 index)
|
||||
{
|
||||
if (fCurrentPlaylistIndex == index)
|
||||
return;
|
||||
|
||||
InvalidateItem(fCurrentPlaylistIndex);
|
||||
fCurrentPlaylistIndex = index;
|
||||
InvalidateItem(fCurrentPlaylistIndex);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistListView::_SetPlaybackState(uint32 state)
|
||||
{
|
||||
if (fPlaybackState == state)
|
||||
return;
|
||||
|
||||
fPlaybackState = state;
|
||||
InvalidateItem(fCurrentPlaylistIndex);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistListView::_RefsReceived(BMessage* message, int32 dropIndex)
|
||||
{
|
||||
if (!fPlaylist->Lock())
|
||||
return;
|
||||
|
||||
fPlaylist->AppendRefs(message, dropIndex);
|
||||
|
||||
fPlaylist->Unlock();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2007, Haiku. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
*/
|
||||
#ifndef PLAYLIST_LIST_VIEW_H
|
||||
#define PLAYLIST_LIST_VIEW_H
|
||||
|
||||
#include "ListViews.h"
|
||||
|
||||
class Controller;
|
||||
class ControllerObserver;
|
||||
class Playlist;
|
||||
class PlaylistItem;
|
||||
class PlaylistObserver;
|
||||
|
||||
class PlaylistListView : public SimpleListView {
|
||||
public:
|
||||
PlaylistListView(BRect frame,
|
||||
Playlist* playlist,
|
||||
Controller* controller);
|
||||
virtual ~PlaylistListView();
|
||||
|
||||
// BView interface
|
||||
virtual void AttachedToWindow();
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
|
||||
virtual void MouseDown(BPoint where);
|
||||
virtual void KeyDown(const char* bytes, int32 numBytes);
|
||||
|
||||
// SimpleListView interface
|
||||
virtual void MoveItems(BList& indices, int32 toIndex);
|
||||
virtual void CopyItems(BList& indices, int32 toIndex);
|
||||
virtual void RemoveItemList(BList& indices);
|
||||
|
||||
virtual void DrawListItem(BView* owner, int32 index,
|
||||
BRect frame) const;
|
||||
|
||||
private:
|
||||
void _FullSync();
|
||||
void _AddItem(const entry_ref& ref, int32 index);
|
||||
void _RemoveItem(int32 index);
|
||||
|
||||
void _SetCurrentPlaylistIndex(int32 index);
|
||||
void _SetPlaybackState(uint32 state);
|
||||
|
||||
void _RefsReceived(BMessage* message,
|
||||
int32 dropIndex);
|
||||
|
||||
Playlist* fPlaylist;
|
||||
PlaylistObserver* fPlaylistObserver;
|
||||
|
||||
Controller* fController;
|
||||
ControllerObserver* fControllerObserver;
|
||||
|
||||
int32 fCurrentPlaylistIndex;
|
||||
uint32 fPlaybackState;
|
||||
|
||||
font_height fFontHeight;
|
||||
PlaylistItem* fLastClickedItem;
|
||||
};
|
||||
|
||||
#endif // PLAYLIST_LIST_VIEW_H
|
||||
@@ -10,161 +10,17 @@
|
||||
#include <ScrollBar.h>
|
||||
#include <ScrollView.h>
|
||||
|
||||
#include "ListViews.h"
|
||||
#include "Playlist.h"
|
||||
#include "PlaylistObserver.h"
|
||||
|
||||
class PlaylistListView : public SimpleListView {
|
||||
public:
|
||||
PlaylistListView(BRect frame,
|
||||
Playlist* playlist);
|
||||
virtual ~PlaylistListView();
|
||||
|
||||
// BView interface
|
||||
virtual void AttachedToWindow();
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
|
||||
// SimpleListView interface
|
||||
virtual void MoveItems(BList& items, int32 toIndex);
|
||||
virtual void CopyItems(BList& items, int32 toIndex);
|
||||
virtual void RemoveItemList(BList& indices);
|
||||
|
||||
private:
|
||||
void _FullSync();
|
||||
void _AddItem(const entry_ref& ref, int32 index);
|
||||
void _RemoveItem(int32 index);
|
||||
|
||||
Playlist* fPlaylist;
|
||||
PlaylistObserver* fPlaylistObserver;
|
||||
};
|
||||
#include "PlaylistListView.h"
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
PlaylistListView::PlaylistListView(BRect frame, Playlist* playlist)
|
||||
: SimpleListView(frame, "playlist listview", NULL)
|
||||
, fPlaylist(playlist)
|
||||
, fPlaylistObserver(new PlaylistObserver(this))
|
||||
{
|
||||
fPlaylist->AddListener(fPlaylistObserver);
|
||||
}
|
||||
|
||||
|
||||
PlaylistListView::~PlaylistListView()
|
||||
{
|
||||
fPlaylist->RemoveListener(fPlaylistObserver);
|
||||
delete fPlaylistObserver;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistListView::AttachedToWindow()
|
||||
{
|
||||
_FullSync();
|
||||
SimpleListView::AttachedToWindow();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistListView::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case MSG_PLAYLIST_REF_ADDED: {
|
||||
entry_ref ref;
|
||||
int32 index;
|
||||
if (message->FindRef("refs", &ref) == B_OK
|
||||
&& message->FindInt32("index", &index) == B_OK)
|
||||
_AddItem(ref, index);
|
||||
break;
|
||||
}
|
||||
case MSG_PLAYLIST_REF_REMOVED: {
|
||||
int32 index;
|
||||
if (message->FindInt32("index", &index) == B_OK)
|
||||
_RemoveItem(index);
|
||||
break;
|
||||
}
|
||||
case MSG_PLAYLIST_REFS_SORTED:
|
||||
_FullSync();
|
||||
break;
|
||||
default:
|
||||
SimpleListView::MessageReceived(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistListView::MoveItems(BList& items, int32 toIndex)
|
||||
{
|
||||
// TODO: drag indices instead of items! (avoids IndexOf())
|
||||
int32 count = items.CountItems();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
BListItem* item = (BListItem*)items.ItemAtFast(i);
|
||||
int32 index = IndexOf(item);
|
||||
entry_ref ref = fPlaylist->RemoveRef(index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistListView::CopyItems(BList& items, int32 toIndex)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistListView::RemoveItemList(BList& indices)
|
||||
{
|
||||
int32 count = indices.CountItems();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
int32 index = (int32)indices.ItemAtFast(i);
|
||||
fPlaylist->RemoveRef(index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistListView::_FullSync()
|
||||
{
|
||||
// BScrollBar* scrollBar = ScrollBar(B_VERTICAL);
|
||||
// SetScrollBar();
|
||||
//
|
||||
MakeEmpty();
|
||||
|
||||
int32 count = fPlaylist->CountItems();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
entry_ref ref;
|
||||
if (fPlaylist->GetRefAt(i, &ref) == B_OK)
|
||||
_AddItem(ref, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistListView::_AddItem(const entry_ref& ref, int32 index)
|
||||
{
|
||||
SimpleItem* item = new SimpleItem(ref.name);
|
||||
AddItem(item, index);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistListView::_RemoveItem(int32 index)
|
||||
{
|
||||
delete RemoveItem(index);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
PlaylistWindow::PlaylistWindow(BRect frame, Playlist* playlist)
|
||||
PlaylistWindow::PlaylistWindow(BRect frame, Playlist* playlist,
|
||||
Controller* controller)
|
||||
: BWindow(frame, "Playlist", B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS)
|
||||
{
|
||||
frame = Bounds();
|
||||
frame.right -= B_V_SCROLL_BAR_WIDTH;
|
||||
PlaylistListView* listView = new PlaylistListView(frame, playlist);
|
||||
PlaylistListView* listView = new PlaylistListView(frame, playlist,
|
||||
controller);
|
||||
|
||||
fTopView = new BScrollView("playlist scrollview",
|
||||
listView, B_FOLLOW_ALL, 0, false, true, B_NO_BORDER);
|
||||
@@ -188,3 +44,18 @@ PlaylistWindow::QuitRequested()
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistWindow::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case B_MODIFIERS_CHANGED:
|
||||
if (LastMouseMovedView())
|
||||
PostMessage(message, LastMouseMovedView());
|
||||
break;
|
||||
default:
|
||||
BWindow::MessageReceived(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,17 +8,21 @@
|
||||
#ifndef PLAYLIST_WINDOW_H
|
||||
#define PLAYLIST_WINDOW_H
|
||||
|
||||
|
||||
#include <Window.h>
|
||||
|
||||
class Controller;
|
||||
class Playlist;
|
||||
|
||||
class PlaylistWindow : public BWindow {
|
||||
public:
|
||||
PlaylistWindow(BRect frame,
|
||||
Playlist* playlist);
|
||||
Playlist* playlist,
|
||||
Controller* controller);
|
||||
virtual ~PlaylistWindow();
|
||||
|
||||
virtual bool QuitRequested();
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
|
||||
private:
|
||||
BView* fTopView;
|
||||
|
||||
Reference in New Issue
Block a user