Replace hardcoded window index w window-targeting
For a replicant, the target-window can now be selected by either novelty, file-type, or an explicit index.
This commit is contained in:
parent
44eda8ab54
commit
f67161ff12
|
@ -11,9 +11,15 @@
|
|||
#include "Song.h"
|
||||
|
||||
|
||||
MediaPlayer::MediaPlayer(int32 window)
|
||||
// This seems a fair amount of Pulse()-es to wait before spam-checking windows.
|
||||
const int32 kTargetHops = 20;
|
||||
|
||||
|
||||
MediaPlayer::MediaPlayer(int32 window, target followType)
|
||||
{
|
||||
fWindowIndex = window;
|
||||
fWindowTarget = followType;
|
||||
fWindowTargetHops = 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -21,7 +27,9 @@ MediaPlayer::MediaPlayer(BMessage* data)
|
|||
:
|
||||
BArchivable(data)
|
||||
{
|
||||
fWindowIndex = data->GetInt32("_window", 0);
|
||||
fWindowIndex = data->GetInt32("_window", -1);
|
||||
fWindowTarget = (target)data->GetInt32("_windowtype", MP_BY_TYPE_AUDIO);
|
||||
fWindowTargetHops = 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -30,6 +38,7 @@ MediaPlayer::Archive(BMessage* data, bool deep) const
|
|||
{
|
||||
status_t status = BArchivable::Archive(data, deep);
|
||||
data->AddInt32("_window", fWindowIndex);
|
||||
data->AddInt32("_windowtype", fWindowTarget);
|
||||
data->AddString("class", "MediaPlayer");
|
||||
data->AddString("add_on", APP_SIGNATURE);
|
||||
return status;
|
||||
|
@ -45,6 +54,16 @@ MediaPlayer::Instantiate(BMessage* data)
|
|||
}
|
||||
|
||||
|
||||
bool
|
||||
MediaPlayer::IsValid()
|
||||
{
|
||||
BString type;
|
||||
BMessage send, reply;
|
||||
_ScriptingCall("Suites", &send, &reply, MP_NO_TRACK, true);
|
||||
return reply.FindString("suites", &type) == B_OK && type == "suite/vnd.Haiku-MediaPlayer";
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
MediaPlayer::IsPlaying()
|
||||
{
|
||||
|
@ -113,6 +132,33 @@ MediaPlayer::PlaylistItem(Song* song, int32 index, bool duration)
|
|||
}
|
||||
|
||||
|
||||
int32
|
||||
MediaPlayer::Window()
|
||||
{
|
||||
if (fWindowTarget == MP_BY_INDEX || fWindowTargetHops-- > 0)
|
||||
return fWindowIndex;
|
||||
|
||||
fWindowTargetHops = kTargetHops;
|
||||
|
||||
for (int32 i = CountWindows() - 1; i >= 0; i--) {
|
||||
MediaPlayer mp(i, MP_BY_INDEX);
|
||||
if (mp.IsValid()) {
|
||||
if (fWindowTarget == MP_BY_LATEST)
|
||||
return i;
|
||||
|
||||
Song current;
|
||||
BString type;
|
||||
if (CurrentItem(¤t, false)
|
||||
&& BNode(current.Path().Path()).ReadAttrString("BEOS:TYPE", &type) == B_OK)
|
||||
if ((type.StartsWith("audio") && fWindowTarget == MP_BY_TYPE_AUDIO)
|
||||
|| (type.StartsWith("video") && fWindowTarget == MP_BY_TYPE_VIDEO))
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return fWindowIndex;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
MediaPlayer::SetWindow(int32 index)
|
||||
{
|
||||
|
@ -127,7 +173,7 @@ int32
|
|||
MediaPlayer::CountWindows()
|
||||
{
|
||||
BMessage send(B_COUNT_PROPERTIES), reply;
|
||||
_ScriptingCall("Window", &send, &reply, MP_NO_TRACK);
|
||||
_ScriptingCall("Window", &send, &reply, MP_NO_TRACK, false);
|
||||
|
||||
int32 count;
|
||||
if (reply.FindInt32("result", &count) == B_OK)
|
||||
|
@ -136,8 +182,23 @@ MediaPlayer::CountWindows()
|
|||
}
|
||||
|
||||
|
||||
target
|
||||
MediaPlayer::Target()
|
||||
{
|
||||
return fWindowTarget;
|
||||
}
|
||||
|
||||
|
||||
target
|
||||
MediaPlayer::SetTarget(target target)
|
||||
{
|
||||
fWindowTargetHops = 0;
|
||||
return fWindowTarget = target;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
MediaPlayer::_GetSong(Song* song, int32 trackIndex, bool durationRequired)
|
||||
MediaPlayer::_GetSong(Song* song, int32 trackIndex, bool durationReq)
|
||||
{
|
||||
BMessage send, reply;
|
||||
_ScriptingCall("URI", &send, &reply, trackIndex);
|
||||
|
@ -146,19 +207,25 @@ MediaPlayer::_GetSong(Song* song, int32 trackIndex, bool durationRequired)
|
|||
return false;
|
||||
|
||||
int64 duration = -1;
|
||||
if (durationRequired) {
|
||||
if (durationReq) {
|
||||
_ScriptingCall("Duration", &send, &reply, trackIndex);
|
||||
if (reply.FindInt64("result", &duration) != B_OK)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (trackIndex == MP_CURRENT_TRACK && fWindowTarget != MP_BY_INDEX
|
||||
&& uriString != fLastItemPath) {
|
||||
fLastItemPath.SetTo(uriString);
|
||||
fWindowTargetHops = 0;
|
||||
}
|
||||
*song = Song(_UriToPath(uriString), duration);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MediaPlayer::_ScriptingCall(const char* attribute, BMessage* send, BMessage* reply, int32 trackIndex)
|
||||
MediaPlayer::_ScriptingCall(const char* attribute, BMessage* send, BMessage* reply, int32 trackIndex,
|
||||
bool window)
|
||||
{
|
||||
if (send->what == 0)
|
||||
send->what = B_GET_PROPERTY;
|
||||
|
@ -169,9 +236,14 @@ MediaPlayer::_ScriptingCall(const char* attribute, BMessage* send, BMessage* rep
|
|||
else if (trackIndex == MP_CURRENT_TRACK)
|
||||
send->AddSpecifier("CurrentTrack");
|
||||
|
||||
send->AddSpecifier("Window", fWindowIndex);
|
||||
if (window)
|
||||
send->AddSpecifier("Window", Window());
|
||||
|
||||
BMessenger("application/x-vnd.Haiku-MediaPlayer").SendMessage(send, reply);
|
||||
if (BMessenger("application/x-vnd.Haiku-MediaPlayer").SendMessage(send, reply) != B_OK)
|
||||
return;
|
||||
|
||||
if (reply != NULL && reply->what == B_MESSAGE_NOT_UNDERSTOOD)
|
||||
fWindowTargetHops = 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -19,17 +19,26 @@ enum {
|
|||
};
|
||||
|
||||
|
||||
enum target {
|
||||
MP_BY_INDEX,
|
||||
MP_BY_TYPE_AUDIO,
|
||||
MP_BY_TYPE_VIDEO,
|
||||
MP_BY_LATEST
|
||||
};
|
||||
|
||||
|
||||
class MediaPlayer : public BArchivable {
|
||||
public:
|
||||
MediaPlayer(int32 window = 0);
|
||||
MediaPlayer(int32 window = 0, target followType = MP_BY_TYPE_AUDIO);
|
||||
MediaPlayer(BMessage* archive);
|
||||
|
||||
virtual status_t Archive(BMessage* data, bool deep = true) const;
|
||||
static MediaPlayer* Instantiate(BMessage* data);
|
||||
|
||||
bool IsValid();
|
||||
|
||||
bool IsPlaying();
|
||||
int64 Duration();
|
||||
int64 Duration();
|
||||
int64 Position();
|
||||
void SetPosition(int64 position);
|
||||
float Volume();
|
||||
|
@ -38,16 +47,25 @@ public:
|
|||
bool CurrentItem(Song* song, bool duration = true);
|
||||
bool PlaylistItem(Song* song, int32 index, bool duration = true);
|
||||
|
||||
int32 Window();
|
||||
int32 SetWindow(int32 index);
|
||||
int32 CountWindows();
|
||||
|
||||
target Target();
|
||||
target SetTarget(target target);
|
||||
|
||||
private:
|
||||
bool _GetSong(Song* song, int32 trackIndex, bool durationRequired = true);
|
||||
bool _GetSong(Song* song, int32 trackIndex, bool duration = true);
|
||||
void _ScriptingCall(const char* attribute, BMessage* send, BMessage* reply,
|
||||
int32 trackIndex = MP_NO_TRACK);
|
||||
int32 trackIndex = MP_NO_TRACK, bool window = true);
|
||||
|
||||
const char* _UriToPath(BString URI);
|
||||
|
||||
int32 fWindowIndex;
|
||||
target fWindowTarget;
|
||||
int32 fWindowTargetHops; // Amount of pulses to wait before re-checking windows
|
||||
|
||||
BString fLastItemPath;
|
||||
};
|
||||
|
||||
#endif // MEDIAPLAYER_H
|
||||
|
|
|
@ -36,7 +36,7 @@ ReplicantView::ReplicantView(BRect frame, const char* name, uint32 draggerPlacem
|
|||
fTransparentInactivity = false;
|
||||
fTransparentDragger = false;
|
||||
|
||||
fMediaPlayer = new MediaPlayer(0);
|
||||
fMediaPlayer = new MediaPlayer();
|
||||
}
|
||||
|
||||
|
||||
|
@ -89,6 +89,25 @@ ReplicantView::MessageReceived(BMessage* msg)
|
|||
{
|
||||
switch (msg->what)
|
||||
{
|
||||
case REPL_WIN_BY_AUDIO:
|
||||
fMediaPlayer->SetTarget(MP_BY_TYPE_AUDIO);
|
||||
break;
|
||||
case REPL_WIN_BY_VIDEO:
|
||||
fMediaPlayer->SetTarget(MP_BY_TYPE_VIDEO);
|
||||
break;
|
||||
case REPL_WIN_BY_LATEST:
|
||||
fMediaPlayer->SetTarget(MP_BY_LATEST);
|
||||
break;
|
||||
case REPL_WIN_BY_INDEX:
|
||||
{
|
||||
int32 index = 0;
|
||||
if (msg->FindInt32("index", &index) == B_OK) {
|
||||
fMediaPlayer->SetTarget(MP_BY_INDEX);
|
||||
fMediaPlayer->SetWindow(index);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case REPL_TRANSPARENTLY_INACTIVE:
|
||||
case REPL_TRANSPARENTLY_DRAG: {
|
||||
if (msg->what == REPL_TRANSPARENTLY_INACTIVE)
|
||||
|
@ -136,7 +155,6 @@ ReplicantView::RightClickPopUp(BPopUpMenu* menu)
|
|||
|
||||
BMenu* hideMenu = new BMenu("Hide when inactive");
|
||||
menu->AddItem(hideMenu);
|
||||
|
||||
BMenuItem* hideInactive = hideMenu->Superitem();
|
||||
hideInactive->SetMessage(new BMessage(REPL_TRANSPARENTLY_INACTIVE));
|
||||
hideInactive->SetMarked(fTransparentInactivity);
|
||||
|
@ -148,12 +166,29 @@ ReplicantView::RightClickPopUp(BPopUpMenu* menu)
|
|||
hideDragger->SetTarget(this);
|
||||
hideMenu->AddItem(hideDragger);
|
||||
|
||||
BMenu* windowMenu = new BMenu("Target window…");
|
||||
menu->AddItem(windowMenu);
|
||||
|
||||
BMenu* indexMenu = _WindowIndexMenu();
|
||||
indexMenu->SetTargetForItems(this);
|
||||
windowMenu->AddItem(indexMenu);
|
||||
|
||||
BMenu* typeMenu = new BMenu("By type…");
|
||||
windowMenu->AddItem(typeMenu);
|
||||
|
||||
BMenuItem* audioItem = new BMenuItem("Audio", new BMessage(REPL_WIN_BY_AUDIO));
|
||||
BMenuItem* videoItem = new BMenuItem("Video", new BMessage(REPL_WIN_BY_VIDEO));
|
||||
audioItem->SetMarked(fMediaPlayer->Target() == MP_BY_TYPE_AUDIO);
|
||||
videoItem->SetMarked(fMediaPlayer->Target() == MP_BY_TYPE_VIDEO);
|
||||
typeMenu->AddItem(audioItem);
|
||||
typeMenu->AddItem(videoItem);
|
||||
typeMenu->SetTargetForItems(this);
|
||||
|
||||
menu->AddSeparatorItem();
|
||||
|
||||
BString aboutLabel = "About %replicant" B_UTF8_ELLIPSIS;
|
||||
aboutLabel.ReplaceAll("%replicant", Name());
|
||||
BMenuItem* aboutItem = new BMenuItem(aboutLabel, new BMessage(B_ABOUT_REQUESTED));
|
||||
aboutItem->SetTarget(this);
|
||||
menu->AddItem(aboutItem);
|
||||
|
||||
if (fReplicated) {
|
||||
|
@ -182,3 +217,31 @@ ReplicantView::SetInactive(bool inactive)
|
|||
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
|
||||
BMenu*
|
||||
ReplicantView::_WindowIndexMenu()
|
||||
{
|
||||
BMenu* menu = new BMenu("By index…");
|
||||
|
||||
BMenuItem* latestItem = new BMenuItem("Latest", new BMessage(REPL_WIN_BY_LATEST));
|
||||
latestItem->SetMarked(fMediaPlayer->Target() == MP_BY_LATEST);
|
||||
menu->AddItem(latestItem);
|
||||
|
||||
int32 windowCount = fMediaPlayer->CountWindows();
|
||||
for (int32 i = 0; i < windowCount; i++)
|
||||
if (MediaPlayer(i, MP_BY_INDEX).IsValid()) {
|
||||
BString label("");
|
||||
label << i;
|
||||
|
||||
BMessage* msg = new BMessage(REPL_WIN_BY_INDEX);
|
||||
msg->AddInt32("index", i);
|
||||
|
||||
BMenuItem* indexItem = new BMenuItem(label, msg);
|
||||
indexItem->SetMarked(fMediaPlayer->Target() == MP_BY_INDEX
|
||||
&& fMediaPlayer->Window() == i);
|
||||
menu->AddItem(indexItem);
|
||||
}
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
|
|
@ -8,19 +8,18 @@
|
|||
#include <View.h>
|
||||
|
||||
class BDragger;
|
||||
class BMenu;
|
||||
class BPopUpMenu;
|
||||
class MediaPlayer;
|
||||
|
||||
|
||||
enum {
|
||||
MP_AUDIO_WINDOW = 'mpaw',
|
||||
MP_VIDEO_WINDOW = 'mpvw',
|
||||
MP_NEWEST_WINDOW = 'mpnw'
|
||||
};
|
||||
|
||||
enum {
|
||||
REPL_TRANSPARENTLY_INACTIVE = 'rtti',
|
||||
REPL_TRANSPARENTLY_DRAG = 'rttd'
|
||||
REPL_TRANSPARENTLY_DRAG = 'rttd',
|
||||
REPL_WIN_BY_INDEX = 'rwbi',
|
||||
REPL_WIN_BY_LATEST = 'rwbl',
|
||||
REPL_WIN_BY_AUDIO = 'rwba',
|
||||
REPL_WIN_BY_VIDEO = 'rwbv'
|
||||
};
|
||||
|
||||
|
||||
|
@ -53,6 +52,9 @@ public:
|
|||
// Set inactivity state, re-render accordingly
|
||||
virtual void SetInactive(bool inactive);
|
||||
|
||||
private:
|
||||
BMenu* _WindowIndexMenu();
|
||||
|
||||
protected:
|
||||
MediaPlayer* fMediaPlayer;
|
||||
BDragger* fDragger;
|
||||
|
|
Ŝarĝante…
Reference in New Issue