commit 810f57dd7fafd4d7a2cfb2fbdf1b45369a9a80c6 Author: Jaidyn Ann Date: Fri Apr 15 16:20:37 2022 -0500 Init diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9599ac1 --- /dev/null +++ b/Makefile @@ -0,0 +1,134 @@ +## Haiku Generic Makefile v2.6 ## + +## Fill in this file to specify the project being created, and the referenced +## Makefile-Engine will do all of the hard work for you. This handles any +## architecture of Haiku. +## +## For more information, see: +## file:///system/develop/documentation/makefile-engine.html + +# The name of the binary. +NAME = MediaMonitor + +# The type of binary, must be one of: +# APP: Application +# SHARED: Shared library or add-on +# STATIC: Static library archive +# DRIVER: Kernel driver +TYPE = APP + +# If you plan to use localization, specify the application's MIME signature. +APP_MIME_SIG = application/x-vnd.mediamonitor + +# The following lines tell Pe and Eddie where the SRCS, RDEFS, and RSRCS are +# so that Pe and Eddie can fill them in for you. +#%{ +# @src->@ + +# Specify the source files to use. Full paths or paths relative to the +# Makefile can be included. All files, regardless of directory, will have +# their object files created in the common object directory. Note that this +# means this Makefile will not work correctly if two source files with the +# 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/LyricsView.cpp \ + src/Song.cpp + +# Specify the resource definition files to use. Full or relative paths can be +# used. +RDEFS = src/MediaMonitor.rdef + +# Specify the resource files to use. Full or relative paths can be used. +# Both RDEFS and RSRCS can be utilized in the same Makefile. +RSRCS = + +# End Pe/Eddie support. +# @<-src@ +#%} + +# Specify libraries to link against. +# There are two acceptable forms of library specifications: +# - if your library follows the naming pattern of libXXX.so or libXXX.a, +# you can simply specify XXX for the library. (e.g. the entry for +# "libtracker.so" would be "tracker") +# +# - for GCC-independent linking of standard C++ libraries, you can use +# $(STDCPPLIBS) instead of the raw "stdc++[.r4] [supc++]" library names. +# +# - 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) + +# Specify additional paths to directories following the standard libXXX.so +# or libXXX.a naming scheme. You can specify full paths or paths relative +# to the Makefile. The paths included are not parsed recursively, so +# include all of the paths where libraries must be found. Directories where +# source files were specified are automatically included. +LIBPATHS = + +# Additional paths to look for system headers. These use the form +# "#include
". Directories that contain the files in SRCS are +# NOT auto-included here. +SYSTEM_INCLUDE_PATHS = + +# Additional paths paths to look for local headers. These use the form +# #include "header". Directories that contain the files in SRCS are +# automatically included. +LOCAL_INCLUDE_PATHS = + +# Specify the level of optimization that you want. Specify either NONE (O0), +# SOME (O1), FULL (O3), or leave blank (for the default optimization level). +OPTIMIZE := + +# Specify the codes for languages you are going to support in this +# application. The default "en" one must be provided too. "make catkeys" +# will recreate only the "locales/en.catkeys" file. Use it as a template +# for creating catkeys for other languages. All localization files must be +# placed in the "locales" subdirectory. +LOCALES = + +# Specify all the preprocessor symbols to be defined. The symbols will not +# have their values set automatically; you must supply the value (if any) to +# use. For example, setting DEFINES to "DEBUG=1" will cause the compiler +# option "-DDEBUG=1" to be used. Setting DEFINES to "DEBUG" would pass +# "-DDEBUG" on the compiler's command line. +DEFINES = + +# Specify the warning level. Either NONE (suppress all warnings), +# ALL (enable all warnings), or leave blank (enable default warnings). +WARNINGS = + +# With image symbols, stack crawls in the debugger are meaningful. +# If set to "TRUE", symbols will be created. +SYMBOLS := + +# Includes debug information, which allows the binary to be debugged easily. +# If set to "TRUE", debug info will be created. +DEBUGGER := + +# Specify any additional compiler flags to be used. +COMPILER_FLAGS = + +# Specify any additional linker flags to be used. +LINKER_FLAGS = + +# Specify the version of this binary. Example: +# -app 3 4 0 d 0 -short 340 -long "340 "`echo -n -e '\302\251'`"1999 GNU GPL" +# This may also be specified in a resource. +APP_VERSION := + +# (Only used when "TYPE" is "DRIVER"). Specify the desired driver install +# location in the /dev hierarchy. Example: +# DRIVER_PATH = video/usb +# will instruct the "driverinstall" rule to place a symlink to your driver's +# binary in ~/add-ons/kernel/drivers/dev/video/usb, so that your driver will +# appear at /dev/video/usb when loaded. The default is "misc". +DRIVER_PATH = + +## Include the Makefile-Engine +DEVEL_DIRECTORY := \ + $(shell findpaths -r "makefile_engine" B_FIND_PATH_DEVELOP_DIRECTORY) +include $(DEVEL_DIRECTORY)/etc/makefile-engine diff --git a/src/App.cpp b/src/App.cpp new file mode 100644 index 0000000..18630cd --- /dev/null +++ b/src/App.cpp @@ -0,0 +1,44 @@ +/* + * Copyright 2022, Jaidyn Levesque + * All rights reserved. Distributed under the terms of the MIT license. + */ + +#include "App.h" + +#include + +#include "MainWindow.h" + + +BString +get_string_mediaplayer(const char* attribute) +{ + BMessage message, reply; + message.what = B_GET_PROPERTY; + message.AddSpecifier(attribute); + message.AddSpecifier("Window", 0); + BMessenger("application/x-vnd.Haiku-MediaPlayer").SendMessage(&message, &reply); + + BString result; + reply.FindString("result", &result); + return result; +} + + +App::App() + : + BApplication("application/x-vnd.mediamonitor") +{ + MainWindow* win = new MainWindow(); + win->SetPulseRate(5000000); + win->Show(); +} + + +int +main(int argc, char** argv) +{ + App app; + app.Run(); + return 0; +} diff --git a/src/App.h b/src/App.h new file mode 100644 index 0000000..ace219d --- /dev/null +++ b/src/App.h @@ -0,0 +1,20 @@ +/* + * Copyright 2022, Jaidyn Levesque + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef _APP_H +#define _APP_H + +#include + + +class App: public BApplication +{ +public: + App(); +}; + + +int main(int argc, char** argv); + +#endif // _APP_H diff --git a/src/LyricsView.cpp b/src/LyricsView.cpp new file mode 100644 index 0000000..55c5a72 --- /dev/null +++ b/src/LyricsView.cpp @@ -0,0 +1,179 @@ +/* + * Copyright 2022, Jaidyn Levesque + * All rights reserved. Distributed under the terms of the MIT license. + */ + +#include "LyricsView.h" + +#include + +#include +#include +#include + +#include "Song.h" + + +LyricsView::LyricsView(BRect frame) + : + BView(frame, "Lyrics", B_FOLLOW_ALL_SIDES, B_WILL_DRAW | B_TRANSPARENT_BACKGROUND | B_PULSE_NEEDED) +{ + fFgColor = ui_color(B_PANEL_TEXT_COLOR); + fBgColor = ui_color(B_PANEL_BACKGROUND_COLOR); + + BDragger* airdrag = new BDragger(frame, this, + B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM, B_WILL_DRAW); + AddChild(airdrag); + + fTextView = new BTextView(Bounds(), "lyricsText", Bounds(), + B_FOLLOW_ALL, B_WILL_DRAW); + fTextView->MakeEditable(false); + fTextView->SetStylable(false); + AddChild(fTextView); + + _Init(frame); +} + + +LyricsView::LyricsView(BMessage* data) + : + BView(data) +{ + fFgColor = ui_color(B_PANEL_TEXT_COLOR); + fBgColor = ui_color(B_PANEL_BACKGROUND_COLOR); + + fTextView = dynamic_cast(FindView("lyricsText")); + data->FindColor("background_color", &fBgColor); + data->FindColor("foreground_color", &fFgColor); + + _Init(Frame()); +} + + +status_t +LyricsView::Archive(BMessage* data, bool deep) const +{ + status_t status = BView::Archive(data, deep); + data->AddColor("background_color", fBgColor); + data->AddColor("foreground_color", fFgColor); + + data->AddString("class", "LyricsView"); + data->AddString("add_on", "application/x-vnd.mediamonitor"); + return status; +} + + +LyricsView* +LyricsView::Instantiate(BMessage* data) +{ + if (!validate_instantiation(data, "LyricsView")) + return NULL; + return new LyricsView(data); +} + + +void +LyricsView::MessageReceived(BMessage* msg) +{ + switch (msg->what) + { + case B_PASTE: { + ssize_t size; + int32 buttons = 0; + rgb_color* recv_color; + status_t found_color = msg->FindData("RGBColor", B_RGB_COLOR_TYPE, + (const void**)&recv_color, &size); + + if (found_color == B_OK && msg->FindInt32("buttons", &buttons) == B_OK) + if (buttons & B_PRIMARY_MOUSE_BUTTON) + fBgColor = *recv_color; + else if (buttons & B_SECONDARY_MOUSE_BUTTON) { + printf("MOM\n"); + fFgColor = *recv_color; + } + + _UpdateColors(); + break; + } + } + BView::MessageReceived(msg); +} + + +void +LyricsView::Pulse() +{ + BString path = _GetCurrentPath(); + if (path.IsEmpty() == false && path != fCurrentPath) { + fCurrentPath = path; + Song song(path.String()); + BString lyrics; + song.Lyrics(&lyrics); + _SetText(lyrics.String()); + } else if (path.IsEmpty() == true && path != fCurrentPath) { + fCurrentPath = path; + _SetText(NULL); + } +} + + +void +LyricsView::_Init(BRect frame) +{ + _SetText(NULL); + _UpdateColors(); + Pulse(); +} + + +void +LyricsView::_SetText(const char* text) +{ + if (text != NULL) { + if (fTextView->IsHidden() == true) + fTextView->Show(); + fTextView->SetText(text); + printf("NOT NULL\n"); + } else if (text == NULL) { + if (fTextView->IsHidden() == false) + fTextView->Hide(); + fTextView->SetText(""); + printf("NULL\n"); + } +} + + +void +LyricsView::_UpdateColors() +{ + SetViewColor(B_TRANSPARENT_COLOR); + fTextView->SetViewColor(fBgColor); + + text_run run; + run.color = fFgColor; + run.font = be_plain_font; + run.offset = 0; + + text_run_array run_array; + run_array.count = 1; + run_array.runs[0] = run; + fTextView->SetRunArray(0, fTextView->TextLength(), &run_array); + + Invalidate(); + fTextView->Invalidate(); +} + + +BString +LyricsView::_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/LyricsView.h b/src/LyricsView.h new file mode 100644 index 0000000..f00d3a3 --- /dev/null +++ b/src/LyricsView.h @@ -0,0 +1,38 @@ +/* + * Copyright 2022, Jaidyn Levesque + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef LYRICSVIEW_H +#define LYRICSVIEW_H + +#include + +class BTextView; + + +class LyricsView : public BView { +public: + LyricsView(BRect frame); + LyricsView(BMessage* archive); + + virtual status_t Archive(BMessage* data, bool deep = true) const; + static LyricsView* Instantiate(BMessage* data); + + virtual void MessageReceived(BMessage* msg); + + virtual void Pulse(); + +private: + void _Init(BRect frame); + void _SetText(const char* text); + void _UpdateColors(); + + BString _GetCurrentPath(); + + BTextView* fTextView; + rgb_color fBgColor; + rgb_color fFgColor; + BString fCurrentPath; +}; + +#endif // LYRICSVIEW_H diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp new file mode 100644 index 0000000..72c9748 --- /dev/null +++ b/src/MainWindow.cpp @@ -0,0 +1,33 @@ +/* + * Copyright 2022, Jaidyn Levesque + * All rights reserved. Distributed under the terms of the MIT license. + */ + +#include "MainWindow.h" + +#include +#include + +#include "LyricsView.h" + + +MainWindow::MainWindow() + : + BWindow(BRect(BPoint(0,0),BSize(500.0, 500.0)), "MediaMonitor", + B_TITLED_WINDOW, B_AUTO_UPDATE_SIZE_LIMITS) +{ + SetPulseRate(0); + _InitInterface(); +} + + +void +MainWindow::_InitInterface() +{ + BTabView* tabView = new BTabView("appletTabView"); + tabView->AddTab(new LyricsView(BRect(BPoint(0,0), BSize(300.0, 200.0)))); + + BLayoutBuilder::Group<>(this, B_VERTICAL, 0.0f) + .Add(tabView) + .End(); +} diff --git a/src/MainWindow.h b/src/MainWindow.h new file mode 100644 index 0000000..4e29cc2 --- /dev/null +++ b/src/MainWindow.h @@ -0,0 +1,19 @@ +/* + * Copyright 2022, Jaidyn Levesque + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include + + +class MainWindow : public BWindow { +public: + MainWindow(); + +private: + void _InitInterface(); +}; + +#endif // MAINWINDOW_H diff --git a/src/MediaMonitor.rdef b/src/MediaMonitor.rdef new file mode 100644 index 0000000..88b9e7d --- /dev/null +++ b/src/MediaMonitor.rdef @@ -0,0 +1,13 @@ +resource app_signature "application/x-vnd.mediamonitor"; + +resource app_version { + major = 1, + middle = 2, + minor = 0, + + variety = B_APPV_FINAL, + internal = 0, + + short_info = "Pin notes to your Desktop", + long_info = "Sticky notes as replicants on your Desktop" +}; diff --git a/src/Song.cpp b/src/Song.cpp new file mode 100644 index 0000000..f3bca69 --- /dev/null +++ b/src/Song.cpp @@ -0,0 +1,75 @@ +/* + * Copyright 2022, Jaidyn Levesque + * All rights reserved. Distributed under the terms of the MIT license. + */ + +#include "Song.h" + +#include + +#include +#include +#include + + +Song::Song(const char* path) +{ + fPath = BPath(path); +} + + +status_t +Song::Lyrics(BString* buffer) +{ + BFile file(_LyricsPath().Path(), B_READ_ONLY); + + off_t size = 0; + char* buf = NULL; + if (file.InitCheck() == B_OK && file.GetSize(&size) == B_OK) { + buf = (char*)malloc((size_t)size); + file.Read(buf, size); + *buffer << buf; + free(buf); + } else + *buffer = "No lyrics available.\n"; + return B_OK; +} + + +// Our song's leaf, sans file extension +const char* +Song::_FileLeaf() +{ + BString leaf(fPath.Leaf()); + leaf.TruncateChars(leaf.FindLast('.')); + return leaf.String(); +} + + +// Search for any text-file with the same leaf of the song +BPath +Song::_LyricsPath() +{ + BString leaf(_FileLeaf()); + BPath parentPath; + if (fPath.GetParent(&parentPath) != B_OK) + return BPath(); + + BNode node; + BEntry entry; + BPath entryPath; + BDirectory parentDir(parentPath.Path()); + + while (parentDir.GetNextEntry(&entry) == B_OK) { + entry.GetPath(&entryPath); + BString entryLeaf(entryPath.Leaf()); + + if (entryLeaf != leaf && entryLeaf.FindFirst(leaf) >= 0) { + BString mimeType; + node.SetTo(&entry); + if (node.ReadAttrString("BEOS:TYPE", &mimeType) == B_OK && mimeType.StartsWith("text/")) + return entryPath; + } + } + return BPath(); +} diff --git a/src/Song.h b/src/Song.h new file mode 100644 index 0000000..62f644a --- /dev/null +++ b/src/Song.h @@ -0,0 +1,23 @@ +/* + * Copyright 2022, Jaidyn Levesque + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef SONG_H +#define SONG_H + +#include + + +class Song { +public: + Song(const char* path); + status_t Lyrics(BString* buffer); + +private: + const char* _FileLeaf(); + BPath _LyricsPath(); + + BPath fPath; +}; + +#endif // SONG_H