From a4c1635962fb0b66734d15fc5d0634079647c8a3 Mon Sep 17 00:00:00 2001 From: Jaidyn Ann Date: Sun, 1 May 2022 13:20:18 -0500 Subject: [PATCH] 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. --- Makefile | 3 +- src/CoverView.cpp | 100 +++++++++++++++++++++++++++++++++++++++++++++ src/CoverView.h | 35 ++++++++++++++++ src/MainWindow.cpp | 2 + src/Song.cpp | 48 +++++++++++++++++++++- src/Song.h | 7 ++++ 6 files changed, 192 insertions(+), 3 deletions(-) create mode 100644 src/CoverView.cpp create mode 100644 src/CoverView.h diff --git a/Makefile b/Makefile index 9599ac1..be52b7b 100644 --- a/Makefile +++ b/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. SRCS = src/App.cpp \ src/MainWindow.cpp \ + src/CoverView.cpp \ src/LyricsView.cpp \ src/Song.cpp @@ -60,7 +61,7 @@ RSRCS = # - if your library does not follow the standard library naming scheme, # 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") -LIBS = be $(STDCPPLIBS) +LIBS = be translation $(STDCPPLIBS) # Specify additional paths to directories following the standard libXXX.so # or libXXX.a naming scheme. You can specify full paths or paths relative diff --git a/src/CoverView.cpp b/src/CoverView.cpp new file mode 100644 index 0000000..1a0547a --- /dev/null +++ b/src/CoverView.cpp @@ -0,0 +1,100 @@ +/* + * Copyright 2022, Jaidyn Levesque + * All rights reserved. Distributed under the terms of the MIT license. + */ + +#include "CoverView.h" + +#include +#include +#include + +#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://", ""); +} diff --git a/src/CoverView.h b/src/CoverView.h new file mode 100644 index 0000000..8157a05 --- /dev/null +++ b/src/CoverView.h @@ -0,0 +1,35 @@ +/* + * Copyright 2022, Jaidyn Levesque + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef COVERVIEW_H +#define COVERVIEW_H + +#include + +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 diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 09eb1e4..726cc53 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -8,6 +8,7 @@ #include #include +#include "CoverView.h" #include "LyricsView.h" @@ -27,6 +28,7 @@ MainWindow::_InitInterface() { BTabView* tabView = new BTabView("appletTabView"); 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) .Add(tabView) diff --git a/src/Song.cpp b/src/Song.cpp index f3bca69..68a824c 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -10,6 +10,7 @@ #include #include #include +#include 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 const char* Song::_FileLeaf() @@ -49,6 +57,38 @@ Song::_FileLeaf() // Search for any text-file with the same leaf of the song BPath 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()); BPath parentPath; @@ -64,10 +104,14 @@ Song::_LyricsPath() entry.GetPath(&entryPath); 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; 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; } } diff --git a/src/Song.h b/src/Song.h index 62f644a..5b34647 100644 --- a/src/Song.h +++ b/src/Song.h @@ -7,15 +7,22 @@ #include +class BBitmap; class Song { public: Song(const char* path); status_t Lyrics(BString* buffer); + BBitmap* Cover(); private: const char* _FileLeaf(); BPath _LyricsPath(); + BPath _CoverPath(); + + BPath _SimilarFileOfType(const char* mimeRoot); + BPath _AnyFileOfType(const char* mimeRoot); + BPath _FindFile(const char* mimeRoot, bool byName); BPath fPath; };