Abstract scripting calls into 'MediaPlayer' class
This commit is contained in:
parent
6a7ed4b302
commit
ff84f929ae
3
Makefile
3
Makefile
|
@ -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
|
||||
|
|
|
@ -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://", "");
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
29
src/Song.cpp
29
src/Song.cpp
|
@ -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()
|
||||
|
|
25
src/Song.h
25
src/Song.h
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
Ŝarĝante…
Reference in New Issue