MediaPlayer: Add per-track scripting items

Somewhat restructures scripting interface: Playlist items can be
accessed/added/removed through PlaylistTrack, current item can be
accessed through CurrentTrack. Also adds an IsPlaying property.

Fixes #13881

Change-Id: Iad333ec20ab00ff57147c7e1359a24dea04d6aa2
Reviewed-on: https://review.haiku-os.org/c/haiku/+/5316
Reviewed-by: Jérôme Duval <jerome.duval@gmail.com>
Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org>
This commit is contained in:
Jaidyn Ann 2022-05-16 12:38:36 -05:00 committed by waddlesplash
parent cc9bc8c6fb
commit 87db9cb2a6

View File

@ -115,56 +115,45 @@ enum {
static property_info sPropertyInfo[] = { static property_info sPropertyInfo[] = {
{ "Next", { B_EXECUTE_PROPERTY }, { "Next", { B_EXECUTE_PROPERTY },
{ B_DIRECT_SPECIFIER, 0 }, { B_DIRECT_SPECIFIER, 0 },
"Skip to the next track.", 0 "Skips to the next track.", 0
}, },
{ "Prev", { B_EXECUTE_PROPERTY }, { "Prev", { B_EXECUTE_PROPERTY },
{ B_DIRECT_SPECIFIER, 0 }, { B_DIRECT_SPECIFIER, 0 },
"Skip to the previous track.", 0 "Skips to the previous track.", 0
}, },
{ "Play", { B_EXECUTE_PROPERTY }, { "Play", { B_EXECUTE_PROPERTY },
{ B_DIRECT_SPECIFIER, 0 }, { B_DIRECT_SPECIFIER, 0 },
"Start playing.", 0 "Starts playing.", 0
}, },
{ "Stop", { B_EXECUTE_PROPERTY }, { "Stop", { B_EXECUTE_PROPERTY },
{ B_DIRECT_SPECIFIER, 0 }, { B_DIRECT_SPECIFIER, 0 },
"Stop playing.", 0 "Stops playing.", 0
}, },
{ "Pause", { B_EXECUTE_PROPERTY }, { "Pause", { B_EXECUTE_PROPERTY },
{ B_DIRECT_SPECIFIER, 0 }, { B_DIRECT_SPECIFIER, 0 },
"Pause playback.", 0 "Pauses playback.", 0
},
{ "IsPlaying", { B_GET_PROPERTY },
{ B_DIRECT_SPECIFIER, 0 },
"Gets whether or not the player is unpaused.", 0,
{ B_BOOL_TYPE }
}, },
{ "TogglePlaying", { B_EXECUTE_PROPERTY }, { "TogglePlaying", { B_EXECUTE_PROPERTY },
{ B_DIRECT_SPECIFIER, 0 }, { B_DIRECT_SPECIFIER, 0 },
"Toggle pause/play.", 0 "Toggles pause/play.", 0
}, },
{ "Mute", { B_EXECUTE_PROPERTY }, { "Mute", { B_EXECUTE_PROPERTY },
{ B_DIRECT_SPECIFIER, 0 }, { B_DIRECT_SPECIFIER, 0 },
"Toggle mute.", 0 "Toggles mute.", 0
}, },
{ "Volume", { B_GET_PROPERTY, B_SET_PROPERTY, 0 }, { "Volume", { B_GET_PROPERTY, B_SET_PROPERTY, 0 },
{ B_DIRECT_SPECIFIER, 0 }, { B_DIRECT_SPECIFIER, 0 },
"Gets/sets the volume (0.0-2.0).", 0, "Gets/sets the volume (0.0-2.0).", 0,
{ B_FLOAT_TYPE } { B_FLOAT_TYPE }
}, },
{ "URI", { B_GET_PROPERTY, 0 },
{ B_DIRECT_SPECIFIER, 0 },
"Gets the URI of the currently playing item.", 0,
{ B_STRING_TYPE }
},
{ "TrackNumber", { B_GET_PROPERTY, 0 },
{ B_DIRECT_SPECIFIER, 0 },
"Gets the number of the current track playing.", 0,
{ B_INT32_TYPE }
},
{ "ToggleFullscreen", { B_EXECUTE_PROPERTY }, { "ToggleFullscreen", { B_EXECUTE_PROPERTY },
{ B_DIRECT_SPECIFIER, 0 }, { B_DIRECT_SPECIFIER, 0 },
"Toggle fullscreen.", 0 "Toggles fullscreen.", 0
},
{ "Duration", { B_GET_PROPERTY, 0 },
{ B_DIRECT_SPECIFIER, 0 },
"Gets the duration of the currently playing item "
"in microseconds.", 0,
{ B_INT64_TYPE }
}, },
{ "Position", { B_GET_PROPERTY, B_SET_PROPERTY, 0 }, { "Position", { B_GET_PROPERTY, B_SET_PROPERTY, 0 },
{ B_DIRECT_SPECIFIER, 0 }, { B_DIRECT_SPECIFIER, 0 },
@ -173,19 +162,73 @@ static property_info sPropertyInfo[] = {
}, },
{ "Seek", { B_SET_PROPERTY }, { "Seek", { B_SET_PROPERTY },
{ B_DIRECT_SPECIFIER, 0 }, { B_DIRECT_SPECIFIER, 0 },
"Seek by the specified amounts of microseconds.", 0, "Seeks by the specified amount in microseconds.", 0,
{ B_INT64_TYPE } { B_INT64_TYPE }
}, },
{ "PlaylistTrackCount", { B_GET_PROPERTY, 0 }, { "PlaylistTrack", { B_COUNT_PROPERTIES, B_CREATE_PROPERTY, 0 },
{ B_DIRECT_SPECIFIER, 0 }, { B_DIRECT_SPECIFIER, 0 },
"Gets the number of tracks in Playlist.", 0, "Counts items in the Playlist or appends an item by URI.", 0,
{ B_INT16_TYPE } { B_INT32_TYPE }
}, },
{ "PlaylistTrackTitle", { B_GET_PROPERTY, 0 }, { "PlaylistTrack", { B_DELETE_PROPERTY, 0 },
{ B_INDEX_SPECIFIER, 0 }, { B_INDEX_SPECIFIER, 0 },
"Gets the title of the nth track in Playlist.", 0, "Deletes the nth item in Playlist.", 0,
{ B_STRING_TYPE } { B_STRING_TYPE }
}, },
{ "PlaylistTrack", {},
{ B_INDEX_SPECIFIER, 0 },
"... of PlaylistTrack { index } of ...", 0
},
{ "CurrentTrack", {},
{},
"... of CurrentTrack of ...", 0,
},
{ 0 }
};
static property_info sItemPropertyInfo[] = {
{ "Title", { B_GET_PROPERTY, 0 },
{ B_DIRECT_SPECIFIER, 0 },
"Gets the title of the item.", 0,
{ B_STRING_TYPE }
},
{ "URI", { B_GET_PROPERTY, 0 },
{ B_DIRECT_SPECIFIER, 0 },
"Gets the URI of the item.", 0,
{ B_STRING_TYPE }
},
{ "Duration", { B_GET_PROPERTY, 0 },
{ B_DIRECT_SPECIFIER, 0 },
"Gets the duration of the item in microseconds.", 0,
{ B_INT64_TYPE }
},
{ "Author", { B_GET_PROPERTY, 0 },
{ B_DIRECT_SPECIFIER, 0 },
"Gets the author of the item.", 0,
{ B_STRING_TYPE }
},
{ "Album", { B_GET_PROPERTY, 0 },
{ B_DIRECT_SPECIFIER, 0 },
"Gets the album of the item.", 0,
{ B_STRING_TYPE }
},
{ "TrackNumber", { B_GET_PROPERTY, 0 },
{ B_DIRECT_SPECIFIER, 0 },
"Gets the track number of the item.", 0,
{ B_INT32_TYPE }
},
{ "PlaylistIndex", { B_GET_PROPERTY, 0 },
{ B_DIRECT_SPECIFIER, 0 },
"Gets the item's position in Playlist.", 0,
{ B_INT32_TYPE }
},
{ "Suites", { B_GET_PROPERTY, 0 },
{ B_DIRECT_SPECIFIER, 0 },
NULL, 0,
{ B_PROPERTY_INFO_TYPE }
},
{ 0 } { 0 }
}; };
@ -491,6 +534,10 @@ MainWin::MessageReceived(BMessage* msg)
case B_EXECUTE_PROPERTY: case B_EXECUTE_PROPERTY:
case B_GET_PROPERTY: case B_GET_PROPERTY:
case B_SET_PROPERTY: case B_SET_PROPERTY:
case B_COUNT_PROPERTIES:
case B_CREATE_PROPERTY:
case B_DELETE_PROPERTY:
case B_GET_SUPPORTED_SUITES:
{ {
BMessage reply(B_REPLY); BMessage reply(B_REPLY);
status_t result = B_BAD_SCRIPT_SYNTAX; status_t result = B_BAD_SCRIPT_SYNTAX;
@ -499,14 +546,12 @@ MainWin::MessageReceived(BMessage* msg)
int32 what; int32 what;
const char* property; const char* property;
if (msg->GetCurrentSpecifier(&index, &specifier, &what, if (msg->GetCurrentSpecifier(&index, &specifier, &what, &property) != B_OK)
&property) != B_OK) {
return BWindow::MessageReceived(msg); return BWindow::MessageReceived(msg);
}
BPropertyInfo propertyInfo(sPropertyInfo); BPropertyInfo propertyInfo(sPropertyInfo);
switch (propertyInfo.FindMatch(msg, index, &specifier, what, int32 match = propertyInfo.FindMatch(msg, index, &specifier, what, property);
property)) { switch (match) {
case 0: case 0:
fControls->SkipForward(); fControls->SkipForward();
result = B_OK; result = B_OK;
@ -533,16 +578,20 @@ MainWin::MessageReceived(BMessage* msg)
break; break;
case 5: case 5:
result = reply.AddBool("result", fController->IsPlaying());
break;
case 6:
fController->TogglePlaying(); fController->TogglePlaying();
result = B_OK; result = B_OK;
break; break;
case 6: case 7:
fController->ToggleMute(); fController->ToggleMute();
result = B_OK; result = B_OK;
break; break;
case 7: case 8:
{ {
if (msg->what == B_GET_PROPERTY) { if (msg->what == B_GET_PROPERTY) {
result = reply.AddFloat("result", result = reply.AddFloat("result",
@ -556,49 +605,11 @@ MainWin::MessageReceived(BMessage* msg)
break; break;
} }
case 8:
{
if (msg->what == B_GET_PROPERTY) {
BAutolock _(fPlaylist);
const PlaylistItem* item = fController->Item();
if (item == NULL) {
result = B_NO_INIT;
break;
}
result = reply.AddString("result", item->LocationURI());
}
break;
}
case 9: case 9:
{
if (msg->what == B_GET_PROPERTY) {
BAutolock _(fPlaylist);
const PlaylistItem* item = fController->Item();
if (item == NULL) {
result = B_NO_INIT;
break;
}
result = reply.AddInt32("result", item->TrackNumber());
}
break;
}
case 10:
PostMessage(M_TOGGLE_FULLSCREEN); PostMessage(M_TOGGLE_FULLSCREEN);
break; break;
case 11: case 10:
if (msg->what != B_GET_PROPERTY)
break;
result = reply.AddInt64("result",
fController->TimeDuration());
break;
case 12:
{ {
if (msg->what == B_GET_PROPERTY) { if (msg->what == B_GET_PROPERTY) {
result = reply.AddInt64("result", result = reply.AddInt64("result",
@ -613,7 +624,7 @@ MainWin::MessageReceived(BMessage* msg)
break; break;
} }
case 13: case 11:
{ {
if (msg->what != B_SET_PROPERTY) if (msg->what != B_SET_PROPERTY)
break; break;
@ -627,22 +638,150 @@ MainWin::MessageReceived(BMessage* msg)
break; break;
} }
case 14: case 12:
result = reply.AddInt16("result", fPlaylist->CountItems()); {
BAutolock _(fPlaylist);
if (msg->what == B_COUNT_PROPERTIES)
result = reply.AddInt32("result", fPlaylist->CountItems());
else if (msg->what == B_CREATE_PROPERTY) {
result = B_OK;
int32 i = msg->GetInt32("index", fPlaylist->CountItems());
if (i > fPlaylist->CountItems()) {
result = B_BAD_INDEX;
break;
}
BString urlString;
entry_ref fileRef;
for (int32 j = 0; msg->FindString("data", j, &urlString) == B_OK; j++) {
BUrl url(urlString);
if (url.IsValid() && url.Protocol() != "file") {
UrlPlaylistItem* item = new UrlPlaylistItem(url);
if (!fPlaylist->AddItem(item, i + j)) {
result = B_NO_INIT;
delete item;
break;
}
} else if (!urlString.IsEmpty()) {
BString path = url.Path().String();
if (path.IsEmpty())
path = urlString;
result = BEntry(path.String()).GetRef(&fileRef);
if (result == B_OK && msg->AddRef("refs", &fileRef) != B_OK)
result = B_NO_INIT;
if (result != B_OK)
break;
}
}
if (result != B_OK)
break; break;
case 15: for (int32 j = 0; msg->FindRef("refs", j, &fileRef) == B_OK; j++)
{ if (!BEntry(&fileRef).Exists()) {
int32 i = specifier.GetInt32("index", 0); result = B_ENTRY_NOT_FOUND;
if (i >= fPlaylist->CountItems()) { break;
} else {
FilePlaylistItem* item = new FilePlaylistItem(fileRef);
if (!fPlaylist->AddItem(item, i + j)) {
result = B_NO_INIT; result = B_NO_INIT;
delete item;
break;
}
}
}
break;
}
case 13:
{
int32 i = 0;
int32 count = fPlaylist->CountItems();
if (specifier.FindInt32("index", &i) != B_OK || i >= count) {
result = B_BAD_INDEX;
break; break;
} }
BAutolock _(fPlaylist); BAutolock _(fPlaylist);
const PlaylistItem* item = fPlaylist->ItemAt(i); if (msg->what == B_DELETE_PROPERTY)
result = item == NULL ? B_NO_INIT result = fPlaylist->RemoveItem(i) == NULL ? B_NO_INIT : B_OK;
: reply.AddString("result", item->Title()); break;
}
// PlaylistItem and CurrentItem
case 14:
case 15:
{
BPropertyInfo itemPropertyInfo(sItemPropertyInfo);
if (msg->what == B_GET_SUPPORTED_SUITES) {
result = reply.AddFlat("messages", &itemPropertyInfo);
break;
}
BAutolock _(fPlaylist);
int32 i = fPlaylist->CurrentItemIndex();
if (match == 14 && (specifier.FindInt32("index", &i) != B_OK
|| i >= fPlaylist->CountItems() || i < 0)) {
result = B_BAD_INDEX;
break;
}
msg->SetCurrentSpecifier(0);
if (msg->GetCurrentSpecifier(&index, &specifier, &what, &property) != B_OK)
break;
const PlaylistItem* item = NULL;
if (match == 14)
item = fPlaylist->ItemAt(i);
else
item = fController->Item();
if (item == NULL) {
result = B_NO_INIT;
break;
}
switch (itemPropertyInfo.FindMatch(msg, index, &specifier, what, property)) {
case 0:
result = reply.AddString("result", item->Title());
break;
case 1:
result = reply.AddString("result", item->LocationURI());
break;
case 2:
// Duration requires non-const item
if (match == 14) {
PlaylistItem* nitem = fPlaylist->ItemAt(i);
if (nitem == NULL)
result = B_NO_INIT;
else
result = reply.AddInt64("result", nitem->Duration());
} else
result = reply.AddInt64("result", fController->TimeDuration());
break;
case 3:
result = reply.AddString("result", item->Author());
break;
case 4:
result = reply.AddString("result", item->Album());
break;
case 5:
result = reply.AddInt32("result", item->TrackNumber());
break;
case 6:
result = reply.AddInt32("result", i);
break;
case 7:
result = reply.AddFlat("messages", &itemPropertyInfo);
break;
}
break; break;
} }