Add a "Cover" replicant (for album covers, etc)
This replicant will search for an image file related to the current playing item, and will display it. Otherwise, it's transparent.
This commit is contained in:
parent
78dec2ec7e
commit
a4c1635962
3
Makefile
3
Makefile
|
@ -33,6 +33,7 @@ APP_MIME_SIG = application/x-vnd.mediamonitor
|
||||||
# Also note that spaces in folder names do not work well with this Makefile.
|
# Also note that spaces in folder names do not work well with this Makefile.
|
||||||
SRCS = src/App.cpp \
|
SRCS = src/App.cpp \
|
||||||
src/MainWindow.cpp \
|
src/MainWindow.cpp \
|
||||||
|
src/CoverView.cpp \
|
||||||
src/LyricsView.cpp \
|
src/LyricsView.cpp \
|
||||||
src/Song.cpp
|
src/Song.cpp
|
||||||
|
|
||||||
|
@ -60,7 +61,7 @@ RSRCS =
|
||||||
# - if your library does not follow the standard library naming scheme,
|
# - if your library does not follow the standard library naming scheme,
|
||||||
# you need to specify the path to the library and it's name.
|
# you need to specify the path to the library and it's name.
|
||||||
# (e.g. for mylib.a, specify "mylib.a" or "path/mylib.a")
|
# (e.g. for mylib.a, specify "mylib.a" or "path/mylib.a")
|
||||||
LIBS = be $(STDCPPLIBS)
|
LIBS = be translation $(STDCPPLIBS)
|
||||||
|
|
||||||
# Specify additional paths to directories following the standard libXXX.so
|
# Specify additional paths to directories following the standard libXXX.so
|
||||||
# or libXXX.a naming scheme. You can specify full paths or paths relative
|
# or libXXX.a naming scheme. You can specify full paths or paths relative
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022, Jaidyn Levesque <jadedctrl@teknik.io>
|
||||||
|
* All rights reserved. Distributed under the terms of the MIT license.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CoverView.h"
|
||||||
|
|
||||||
|
#include <Bitmap.h>
|
||||||
|
#include <Dragger.h>
|
||||||
|
#include <Messenger.h>
|
||||||
|
|
||||||
|
#include "Song.h"
|
||||||
|
|
||||||
|
|
||||||
|
CoverView::CoverView(BRect frame)
|
||||||
|
:
|
||||||
|
BView(frame, "Cover", B_FOLLOW_ALL_SIDES, B_WILL_DRAW | B_TRANSPARENT_BACKGROUND | B_PULSE_NEEDED)
|
||||||
|
{
|
||||||
|
BRect dragRect(0, 0, 10, frame.Height());
|
||||||
|
fDragger = new BDragger(dragRect, this,
|
||||||
|
B_FOLLOW_LEFT | B_FOLLOW_BOTTOM, B_WILL_DRAW);
|
||||||
|
fDragger->SetViewColor(B_TRANSPARENT_COLOR);
|
||||||
|
AddChild(fDragger);
|
||||||
|
|
||||||
|
fCover = NULL;
|
||||||
|
SetViewColor(B_TRANSPARENT_COLOR);
|
||||||
|
Pulse();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CoverView::CoverView(BMessage* data)
|
||||||
|
:
|
||||||
|
BView(data)
|
||||||
|
{
|
||||||
|
fCover = NULL;
|
||||||
|
SetViewColor(B_TRANSPARENT_COLOR);
|
||||||
|
Pulse();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
CoverView::Archive(BMessage* data, bool deep) const
|
||||||
|
{
|
||||||
|
status_t status = BView::Archive(data, deep);
|
||||||
|
data->AddString("class", "CoverView");
|
||||||
|
data->AddString("add_on", "application/x-vnd.mediamonitor");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CoverView*
|
||||||
|
CoverView::Instantiate(BMessage* data)
|
||||||
|
{
|
||||||
|
if (!validate_instantiation(data, "CoverView"))
|
||||||
|
return NULL;
|
||||||
|
return new CoverView(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CoverView::Pulse()
|
||||||
|
{
|
||||||
|
BString path = _GetCurrentPath();
|
||||||
|
if (path.IsEmpty() == false && path != fCurrentPath) {
|
||||||
|
fCurrentPath = path;
|
||||||
|
Song song(path.String());
|
||||||
|
delete fCover;
|
||||||
|
fCover = song.Cover();
|
||||||
|
Invalidate();
|
||||||
|
} else if (path.IsEmpty() == true && path != fCurrentPath) {
|
||||||
|
fCurrentPath = path;
|
||||||
|
delete fCover;
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CoverView::Draw(BRect updateRect)
|
||||||
|
{
|
||||||
|
BView::Draw(updateRect);
|
||||||
|
|
||||||
|
if (fCover != NULL)
|
||||||
|
DrawBitmap(fCover, Bounds());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BString
|
||||||
|
CoverView::_GetCurrentPath()
|
||||||
|
{
|
||||||
|
BMessage message, reply;
|
||||||
|
message.what = B_GET_PROPERTY;
|
||||||
|
message.AddSpecifier("URI");
|
||||||
|
message.AddSpecifier("Window", 0);
|
||||||
|
BMessenger("application/x-vnd.Haiku-MediaPlayer").SendMessage(&message, &reply);
|
||||||
|
|
||||||
|
BString result;
|
||||||
|
reply.FindString("result", &result);
|
||||||
|
return result.ReplaceAll("file://", "");
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022, Jaidyn Levesque <jadedctrl@teknik.io>
|
||||||
|
* All rights reserved. Distributed under the terms of the MIT license.
|
||||||
|
*/
|
||||||
|
#ifndef COVERVIEW_H
|
||||||
|
#define COVERVIEW_H
|
||||||
|
|
||||||
|
#include <View.h>
|
||||||
|
|
||||||
|
class BDragger;
|
||||||
|
|
||||||
|
|
||||||
|
class CoverView : public BView {
|
||||||
|
public:
|
||||||
|
CoverView(BRect frame);
|
||||||
|
CoverView(BMessage* archive);
|
||||||
|
|
||||||
|
virtual status_t Archive(BMessage* data, bool deep = true) const;
|
||||||
|
static CoverView* Instantiate(BMessage* data);
|
||||||
|
|
||||||
|
virtual void Pulse();
|
||||||
|
|
||||||
|
virtual void Draw(BRect updateRect);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _Init(BRect frame);
|
||||||
|
BString _GetCurrentPath();
|
||||||
|
BString _GetCoverPath();
|
||||||
|
|
||||||
|
BDragger* fDragger;
|
||||||
|
BBitmap* fCover;
|
||||||
|
BString fCurrentPath;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // COVERVIEW_H
|
|
@ -8,6 +8,7 @@
|
||||||
#include <LayoutBuilder.h>
|
#include <LayoutBuilder.h>
|
||||||
#include <TabView.h>
|
#include <TabView.h>
|
||||||
|
|
||||||
|
#include "CoverView.h"
|
||||||
#include "LyricsView.h"
|
#include "LyricsView.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,6 +28,7 @@ MainWindow::_InitInterface()
|
||||||
{
|
{
|
||||||
BTabView* tabView = new BTabView("appletTabView");
|
BTabView* tabView = new BTabView("appletTabView");
|
||||||
tabView->AddTab(new LyricsView(BRect(BPoint(0,0), BSize(300.0, 200.0))));
|
tabView->AddTab(new LyricsView(BRect(BPoint(0,0), BSize(300.0, 200.0))));
|
||||||
|
tabView->AddTab(new CoverView(BRect(BPoint(0,0), BSize(300.0, 200.0))));
|
||||||
|
|
||||||
BLayoutBuilder::Group<>(this, B_VERTICAL, 0.0f)
|
BLayoutBuilder::Group<>(this, B_VERTICAL, 0.0f)
|
||||||
.Add(tabView)
|
.Add(tabView)
|
||||||
|
|
48
src/Song.cpp
48
src/Song.cpp
|
@ -10,6 +10,7 @@
|
||||||
#include <Directory.h>
|
#include <Directory.h>
|
||||||
#include <File.h>
|
#include <File.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
#include <TranslationUtils.h>
|
||||||
|
|
||||||
|
|
||||||
Song::Song(const char* path)
|
Song::Song(const char* path)
|
||||||
|
@ -36,6 +37,13 @@ Song::Lyrics(BString* buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BBitmap*
|
||||||
|
Song::Cover()
|
||||||
|
{
|
||||||
|
return BTranslationUtils::GetBitmapFile(_CoverPath().Path());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Our song's leaf, sans file extension
|
// Our song's leaf, sans file extension
|
||||||
const char*
|
const char*
|
||||||
Song::_FileLeaf()
|
Song::_FileLeaf()
|
||||||
|
@ -49,6 +57,38 @@ Song::_FileLeaf()
|
||||||
// Search for any text-file with the same leaf of the song
|
// Search for any text-file with the same leaf of the song
|
||||||
BPath
|
BPath
|
||||||
Song::_LyricsPath()
|
Song::_LyricsPath()
|
||||||
|
{
|
||||||
|
return _SimilarFileOfType("text/");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Search for any image-file in the same directory
|
||||||
|
BPath
|
||||||
|
Song::_CoverPath()
|
||||||
|
{
|
||||||
|
BPath path = _SimilarFileOfType("image/");
|
||||||
|
if (path.InitCheck() != B_OK)
|
||||||
|
path = _AnyFileOfType("image/");
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BPath
|
||||||
|
Song::_SimilarFileOfType(const char* mimeRoot)
|
||||||
|
{
|
||||||
|
return _FindFile(mimeRoot, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BPath
|
||||||
|
Song::_AnyFileOfType(const char* mimeRoot)
|
||||||
|
{
|
||||||
|
return _FindFile(mimeRoot, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BPath
|
||||||
|
Song::_FindFile(const char* mimeRoot, bool byName)
|
||||||
{
|
{
|
||||||
BString leaf(_FileLeaf());
|
BString leaf(_FileLeaf());
|
||||||
BPath parentPath;
|
BPath parentPath;
|
||||||
|
@ -64,10 +104,14 @@ Song::_LyricsPath()
|
||||||
entry.GetPath(&entryPath);
|
entry.GetPath(&entryPath);
|
||||||
BString entryLeaf(entryPath.Leaf());
|
BString entryLeaf(entryPath.Leaf());
|
||||||
|
|
||||||
if (entryLeaf != leaf && entryLeaf.FindFirst(leaf) >= 0) {
|
bool nameAgrees = (entryLeaf != leaf && entryLeaf.FindFirst(leaf) >= 0);
|
||||||
|
|
||||||
|
if (byName == false || nameAgrees == true) {
|
||||||
BString mimeType;
|
BString mimeType;
|
||||||
node.SetTo(&entry);
|
node.SetTo(&entry);
|
||||||
if (node.ReadAttrString("BEOS:TYPE", &mimeType) == B_OK && mimeType.StartsWith("text/"))
|
if (mimeRoot == NULL ||
|
||||||
|
(node.ReadAttrString("BEOS:TYPE", &mimeType) == B_OK
|
||||||
|
&& mimeType.StartsWith(mimeRoot)))
|
||||||
return entryPath;
|
return entryPath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,15 +7,22 @@
|
||||||
|
|
||||||
#include <Path.h>
|
#include <Path.h>
|
||||||
|
|
||||||
|
class BBitmap;
|
||||||
|
|
||||||
class Song {
|
class Song {
|
||||||
public:
|
public:
|
||||||
Song(const char* path);
|
Song(const char* path);
|
||||||
status_t Lyrics(BString* buffer);
|
status_t Lyrics(BString* buffer);
|
||||||
|
BBitmap* Cover();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char* _FileLeaf();
|
const char* _FileLeaf();
|
||||||
BPath _LyricsPath();
|
BPath _LyricsPath();
|
||||||
|
BPath _CoverPath();
|
||||||
|
|
||||||
|
BPath _SimilarFileOfType(const char* mimeRoot);
|
||||||
|
BPath _AnyFileOfType(const char* mimeRoot);
|
||||||
|
BPath _FindFile(const char* mimeRoot, bool byName);
|
||||||
|
|
||||||
BPath fPath;
|
BPath fPath;
|
||||||
};
|
};
|
||||||
|
|
Ŝarĝante…
Reference in New Issue