diff --git a/.gitignore b/.gitignore index ca2c45072..031d9ad29 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,27 @@ _codeql_detected_source_root /build*/ !/build_tools/ !/build_tools/** + +# macOS noise +.DS_Store +/bin +/CMakeLists.txt.user +/.qtcreator +/.kdev4 +/strawberry.kdev4 +/.vscode +/.code-workspace +/.sublime-workspace +/.idea +/.vs +/out +/CMakeSettings.json +/dist/scripts/maketarball.sh +/debian/changelog +_codeql_detected_source_root + +# Build output (keep build tooling scripts in /build_tools/ tracked) +/cmake-build*/ +/build*/ +!/build_tools/ +!/build_tools/** diff --git a/Changelog b/Changelog index dd2c1ed1b..68ada1d2f 100644 --- a/Changelog +++ b/Changelog @@ -343,7 +343,7 @@ Version 1.1.0 (2024.07.14): * Only use playbin3 with GStreamer 1.24 and higher, not with GStreamer 1.22 or lower. * (macOS/Windows) Fixed dash and hls streaming, plugins were missing. * (Windows) Fixed incorrect colors in smart playlist wizard with Fusion in dark mode (#1399). - * (Windows) Fixed update window blocking sponsor window on startup. + * (Windows) Fixed update window blocking startup window on launch. Enhancements: * Improve error messages when connecting and copying to devices. diff --git a/README.md b/README.md index 20cbec3dc..50fd092bc 100644 --- a/README.md +++ b/README.md @@ -1,60 +1,49 @@ -# :strawberry: Strawberry Music Player [![Build Status](https://github.com/strawberrymusicplayer/strawberry/workflows/Build/badge.svg)](https://github.com/strawberrymusicplayer/strawberry/actions) -[![Sponsor](https://img.shields.io/badge/-Sponsor-green?logo=github)](https://github.com/sponsors/jonaski) -[![Patreon](https://img.shields.io/badge/patreon-donate-green.svg)](https://patreon.com/jonaskvinge) -[![PayPal](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://paypal.me/jonaskvinge) +# Strawberry (macOS-focused fork) -Strawberry is a **music player and music collection organizer**, originally forked from *Clementine* in 2018. -It’s written in **C++ using the Qt framework**, designed for **audiophiles and music collectors**. +This repository is a **macOS-focused fork** of the upstream Strawberry Music Player project originally created and maintained by **Jonas Kvinge** (itself originally forked from Clementine). -![Screenshot of Strawberry Music Player](https://raw.githubusercontent.com/strawberrymusicplayer/strawberry/master/data/screenshot/screenshot.png) +The goal of this fork is to make Strawberry **build cleanly and repeatably on macOS**, with: ---- +- Homebrew dependency installation via `Brewfile` +- local Homebrew formulas (tap) for missing dependencies +- build / deploy / signing / notarization helper scripts under `build_tools/` +- Sparkle feed configuration knobs so you can publish your own updates -## :globe_with_meridians: Resources +## Upstream vs this fork (macOS distribution) -- **Website:** https://www.strawberrymusicplayer.org -- **Wiki:** https://wiki.strawberrymusicplayer.org -- **Forum:** https://forum.strawberrymusicplayer.org -- **GitHub:** https://github.com/strawberrymusicplayer/strawberry -- **Latest builds:** https://builds.strawberrymusicplayer.org -- **openSUSE Build Service:** - - Stable: https://build.opensuse.org/package/show/home:jonaski:strawberry/strawberry - - Unstable: https://build.opensuse.org/package/show/home:jonaski:strawberry-dev/strawberry -- **Ubuntu PPAs:** - - Stable: https://launchpad.net/~jonaski/+archive/ubuntu/strawberry - - Unstable: https://launchpad.net/~jonaski/+archive/ubuntu/strawberry-unstable -- **Translations:** https://crowdin.com/project/strawberrymusicplayer +Upstream Strawberry is free/open-source, but upstream’s **macOS binaries** may be distributed via a **paid-access channel** depending on the release period and policy. ---- +This fork is intended for people who want to: -## :warning: Opening an Issue +- **build from source on macOS** without guesswork +- **produce signed + notarized binaries** themselves (and optionally distribute them) -Before creating a new GitHub issue: +General safety note: whether you use upstream builds, your own builds, or someone else’s, only install software from sources you trust and prefer **signed + notarized** releases. -1. **Read the [FAQ](https://wiki.strawberrymusicplayer.org/wiki/FAQ)**. -2. **Search existing issues** to avoid duplicates. If one already exists, comment there with any additional information. -3. **Use the [forum](https://forum.strawberrymusicplayer.org/)** for technical problems, discussions or feature suggestions — it’s better suited for back-and-forth conversation. -4. **Feature requests are not accepted on GitHub.** Issues created for feature requests will be closed. You can still discuss ideas on the forum. -5. **Flatpak users:** We do **not** maintain the Flatpak package. Report Flatpak-specific issues via [Flatpak support](https://flatpak.org/about/). +## Quick start (macOS) ---- +Install Homebrew dependencies: -## :moneybag: Sponsoring +```bash +./build_tools/macos/install_brew_deps.sh +``` -Strawberry is **free software released under the GPL**. -If you enjoy using it, please consider **supporting development** through sponsorship or donation. +Build: -**Sponsorship options:** -1. [Patreon](https://www.patreon.com/jonaskvinge) -2. [GitHub](https://github.com/sponsors/jonaski) -3. [Ko-fi](https://ko-fi.com/jonaskvinge) -4. [PayPal](https://paypal.me/jonaskvinge) +```bash +./build_tools/macos/build_app.sh --release --clean +open ./cmake-build-macos-release/strawberry.app +``` -Supporting open-source developers helps ensure continued maintenance and improvements. +Build + deploy + sign + notarize (+ DMG): ---- +```bash +./build_tools/macos/build_sign_notarize.sh --run --release --clean --deploy --dmg \ + --identity "Developer ID Application: Your Name (TEAMID)" \ + --notary-profile "" +``` -## :white_check_mark: Features +## Features - Play and organize your music collection - Supports formats: WAV, FLAC, WavPack, Ogg Vorbis, Opus, MPC, TrueAudio, AIFF, MP4, MP3, ASF, and Monkey’s Audio @@ -78,11 +67,6 @@ Supporting open-source developers helps ensure continued maintenance and improve :white_check_mark: Tested on **Linux**, **OpenBSD**, **FreeBSD**, **macOS**, and **Windows**. -> **Note:** macOS and Windows releases are currently **available to sponsors only**. -> A monthly sponsorship via [Patreon](https://www.patreon.com/jonaskvinge) grants direct access to new releases. - ---- - ## :gear: Requirements To build Strawberry from source, you’ll need: diff --git a/src/core/mainwindow.cpp b/src/core/mainwindow.cpp index 455d114d3..c06c0c56b 100644 --- a/src/core/mainwindow.cpp +++ b/src/core/mainwindow.cpp @@ -1142,18 +1142,7 @@ MainWindow::MainWindow(Application *app, asked_permission = s.value("asked_permission", false).toBool(); s.endGroup(); #endif - if (asked_permission) { - s.beginGroup(MainWindowSettings::kSettingsGroup); - const bool do_not_show_sponsor_message = s.value(MainWindowSettings::kDoNotShowSponsorMessage, false).toBool(); - s.endGroup(); - if (!do_not_show_sponsor_message) { - MessageDialog *sponsor_message = new MessageDialog(this); - sponsor_message->set_settings_group(QLatin1String(MainWindowSettings::kSettingsGroup)); - sponsor_message->set_do_not_show_message_again(QLatin1String(MainWindowSettings::kDoNotShowSponsorMessage)); - sponsor_message->setAttribute(Qt::WA_DeleteOnClose); - sponsor_message->ShowMessage(tr("Sponsoring Strawberry"), tr("Strawberry is free and open source software. If you like Strawberry, please consider sponsoring the project. For more information about sponsorship see our website %1").arg(u"www.strawberrymusicplayer.org"_s), IconLoader::Load(u"dialog-information"_s)); - } - } + Q_UNUSED(asked_permission) } qLog(Debug) << "Started" << QThread::currentThread(); diff --git a/src/dialogs/about.cpp b/src/dialogs/about.cpp index 419f18041..143624a31 100644 --- a/src/dialogs/about.cpp +++ b/src/dialogs/about.cpp @@ -124,17 +124,6 @@ QString About::MainHtml() const { ret += tr("You should have received a copy of the GNU General Public License along with this program. If not, see %1").arg(QStringLiteral("http://www.gnu.org/licenses/").arg(palette().text().color().name())); ret += "

"_L1; - ret += "

"_L1; - ret += tr("If you like Strawberry and can make use of it, consider sponsoring or donating."); - ret += "
"_L1; - ret += tr("You can sponsor the author on %1 or %2. You can also make a one-time payment through %3.").arg( - QStringLiteral("Patreon").arg(palette().text().color().name()), - QStringLiteral("GitHub").arg(palette().text().color().name()), - QStringLiteral("paypal.me/jonaskvinge").arg(palette().text().color().name()) - ); - - ret += "

"_L1; - return ret; } diff --git a/src/radios/radiomodel.cpp b/src/radios/radiomodel.cpp index 4d7ce9371..ca64c0cfa 100644 --- a/src/radios/radiomodel.cpp +++ b/src/radios/radiomodel.cpp @@ -113,11 +113,6 @@ QVariant RadioModel::data(const RadioItem *item, int role) const { if (service) return service->Homepage(); break; } - case Role_Donate:{ - RadioService *service = radio_services_->ServiceBySource(item->source); - if (service) return service->Donate(); - break; - } default: return QVariant(); } diff --git a/src/radios/radiomodel.h b/src/radios/radiomodel.h index 68b4ec52f..d1c623991 100644 --- a/src/radios/radiomodel.h +++ b/src/radios/radiomodel.h @@ -56,7 +56,6 @@ class RadioModel : public SimpleTreeModel { Role_Source, Role_Url, Role_Homepage, - Role_Donate, RoleCount }; diff --git a/src/radios/radioparadiseservice.cpp b/src/radios/radioparadiseservice.cpp index 8ba558a1b..bc5783b14 100644 --- a/src/radios/radioparadiseservice.cpp +++ b/src/radios/radioparadiseservice.cpp @@ -41,7 +41,6 @@ RadioParadiseService::RadioParadiseService(const SharedPtr task_man : RadioService(Song::Source::RadioParadise, u"Radio Paradise"_s, IconLoader::Load(u"radioparadise"_s), task_manager, network, parent) {} QUrl RadioParadiseService::Homepage() { return QUrl(u"https://radioparadise.com/"_s); } -QUrl RadioParadiseService::Donate() { return QUrl(u"https://payments.radioparadise.com/rp2s-content.php?name=Support&file=support"_s); } void RadioParadiseService::Abort() { diff --git a/src/radios/radioparadiseservice.h b/src/radios/radioparadiseservice.h index b411011a8..d55490296 100644 --- a/src/radios/radioparadiseservice.h +++ b/src/radios/radioparadiseservice.h @@ -37,7 +37,6 @@ class RadioParadiseService : public RadioService { explicit RadioParadiseService(const SharedPtr task_manager, const SharedPtr network, QObject *parent = nullptr); QUrl Homepage() override; - QUrl Donate() override; void Abort(); diff --git a/src/radios/radioservice.h b/src/radios/radioservice.h index 34eba9d85..6b2f81546 100644 --- a/src/radios/radioservice.h +++ b/src/radios/radioservice.h @@ -56,7 +56,6 @@ class RadioService : public QObject { virtual void ReloadSettings() {} virtual QUrl Homepage() = 0; - virtual QUrl Donate() = 0; Q_SIGNALS: void NewChannels(const RadioChannelList &channels = RadioChannelList()); diff --git a/src/radios/radioview.cpp b/src/radios/radioview.cpp index aaa0285ec..e94c9300e 100644 --- a/src/radios/radioview.cpp +++ b/src/radios/radioview.cpp @@ -44,7 +44,6 @@ RadioView::RadioView(QWidget *parent) action_playlist_replace_(nullptr), action_playlist_new_(nullptr), action_homepage_(nullptr), - action_donate_(nullptr), initialized_(false) { setItemDelegate(new CollectionItemDelegate(this)); @@ -88,10 +87,6 @@ void RadioView::contextMenuEvent(QContextMenuEvent *e) { QObject::connect(action_homepage_, &QAction::triggered, this, &RadioView::Homepage); menu_->addAction(action_homepage_); - action_donate_ = new QAction(IconLoader::Load(u"download"_s), tr("Donate"), this); - QObject::connect(action_donate_, &QAction::triggered, this, &RadioView::Donate); - menu_->addAction(action_donate_); - menu_->addAction(IconLoader::Load(u"view-refresh"_s), tr("Refresh channels"), this, &RadioView::GetChannels); } @@ -101,7 +96,6 @@ void RadioView::contextMenuEvent(QContextMenuEvent *e) { action_playlist_replace_->setVisible(channels_selected); action_playlist_new_->setVisible(channels_selected); action_homepage_->setVisible(channels_selected); - action_donate_->setVisible(channels_selected); menu_->popup(e->globalPos()); @@ -165,22 +159,3 @@ void RadioView::Homepage() { } } - -void RadioView::Donate() { - - const QModelIndexList selected_indexes = selectedIndexes(); - if (selected_indexes.isEmpty()) return; - - QList urls; - for (const QModelIndex &idx : selected_indexes) { - QUrl url = idx.data(RadioModel::Role_Donate).toUrl(); - if (!urls.contains(url)) { - urls << url; // clazy:exclude=reserve-candidates - } - } - - for (const QUrl &url : std::as_const(urls)) { - QDesktopServices::openUrl(url); - } - -} diff --git a/src/radios/radioview.h b/src/radios/radioview.h index 6e8b9513a..18efa9ce7 100644 --- a/src/radios/radioview.h +++ b/src/radios/radioview.h @@ -50,7 +50,6 @@ class RadioView : public AutoExpandingTreeView { void ReplacePlaylist(); void OpenInNewPlaylist(); void Homepage(); - void Donate(); private: QMenu *menu_; @@ -58,7 +57,6 @@ class RadioView : public AutoExpandingTreeView { QAction *action_playlist_replace_; QAction *action_playlist_new_; QAction *action_homepage_; - QAction *action_donate_; bool initialized_; }; diff --git a/src/radios/somafmservice.cpp b/src/radios/somafmservice.cpp index 8c63081ee..0c7bf86ba 100644 --- a/src/radios/somafmservice.cpp +++ b/src/radios/somafmservice.cpp @@ -49,7 +49,6 @@ SomaFMService::~SomaFMService() { } QUrl SomaFMService::Homepage() { return QUrl(u"https://somafm.com/"_s); } -QUrl SomaFMService::Donate() { return QUrl(u"https://somafm.com/support/"_s); } void SomaFMService::Abort() { diff --git a/src/radios/somafmservice.h b/src/radios/somafmservice.h index 585155d6a..eed41008f 100644 --- a/src/radios/somafmservice.h +++ b/src/radios/somafmservice.h @@ -40,7 +40,6 @@ class SomaFMService : public RadioService { ~SomaFMService(); QUrl Homepage() override; - QUrl Donate() override; void Abort();