Abstract scripting calls into 'MediaPlayer' class

This commit is contained in:
Jaidyn Ann 2022-05-25 10:58:32 -05:00
parent 6a7ed4b302
commit ff84f929ae
9 changed files with 308 additions and 83 deletions

View File

@ -32,9 +32,10 @@ APP_MIME_SIG = application/x-vnd.mediamonitor
# same name (source.c or source.cpp) are included from different directories.
# Also note that spaces in folder names do not work well with this Makefile.
SRCS = src/App.cpp \
src/MainWindow.cpp \
src/CoverView.cpp \
src/LyricsView.cpp \
src/MainWindow.cpp \
src/MediaPlayer.cpp \
src/Song.cpp
# Specify the resource definition files to use. Full or relative paths can be

View File

@ -9,7 +9,7 @@
#include <Dragger.h>
#include <Messenger.h>
#include "Song.h"
#include "MediaPlayer.h"
CoverView::CoverView(BRect frame)
@ -22,6 +22,8 @@ CoverView::CoverView(BRect frame)
fDragger->SetViewColor(B_TRANSPARENT_COLOR);
AddChild(fDragger);
fMediaPlayer = new MediaPlayer(0);
fCover = NULL;
SetViewColor(B_TRANSPARENT_COLOR);
Pulse();
@ -32,6 +34,10 @@ CoverView::CoverView(BMessage* data)
:
BView(data)
{
BMessage mediaplayer;
data->FindMessage("mediaplayer", &mediaplayer);
fMediaPlayer = new MediaPlayer(&mediaplayer);
fCover = NULL;
SetViewColor(B_TRANSPARENT_COLOR);
Pulse();
@ -42,6 +48,10 @@ status_t
CoverView::Archive(BMessage* data, bool deep) const
{
status_t status = BView::Archive(data, deep);
BMessage mediaPlayer;
fMediaPlayer->Archive(&mediaPlayer);
data->AddMessage("mediaplayer", &mediaPlayer);
data->AddString("class", "CoverView");
data->AddString("add_on", "application/x-vnd.mediamonitor");
return status;
@ -60,17 +70,18 @@ CoverView::Instantiate(BMessage* data)
void
CoverView::Pulse()
{
BString path = _GetCurrentPath();
if (path.IsEmpty() == false && path != fCurrentPath) {
fCurrentPath = path;
Song song(path.String());
Song song;
if (fMediaPlayer->CurrentItem(&song, false) == false) {
if (fCurrentSong.InitCheck()) {
fCurrentSong = song;
delete fCover;
Invalidate();
}
} else if (song != fCurrentSong) {
fCurrentSong = song;
delete fCover;
fCover = song.Cover();
Invalidate();
} else if (path.IsEmpty() && path != fCurrentPath) {
fCurrentPath = path;
delete fCover;
Invalidate();
}
}
@ -83,19 +94,3 @@ CoverView::Draw(BRect updateRect)
if (fCover != NULL && fCover->IsValid())
DrawBitmap(fCover, Bounds());
}
BString
CoverView::_GetCurrentPath()
{
BMessage message, reply;
message.what = B_GET_PROPERTY;
message.AddSpecifier("URI");
message.AddSpecifier("CurrentTrack");
message.AddSpecifier("Window", 0);
BMessenger("application/x-vnd.Haiku-MediaPlayer").SendMessage(&message, &reply);
BString result;
reply.FindString("result", &result);
return result.ReplaceAll("file://", "");
}

View File

@ -7,7 +7,10 @@
#include <View.h>
#include "Song.h"
class BDragger;
class MediaPlayer;
class CoverView : public BView {
@ -24,12 +27,12 @@ public:
private:
void _Init(BRect frame);
BString _GetCurrentPath();
BString _GetCoverPath();
MediaPlayer* fMediaPlayer;
Song fCurrentSong;
BDragger* fDragger;
BBitmap* fCover;
BString fCurrentPath;
};
#endif // COVERVIEW_H

View File

@ -5,8 +5,6 @@
#include "LyricsView.h"
#include <cstdio>
#include <Dragger.h>
#include <MenuItem.h>
#include <Messenger.h>
@ -14,7 +12,7 @@
#include <ScrollView.h>
#include <Window.h>
#include "Song.h"
#include "MediaPlayer.h"
LyricsTextView::LyricsTextView(BRect frame, const char* name, BRect textFrame,
@ -93,6 +91,8 @@ LyricsView::LyricsView(BRect frame)
fFgColor = ui_color(B_PANEL_TEXT_COLOR);
fBgColor = ui_color(B_PANEL_BACKGROUND_COLOR);
fMediaPlayer = new MediaPlayer(0);
_Init(frame);
}
@ -117,6 +117,10 @@ LyricsView::LyricsView(BMessage* data)
data->FindBool("transparent_inactivity", &fTransparentInactivity);
data->FindBool("transparent_dragger", &fTransparentDragger);
BMessage mediaplayer;
data->FindMessage("mediaplayer", &mediaplayer);
fMediaPlayer = new MediaPlayer(&mediaplayer);
_Init(Frame());
}
@ -125,15 +129,19 @@ status_t
LyricsView::Archive(BMessage* data, bool deep) const
{
status_t status = BView::Archive(data, deep);
BMessage mediaPlayer;
fMediaPlayer->Archive(&mediaPlayer);
data->AddMessage("mediaplayer", &mediaPlayer);
data->AddColor("background_color", fBgColor);
data->AddColor("foreground_color", fFgColor);
data->AddBool("autoscroll", fAutoScroll);
data->AddBool("transparent_inactivity", fTransparentInactivity);
data->AddBool("transparent_dragger", fTransparentDragger);
data->AddString("class", "LyricsView");
data->AddString("add_on", "application/x-vnd.mediamonitor");
data->PrintToStream();
return status;
}
@ -178,7 +186,7 @@ LyricsView::MessageReceived(BMessage* msg)
if (msg->what == LYRICS_TRANSPARENTLY_DRAG)
fTransparentDragger = !fTransparentDragger;
if (fCurrentPath.IsEmpty())
if (fCurrentSong.InitCheck() == false)
_ClearText();
break;
}
@ -192,16 +200,20 @@ LyricsView::MessageReceived(BMessage* msg)
void
LyricsView::Pulse()
{
BString path = _GetCurrentPath();
if (path.IsEmpty() == false && path != fCurrentPath) {
fCurrentPath = path;
Song song(path.String());
Song song;
if (fMediaPlayer->CurrentItem(&song, fAutoScroll) == false) {
if (fCurrentSong.InitCheck()) {
fCurrentSong = song;
_ClearText();
}
return;
}
if (song != fCurrentSong) {
fCurrentSong = song;
BString lyrics;
song.Lyrics(&lyrics);
_SetText(lyrics.String());
} else if (path.IsEmpty() && path != fCurrentPath) {
fCurrentPath = path;
_ClearText();
}
if (fAutoScroll) {
@ -334,45 +346,12 @@ LyricsView::_RightClickPopUp()
}
BString
LyricsView::_GetCurrentPath()
{
BMessage message, reply;
message.what = B_GET_PROPERTY;
message.AddSpecifier("URI");
message.AddSpecifier("CurrentTrack");
message.AddSpecifier("Window", 0);
BMessenger("application/x-vnd.Haiku-MediaPlayer").SendMessage(&message, &reply);
BString result;
reply.FindString("result", &result);
return result.ReplaceAll("file://", "");
}
float
LyricsView::_GetPositionProportion()
{
int64 position = _GetIntProperty("Position");
int64 duration = _GetIntProperty("Duration", true);
int64 position = fMediaPlayer->Position();
int64 duration = fCurrentSong.Duration();
if (position >= 0 && duration > 0)
return (float)position / (float)duration;
return -1.0;
}
int64
LyricsView::_GetIntProperty(const char* specifier, bool currentItem)
{
BMessage message, reply;
message.what = B_GET_PROPERTY;
message.AddSpecifier(specifier);
if (currentItem)
message.AddSpecifier("CurrentTrack");
message.AddSpecifier("Window", 0);
BMessenger("application/x-vnd.Haiku-MediaPlayer").SendMessage(&message, &reply);
int64 result = -1;
reply.FindInt64("result", &result);
return result;
}

View File

@ -7,9 +7,12 @@
#include <TextView.h>
#include "Song.h"
class BDragger;
class BPopUpMenu;
class BScrollView;
class MediaPlayer;
enum {
@ -55,9 +58,10 @@ private:
BPopUpMenu* _RightClickPopUp();
BString _GetCurrentPath();
float _GetPositionProportion();
int64 _GetIntProperty(const char* specifier, bool currentTrack = false);
MediaPlayer* fMediaPlayer;
Song fCurrentSong;
LyricsTextView* fTextView;
BScrollView* fScrollView;
@ -69,7 +73,6 @@ private:
rgb_color fBgColor;
rgb_color fFgColor;
BString fCurrentPath;
};
#endif // LYRICSVIEW_H

146
src/MediaPlayer.cpp Normal file
View File

@ -0,0 +1,146 @@
/*
* Copyright 2022, Jaidyn Levesque <jadedctrl@teknik.io>
* All rights reserved. Distributed under the terms of the MIT license.
*/
#include "MediaPlayer.h"
#include <Messenger.h>
#include <Url.h>
#include "Song.h"
MediaPlayer::MediaPlayer(int32 window)
{
fWindowIndex = window;
}
MediaPlayer::MediaPlayer(BMessage* data)
:
BArchivable(data)
{
fWindowIndex = data->GetInt32("_window", 0);
}
status_t
MediaPlayer::Archive(BMessage* data, bool deep) const
{
status_t status = BArchivable::Archive(data, deep);
data->AddInt32("_window", fWindowIndex);
data->AddString("class", "MediaPlayer");
data->AddString("add_on", "application/x-vnd.mediamonitor");
return status;
}
MediaPlayer*
MediaPlayer::Instantiate(BMessage* data)
{
if (!validate_instantiation(data, "MediaPlayer"))
return NULL;
return new MediaPlayer(data);
}
bool
MediaPlayer::IsPlaying()
{
BMessage reply;
_GetResponse("IsPlaying", &reply);
return reply.GetBool("result", false);
}
int64
MediaPlayer::Position()
{
BMessage reply;
_GetResponse("Position", &reply);
return reply.GetInt64("result", -1);
}
bool
MediaPlayer::CurrentItem(Song* song, bool duration)
{
return _GetSong(song, MP_CURRENT_TRACK, duration);
}
bool
MediaPlayer::PlaylistItem(Song* song, int32 index, bool duration)
{
return _GetSong(song, index, duration);
}
int32
MediaPlayer::SetWindow(int32 index)
{
if (index < CountWindows())
return fWindowIndex = index;
else
return -1;
}
int32
MediaPlayer::CountWindows()
{
BMessage reply;
_GetResponse("Window", &reply, MP_NO_TRACK, B_COUNT_PROPERTIES);
int32 count;
if (reply.FindInt32("result", &count) == B_OK)
return count;
return -1;
}
bool
MediaPlayer::_GetSong(Song* song, int32 trackIndex, bool durationRequired)
{
BMessage reply;
_GetResponse("URI", &reply, trackIndex);
BString uriString;
if (reply.FindString("result", &uriString) != B_OK)
return false;
int64 duration = -1;
if (durationRequired) {
_GetResponse("Duration", &reply, trackIndex);
if (reply.FindInt64("result", &duration) != B_OK)
return false;
}
*song = Song(_UriToPath(uriString), duration);
return true;
}
void
MediaPlayer::_GetResponse(const char* attribute, BMessage* reply, int32 trackIndex, int32 what)
{
BMessage message;
message.what = what;
message.AddSpecifier(attribute);
if (trackIndex > 0)
message.AddSpecifier("PlaylistTrack", trackIndex);
else if (trackIndex == MP_CURRENT_TRACK)
message.AddSpecifier("CurrentTrack");
message.AddSpecifier("Window", fWindowIndex);
BMessenger("application/x-vnd.Haiku-MediaPlayer").SendMessage(&message, reply);
}
const char*
MediaPlayer::_UriToPath(BString URI)
{
if (URI.StartsWith("file://"))
return URI.ReplaceFirst("file://", "").String();
else
return NULL;
}

48
src/MediaPlayer.h Normal file
View File

@ -0,0 +1,48 @@
/*
* Copyright 2022, Jaidyn Levesque <jadedctrl@teknik.io>
* All rights reserved. Distributed under the terms of the MIT license.
*/
#ifndef MEDIAPLAYER_H
#define MEDIAPLAYER_H
#include <AppDefs.h>
#include <Archivable.h>
#include <String.h>
class BMessage;
class Song;
enum {
MP_CURRENT_TRACK = -1,
MP_NO_TRACK = -2
};
class MediaPlayer : public BArchivable {
public:
MediaPlayer(int32 window = 0);
MediaPlayer(BMessage* archive);
virtual status_t Archive(BMessage* data, bool deep = true) const;
static MediaPlayer* Instantiate(BMessage* data);
bool IsPlaying();
int64 Position();
bool CurrentItem(Song* song, bool duration = true);
bool PlaylistItem(Song* song, int32 index, bool duration = true);
int32 SetWindow(int32 index);
int32 CountWindows();
private:
bool _GetSong(Song* song, int32 trackIndex, bool durationRequired = true);
void _GetResponse(const char* attribute, BMessage* reply,
int32 trackIndex = MP_NO_TRACK, int32 what = B_GET_PROPERTY);
const char* _UriToPath(BString URI);
int32 fWindowIndex;
};
#endif // MEDIAPLAYER_H

View File

@ -13,9 +13,22 @@
#include <TranslationUtils.h>
Song::Song(const char* path)
Song::Song()
{
}
Song::Song(const char* path, int64 duration)
{
fPath = BPath(path);
fDuration = duration;
}
bool
Song::InitCheck()
{
return fPath.InitCheck() == B_OK && fDuration >= -1;
}
@ -44,6 +57,20 @@ Song::Cover()
}
BPath
Song::Path()
{
return fPath;
}
int64
Song::Duration()
{
return fDuration;
}
// Our song's leaf, sans file extension
const char*
Song::_FileLeaf()

View File

@ -11,10 +11,32 @@ class BBitmap;
class Song {
public:
Song(const char* path);
Song();
Song(const char* path, int64 duration = -1);
bool InitCheck();
status_t Lyrics(BString* buffer);
BBitmap* Cover();
BPath Path();
int64 Duration();
int operator ==(Song a)
{
if (a.Path() == fPath)
return 1;
return 0;
}
int operator !=(Song a)
{
if (a.Path() != fPath)
return 1;
return 0;
}
private:
const char* _FileLeaf();
BPath _LyricsPath();
@ -24,6 +46,7 @@ private:
BPath _AnyFileOfType(const char* mimeRoot);
BPath _FindFile(const char* mimeRoot, bool byName);
int64 fDuration;
BPath fPath;
};