From 205b7f2401dbb0d63d0864f03d6d53cc80440a9a Mon Sep 17 00:00:00 2001 From: Jonas Kvinge Date: Wed, 28 Dec 2022 03:12:00 +0100 Subject: [PATCH] Split utilities functions into separate files --- ext/libstrawberry-tagreader/tagreadergme.cpp | 2 +- .../tagreadertaglib.cpp | 2 +- src/CMakeLists.txt | 22 +- src/collection/collection.cpp | 2 +- src/collection/collection.h | 2 +- src/collection/collectiondirectorymodel.cpp | 2 +- src/collection/collectionview.cpp | 2 +- src/collection/collectionwatcher.cpp | 4 +- src/context/contextalbum.cpp | 2 +- src/context/contextview.cpp | 3 +- src/core/filesystemmusicstorage.cpp | 2 +- src/core/mac_startup.h | 48 +- src/core/mac_startup.mm | 2 +- src/core/mainwindow.cpp | 8 +- src/core/mainwindow.h | 8 +- src/core/mpris2.cpp | 2 +- src/core/platforminterface.h | 40 + src/core/player.cpp | 2 +- src/core/scopedwchararray.cpp | 29 + src/core/scopedwchararray.h | 48 + src/core/song.cpp | 6 +- src/core/thread.cpp | 2 +- src/core/thread.h | 2 +- src/core/utilities.cpp | 1029 ----------------- src/core/utilities.h | 171 --- .../albumcoverchoicecontroller.cpp | 5 +- src/covermanager/albumcoverfetchersearch.cpp | 4 +- src/covermanager/albumcoverloader.cpp | 6 +- src/covermanager/albumcovermanager.cpp | 6 +- src/covermanager/albumcoversearcher.cpp | 4 +- src/covermanager/coverfromurldialog.cpp | 2 +- .../coversearchstatisticsdialog.cpp | 2 +- src/covermanager/discogscoverprovider.cpp | 2 +- src/covermanager/spotifycoverprovider.cpp | 4 +- src/device/cddasongloader.cpp | 2 +- src/device/devicemanager.cpp | 2 +- src/device/deviceview.cpp | 2 +- src/device/udisks2lister.cpp | 2 +- src/dialogs/edittagdialog.cpp | 6 +- src/engine/enginebase.cpp | 4 +- src/engine/gstengine.cpp | 2 +- src/engine/gstengine.h | 2 +- src/engine/gstenginepipeline.cpp | 2 +- src/engine/gststartup.cpp | 2 +- src/engine/vlcengine.cpp | 2 +- src/lyrics/auddlyricsprovider.cpp | 2 +- src/lyrics/chartlyricsprovider.cpp | 2 +- src/lyrics/geniuslyricsprovider.cpp | 3 +- src/lyrics/lololyricsprovider.cpp | 2 +- src/lyrics/lyricsprovider.cpp | 2 +- src/lyrics/musixmatchlyricsprovider.cpp | 2 +- src/lyrics/ovhlyricsprovider.cpp | 2 +- src/main.cpp | 8 +- src/moodbar/moodbarpipeline.cpp | 2 +- src/musicbrainz/acoustidclient.cpp | 2 +- src/musicbrainz/musicbrainzclient.cpp | 2 +- src/musicbrainz/tagfetcher.cpp | 2 +- src/organize/organize.cpp | 2 +- src/organize/organizedialog.cpp | 2 +- src/organize/organizeformat.cpp | 4 +- src/osd/osdbase.cpp | 2 +- src/osd/osdpretty.cpp | 4 +- src/playlist/playlist.cpp | 2 +- src/playlist/playlistdelegates.cpp | 3 +- src/playlist/playlistmanager.cpp | 2 +- src/playlistparsers/asxparser.cpp | 2 +- src/playlistparsers/cueparser.cpp | 2 +- src/playlistparsers/m3uparser.cpp | 2 +- src/playlistparsers/plsparser.cpp | 2 +- src/playlistparsers/wplparser.cpp | 2 +- src/playlistparsers/xspfparser.cpp | 4 +- src/qobuz/qobuzrequest.cpp | 4 +- src/qobuz/qobuzservice.cpp | 2 +- src/qobuz/qobuzstreamurlrequest.cpp | 2 +- src/queue/queue.cpp | 2 +- src/scrobbler/listenbrainzscrobbler.cpp | 2 +- src/scrobbler/scrobblingapi20.cpp | 2 +- src/scrobbler/subsonicscrobbler.cpp | 2 +- src/settings/appearancesettingspage.cpp | 2 +- src/settings/collectionsettingspage.cpp | 3 +- src/settings/globalshortcutssettingspage.cpp | 2 +- .../smartplaylistsearchtermwidget.cpp | 2 +- src/subsonic/subsonicbaserequest.cpp | 2 +- src/subsonic/subsonicrequest.cpp | 4 +- src/subsonic/subsonicservice.cpp | 2 +- src/tidal/tidalrequest.cpp | 4 +- src/tidal/tidalservice.cpp | 4 +- src/utilities/colorutils.cpp | 41 + src/utilities/colorutils.h | 33 + src/utilities/cryptutils.cpp | 75 ++ src/utilities/cryptutils.h | 37 + src/utilities/diskutils.cpp | 76 ++ src/utilities/diskutils.h | 33 + src/utilities/envutils.cpp | 73 ++ src/utilities/envutils.h | 33 + src/utilities/filemanagerutils.cpp | 167 +++ src/utilities/filemanagerutils.h | 32 + src/utilities/fileutils.cpp | 127 ++ src/utilities/fileutils.h | 37 + src/{core => utilities}/imageutils.cpp | 5 +- src/{core => utilities}/imageutils.h | 2 - src/utilities/macaddrutils.cpp | 54 + .../macaddrutils.h} | 17 +- .../macosutils.h} | 28 +- src/utilities/macosutils.mm | 62 + src/utilities/mimeutils.cpp | 36 + src/utilities/mimeutils.h | 32 + src/utilities/randutils.cpp | 63 + src/utilities/randutils.h | 34 + src/utilities/strutils.cpp | 204 ++++ src/utilities/strutils.h | 54 + src/utilities/threadutils.cpp | 59 + src/utilities/threadutils.h | 45 + src/{core => utilities}/timeconstants.h | 0 src/utilities/timeutils.cpp | 152 +++ src/utilities/timeutils.h | 42 + src/utilities/transliterate.cpp | 94 ++ src/utilities/transliterate.h | 31 + src/utilities/winutils.cpp | 84 ++ src/utilities/winutils.h | 33 + src/utilities/xmlutils.cpp | 69 ++ src/utilities/xmlutils.h | 40 + src/widgets/fileviewlist.cpp | 2 +- src/widgets/freespacebar.cpp | 2 +- src/widgets/playingwidget.cpp | 2 +- src/widgets/trackslider.cpp | 4 +- src/widgets/tracksliderslider.cpp | 4 +- 127 files changed, 2269 insertions(+), 1361 deletions(-) create mode 100644 src/core/platforminterface.h create mode 100644 src/core/scopedwchararray.cpp create mode 100644 src/core/scopedwchararray.h delete mode 100644 src/core/utilities.cpp delete mode 100644 src/core/utilities.h create mode 100644 src/utilities/colorutils.cpp create mode 100644 src/utilities/colorutils.h create mode 100644 src/utilities/cryptutils.cpp create mode 100644 src/utilities/cryptutils.h create mode 100644 src/utilities/diskutils.cpp create mode 100644 src/utilities/diskutils.h create mode 100644 src/utilities/envutils.cpp create mode 100644 src/utilities/envutils.h create mode 100644 src/utilities/filemanagerutils.cpp create mode 100644 src/utilities/filemanagerutils.h create mode 100644 src/utilities/fileutils.cpp create mode 100644 src/utilities/fileutils.h rename src/{core => utilities}/imageutils.cpp (99%) rename src/{core => utilities}/imageutils.h (98%) create mode 100644 src/utilities/macaddrutils.cpp rename src/{core/mac_utilities.mm => utilities/macaddrutils.h} (74%) rename src/{core/mac_utilities.h => utilities/macosutils.h} (74%) create mode 100644 src/utilities/macosutils.mm create mode 100644 src/utilities/mimeutils.cpp create mode 100644 src/utilities/mimeutils.h create mode 100644 src/utilities/randutils.cpp create mode 100644 src/utilities/randutils.h create mode 100644 src/utilities/strutils.cpp create mode 100644 src/utilities/strutils.h create mode 100644 src/utilities/threadutils.cpp create mode 100644 src/utilities/threadutils.h rename src/{core => utilities}/timeconstants.h (100%) create mode 100644 src/utilities/timeutils.cpp create mode 100644 src/utilities/timeutils.h create mode 100644 src/utilities/transliterate.cpp create mode 100644 src/utilities/transliterate.h create mode 100644 src/utilities/winutils.cpp create mode 100644 src/utilities/winutils.h create mode 100644 src/utilities/xmlutils.cpp create mode 100644 src/utilities/xmlutils.h diff --git a/ext/libstrawberry-tagreader/tagreadergme.cpp b/ext/libstrawberry-tagreader/tagreadergme.cpp index ce996d24..2b185d2b 100644 --- a/ext/libstrawberry-tagreader/tagreadergme.cpp +++ b/ext/libstrawberry-tagreader/tagreadergme.cpp @@ -29,8 +29,8 @@ #include #include +#include "utilities/timeconstants.h" #include "core/logging.h" -#include "core/timeconstants.h" #include "core/messagehandler.h" #include "tagreaderbase.h" #include "tagreadertaglib.h" diff --git a/ext/libstrawberry-tagreader/tagreadertaglib.cpp b/ext/libstrawberry-tagreader/tagreadertaglib.cpp index 5e327492..ab3e625f 100644 --- a/ext/libstrawberry-tagreader/tagreadertaglib.cpp +++ b/ext/libstrawberry-tagreader/tagreadertaglib.cpp @@ -92,7 +92,7 @@ #include "core/logging.h" #include "core/messagehandler.h" -#include "core/timeconstants.h" +#include "utilities/timeconstants.h" class FileRefFactory { public: diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ebdc9ba1..7695ca5d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -35,14 +35,28 @@ set(SOURCES core/taskmanager.cpp core/thread.cpp core/urlhandler.cpp - core/utilities.cpp - core/imageutils.cpp core/iconloader.cpp core/standarditemiconloader.cpp core/scopedtransaction.cpp core/translations.cpp core/systemtrayicon.cpp + utilities/strutils.cpp + utilities/envutils.cpp + utilities/colorutils.cpp + utilities/cryptutils.cpp + utilities/fileutils.cpp + utilities/diskutils.cpp + utilities/imageutils.cpp + utilities/macaddrutils.cpp + utilities/mimeutils.cpp + utilities/randutils.cpp + utilities/threadutils.cpp + utilities/timeutils.cpp + utilities/transliterate.cpp + utilities/xmlutils.cpp + utilities/filemanagerutils.cpp + engine/enginetype.cpp engine/enginebase.cpp engine/devicefinders.cpp @@ -782,8 +796,8 @@ optional_source(HAVE_AUDIOCD # Platform specific - macOS optional_source(APPLE SOURCES + utilities/macosutils.mm core/scoped_nsautorelease_pool.mm - core/mac_utilities.mm core/mac_startup.mm core/macsystemtrayicon.mm core/macfslistener.mm @@ -804,8 +818,10 @@ optional_source(APPLE # Platform specific - Windows optional_source(WIN32 SOURCES + utilities/winutils.cpp engine/directsounddevicefinder.cpp engine/mmdevicefinder.cpp + core/scopedwchararray.cpp core/windows7thumbbar.cpp HEADERS core/windows7thumbbar.h diff --git a/src/collection/collection.cpp b/src/collection/collection.cpp index d4fefb9b..438f2e34 100644 --- a/src/collection/collection.cpp +++ b/src/collection/collection.cpp @@ -34,9 +34,9 @@ #include "core/player.h" #include "core/tagreaderclient.h" #include "core/thread.h" -#include "core/utilities.h" #include "core/song.h" #include "core/logging.h" +#include "utilities/threadutils.h" #include "collection.h" #include "collectionwatcher.h" #include "collectionbackend.h" diff --git a/src/collection/collection.h b/src/collection/collection.h index 22a9649c..bdeac156 100644 --- a/src/collection/collection.h +++ b/src/collection/collection.h @@ -31,7 +31,7 @@ #include #include "core/song.h" -#include "core/utilities.h" +#include "utilities/threadutils.h" class Application; class Thread; diff --git a/src/collection/collectiondirectorymodel.cpp b/src/collection/collectiondirectorymodel.cpp index eceb709c..13d5f6b5 100644 --- a/src/collection/collectiondirectorymodel.cpp +++ b/src/collection/collectiondirectorymodel.cpp @@ -29,7 +29,7 @@ #include "core/filesystemmusicstorage.h" #include "core/iconloader.h" #include "core/musicstorage.h" -#include "core/utilities.h" +#include "utilities/diskutils.h" #include "directory.h" #include "collectionbackend.h" #include "collectiondirectorymodel.h" diff --git a/src/collection/collectionview.cpp b/src/collection/collectionview.cpp index e56d5d55..cda3cab3 100644 --- a/src/collection/collectionview.cpp +++ b/src/collection/collectionview.cpp @@ -50,9 +50,9 @@ #include "core/application.h" #include "core/iconloader.h" #include "core/mimedata.h" -#include "core/utilities.h" #include "core/musicstorage.h" #include "core/deletefiles.h" +#include "utilities/filemanagerutils.h" #include "collection.h" #include "collectionbackend.h" #include "collectiondirectorymodel.h" diff --git a/src/collection/collectionwatcher.cpp b/src/collection/collectionwatcher.cpp index ed92858f..bbf76e38 100644 --- a/src/collection/collectionwatcher.cpp +++ b/src/collection/collectionwatcher.cpp @@ -46,10 +46,10 @@ #include "core/filesystemwatcherinterface.h" #include "core/logging.h" -#include "core/timeconstants.h" #include "core/tagreaderclient.h" #include "core/taskmanager.h" -#include "core/imageutils.h" +#include "utilities/imageutils.h" +#include "utilities/timeconstants.h" #include "directory.h" #include "collectionbackend.h" #include "collectionwatcher.h" diff --git a/src/context/contextalbum.cpp b/src/context/contextalbum.cpp index 5ac0ceb3..84c8a70f 100644 --- a/src/context/contextalbum.cpp +++ b/src/context/contextalbum.cpp @@ -37,7 +37,7 @@ #include #include -#include "core/imageutils.h" +#include "utilities/imageutils.h" #include "covermanager/albumcoverchoicecontroller.h" #include "contextview.h" diff --git a/src/context/contextview.cpp b/src/context/contextview.cpp index 2d206cb5..4d07a544 100644 --- a/src/context/contextview.cpp +++ b/src/context/contextview.cpp @@ -51,8 +51,9 @@ #include "core/application.h" #include "core/player.h" #include "core/song.h" -#include "core/utilities.h" #include "core/iconloader.h" +#include "utilities/strutils.h" +#include "utilities/timeutils.h" #include "widgets/resizabletextedit.h" #include "engine/engine_fwd.h" #include "engine/enginebase.h" diff --git a/src/core/filesystemmusicstorage.cpp b/src/core/filesystemmusicstorage.cpp index b77d82e5..52141fc0 100644 --- a/src/core/filesystemmusicstorage.cpp +++ b/src/core/filesystemmusicstorage.cpp @@ -29,7 +29,7 @@ #include #include "core/logging.h" -#include "utilities.h" +#include "utilities/fileutils.h" #include "musicstorage.h" #include "filesystemmusicstorage.h" diff --git a/src/core/mac_startup.h b/src/core/mac_startup.h index 882892de..dc0e79d9 100644 --- a/src/core/mac_startup.h +++ b/src/core/mac_startup.h @@ -1,29 +1,44 @@ +/* + * Strawberry Music Player + * This file was part of Clementine. + * Copyright 2010, David Sansome + * Copyright 2018-2021, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + #ifndef MAC_STARTUP_H #define MAC_STARTUP_H #include "config.h" +#include + #include +#include #include -class QObject; -class QWidget; +#ifdef __OBJC__ +@class NSEvent; +#else +class NSEvent; +#endif +class PlatformInterface; class GlobalShortcutsBackendMacOS; -class PlatformInterface { - public: - PlatformInterface() = default; - virtual ~PlatformInterface() {} - - // Called when the application should show itself. - virtual void Activate() = 0; - virtual bool LoadUrl(const QString &url) = 0; - - private: - Q_DISABLE_COPY(PlatformInterface) -}; - namespace mac { void MacMain(); @@ -32,6 +47,9 @@ void SetApplicationHandler(PlatformInterface *handler); void EnableFullScreen(const QWidget &main_window); +QKeySequence KeySequenceFromNSEvent(NSEvent *event); +void DumpDictionary(CFDictionaryRef dict); + } // namespace mac #endif diff --git a/src/core/mac_startup.mm b/src/core/mac_startup.mm index 1d211da2..5b80b016 100644 --- a/src/core/mac_startup.mm +++ b/src/core/mac_startup.mm @@ -45,10 +45,10 @@ #include "config.h" +#include "platforminterface.h" #include "mac_delegate.h" #include "mac_startup.h" #include "mac_utilities.h" -#include "utilities.h" #include "scoped_cftyperef.h" #include "core/logging.h" #include "core/scoped_nsautorelease_pool.h" diff --git a/src/core/mainwindow.cpp b/src/core/mainwindow.cpp index 8a7319c6..d8bff5b1 100644 --- a/src/core/mainwindow.cpp +++ b/src/core/mainwindow.cpp @@ -74,13 +74,10 @@ #include #include "core/logging.h" -#include "core/networkaccessmanager.h" #include "mainwindow.h" #include "ui_mainwindow.h" -#include "utilities.h" -#include "timeconstants.h" #include "commandlineoptions.h" #include "mimedata.h" #include "iconloader.h" @@ -95,10 +92,15 @@ #include "filesystemmusicstorage.h" #include "deletefiles.h" #ifdef Q_OS_MACOS +# include "mac_startup.h" # include "macsystemtrayicon.h" #else # include "qtsystemtrayicon.h" #endif +#include "networkaccessmanager.h" +#include "utilities/envutils.h" +#include "utilities/filemanagerutils.h" +#include "utilities/timeconstants.h" #include "engine/enginetype.h" #include "engine/enginebase.h" #include "engine/engine_fwd.h" diff --git a/src/core/mainwindow.h b/src/core/mainwindow.h index bdacfbbb..ba7e9264 100644 --- a/src/core/mainwindow.h +++ b/src/core/mainwindow.h @@ -48,12 +48,12 @@ #include #include -#include "core/lazy.h" -#include "core/tagreaderclient.h" -#include "core/song.h" +#include "lazy.h" +#include "platforminterface.h" +#include "song.h" +#include "tagreaderclient.h" #include "engine/enginetype.h" #include "engine/engine_fwd.h" -#include "mac_startup.h" #include "osd/osdbase.h" #include "collection/collectionmodel.h" #include "playlist/playlist.h" diff --git a/src/core/mpris2.cpp b/src/core/mpris2.cpp index c5afa389..50e5e679 100644 --- a/src/core/mpris2.cpp +++ b/src/core/mpris2.cpp @@ -46,10 +46,10 @@ #include "mpris_common.h" #include "mpris2.h" -#include "timeconstants.h" #include "song.h" #include "application.h" #include "player.h" +#include "utilities/timeconstants.h" #include "engine/enginebase.h" #include "playlist/playlist.h" #include "playlist/playlistitem.h" diff --git a/src/core/platforminterface.h b/src/core/platforminterface.h new file mode 100644 index 00000000..ed8e9027 --- /dev/null +++ b/src/core/platforminterface.h @@ -0,0 +1,40 @@ +/* + * Strawberry Music Player + * Copyright 2010, David Sansome + * Copyright 2018-2021, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#ifndef PLATFORMINTERFACE_H +#define PLATFORMINTERFACE_H + +#include +#include + +class PlatformInterface { + public: + PlatformInterface() = default; + virtual ~PlatformInterface() {} + + // Called when the application should show itself. + virtual void Activate() = 0; + virtual bool LoadUrl(const QString &url) = 0; + + private: + Q_DISABLE_COPY(PlatformInterface) +}; + +#endif // PLATFORMINTERFACE_H diff --git a/src/core/player.cpp b/src/core/player.cpp index 1c5a6d37..b44d71d8 100644 --- a/src/core/player.cpp +++ b/src/core/player.cpp @@ -36,9 +36,9 @@ #include #include "core/logging.h" +#include "utilities/timeconstants.h" #include "song.h" -#include "timeconstants.h" #include "urlhandler.h" #include "application.h" diff --git a/src/core/scopedwchararray.cpp b/src/core/scopedwchararray.cpp new file mode 100644 index 00000000..ceb1c3be --- /dev/null +++ b/src/core/scopedwchararray.cpp @@ -0,0 +1,29 @@ +/* + * Strawberry Music Player + * Copyright 2010, David Sansome + * Copyright 2018-2021, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#include + +#include "scopedwchararray.h" + +ScopedWCharArray::ScopedWCharArray(const QString &str) + : chars_(str.length()), data_(new wchar_t[chars_ + 1]) { + str.toWCharArray(data_.get()); + data_[chars_] = '\0'; +} diff --git a/src/core/scopedwchararray.h b/src/core/scopedwchararray.h new file mode 100644 index 00000000..ac2e0c24 --- /dev/null +++ b/src/core/scopedwchararray.h @@ -0,0 +1,48 @@ +/* + * Strawberry Music Player + * Copyright 2010, David Sansome + * Copyright 2018-2021, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#ifndef SCOPEDWCHARARRAY_H +#define SCOPEDWCHARARRAY_H + +#include + +#include +#include + +class ScopedWCharArray { + public: + explicit ScopedWCharArray(const QString &str); + + QString ToString() const { return QString::fromWCharArray(data_.get()); } + + wchar_t *get() const { return data_.get(); } + explicit operator wchar_t *() const { return get(); } + + qint64 characters() const { return chars_; } + qint64 bytes() const { return (chars_ + 1) * sizeof(wchar_t); } + + private: + Q_DISABLE_COPY(ScopedWCharArray) + + qint64 chars_; + std::unique_ptr data_; +}; + +#endif // SCOPEDWCHARARRAY_H diff --git a/src/core/song.cpp b/src/core/song.cpp index 4f7e299e..dc2a0f37 100644 --- a/src/core/song.cpp +++ b/src/core/song.cpp @@ -50,8 +50,10 @@ #include "core/iconloader.h" #include "engine/enginebase.h" -#include "timeconstants.h" -#include "utilities.h" +#include "utilities/strutils.h" +#include "utilities/timeutils.h" +#include "utilities/cryptutils.h" +#include "utilities/timeconstants.h" #include "song.h" #include "application.h" #include "sqlquery.h" diff --git a/src/core/thread.cpp b/src/core/thread.cpp index e85fa2ec..4e9546f5 100644 --- a/src/core/thread.cpp +++ b/src/core/thread.cpp @@ -20,7 +20,7 @@ #include #include "thread.h" -#include "utilities.h" +#include "utilities/threadutils.h" void Thread::run() { diff --git a/src/core/thread.h b/src/core/thread.h index 771f9b2d..3debf3a2 100644 --- a/src/core/thread.h +++ b/src/core/thread.h @@ -22,7 +22,7 @@ #include -#include "utilities.h" +#include "utilities/threadutils.h" class QObject; diff --git a/src/core/utilities.cpp b/src/core/utilities.cpp deleted file mode 100644 index e5149f5a..00000000 --- a/src/core/utilities.cpp +++ /dev/null @@ -1,1029 +0,0 @@ -/* - * Strawberry Music Player - * This file was part of Clementine. - * Copyright 2010, David Sansome - * Copyright 2018-2021, Jonas Kvinge - * - * Strawberry is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Strawberry is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Strawberry. If not, see . - * - */ - -#include "config.h" - -#include -#include - -#ifdef HAVE_ICU -# include -#else -# include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) -# include -#endif - -#include - -#ifdef Q_OS_LINUX -# include -# include -#endif -#ifdef Q_OS_MACOS -# include -# include -# include -#endif - -#if defined(Q_OS_UNIX) -# include -#elif defined(Q_OS_WIN) -# include -# include -#endif - -#ifdef Q_OS_MACOS -# include "CoreServices/CoreServices.h" -# include "IOKit/ps/IOPSKeys.h" -# include "IOKit/ps/IOPowerSources.h" -#endif - -#include "core/logging.h" -#include "core/song.h" - -#include "utilities.h" -#include "timeconstants.h" -#include "application.h" - -#ifdef Q_OS_MACOS -# include "mac_startup.h" -# include "mac_utilities.h" -# include "scoped_cftyperef.h" -#endif - -namespace Utilities { - -static QString tr(const char *str) { - return QCoreApplication::translate("", str); -} - -QString PrettyTimeDelta(const int seconds) { - return (seconds >= 0 ? "+" : "-") + PrettyTime(seconds); -} - -QString PrettyTime(int seconds) { - - // last.fm sometimes gets the track length wrong, so you end up with negative times. - seconds = qAbs(seconds); - - int hours = seconds / (60 * 60); - int minutes = (seconds / 60) % 60; - seconds %= 60; - - QString ret; - if (hours > 0) ret = QString::asprintf("%d:%02d:%02d", hours, minutes, seconds); - else ret = QString::asprintf("%d:%02d", minutes, seconds); - - return ret; - -} - -QString PrettyTimeNanosec(const qint64 nanoseconds) { - return PrettyTime(static_cast(nanoseconds / kNsecPerSec)); -} - -QString WordyTime(const quint64 seconds) { - - quint64 days = seconds / (60 * 60 * 24); - - // TODO: Make the plural rules translatable - QStringList parts; - - if (days > 0) parts << (days == 1 ? tr("1 day") : tr("%1 days").arg(days)); - parts << PrettyTime(static_cast(seconds - days * 60 * 60 * 24)); - - return parts.join(" "); - -} - -QString WordyTimeNanosec(const quint64 nanoseconds) { - return WordyTime(nanoseconds / kNsecPerSec); -} - -QString Ago(const qint64 seconds_since_epoch, const QLocale &locale) { - - const QDateTime now = QDateTime::currentDateTime(); - const QDateTime then = QDateTime::fromSecsSinceEpoch(seconds_since_epoch); - const qint64 days_ago = then.date().daysTo(now.date()); - const QString time = then.time().toString(locale.timeFormat(QLocale::ShortFormat)); - - if (days_ago == 0) return tr("Today") + " " + time; - if (days_ago == 1) return tr("Yesterday") + " " + time; - if (days_ago <= 7) return tr("%1 days ago").arg(days_ago); - - return then.date().toString(locale.dateFormat(QLocale::ShortFormat)); - -} - -QString PrettyFutureDate(const QDate date) { - - const QDate now = QDate::currentDate(); - const qint64 delta_days = now.daysTo(date); - - if (delta_days < 0) return QString(); - if (delta_days == 0) return tr("Today"); - if (delta_days == 1) return tr("Tomorrow"); - if (delta_days <= 7) return tr("In %1 days").arg(delta_days); - if (delta_days <= 14) return tr("Next week"); - - return tr("In %1 weeks").arg(delta_days / 7); - -} - -QString PrettySize(const quint64 bytes) { - - QString ret; - - if (bytes > 0) { - if (bytes <= 1000) { - ret = QString::number(bytes) + " bytes"; - } - else if (bytes <= 1000 * 1000) { - ret = QString::asprintf("%.1f KB", static_cast(bytes) / 1000.0F); - } - else if (bytes <= 1000 * 1000 * 1000) { - ret = QString::asprintf("%.1f MB", static_cast(bytes) / (1000.0F * 1000.0F)); - } - else { - ret = QString::asprintf("%.1f GB", static_cast(bytes) / (1000.0F * 1000.0F * 1000.0F)); - } - } - return ret; - -} - -quint64 FileSystemCapacity(const QString &path) { - -#if defined(Q_OS_UNIX) - struct statvfs fs_info {}; - if (statvfs(path.toLocal8Bit().constData(), &fs_info) == 0) - return static_cast(fs_info.f_blocks) * static_cast(fs_info.f_bsize); -#elif defined(Q_OS_WIN32) - _ULARGE_INTEGER ret; - ScopedWCharArray wchar(QDir::toNativeSeparators(path)); - if (GetDiskFreeSpaceEx(wchar.get(), nullptr, &ret, nullptr) != 0) - return ret.QuadPart; -#endif - - return 0; - -} - -quint64 FileSystemFreeSpace(const QString &path) { - -#if defined(Q_OS_UNIX) - struct statvfs fs_info {}; - if (statvfs(path.toLocal8Bit().constData(), &fs_info) == 0) - return static_cast(fs_info.f_bavail) * static_cast(fs_info.f_bsize); -#elif defined(Q_OS_WIN32) - _ULARGE_INTEGER ret; - ScopedWCharArray wchar(QDir::toNativeSeparators(path)); - if (GetDiskFreeSpaceEx(wchar.get(), &ret, nullptr, nullptr) != 0) - return ret.QuadPart; -#endif - - return 0; - -} - -bool RemoveRecursive(const QString &path) { - - QDir dir(path); - for (const QString &child : dir.entryList(QDir::NoDotAndDotDot | QDir::Dirs | QDir::Hidden)) { - if (!RemoveRecursive(path + "/" + child)) { - return false; - } - } - - for (const QString &child : dir.entryList(QDir::NoDotAndDotDot | QDir::Files | QDir::Hidden)) { - if (!QFile::remove(path + "/" + child)) { - return false; - } - } - - return dir.rmdir(path); - -} - -bool CopyRecursive(const QString &source, const QString &destination) { - - // Make the destination directory - QString dir_name = source.section('/', -1, -1); - QString dest_path = destination + "/" + dir_name; - QDir().mkpath(dest_path); - - QDir dir(source); - for (const QString &child : dir.entryList(QDir::NoDotAndDotDot | QDir::Dirs)) { - if (!CopyRecursive(source + "/" + child, dest_path)) { - qLog(Warning) << "Failed to copy dir" << source + "/" + child << "to" << dest_path; - return false; - } - } - - for (const QString &child : dir.entryList(QDir::NoDotAndDotDot | QDir::Files)) { - if (!QFile::copy(source + "/" + child, dest_path + "/" + child)) { - qLog(Warning) << "Failed to copy file" << source + "/" + child << "to" << dest_path; - return false; - } - } - return true; - -} - -bool Copy(QIODevice *source, QIODevice *destination) { - - if (!source->open(QIODevice::ReadOnly)) return false; - - if (!destination->open(QIODevice::WriteOnly)) return false; - - const qint64 bytes = source->size(); - std::unique_ptr data(new char[bytes]); - qint64 pos = 0; - - qint64 bytes_read = 0; - do { - bytes_read = source->read(data.get() + pos, bytes - pos); - if (bytes_read == -1) return false; - - pos += bytes_read; - } while (bytes_read > 0 && pos != bytes); - - pos = 0; - qint64 bytes_written = 0; - do { - bytes_written = destination->write(data.get() + pos, bytes - pos); - if (bytes_written == -1) return false; - - pos += bytes_written; - } while (bytes_written > 0 && pos != bytes); - - return true; - -} - -QString ColorToRgba(const QColor &c) { - - return QString("rgba(%1, %2, %3, %4)") - .arg(c.red()) - .arg(c.green()) - .arg(c.blue()) - .arg(c.alpha()); - -} - -#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) -void OpenInFileManager(const QString &path, const QUrl &url); -void OpenInFileManager(const QString &path, const QUrl &url) { - - if (!url.isLocalFile()) return; - - QProcess proc; -#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) - proc.startCommand("xdg-mime query default inode/directory"); -#else - proc.start("xdg-mime", QStringList() << "query" << "default" << "inode/directory"); -#endif - proc.waitForFinished(); - QString desktop_file = proc.readLine().simplified(); - QStringList data_dirs = QString(qgetenv("XDG_DATA_DIRS")).split(":"); - - QString command; - QStringList command_params; - for (const QString &data_dir : data_dirs) { - QString desktop_file_path = QString("%1/applications/%2").arg(data_dir, desktop_file); - if (!QFile::exists(desktop_file_path)) continue; - QSettings setting(desktop_file_path, QSettings::IniFormat); - setting.beginGroup("Desktop Entry"); - if (setting.contains("Exec")) { - QString cmd = setting.value("Exec").toString(); - if (cmd.isEmpty()) break; - cmd = cmd.remove(QRegularExpression("[%][a-zA-Z]*( |$)", QRegularExpression::CaseInsensitiveOption)); -# if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) - command_params = cmd.split(' ', Qt::SkipEmptyParts); -# else - command_params = cmd.split(' ', QString::SkipEmptyParts); -# endif - command = command_params.first(); - command_params.removeFirst(); - } - setting.endGroup(); - if (!command.isEmpty()) break; - } - - if (command.startsWith("/usr/bin/")) { - command = command.split("/").last(); - } - - if (command.isEmpty() || command == "exo-open") { - QDesktopServices::openUrl(QUrl::fromLocalFile(path)); - } - else if (command.startsWith("nautilus")) { - proc.startDetached(command, QStringList() << command_params << "--select" << url.toLocalFile()); - } - else if (command.startsWith("dolphin") || command.startsWith("konqueror") || command.startsWith("kfmclient")) { - proc.startDetached(command, QStringList() << command_params << "--select" << "--new-window" << url.toLocalFile()); - } - else if (command.startsWith("caja")) { - proc.startDetached(command, QStringList() << command_params << "--no-desktop" << path); - } - else if (command.startsWith("pcmanfm") || command.startsWith("thunar") || command.startsWith("spacefm")) { - proc.startDetached(command, QStringList() << command_params << path); - } - else { - proc.startDetached(command, QStringList() << command_params << url.toLocalFile()); - } - -} -#endif - -#ifdef Q_OS_MACOS -// Better than openUrl(dirname(path)) - also highlights file at path -void RevealFileInFinder(const QString &path) { - QProcess::execute("/usr/bin/open", QStringList() << "-R" << path); -} -#endif // Q_OS_MACOS - -#ifdef Q_OS_WIN -void ShowFileInExplorer(const QString &path); -void ShowFileInExplorer(const QString &path) { - QProcess::execute("explorer.exe", QStringList() << "/select," << QDir::toNativeSeparators(path)); -} -#endif - -void OpenInFileBrowser(const QList &urls) { - - QMap dirs; - - for (const QUrl &url : urls) { - if (!url.isLocalFile()) { - continue; - } - QString path = url.toLocalFile(); - if (!QFile::exists(path)) continue; - - const QString directory = QFileInfo(path).dir().path(); - if (dirs.contains(directory)) continue; - dirs.insert(directory, url); - } - - if (dirs.count() > 50) { - QMessageBox messagebox(QMessageBox::Critical, tr("Show in file browser"), tr("Too many songs selected.")); - messagebox.exec(); - return; - } - - if (dirs.count() > 5) { - QMessageBox messagebox(QMessageBox::Information, tr("Show in file browser"), tr("%1 songs in %2 different directories selected, are you sure you want to open them all?").arg(urls.count()).arg(dirs.count()), QMessageBox::Open|QMessageBox::Cancel); - messagebox.setTextFormat(Qt::RichText); - int result = messagebox.exec(); - switch (result) { - case QMessageBox::Open: - break; - case QMessageBox::Cancel: - default: - return; - } - } - - QMap::iterator i; - for (i = dirs.begin(); i != dirs.end(); ++i) { -#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) - OpenInFileManager(i.key(), i.value()); -#elif defined(Q_OS_MACOS) - // Revealing multiple files in the finder only opens one window, so it also makes sense to reveal at most one per directory - RevealFileInFinder(i.value().toLocalFile()); -#elif defined(Q_OS_WIN32) - ShowFileInExplorer(i.value().toLocalFile()); -#endif - } - -} - -QByteArray Hmac(const QByteArray &key, const QByteArray &data, const QCryptographicHash::Algorithm method) { - - constexpr int block_size = 64; - Q_ASSERT(key.length() <= block_size); - - QByteArray inner_padding(block_size, static_cast(0x36)); - QByteArray outer_padding(block_size, static_cast(0x5c)); - - for (int i = 0; i < key.length(); ++i) { - inner_padding[i] = static_cast(inner_padding[i] ^ key[i]); - outer_padding[i] = static_cast(outer_padding[i] ^ key[i]); - } - - QByteArray part; - part.append(inner_padding); - part.append(data); - - QByteArray total; - total.append(outer_padding); - total.append(QCryptographicHash::hash(part, method)); - - return QCryptographicHash::hash(total, method); - -} - -QByteArray HmacSha256(const QByteArray &key, const QByteArray &data) { - return Hmac(key, data, QCryptographicHash::Sha256); -} - -QByteArray HmacMd5(const QByteArray &key, const QByteArray &data) { - return Hmac(key, data, QCryptographicHash::Md5); -} - -QByteArray HmacSha1(const QByteArray &key, const QByteArray &data) { - return Hmac(key, data, QCryptographicHash::Sha1); -} - -QByteArray Sha1CoverHash(const QString &artist, const QString &album) { - - QCryptographicHash hash(QCryptographicHash::Sha1); - hash.addData(artist.toLower().toUtf8()); - hash.addData(album.toLower().toUtf8()); - - return hash.result(); - -} - -QString PrettySize(const QSize size) { - return QString::number(size.width()) + "x" + QString::number(size.height()); -} - -void ConsumeCurrentElement(QXmlStreamReader *reader) { - - int level = 1; - while (level != 0 && !reader->atEnd()) { - switch (reader->readNext()) { - case QXmlStreamReader::StartElement: ++level; break; - case QXmlStreamReader::EndElement: --level; break; - default: break; - } - } - -} - -bool ParseUntilElement(QXmlStreamReader *reader, const QString &name) { - - while (!reader->atEnd()) { - QXmlStreamReader::TokenType type = reader->readNext(); - if (type == QXmlStreamReader::StartElement && reader->name() == name) { - return true; - } - } - return false; - -} - -bool ParseUntilElementCI(QXmlStreamReader *reader, const QString &name) { - - while (!reader->atEnd()) { - QXmlStreamReader::TokenType type = reader->readNext(); - if (type == QXmlStreamReader::StartElement) { - QString element = reader->name().toString().toLower(); - if (element == name) { - return true; - } - } - } - - return false; - -} - -QDateTime ParseRFC822DateTime(const QString &text) { - - QRegularExpression regexp("(\\d{1,2}) (\\w{3,12}) (\\d+) (\\d{1,2}):(\\d{1,2}):(\\d{1,2})"); - QRegularExpressionMatch re_match = regexp.match(text); - if (!re_match.hasMatch()) { - return QDateTime(); - } - - enum class MatchNames { DAYS = 1, MONTHS, YEARS, HOURS, MINUTES, SECONDS }; - - QMap monthmap; - monthmap["Jan"] = 1; - monthmap["Feb"] = 2; - monthmap["Mar"] = 3; - monthmap["Apr"] = 4; - monthmap["May"] = 5; - monthmap["Jun"] = 6; - monthmap["Jul"] = 7; - monthmap["Aug"] = 8; - monthmap["Sep"] = 9; - monthmap["Oct"] = 10; - monthmap["Nov"] = 11; - monthmap["Dec"] = 12; - monthmap["January"] = 1; - monthmap["February"] = 2; - monthmap["March"] = 3; - monthmap["April"] = 4; - monthmap["May"] = 5; - monthmap["June"] = 6; - monthmap["July"] = 7; - monthmap["August"] = 8; - monthmap["September"] = 9; - monthmap["October"] = 10; - monthmap["November"] = 11; - monthmap["December"] = 12; - - const QDate date(re_match.captured(static_cast(MatchNames::YEARS)).toInt(), monthmap[re_match.captured(static_cast(MatchNames::MONTHS))], re_match.captured(static_cast(MatchNames::DAYS)).toInt()); - - const QTime time(re_match.captured(static_cast(MatchNames::HOURS)).toInt(), re_match.captured(static_cast(MatchNames::MINUTES)).toInt(), re_match.captured(static_cast(MatchNames::SECONDS)).toInt()); - - return QDateTime(date, time); - -} - -const char *EnumToString(const QMetaObject &meta, const char *name, const int value) { - - int index = meta.indexOfEnumerator(name); - if (index == -1) return "[UnknownEnum]"; - QMetaEnum metaenum = meta.enumerator(index); - const char *result = metaenum.valueToKey(value); - if (!result) return "[UnknownEnumValue]"; - return result; - -} - -QStringList Prepend(const QString &text, const QStringList &list) { - - QStringList ret(list); - for (int i = 0; i < ret.count(); ++i) ret[i].prepend(text); - return ret; - -} - -QStringList Updateify(const QStringList &list) { - - QStringList ret(list); - for (int i = 0; i < ret.count(); ++i) ret[i].prepend(ret[i] + " = :"); - return ret; - -} - -QString DecodeHtmlEntities(const QString &text) { - - QString copy(text); - copy.replace("&", "&") - .replace("&", "&") - .replace(""", "\"") - .replace(""", "\"") - .replace("'", "'") - .replace("'", "'") - .replace("<", "<") - .replace("<", "<") - .replace(">", ">") - .replace(">", ">") - .replace("'", "'"); - - return copy; - -} - -long SetThreadIOPriority(const IoPriority priority) { - -#ifdef Q_OS_LINUX - return syscall(SYS_ioprio_set, IOPRIO_WHO_PROCESS, GetThreadId(), 4 | priority << IOPRIO_CLASS_SHIFT); -#elif defined(Q_OS_MACOS) - return setpriority(PRIO_DARWIN_THREAD, 0, priority == IOPRIO_CLASS_IDLE ? PRIO_DARWIN_BG : 0); -#else - Q_UNUSED(priority); - return 0; -#endif - -} - -long GetThreadId() { - -#ifdef Q_OS_LINUX - return syscall(SYS_gettid); -#else - return 0; -#endif - -} - -QString PathWithoutFilenameExtension(const QString &filename) { - if (filename.section('/', -1, -1).contains('.')) return filename.section('.', 0, -2); - return filename; -} - -QString FiddleFileExtension(const QString &filename, const QString &new_extension) { - return PathWithoutFilenameExtension(filename) + "." + new_extension; -} - -QString GetEnv(const QString &key) { - const QByteArray key_data = key.toLocal8Bit(); - return QString::fromLocal8Bit(qgetenv(key_data.constData())); -} - -void SetEnv(const char *key, const QString &value) { - -#ifdef Q_OS_WIN32 - _putenv(QString("%1=%2").arg(key, value).toLocal8Bit().constData()); -#else - setenv(key, value.toLocal8Bit().constData(), 1); -#endif - -} - -void IncreaseFDLimit() { - -#ifdef Q_OS_MACOS - // Bump the soft limit for the number of file descriptors from the default of 256 to the maximum (usually 10240). - struct rlimit limit; - getrlimit(RLIMIT_NOFILE, &limit); - - // getrlimit() lies about the hard limit so we have to check sysctl. - int max_fd = 0; - size_t len = sizeof(max_fd); - sysctlbyname("kern.maxfilesperproc", &max_fd, &len, nullptr, 0); - - limit.rlim_cur = max_fd; - int ret = setrlimit(RLIMIT_NOFILE, &limit); - - if (ret == 0) { - qLog(Debug) << "Max fd:" << max_fd; - } -#endif - -} - -QString GetRandomStringWithChars(const int len) { - const QString UseCharacters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); - return GetRandomString(len, UseCharacters); -} - -QString GetRandomStringWithCharsAndNumbers(const int len) { - const QString UseCharacters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"); - return GetRandomString(len, UseCharacters); -} - -QString CryptographicRandomString(const int len) { - const QString UseCharacters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~"); - return GetRandomString(len, UseCharacters); -} - -QString GetRandomString(const int len, const QString &UseCharacters) { - - QString randstr; - for (int i = 0; i < len; ++i) { -#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) - const qint64 index = QRandomGenerator::global()->bounded(0, UseCharacters.length()); -#else - const int index = qrand() % UseCharacters.length(); -#endif - QChar nextchar = UseCharacters.at(index); - randstr.append(nextchar); - } - - return randstr; - -} - -QString DesktopEnvironment() { - - const QString de = GetEnv("XDG_CURRENT_DESKTOP"); - if (!de.isEmpty()) return de; - - if (!qEnvironmentVariableIsEmpty("KDE_FULL_SESSION")) return "KDE"; - if (!qEnvironmentVariableIsEmpty("GNOME_DESKTOP_SESSION_ID")) return "Gnome"; - - QString session = GetEnv("DESKTOP_SESSION"); - qint64 slash = session.lastIndexOf('/'); - if (slash != -1) { - QSettings desktop_file(QString(session + ".desktop"), QSettings::IniFormat); - desktop_file.beginGroup("Desktop Entry"); - QString name = desktop_file.value("DesktopNames").toString(); - desktop_file.endGroup(); - if (!name.isEmpty()) return name; - session = session.mid(slash + 1); - } - - if (session == "kde") return "KDE"; - else if (session == "gnome") return "Gnome"; - else if (session == "xfce") return "XFCE"; - - return "Unknown"; - -} - -#ifdef HAVE_ICU - -QString Transliterate(const QString &accented_str) { - - UErrorCode errorcode = U_ZERO_ERROR; - std::unique_ptr transliterator; - transliterator.reset(icu::Transliterator::createInstance("Any-Latin; Latin-ASCII;", UTRANS_FORWARD, errorcode)); - - if (!transliterator) return accented_str; - - QByteArray accented_data = accented_str.toUtf8(); - icu::UnicodeString ustring = icu::UnicodeString(accented_data.constData()); - transliterator->transliterate(ustring); - - std::string unaccented_str; - ustring.toUTF8String(unaccented_str); - - return QString::fromStdString(unaccented_str); - -} - -#else - -QString Transliterate(const QString &accented_str) { - -#ifdef LC_ALL - setlocale(LC_ALL, ""); -#endif - - iconv_t conv = iconv_open("ASCII//TRANSLIT", "UTF-8"); - if (conv == reinterpret_cast(-1)) return accented_str; - - QByteArray utf8 = accented_str.toUtf8(); - - size_t input_len = utf8.length() + 1; - char *input_ptr = new char[input_len]; - char *input = input_ptr; - - size_t output_len = input_len * 2; - char *output_ptr = new char[output_len]; - char *output = output_ptr; - - snprintf(input, input_len, "%s", utf8.constData()); - - iconv(conv, &input, &input_len, &output, &output_len); - iconv_close(conv); - - QString ret(output_ptr); - ret = ret.replace('?', '_'); - - delete[] input_ptr; - delete[] output_ptr; - - return ret; - -} - -#endif - -QString MacAddress() { - - QString ret; - - for (QNetworkInterface &netif : QNetworkInterface::allInterfaces()) { - if ( - (netif.hardwareAddress() == "00:00:00:00:00:00") || - (netif.flags() & QNetworkInterface::IsLoopBack) || - !(netif.flags() & QNetworkInterface::IsUp) || - !(netif.flags() & QNetworkInterface::IsRunning) - ) { continue; } - if (ret.isEmpty() -#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)) - || netif.type() == QNetworkInterface::Ethernet || netif.type() == QNetworkInterface::Wifi -#endif - ) { - ret = netif.hardwareAddress(); - } - } - - if (ret.isEmpty()) ret = "00:00:00:00:00:00"; - - return ret; - -} - -QString ReplaceMessage(const QString &message, const Song &song, const QString &newline, const bool html_escaped) { - - QRegularExpression variable_replacer("[%][a-z]+[%]"); - QString copy(message); - - // Replace the first line - qint64 pos = 0; - QRegularExpressionMatch match; - for (match = variable_replacer.match(message, pos); match.hasMatch(); match = variable_replacer.match(message, pos)) { - pos = match.capturedStart(); - QStringList captured = match.capturedTexts(); - copy.replace(captured[0], ReplaceVariable(captured[0], song, newline, html_escaped)); - pos += match.capturedLength(); - } - - qint64 index_of = copy.indexOf(QRegularExpression(" - (>|$)")); - if (index_of >= 0) copy = copy.remove(index_of, 3); - - return copy; - -} - -QString ReplaceVariable(const QString &variable, const Song &song, const QString &newline, const bool html_escaped) { - - QString value = variable; - - if (variable == "%title%") { - value = song.PrettyTitle(); - } - else if (variable == "%album%") { - value = song.album(); - } - else if (variable == "%artist%") { - value = song.artist(); - } - else if (variable == "%albumartist%") { - value = song.effective_albumartist(); - } - else if (variable == "%track%") { - value.setNum(song.track()); - } - else if (variable == "%disc%") { - value.setNum(song.disc()); - } - else if (variable == "%year%") { - value = song.PrettyYear(); - } - else if (variable == "%originalyear%") { - value = song.PrettyOriginalYear(); - } - else if (variable == "%genre%") { - value = song.genre(); - } - else if (variable == "%composer%") { - value = song.composer(); - } - else if (variable == "%performer%") { - value = song.performer(); - } - else if (variable == "%grouping%") { - value = song.grouping(); - } - else if (variable == "%length%") { - value = song.PrettyLength(); - } - else if (variable == "%filename%") { - value = song.basefilename(); - } - else if (variable == "%url%") { - value = song.url().toString(); - } - else if (variable == "%playcount%") { - value.setNum(song.playcount()); - } - else if (variable == "%skipcount%") { - value.setNum(song.skipcount()); - } - else if (variable == "%rating%") { - value = song.PrettyRating(); - } - else if (variable == "%newline%") { - return QString(newline); // No HTML escaping, return immediately. - } - - if (html_escaped) { - value = value.toHtmlEscaped(); - } - return value; - -} - -bool IsColorDark(const QColor &color) { - return ((30 * color.red() + 59 * color.green() + 11 * color.blue()) / 100) <= 130; -} - -QByteArray ReadDataFromFile(const QString &filename) { - - QFile file(filename); - QByteArray data; - if (file.open(QIODevice::ReadOnly)) { - data = file.readAll(); - file.close(); - } - else { - qLog(Error) << "Failed to open file" << filename << "for reading:" << file.errorString(); - } - return data; - -} - -QString MimeTypeFromData(const QByteArray &data) { - - if (data.isEmpty()) return QString(); - - return QMimeDatabase().mimeTypeForData(data).name(); - -} - -#ifdef Q_OS_WIN - -HRGN qt_RectToHRGN(const QRect &rc); -HRGN qt_RectToHRGN(const QRect &rc) { - return CreateRectRgn(rc.left(), rc.top(), rc.right() + 1, rc.bottom() + 1); -} - -HRGN toHRGN(const QRegion ®ion); -HRGN toHRGN(const QRegion ®ion) { - -# if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - return region.toHRGN(); -# else - - const int rect_count = region.rectCount(); - if (rect_count == 0) { - return nullptr; - } - - HRGN resultRgn = nullptr; - QRegion::const_iterator rects = region.begin(); - resultRgn = qt_RectToHRGN(rects[0]); - for (int i = 1; i < rect_count; ++i) { - HRGN tmpRgn = qt_RectToHRGN(rects[i]); - const int res = CombineRgn(resultRgn, resultRgn, tmpRgn, RGN_OR); - if (res == ERROR) qWarning("Error combining HRGNs."); - DeleteObject(tmpRgn); - } - - return resultRgn; - -# endif // Qt 6 -} - -void enableBlurBehindWindow(QWindow *window, const QRegion ®ion) { - - DWM_BLURBEHIND dwmbb = { 0, 0, nullptr, 0 }; - dwmbb.dwFlags = DWM_BB_ENABLE; - dwmbb.fEnable = TRUE; - HRGN rgn = nullptr; - if (!region.isNull()) { - rgn = toHRGN(region); - if (rgn) { - dwmbb.hRgnBlur = rgn; - dwmbb.dwFlags |= DWM_BB_BLURREGION; - } - } - DwmEnableBlurBehindWindow(reinterpret_cast(window->winId()), &dwmbb); - if (rgn) { - DeleteObject(rgn); - } -} - -#endif // Q_OS_WIN - -} // namespace Utilities - -ScopedWCharArray::ScopedWCharArray(const QString &str) - : chars_(str.length()), data_(new wchar_t[chars_ + 1]) { - str.toWCharArray(data_.get()); - data_[chars_] = '\0'; -} diff --git a/src/core/utilities.h b/src/core/utilities.h deleted file mode 100644 index 859ab179..00000000 --- a/src/core/utilities.h +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Strawberry Music Player - * This file was part of Clementine. - * Copyright 2010, David Sansome - * Copyright 2018-2021, Jonas Kvinge - * - * Strawberry is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Strawberry is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Strawberry. If not, see . - * - */ - -#ifndef UTILITIES_H -#define UTILITIES_H - -#include "config.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "core/song.h" - -class QWidget; -class QIODevice; -class QXmlStreamReader; - -namespace Utilities { -QString PrettyTime(int seconds); -QString PrettyTimeDelta(const int seconds); -QString PrettyTimeNanosec(const qint64 nanoseconds); -QString PrettySize(const quint64 bytes); -QString PrettySize(const QSize size); -QString WordyTime(const quint64 seconds); -QString WordyTimeNanosec(const quint64 nanoseconds); -QString Ago(const qint64 seconds_since_epoch, const QLocale &locale); -QString PrettyFutureDate(const QDate date); - -QString ColorToRgba(const QColor &color); - -quint64 FileSystemCapacity(const QString &path); -quint64 FileSystemFreeSpace(const QString &path); - -bool RemoveRecursive(const QString &path); -bool CopyRecursive(const QString &source, const QString &destination); -bool Copy(QIODevice *source, QIODevice *destination); - -void OpenInFileBrowser(const QList &urls); - -QByteArray Hmac(const QByteArray &key, const QByteArray &data, const QCryptographicHash::Algorithm method); -QByteArray HmacMd5(const QByteArray &key, const QByteArray &data); -QByteArray HmacSha256(const QByteArray &key, const QByteArray &data); -QByteArray HmacSha1(const QByteArray &key, const QByteArray &data); -QByteArray Sha1CoverHash(const QString &artist, const QString &album); - -// Reads all children of the current element, -// and returns with the stream reader either on the EndElement for the current element, or the end of the file - whichever came first. -void ConsumeCurrentElement(QXmlStreamReader *reader); - -// Advances the stream reader until it finds an element with the given name. -// Returns false if the end of the document was reached before finding a matching element. -bool ParseUntilElement(QXmlStreamReader *reader, const QString &name); -bool ParseUntilElementCI(QXmlStreamReader *reader, const QString &name); - -// Parses a string containing an RFC822 time and date. -QDateTime ParseRFC822DateTime(const QString &text); - -// Replaces some HTML entities with their normal characters. -QString DecodeHtmlEntities(const QString &text); - -// Shortcut for getting a Qt-aware enum value as a string. -// Pass in the QMetaObject of the class that owns the enum, the string name of the enum and a valid value from that enum. -const char *EnumToString(const QMetaObject &meta, const char *name, int value); - -QStringList Prepend(const QString &text, const QStringList &list); -QStringList Updateify(const QStringList &list); - -// Get the path without the filename extension -QString PathWithoutFilenameExtension(const QString &filename); -QString FiddleFileExtension(const QString &filename, const QString &new_extension); - -QString GetEnv(const QString &key); -void SetEnv(const char *key, const QString &value); -void IncreaseFDLimit(); - -// Borrowed from schedutils -enum IoPriority { - IOPRIO_CLASS_NONE = 0, - IOPRIO_CLASS_RT, - IOPRIO_CLASS_BE, - IOPRIO_CLASS_IDLE, -}; -enum { - IOPRIO_WHO_PROCESS = 1, - IOPRIO_WHO_PGRP, - IOPRIO_WHO_USER, -}; -static const int IOPRIO_CLASS_SHIFT = 13; - -long SetThreadIOPriority(const IoPriority priority); -long GetThreadId(); - -QString GetRandomStringWithChars(const int len); -QString GetRandomStringWithCharsAndNumbers(const int len); -QString CryptographicRandomString(const int len); -QString GetRandomString(const int len, const QString &UseCharacters); - -QString DesktopEnvironment(); - -QString Transliterate(const QString &accented_str); - -QString MacAddress(); - -QString ReplaceMessage(const QString &message, const Song &song, const QString &newline, const bool html_escaped = false); -QString ReplaceVariable(const QString &variable, const Song &song, const QString &newline, const bool html_escaped = false); - -bool IsColorDark(const QColor &color); - -QByteArray ReadDataFromFile(const QString &filename); -QString MimeTypeFromData(const QByteArray &data); - -#ifdef Q_OS_WIN -void enableBlurBehindWindow(QWindow *window, const QRegion ®ion); -#endif - -} // namespace Utilities - -class ScopedWCharArray { - public: - explicit ScopedWCharArray(const QString &str); - - QString ToString() const { return QString::fromWCharArray(data_.get()); } - - wchar_t *get() const { return data_.get(); } - explicit operator wchar_t *() const { return get(); } - - qint64 characters() const { return chars_; } - qint64 bytes() const { return (chars_ + 1) * sizeof(wchar_t); } - - private: - Q_DISABLE_COPY(ScopedWCharArray) - - qint64 chars_; - std::unique_ptr data_; -}; - -#endif // UTILITIES_H diff --git a/src/covermanager/albumcoverchoicecontroller.cpp b/src/covermanager/albumcoverchoicecontroller.cpp index 6db6d92b..8c17bde6 100644 --- a/src/covermanager/albumcoverchoicecontroller.cpp +++ b/src/covermanager/albumcoverchoicecontroller.cpp @@ -53,8 +53,9 @@ #include #include -#include "core/utilities.h" -#include "core/imageutils.h" +#include "utilities/strutils.h" +#include "utilities/mimeutils.h" +#include "utilities/imageutils.h" #include "core/application.h" #include "core/song.h" #include "core/iconloader.h" diff --git a/src/covermanager/albumcoverfetchersearch.cpp b/src/covermanager/albumcoverfetchersearch.cpp index a40ec0a7..cc2f6ae3 100644 --- a/src/covermanager/albumcoverfetchersearch.cpp +++ b/src/covermanager/albumcoverfetchersearch.cpp @@ -36,10 +36,10 @@ #include #include "core/logging.h" -#include "core/utilities.h" -#include "core/imageutils.h" #include "core/networkaccessmanager.h" #include "core/networktimeouts.h" +#include "utilities/imageutils.h" +#include "utilities/mimeutils.h" #include "albumcoverfetcher.h" #include "albumcoverfetchersearch.h" #include "coverprovider.h" diff --git a/src/covermanager/albumcoverloader.cpp b/src/covermanager/albumcoverloader.cpp index 599040e8..a550da46 100644 --- a/src/covermanager/albumcoverloader.cpp +++ b/src/covermanager/albumcoverloader.cpp @@ -46,8 +46,10 @@ #include "core/networkaccessmanager.h" #include "core/song.h" #include "core/tagreaderclient.h" -#include "core/utilities.h" -#include "core/imageutils.h" +#include "utilities/transliterate.h" +#include "utilities/mimeutils.h" +#include "utilities/cryptutils.h" +#include "utilities/imageutils.h" #include "settings/collectionsettingspage.h" #include "organize/organizeformat.h" #include "albumcoverloader.h" diff --git a/src/covermanager/albumcovermanager.cpp b/src/covermanager/albumcovermanager.cpp index e63301f0..225febc1 100644 --- a/src/covermanager/albumcovermanager.cpp +++ b/src/covermanager/albumcovermanager.cpp @@ -64,10 +64,12 @@ #include #include +#include "utilities/strutils.h" +#include "utilities/fileutils.h" +#include "utilities/imageutils.h" +#include "utilities/mimeutils.h" #include "core/application.h" #include "core/iconloader.h" -#include "core/utilities.h" -#include "core/imageutils.h" #include "core/tagreaderclient.h" #include "core/database.h" #include "core/sqlrow.h" diff --git a/src/covermanager/albumcoversearcher.cpp b/src/covermanager/albumcoversearcher.cpp index 7c49f8bf..ef089a70 100644 --- a/src/covermanager/albumcoversearcher.cpp +++ b/src/covermanager/albumcoversearcher.cpp @@ -48,7 +48,9 @@ #include #include "core/application.h" -#include "core/utilities.h" +#include "utilities/strutils.h" +#include "utilities/timeutils.h" +#include "utilities/mimeutils.h" #include "widgets/busyindicator.h" #include "widgets/forcescrollperpixel.h" #include "widgets/groupediconview.h" diff --git a/src/covermanager/coverfromurldialog.cpp b/src/covermanager/coverfromurldialog.cpp index 881f9a31..ec8cdc2a 100644 --- a/src/covermanager/coverfromurldialog.cpp +++ b/src/covermanager/coverfromurldialog.cpp @@ -31,7 +31,7 @@ #include #include -#include "core/utilities.h" +#include "utilities/mimeutils.h" #include "core/networkaccessmanager.h" #include "widgets/busyindicator.h" #include "albumcoverimageresult.h" diff --git a/src/covermanager/coversearchstatisticsdialog.cpp b/src/covermanager/coversearchstatisticsdialog.cpp index eaefd9b1..b30d94e5 100644 --- a/src/covermanager/coversearchstatisticsdialog.cpp +++ b/src/covermanager/coversearchstatisticsdialog.cpp @@ -30,7 +30,7 @@ #include #include -#include "core/utilities.h" +#include "utilities/strutils.h" #include "coversearchstatistics.h" #include "coversearchstatisticsdialog.h" #include "ui_coversearchstatisticsdialog.h" diff --git a/src/covermanager/discogscoverprovider.cpp b/src/covermanager/discogscoverprovider.cpp index 78b86a5b..dd77d70f 100644 --- a/src/covermanager/discogscoverprovider.cpp +++ b/src/covermanager/discogscoverprovider.cpp @@ -44,7 +44,7 @@ #include "core/application.h" #include "core/logging.h" #include "core/networkaccessmanager.h" -#include "core/utilities.h" +#include "utilities/cryptutils.h" #include "albumcoverfetcher.h" #include "jsoncoverprovider.h" #include "discogscoverprovider.h" diff --git a/src/covermanager/spotifycoverprovider.cpp b/src/covermanager/spotifycoverprovider.cpp index 115448b0..06895472 100644 --- a/src/covermanager/spotifycoverprovider.cpp +++ b/src/covermanager/spotifycoverprovider.cpp @@ -44,8 +44,8 @@ #include "core/application.h" #include "core/networkaccessmanager.h" #include "core/logging.h" -#include "core/utilities.h" -#include "core/timeconstants.h" +#include "utilities/randutils.h" +#include "utilities/timeconstants.h" #include "internet/localredirectserver.h" #include "albumcoverfetcher.h" #include "jsoncoverprovider.h" diff --git a/src/device/cddasongloader.cpp b/src/device/cddasongloader.cpp index 939dfeca..0d865b72 100644 --- a/src/device/cddasongloader.cpp +++ b/src/device/cddasongloader.cpp @@ -39,7 +39,7 @@ #include "cddasongloader.h" #include "core/logging.h" -#include "core/timeconstants.h" +#include "utilities/timeconstants.h" CddaSongLoader::CddaSongLoader(const QUrl &url, QObject *parent) : QObject(parent), diff --git a/src/device/devicemanager.cpp b/src/device/devicemanager.cpp index 3c5ea1f8..dfbc4209 100644 --- a/src/device/devicemanager.cpp +++ b/src/device/devicemanager.cpp @@ -50,8 +50,8 @@ #include "core/logging.h" #include "core/musicstorage.h" #include "core/taskmanager.h" -#include "core/utilities.h" #include "core/simpletreemodel.h" +#include "utilities/strutils.h" #include "filesystemdevice.h" #include "connecteddevice.h" #include "devicelister.h" diff --git a/src/device/deviceview.cpp b/src/device/deviceview.cpp index 848ad051..b790e4c9 100644 --- a/src/device/deviceview.cpp +++ b/src/device/deviceview.cpp @@ -54,7 +54,7 @@ #include "core/mergedproxymodel.h" #include "core/mimedata.h" #include "core/musicstorage.h" -#include "core/utilities.h" +#include "utilities/colorutils.h" #include "organize/organizedialog.h" #include "organize/organizeerrordialog.h" #include "collection/collectiondirectorymodel.h" diff --git a/src/device/udisks2lister.cpp b/src/device/udisks2lister.cpp index d1ab2e53..ef8f7add 100644 --- a/src/device/udisks2lister.cpp +++ b/src/device/udisks2lister.cpp @@ -42,7 +42,7 @@ #include #include "core/logging.h" -#include "core/utilities.h" +#include "utilities/diskutils.h" #include "udisks2lister.h" diff --git a/src/dialogs/edittagdialog.cpp b/src/dialogs/edittagdialog.cpp index 80a522f6..5ff02cbc 100644 --- a/src/dialogs/edittagdialog.cpp +++ b/src/dialogs/edittagdialog.cpp @@ -73,8 +73,10 @@ #include "core/iconloader.h" #include "core/logging.h" #include "core/tagreaderclient.h" -#include "core/utilities.h" -#include "core/imageutils.h" +#include "utilities/strutils.h" +#include "utilities/timeutils.h" +#include "utilities/imageutils.h" +#include "utilities/cryptutils.h" #include "widgets/busyindicator.h" #include "widgets/lineedit.h" #include "collection/collectionbackend.h" diff --git a/src/engine/enginebase.cpp b/src/engine/enginebase.cpp index 0b60ecda..fa84ee16 100644 --- a/src/engine/enginebase.cpp +++ b/src/engine/enginebase.cpp @@ -30,8 +30,8 @@ #include #include -#include "core/utilities.h" -#include "core/timeconstants.h" +#include "utilities/envutils.h" +#include "utilities/timeconstants.h" #include "core/networkproxyfactory.h" #include "engine_fwd.h" #include "enginebase.h" diff --git a/src/engine/gstengine.cpp b/src/engine/gstengine.cpp index 1691dd72..d73e482a 100644 --- a/src/engine/gstengine.cpp +++ b/src/engine/gstengine.cpp @@ -49,8 +49,8 @@ #include "core/logging.h" #include "core/taskmanager.h" -#include "core/timeconstants.h" #include "core/signalchecker.h" +#include "utilities/timeconstants.h" #include "enginebase.h" #include "enginetype.h" #include "gstengine.h" diff --git a/src/engine/gstengine.h b/src/engine/gstengine.h index c9f6f43e..3236f7dc 100644 --- a/src/engine/gstengine.h +++ b/src/engine/gstengine.h @@ -38,7 +38,7 @@ #include #include -#include "core/timeconstants.h" +#include "utilities/timeconstants.h" #include "engine_fwd.h" #include "enginebase.h" #include "gststartup.h" diff --git a/src/engine/gstenginepipeline.cpp b/src/engine/gstenginepipeline.cpp index c3f3eb4a..3aca4ab1 100644 --- a/src/engine/gstenginepipeline.cpp +++ b/src/engine/gstenginepipeline.cpp @@ -48,7 +48,7 @@ #include "core/logging.h" #include "core/signalchecker.h" -#include "core/timeconstants.h" +#include "utilities/timeconstants.h" #include "settings/backendsettingspage.h" #include "enginebase.h" #include "gstengine.h" diff --git a/src/engine/gststartup.cpp b/src/engine/gststartup.cpp index 2474dc5c..40b9cac7 100644 --- a/src/engine/gststartup.cpp +++ b/src/engine/gststartup.cpp @@ -36,7 +36,7 @@ #include #include "core/logging.h" -#include "core/utilities.h" +#include "utilities/envutils.h" #ifdef HAVE_MOODBAR # include "ext/gstmoodbar/gstmoodbarplugin.h" diff --git a/src/engine/vlcengine.cpp b/src/engine/vlcengine.cpp index a3a0e2ae..93ee83e3 100644 --- a/src/engine/vlcengine.cpp +++ b/src/engine/vlcengine.cpp @@ -29,9 +29,9 @@ #include #include -#include "core/timeconstants.h" #include "core/taskmanager.h" #include "core/logging.h" +#include "utilities/timeconstants.h" #include "engine_fwd.h" #include "enginebase.h" #include "enginetype.h" diff --git a/src/lyrics/auddlyricsprovider.cpp b/src/lyrics/auddlyricsprovider.cpp index 88f383fd..a70b9cb6 100644 --- a/src/lyrics/auddlyricsprovider.cpp +++ b/src/lyrics/auddlyricsprovider.cpp @@ -34,7 +34,7 @@ #include "core/logging.h" #include "core/networkaccessmanager.h" -#include "core/utilities.h" +#include "utilities/strutils.h" #include "jsonlyricsprovider.h" #include "lyricsfetcher.h" #include "lyricsprovider.h" diff --git a/src/lyrics/chartlyricsprovider.cpp b/src/lyrics/chartlyricsprovider.cpp index 7d723391..d4d199f6 100644 --- a/src/lyrics/chartlyricsprovider.cpp +++ b/src/lyrics/chartlyricsprovider.cpp @@ -31,7 +31,7 @@ #include "core/logging.h" #include "core/networkaccessmanager.h" -#include "core/utilities.h" +#include "utilities/strutils.h" #include "lyricsprovider.h" #include "lyricsfetcher.h" #include "chartlyricsprovider.h" diff --git a/src/lyrics/geniuslyricsprovider.cpp b/src/lyrics/geniuslyricsprovider.cpp index 16d460b8..a1e4a223 100644 --- a/src/lyrics/geniuslyricsprovider.cpp +++ b/src/lyrics/geniuslyricsprovider.cpp @@ -44,8 +44,9 @@ #include #include "core/logging.h" -#include "core/utilities.h" #include "core/networkaccessmanager.h" +#include "utilities/strutils.h" +#include "utilities/randutils.h" #include "internet/localredirectserver.h" #include "jsonlyricsprovider.h" #include "lyricsfetcher.h" diff --git a/src/lyrics/lololyricsprovider.cpp b/src/lyrics/lololyricsprovider.cpp index 1b725cee..dd8fdbf5 100644 --- a/src/lyrics/lololyricsprovider.cpp +++ b/src/lyrics/lololyricsprovider.cpp @@ -32,7 +32,7 @@ #include "core/logging.h" #include "core/networkaccessmanager.h" -#include "core/utilities.h" +#include "utilities/strutils.h" #include "lyricsprovider.h" #include "lyricsfetcher.h" #include "lololyricsprovider.h" diff --git a/src/lyrics/lyricsprovider.cpp b/src/lyrics/lyricsprovider.cpp index a1670209..60de2bef 100644 --- a/src/lyrics/lyricsprovider.cpp +++ b/src/lyrics/lyricsprovider.cpp @@ -23,7 +23,7 @@ #include #include -#include "core/utilities.h" +#include "utilities/strutils.h" #include "core/networkaccessmanager.h" #include "lyricsprovider.h" diff --git a/src/lyrics/musixmatchlyricsprovider.cpp b/src/lyrics/musixmatchlyricsprovider.cpp index 2130a9d6..e21935ec 100644 --- a/src/lyrics/musixmatchlyricsprovider.cpp +++ b/src/lyrics/musixmatchlyricsprovider.cpp @@ -35,7 +35,7 @@ #include "core/logging.h" #include "core/networkaccessmanager.h" -#include "core/utilities.h" +#include "utilities/strutils.h" #include "jsonlyricsprovider.h" #include "lyricsfetcher.h" #include "musixmatchlyricsprovider.h" diff --git a/src/lyrics/ovhlyricsprovider.cpp b/src/lyrics/ovhlyricsprovider.cpp index 9a414259..c1916cb2 100644 --- a/src/lyrics/ovhlyricsprovider.cpp +++ b/src/lyrics/ovhlyricsprovider.cpp @@ -29,7 +29,7 @@ #include "core/logging.h" #include "core/networkaccessmanager.h" -#include "core/utilities.h" +#include "utilities/strutils.h" #include "lyricsfetcher.h" #include "jsonlyricsprovider.h" #include "ovhlyricsprovider.h" diff --git a/src/main.cpp b/src/main.cpp index 0cfdc3ef..dd75ddfc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -77,10 +77,14 @@ # endif #endif // HAVE_QTSPARKLE +#ifdef Q_OS_MACOS +# include "utilities/macosutils.h" +# include "core/mac_startup.h" +#endif + #ifdef HAVE_DBUS # include "core/mpris2.h" #endif -#include "core/utilities.h" #include "core/metatypes.h" #include "core/iconloader.h" #include "core/mainwindow.h" @@ -175,7 +179,9 @@ int main(int argc, char *argv[]) { qsrand(t); #endif +#ifdef Q_OS_MACOS Utilities::IncreaseFDLimit(); +#endif QGuiApplication::setQuitOnLastWindowClosed(false); diff --git a/src/moodbar/moodbarpipeline.cpp b/src/moodbar/moodbarpipeline.cpp index e2ec6fbd..6e52c533 100644 --- a/src/moodbar/moodbarpipeline.cpp +++ b/src/moodbar/moodbarpipeline.cpp @@ -29,7 +29,7 @@ #include "core/logging.h" #include "core/signalchecker.h" -#include "core/utilities.h" +#include "utilities/threadutils.h" #include "moodbar/moodbarbuilder.h" #include "ext/gstmoodbar/gstfastspectrum.h" diff --git a/src/musicbrainz/acoustidclient.cpp b/src/musicbrainz/acoustidclient.cpp index b5698bdc..a8e649c4 100644 --- a/src/musicbrainz/acoustidclient.cpp +++ b/src/musicbrainz/acoustidclient.cpp @@ -43,8 +43,8 @@ #include "acoustidclient.h" #include "core/networkaccessmanager.h" #include "core/networktimeouts.h" -#include "core/timeconstants.h" #include "core/logging.h" +#include "utilities/timeconstants.h" const char *AcoustidClient::kClientId = "0qjUoxbowg"; const char *AcoustidClient::kUrl = "https://api.acoustid.org/v2/lookup"; diff --git a/src/musicbrainz/musicbrainzclient.cpp b/src/musicbrainz/musicbrainzclient.cpp index 2829497a..b9a9a2be 100644 --- a/src/musicbrainz/musicbrainzclient.cpp +++ b/src/musicbrainz/musicbrainzclient.cpp @@ -46,7 +46,7 @@ #include "core/logging.h" #include "core/networkaccessmanager.h" #include "core/networktimeouts.h" -#include "core/utilities.h" +#include "utilities/xmlutils.h" #include "musicbrainzclient.h" const char *MusicBrainzClient::kTrackUrl = "https://musicbrainz.org/ws/2/recording/"; diff --git a/src/musicbrainz/tagfetcher.cpp b/src/musicbrainz/tagfetcher.cpp index ac35e7cd..d230866b 100644 --- a/src/musicbrainz/tagfetcher.cpp +++ b/src/musicbrainz/tagfetcher.cpp @@ -29,7 +29,7 @@ #include #include -#include "core/timeconstants.h" +#include "utilities/timeconstants.h" #include "engine/chromaprinter.h" #include "acoustidclient.h" #include "musicbrainzclient.h" diff --git a/src/organize/organize.cpp b/src/organize/organize.cpp index 8b959103..0e8400e6 100644 --- a/src/organize/organize.cpp +++ b/src/organize/organize.cpp @@ -34,11 +34,11 @@ #include #include "core/logging.h" -#include "core/utilities.h" #include "core/taskmanager.h" #include "core/musicstorage.h" #include "core/tagreaderclient.h" #include "core/song.h" +#include "utilities/strutils.h" #include "organize.h" #ifdef HAVE_GSTREAMER # include "transcoder/transcoder.h" diff --git a/src/organize/organizedialog.cpp b/src/organize/organizedialog.cpp index af00af71..b1cc3488 100644 --- a/src/organize/organizedialog.cpp +++ b/src/organize/organizedialog.cpp @@ -59,7 +59,7 @@ #include "core/iconloader.h" #include "core/musicstorage.h" #include "core/tagreaderclient.h" -#include "core/utilities.h" +#include "utilities/strutils.h" #include "widgets/freespacebar.h" #include "widgets/linetextedit.h" #include "collection/collectionbackend.h" diff --git a/src/organize/organizeformat.cpp b/src/organize/organizeformat.cpp index 07cdcb64..b6175d94 100644 --- a/src/organize/organizeformat.cpp +++ b/src/organize/organizeformat.cpp @@ -38,9 +38,9 @@ #include #include "core/arraysize.h" -#include "core/timeconstants.h" -#include "core/utilities.h" #include "core/song.h" +#include "utilities/transliterate.h" +#include "utilities/timeconstants.h" #include "organizeformat.h" diff --git a/src/osd/osdbase.cpp b/src/osd/osdbase.cpp index 0ebfece1..66dcd4be 100644 --- a/src/osd/osdbase.cpp +++ b/src/osd/osdbase.cpp @@ -33,12 +33,12 @@ #include "core/application.h" #include "core/logging.h" -#include "core/utilities.h" #ifdef Q_OS_MACOS # include "core/macsystemtrayicon.h" #else # include "core/qtsystemtrayicon.h" #endif +#include "utilities/strutils.h" #include "covermanager/currentalbumcoverloader.h" const char *OSDBase::kSettingsGroup = "OSD"; diff --git a/src/osd/osdpretty.cpp b/src/osd/osdpretty.cpp index 2b6760ed..88ebeca6 100644 --- a/src/osd/osdpretty.cpp +++ b/src/osd/osdpretty.cpp @@ -64,7 +64,9 @@ # include #endif -#include "core/utilities.h" +#ifdef Q_OS_WIN +# include "utilities/winutils.h" +#endif using namespace std::chrono_literals; diff --git a/src/playlist/playlist.cpp b/src/playlist/playlist.cpp index 164536ef..1eff246f 100644 --- a/src/playlist/playlist.cpp +++ b/src/playlist/playlist.cpp @@ -63,7 +63,7 @@ #include "core/mimedata.h" #include "core/tagreaderclient.h" #include "core/song.h" -#include "core/timeconstants.h" +#include "utilities/timeconstants.h" #include "collection/collection.h" #include "collection/collectionbackend.h" #include "collection/collectionplaylistitem.h" diff --git a/src/playlist/playlistdelegates.cpp b/src/playlist/playlistdelegates.cpp index 97dfcb58..c68f2b0b 100644 --- a/src/playlist/playlistdelegates.cpp +++ b/src/playlist/playlistdelegates.cpp @@ -65,7 +65,8 @@ #include "core/logging.h" #include "core/song.h" -#include "core/utilities.h" +#include "utilities/strutils.h" +#include "utilities/timeutils.h" #include "collection/collectionbackend.h" #include "playlist/playlist.h" #include "playlistdelegates.h" diff --git a/src/playlist/playlistmanager.cpp b/src/playlist/playlistmanager.cpp index 9f312823..c558c8d9 100644 --- a/src/playlist/playlistmanager.cpp +++ b/src/playlist/playlistmanager.cpp @@ -44,7 +44,7 @@ #include "core/application.h" #include "core/player.h" -#include "core/utilities.h" +#include "utilities/timeutils.h" #include "collection/collectionbackend.h" #include "covermanager/currentalbumcoverloader.h" #include "organize/organizeformat.h" diff --git a/src/playlistparsers/asxparser.cpp b/src/playlistparsers/asxparser.cpp index e83c6427..3585c1df 100644 --- a/src/playlistparsers/asxparser.cpp +++ b/src/playlistparsers/asxparser.cpp @@ -30,7 +30,7 @@ #include #include -#include "core/utilities.h" +#include "utilities/xmlutils.h" #include "settings/playlistsettingspage.h" #include "xmlparser.h" #include "asxparser.h" diff --git a/src/playlistparsers/cueparser.cpp b/src/playlistparsers/cueparser.cpp index 37c8ae87..77eee3de 100644 --- a/src/playlistparsers/cueparser.cpp +++ b/src/playlistparsers/cueparser.cpp @@ -33,7 +33,7 @@ #include #include "core/logging.h" -#include "core/timeconstants.h" +#include "utilities/timeconstants.h" #include "settings/playlistsettingspage.h" #include "parserbase.h" #include "cueparser.h" diff --git a/src/playlistparsers/m3uparser.cpp b/src/playlistparsers/m3uparser.cpp index 33d2771b..07b383a8 100644 --- a/src/playlistparsers/m3uparser.cpp +++ b/src/playlistparsers/m3uparser.cpp @@ -28,7 +28,7 @@ #include #include "core/logging.h" -#include "core/timeconstants.h" +#include "utilities/timeconstants.h" #include "settings/playlistsettingspage.h" #include "parserbase.h" #include "m3uparser.h" diff --git a/src/playlistparsers/plsparser.cpp b/src/playlistparsers/plsparser.cpp index e76b0a52..53d54604 100644 --- a/src/playlistparsers/plsparser.cpp +++ b/src/playlistparsers/plsparser.cpp @@ -29,7 +29,7 @@ #include #include -#include "core/timeconstants.h" +#include "utilities/timeconstants.h" #include "settings/playlistsettingspage.h" #include "parserbase.h" #include "plsparser.h" diff --git a/src/playlistparsers/wplparser.cpp b/src/playlistparsers/wplparser.cpp index 9e15d733..84878c0d 100644 --- a/src/playlistparsers/wplparser.cpp +++ b/src/playlistparsers/wplparser.cpp @@ -29,7 +29,7 @@ #include #include -#include "core/utilities.h" +#include "utilities/xmlutils.h" #include "settings/playlistsettingspage.h" #include "xmlparser.h" #include "wplparser.h" diff --git a/src/playlistparsers/xspfparser.cpp b/src/playlistparsers/xspfparser.cpp index 806d4360..562ee7a7 100644 --- a/src/playlistparsers/xspfparser.cpp +++ b/src/playlistparsers/xspfparser.cpp @@ -29,8 +29,8 @@ #include #include -#include "core/timeconstants.h" -#include "core/utilities.h" +#include "utilities/xmlutils.h" +#include "utilities/timeconstants.h" #include "settings/playlistsettingspage.h" #include "xmlparser.h" #include "xspfparser.h" diff --git a/src/qobuz/qobuzrequest.cpp b/src/qobuz/qobuzrequest.cpp index b5f21cab..84f52c9e 100644 --- a/src/qobuz/qobuzrequest.cpp +++ b/src/qobuz/qobuzrequest.cpp @@ -35,9 +35,9 @@ #include "core/logging.h" #include "core/networkaccessmanager.h" #include "core/song.h" -#include "core/timeconstants.h" #include "core/application.h" -#include "core/imageutils.h" +#include "utilities/imageutils.h" +#include "utilities/timeconstants.h" #include "qobuzservice.h" #include "qobuzurlhandler.h" #include "qobuzbaserequest.h" diff --git a/src/qobuz/qobuzservice.cpp b/src/qobuz/qobuzservice.cpp index 2306a873..a92394b1 100644 --- a/src/qobuz/qobuzservice.cpp +++ b/src/qobuz/qobuzservice.cpp @@ -44,7 +44,7 @@ #include "core/networkaccessmanager.h" #include "core/database.h" #include "core/song.h" -#include "core/utilities.h" +#include "utilities/macaddrutils.h" #include "internet/internetsearchview.h" #include "collection/collectionbackend.h" #include "collection/collectionmodel.h" diff --git a/src/qobuz/qobuzstreamurlrequest.cpp b/src/qobuz/qobuzstreamurlrequest.cpp index 15600a73..d5c4931d 100644 --- a/src/qobuz/qobuzstreamurlrequest.cpp +++ b/src/qobuz/qobuzstreamurlrequest.cpp @@ -36,7 +36,7 @@ #include "core/logging.h" #include "core/networkaccessmanager.h" #include "core/song.h" -#include "core/timeconstants.h" +#include "utilities/timeconstants.h" #include "qobuzservice.h" #include "qobuzbaserequest.h" #include "qobuzstreamurlrequest.h" diff --git a/src/queue/queue.cpp b/src/queue/queue.cpp index f9725e70..88fad4c4 100644 --- a/src/queue/queue.cpp +++ b/src/queue/queue.cpp @@ -35,7 +35,7 @@ #include #include -#include "core/utilities.h" +#include "utilities/timeutils.h" #include "playlist/playlist.h" #include "queue.h" diff --git a/src/scrobbler/listenbrainzscrobbler.cpp b/src/scrobbler/listenbrainzscrobbler.cpp index 41dd8e88..158ba25b 100644 --- a/src/scrobbler/listenbrainzscrobbler.cpp +++ b/src/scrobbler/listenbrainzscrobbler.cpp @@ -43,8 +43,8 @@ #include "core/application.h" #include "core/networkaccessmanager.h" #include "core/song.h" -#include "core/timeconstants.h" #include "core/logging.h" +#include "utilities/timeconstants.h" #include "internet/localredirectserver.h" #include "settings/scrobblersettingspage.h" diff --git a/src/scrobbler/scrobblingapi20.cpp b/src/scrobbler/scrobblingapi20.cpp index 367bc47f..70777cd6 100644 --- a/src/scrobbler/scrobblingapi20.cpp +++ b/src/scrobbler/scrobblingapi20.cpp @@ -47,8 +47,8 @@ #include "core/application.h" #include "core/networkaccessmanager.h" #include "core/song.h" -#include "core/timeconstants.h" #include "core/logging.h" +#include "utilities/timeconstants.h" #include "internet/localredirectserver.h" #include "settings/scrobblersettingspage.h" diff --git a/src/scrobbler/subsonicscrobbler.cpp b/src/scrobbler/subsonicscrobbler.cpp index 7b9e5434..42deef13 100644 --- a/src/scrobbler/subsonicscrobbler.cpp +++ b/src/scrobbler/subsonicscrobbler.cpp @@ -27,8 +27,8 @@ #include "core/application.h" #include "core/song.h" -#include "core/timeconstants.h" #include "core/logging.h" +#include "utilities/timeconstants.h" #include "internet/internetservices.h" #include "settings/subsonicsettingspage.h" #include "subsonic/subsonicservice.h" diff --git a/src/settings/appearancesettingspage.cpp b/src/settings/appearancesettingspage.cpp index 52d5ce9d..a506c876 100644 --- a/src/settings/appearancesettingspage.cpp +++ b/src/settings/appearancesettingspage.cpp @@ -41,7 +41,7 @@ #include #include "appearancesettingspage.h" -#include "core/utilities.h" +#include "utilities/colorutils.h" #include "core/appearance.h" #include "core/iconloader.h" #include "core/stylehelper.h" diff --git a/src/settings/collectionsettingspage.cpp b/src/settings/collectionsettingspage.cpp index 7ea2b2a4..f88965c5 100644 --- a/src/settings/collectionsettingspage.cpp +++ b/src/settings/collectionsettingspage.cpp @@ -44,7 +44,8 @@ #include "core/application.h" #include "core/iconloader.h" -#include "core/utilities.h" +#include "utilities/strutils.h" +#include "utilities/timeutils.h" #include "collection/collection.h" #include "collection/collectionmodel.h" #include "collection/collectiondirectorymodel.h" diff --git a/src/settings/globalshortcutssettingspage.cpp b/src/settings/globalshortcutssettingspage.cpp index 0523642e..a612bf1c 100644 --- a/src/settings/globalshortcutssettingspage.cpp +++ b/src/settings/globalshortcutssettingspage.cpp @@ -40,7 +40,7 @@ #include "core/iconloader.h" #include "core/logging.h" -#include "core/utilities.h" +#include "utilities/envutils.h" #include "globalshortcuts/globalshortcutgrabber.h" #include "globalshortcuts/globalshortcutsmanager.h" #include "settingspage.h" diff --git a/src/smartplaylists/smartplaylistsearchtermwidget.cpp b/src/smartplaylists/smartplaylistsearchtermwidget.cpp index 56cf8edf..0ea0185b 100644 --- a/src/smartplaylists/smartplaylistsearchtermwidget.cpp +++ b/src/smartplaylists/smartplaylistsearchtermwidget.cpp @@ -34,7 +34,7 @@ #include #include -#include "core/utilities.h" +#include "utilities/colorutils.h" #include "core/iconloader.h" #include "playlist/playlist.h" #include "playlist/playlistdelegates.h" diff --git a/src/subsonic/subsonicbaserequest.cpp b/src/subsonic/subsonicbaserequest.cpp index 41551fdd..6c1122f6 100644 --- a/src/subsonic/subsonicbaserequest.cpp +++ b/src/subsonic/subsonicbaserequest.cpp @@ -39,7 +39,7 @@ #include #include -#include "core/utilities.h" +#include "utilities/randutils.h" #include "subsonicservice.h" #include "subsonicbaserequest.h" diff --git a/src/subsonic/subsonicrequest.cpp b/src/subsonic/subsonicrequest.cpp index 2ca9e737..b428b29f 100644 --- a/src/subsonic/subsonicrequest.cpp +++ b/src/subsonic/subsonicrequest.cpp @@ -41,9 +41,9 @@ #include "core/application.h" #include "core/logging.h" #include "core/song.h" -#include "core/timeconstants.h" -#include "core/imageutils.h" #include "core/networktimeouts.h" +#include "utilities/imageutils.h" +#include "utilities/timeconstants.h" #include "subsonicservice.h" #include "subsonicurlhandler.h" #include "subsonicbaserequest.h" diff --git a/src/subsonic/subsonicservice.cpp b/src/subsonic/subsonicservice.cpp index 6441bfa6..daa83991 100644 --- a/src/subsonic/subsonicservice.cpp +++ b/src/subsonic/subsonicservice.cpp @@ -42,7 +42,7 @@ #include #include -#include "core/utilities.h" +#include "utilities/randutils.h" #include "core/application.h" #include "core/player.h" #include "core/logging.h" diff --git a/src/tidal/tidalrequest.cpp b/src/tidal/tidalrequest.cpp index 30f915d5..42b79df0 100644 --- a/src/tidal/tidalrequest.cpp +++ b/src/tidal/tidalrequest.cpp @@ -35,9 +35,9 @@ #include "core/logging.h" #include "core/networkaccessmanager.h" #include "core/song.h" -#include "core/timeconstants.h" #include "core/application.h" -#include "core/imageutils.h" +#include "utilities/timeconstants.h" +#include "utilities/imageutils.h" #include "tidalservice.h" #include "tidalurlhandler.h" #include "tidalbaserequest.h" diff --git a/src/tidal/tidalservice.cpp b/src/tidal/tidalservice.cpp index 9f87c774..03fe6c00 100644 --- a/src/tidal/tidalservice.cpp +++ b/src/tidal/tidalservice.cpp @@ -47,8 +47,8 @@ #include "core/networkaccessmanager.h" #include "core/database.h" #include "core/song.h" -#include "core/utilities.h" -#include "core/timeconstants.h" +#include "utilities/randutils.h" +#include "utilities/timeconstants.h" #include "internet/internetsearchview.h" #include "collection/collectionbackend.h" #include "collection/collectionmodel.h" diff --git a/src/utilities/colorutils.cpp b/src/utilities/colorutils.cpp new file mode 100644 index 00000000..3f94d3b1 --- /dev/null +++ b/src/utilities/colorutils.cpp @@ -0,0 +1,41 @@ +/* + * Strawberry Music Player + * Copyright 2018-2021, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#include +#include + +#include "colorutils.h" + +namespace Utilities { + +QString ColorToRgba(const QColor &c) { + + return QString("rgba(%1, %2, %3, %4)") + .arg(c.red()) + .arg(c.green()) + .arg(c.blue()) + .arg(c.alpha()); + +} + +bool IsColorDark(const QColor &color) { + return ((30 * color.red() + 59 * color.green() + 11 * color.blue()) / 100) <= 130; +} + +} // namespace Utilities diff --git a/src/utilities/colorutils.h b/src/utilities/colorutils.h new file mode 100644 index 00000000..ac775264 --- /dev/null +++ b/src/utilities/colorutils.h @@ -0,0 +1,33 @@ +/* + * Strawberry Music Player + * Copyright 2018-2021, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#ifndef COLORUTILS_H +#define COLORUTILS_H + +#include +#include + +namespace Utilities { + +QString ColorToRgba(const QColor &color); +bool IsColorDark(const QColor &color); + +} // namespace Utilities + +#endif // COLORUTILS_H diff --git a/src/utilities/cryptutils.cpp b/src/utilities/cryptutils.cpp new file mode 100644 index 00000000..fea526c4 --- /dev/null +++ b/src/utilities/cryptutils.cpp @@ -0,0 +1,75 @@ +/* + * Strawberry Music Player + * Copyright 2018-2021, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#include +#include +#include + +#include "cryptutils.h" + +namespace Utilities { + +QByteArray Hmac(const QByteArray &key, const QByteArray &data, const QCryptographicHash::Algorithm method) { + + constexpr int block_size = 64; + Q_ASSERT(key.length() <= block_size); + + QByteArray inner_padding(block_size, static_cast(0x36)); + QByteArray outer_padding(block_size, static_cast(0x5c)); + + for (int i = 0; i < key.length(); ++i) { + inner_padding[i] = static_cast(inner_padding[i] ^ key[i]); + outer_padding[i] = static_cast(outer_padding[i] ^ key[i]); + } + + QByteArray part; + part.append(inner_padding); + part.append(data); + + QByteArray total; + total.append(outer_padding); + total.append(QCryptographicHash::hash(part, method)); + + return QCryptographicHash::hash(total, method); + +} + +QByteArray HmacSha256(const QByteArray &key, const QByteArray &data) { + return Hmac(key, data, QCryptographicHash::Sha256); +} + +QByteArray HmacMd5(const QByteArray &key, const QByteArray &data) { + return Hmac(key, data, QCryptographicHash::Md5); +} + +QByteArray HmacSha1(const QByteArray &key, const QByteArray &data) { + return Hmac(key, data, QCryptographicHash::Sha1); +} + +QByteArray Sha1CoverHash(const QString &artist, const QString &album) { + + QCryptographicHash hash(QCryptographicHash::Sha1); + hash.addData(artist.toLower().toUtf8()); + hash.addData(album.toLower().toUtf8()); + + return hash.result(); + +} + +} // namespace Utilities diff --git a/src/utilities/cryptutils.h b/src/utilities/cryptutils.h new file mode 100644 index 00000000..bfb2ae13 --- /dev/null +++ b/src/utilities/cryptutils.h @@ -0,0 +1,37 @@ +/* + * Strawberry Music Player + * Copyright 2018-2021, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#ifndef CRYPTUTILS_H +#define CRYPTUTILS_H + +#include +#include +#include + +namespace Utilities { + +QByteArray Hmac(const QByteArray &key, const QByteArray &data, const QCryptographicHash::Algorithm method); +QByteArray HmacMd5(const QByteArray &key, const QByteArray &data); +QByteArray HmacSha256(const QByteArray &key, const QByteArray &data); +QByteArray HmacSha1(const QByteArray &key, const QByteArray &data); +QByteArray Sha1CoverHash(const QString &artist, const QString &album); + +} // namespace Utilities + +#endif // CRYPTUTILS_H diff --git a/src/utilities/diskutils.cpp b/src/utilities/diskutils.cpp new file mode 100644 index 00000000..dda380a6 --- /dev/null +++ b/src/utilities/diskutils.cpp @@ -0,0 +1,76 @@ +/* + * Strawberry Music Player + * Copyright 2010, David Sansome + * Copyright 2018-2021, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#include + +#ifdef Q_OS_UNIX +# include +#endif + +#ifdef Q_OS_WIN +# include +#endif + +#include +#include + +#include "diskutils.h" + +#ifdef Q_OS_WIN32 +# include "core/scopedwchararray.h" +#endif + +namespace Utilities { + +quint64 FileSystemCapacity(const QString &path) { + +#if defined(Q_OS_UNIX) + struct statvfs fs_info {}; + if (statvfs(path.toLocal8Bit().constData(), &fs_info) == 0) + return static_cast(fs_info.f_blocks) * static_cast(fs_info.f_bsize); +#elif defined(Q_OS_WIN32) + _ULARGE_INTEGER ret; + ScopedWCharArray wchar(QDir::toNativeSeparators(path)); + if (GetDiskFreeSpaceEx(wchar.get(), nullptr, &ret, nullptr) != 0) + return ret.QuadPart; +#endif + + return 0; + +} + +quint64 FileSystemFreeSpace(const QString &path) { + +#if defined(Q_OS_UNIX) + struct statvfs fs_info {}; + if (statvfs(path.toLocal8Bit().constData(), &fs_info) == 0) + return static_cast(fs_info.f_bavail) * static_cast(fs_info.f_bsize); +#elif defined(Q_OS_WIN32) + _ULARGE_INTEGER ret; + ScopedWCharArray wchar(QDir::toNativeSeparators(path)); + if (GetDiskFreeSpaceEx(wchar.get(), &ret, nullptr, nullptr) != 0) + return ret.QuadPart; +#endif + + return 0; + +} + +} // namespace Utilities diff --git a/src/utilities/diskutils.h b/src/utilities/diskutils.h new file mode 100644 index 00000000..397f266f --- /dev/null +++ b/src/utilities/diskutils.h @@ -0,0 +1,33 @@ +/* + * Strawberry Music Player + * Copyright 2010, David Sansome + * Copyright 2018-2021, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#ifndef DISKUTILS_H +#define DISKUTILS_H + +#include + +namespace Utilities { + +quint64 FileSystemCapacity(const QString &path); +quint64 FileSystemFreeSpace(const QString &path); + +} // namespace Utilities + +#endif // DISKUTILS_H diff --git a/src/utilities/envutils.cpp b/src/utilities/envutils.cpp new file mode 100644 index 00000000..9709ccc1 --- /dev/null +++ b/src/utilities/envutils.cpp @@ -0,0 +1,73 @@ +/* + * Strawberry Music Player + * Copyright 2018-2021, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#include + +#include +#include +#include +#include + +#include "envutils.h" + +namespace Utilities { + +QString GetEnv(const QString &key) { + const QByteArray key_data = key.toLocal8Bit(); + return QString::fromLocal8Bit(qgetenv(key_data.constData())); +} + +void SetEnv(const char *key, const QString &value) { + +#ifdef Q_OS_WIN32 + _putenv(QString("%1=%2").arg(key, value).toLocal8Bit().constData()); +#else + setenv(key, value.toLocal8Bit().constData(), 1); +#endif + +} + +QString DesktopEnvironment() { + + const QString de = GetEnv("XDG_CURRENT_DESKTOP"); + if (!de.isEmpty()) return de; + + if (!qEnvironmentVariableIsEmpty("KDE_FULL_SESSION")) return "KDE"; + if (!qEnvironmentVariableIsEmpty("GNOME_DESKTOP_SESSION_ID")) return "Gnome"; + + QString session = GetEnv("DESKTOP_SESSION"); + qint64 slash = session.lastIndexOf('/'); + if (slash != -1) { + QSettings desktop_file(QString(session + ".desktop"), QSettings::IniFormat); + desktop_file.beginGroup("Desktop Entry"); + QString name = desktop_file.value("DesktopNames").toString(); + desktop_file.endGroup(); + if (!name.isEmpty()) return name; + session = session.mid(slash + 1); + } + + if (session == "kde") return "KDE"; + else if (session == "gnome") return "Gnome"; + else if (session == "xfce") return "XFCE"; + + return "Unknown"; + +} + +} // namespace Utilities diff --git a/src/utilities/envutils.h b/src/utilities/envutils.h new file mode 100644 index 00000000..48a14598 --- /dev/null +++ b/src/utilities/envutils.h @@ -0,0 +1,33 @@ +/* + * Strawberry Music Player + * Copyright 2018-2021, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#ifndef ENVUTILS_H +#define ENVUTILS_H + +#include + +namespace Utilities { + +QString GetEnv(const QString &key); +void SetEnv(const char *key, const QString &value); +QString DesktopEnvironment(); + +} // namespace Utilities + +#endif // ENVUTILS_H diff --git a/src/utilities/filemanagerutils.cpp b/src/utilities/filemanagerutils.cpp new file mode 100644 index 00000000..4d396e1d --- /dev/null +++ b/src/utilities/filemanagerutils.cpp @@ -0,0 +1,167 @@ +/* + * Strawberry Music Player + * Copyright 2018-2021, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "filemanagerutils.h" + +namespace Utilities { + +#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) +void OpenInFileManager(const QString &path, const QUrl &url); +void OpenInFileManager(const QString &path, const QUrl &url) { + + if (!url.isLocalFile()) return; + + QProcess proc; +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + proc.startCommand("xdg-mime query default inode/directory"); +#else + proc.start("xdg-mime", QStringList() << "query" << "default" << "inode/directory"); +#endif + proc.waitForFinished(); + QString desktop_file = proc.readLine().simplified(); + QStringList data_dirs = QString(qgetenv("XDG_DATA_DIRS")).split(":"); + + QString command; + QStringList command_params; + for (const QString &data_dir : data_dirs) { + QString desktop_file_path = QString("%1/applications/%2").arg(data_dir, desktop_file); + if (!QFile::exists(desktop_file_path)) continue; + QSettings setting(desktop_file_path, QSettings::IniFormat); + setting.beginGroup("Desktop Entry"); + if (setting.contains("Exec")) { + QString cmd = setting.value("Exec").toString(); + if (cmd.isEmpty()) break; + cmd = cmd.remove(QRegularExpression("[%][a-zA-Z]*( |$)", QRegularExpression::CaseInsensitiveOption)); +# if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + command_params = cmd.split(' ', Qt::SkipEmptyParts); +# else + command_params = cmd.split(' ', QString::SkipEmptyParts); +# endif + command = command_params.first(); + command_params.removeFirst(); + } + setting.endGroup(); + if (!command.isEmpty()) break; + } + + if (command.startsWith("/usr/bin/")) { + command = command.split("/").last(); + } + + if (command.isEmpty() || command == "exo-open") { + QDesktopServices::openUrl(QUrl::fromLocalFile(path)); + } + else if (command.startsWith("nautilus")) { + proc.startDetached(command, QStringList() << command_params << "--select" << url.toLocalFile()); + } + else if (command.startsWith("dolphin") || command.startsWith("konqueror") || command.startsWith("kfmclient")) { + proc.startDetached(command, QStringList() << command_params << "--select" << "--new-window" << url.toLocalFile()); + } + else if (command.startsWith("caja")) { + proc.startDetached(command, QStringList() << command_params << "--no-desktop" << path); + } + else if (command.startsWith("pcmanfm") || command.startsWith("thunar") || command.startsWith("spacefm")) { + proc.startDetached(command, QStringList() << command_params << path); + } + else { + proc.startDetached(command, QStringList() << command_params << url.toLocalFile()); + } + +} +#endif + +#ifdef Q_OS_MACOS +// Better than openUrl(dirname(path)) - also highlights file at path +void RevealFileInFinder(const QString &path) { + QProcess::execute("/usr/bin/open", QStringList() << "-R" << path); +} +#endif // Q_OS_MACOS + +#ifdef Q_OS_WIN +void ShowFileInExplorer(const QString &path); +void ShowFileInExplorer(const QString &path) { + QProcess::execute("explorer.exe", QStringList() << "/select," << QDir::toNativeSeparators(path)); +} +#endif + +void OpenInFileBrowser(const QList &urls) { + + QMap dirs; + + for (const QUrl &url : urls) { + if (!url.isLocalFile()) { + continue; + } + QString path = url.toLocalFile(); + if (!QFile::exists(path)) continue; + + const QString directory = QFileInfo(path).dir().path(); + if (dirs.contains(directory)) continue; + dirs.insert(directory, url); + } + + if (dirs.count() > 50) { + QMessageBox messagebox(QMessageBox::Critical, QObject::tr("Show in file browser"), QObject::tr("Too many songs selected.")); + messagebox.exec(); + return; + } + + if (dirs.count() > 5) { + QMessageBox messagebox(QMessageBox::Information, QObject::tr("Show in file browser"), QObject::tr("%1 songs in %2 different directories selected, are you sure you want to open them all?").arg(urls.count()).arg(dirs.count()), QMessageBox::Open|QMessageBox::Cancel); + messagebox.setTextFormat(Qt::RichText); + int result = messagebox.exec(); + switch (result) { + case QMessageBox::Open: + break; + case QMessageBox::Cancel: + default: + return; + } + } + + QMap::iterator i; + for (i = dirs.begin(); i != dirs.end(); ++i) { +#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) + OpenInFileManager(i.key(), i.value()); +#elif defined(Q_OS_MACOS) + // Revealing multiple files in the finder only opens one window, so it also makes sense to reveal at most one per directory + RevealFileInFinder(i.value().toLocalFile()); +#elif defined(Q_OS_WIN32) + ShowFileInExplorer(i.value().toLocalFile()); +#endif + } + +} + +} diff --git a/src/utilities/filemanagerutils.h b/src/utilities/filemanagerutils.h new file mode 100644 index 00000000..522cb705 --- /dev/null +++ b/src/utilities/filemanagerutils.h @@ -0,0 +1,32 @@ +/* + * Strawberry Music Player + * Copyright 2018-2021, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#ifndef FILEMANAGERUTILS_H +#define FILEMANAGERUTILS_H + +#include +#include + +namespace Utilities { + +void OpenInFileBrowser(const QList &urls); + +} // namespace Utilities + +#endif // FILEMANAGERUTILS_H diff --git a/src/utilities/fileutils.cpp b/src/utilities/fileutils.cpp new file mode 100644 index 00000000..d263f371 --- /dev/null +++ b/src/utilities/fileutils.cpp @@ -0,0 +1,127 @@ +/* + * Strawberry Music Player + * Copyright 2010, David Sansome + * Copyright 2018-2021, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#include + +#include + +#include +#include +#include +#include +#include + +#include "core/logging.h" + +#include "fileutils.h" + +namespace Utilities { + +QByteArray ReadDataFromFile(const QString &filename) { + + QFile file(filename); + QByteArray data; + if (file.open(QIODevice::ReadOnly)) { + data = file.readAll(); + file.close(); + } + else { + qLog(Error) << "Failed to open file" << filename << "for reading:" << file.errorString(); + } + return data; + +} + +bool Copy(QIODevice *source, QIODevice *destination) { + + if (!source->open(QIODevice::ReadOnly)) return false; + + if (!destination->open(QIODevice::WriteOnly)) return false; + + const qint64 bytes = source->size(); + std::unique_ptr data(new char[bytes]); + qint64 pos = 0; + + qint64 bytes_read = 0; + do { + bytes_read = source->read(data.get() + pos, bytes - pos); + if (bytes_read == -1) return false; + + pos += bytes_read; + } while (bytes_read > 0 && pos != bytes); + + pos = 0; + qint64 bytes_written = 0; + do { + bytes_written = destination->write(data.get() + pos, bytes - pos); + if (bytes_written == -1) return false; + + pos += bytes_written; + } while (bytes_written > 0 && pos != bytes); + + return true; + +} + +bool CopyRecursive(const QString &source, const QString &destination) { + + // Make the destination directory + QString dir_name = source.section('/', -1, -1); + QString dest_path = destination + "/" + dir_name; + QDir().mkpath(dest_path); + + QDir dir(source); + for (const QString &child : dir.entryList(QDir::NoDotAndDotDot | QDir::Dirs)) { + if (!CopyRecursive(source + "/" + child, dest_path)) { + qLog(Warning) << "Failed to copy dir" << source + "/" + child << "to" << dest_path; + return false; + } + } + + for (const QString &child : dir.entryList(QDir::NoDotAndDotDot | QDir::Files)) { + if (!QFile::copy(source + "/" + child, dest_path + "/" + child)) { + qLog(Warning) << "Failed to copy file" << source + "/" + child << "to" << dest_path; + return false; + } + } + return true; + +} + +bool RemoveRecursive(const QString &path) { + + QDir dir(path); + for (const QString &child : dir.entryList(QDir::NoDotAndDotDot | QDir::Dirs | QDir::Hidden)) { + if (!RemoveRecursive(path + "/" + child)) { + return false; + } + } + + for (const QString &child : dir.entryList(QDir::NoDotAndDotDot | QDir::Files | QDir::Hidden)) { + if (!QFile::remove(path + "/" + child)) { + return false; + } + } + + return dir.rmdir(path); + +} + +} // namespace Utilities diff --git a/src/utilities/fileutils.h b/src/utilities/fileutils.h new file mode 100644 index 00000000..0cc23335 --- /dev/null +++ b/src/utilities/fileutils.h @@ -0,0 +1,37 @@ +/* + * Strawberry Music Player + * Copyright 2010, David Sansome + * Copyright 2018-2021, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#ifndef FILEUTILS_H +#define FILEUTILS_H + +#include + +class QIODevice; + +namespace Utilities { + +QByteArray ReadDataFromFile(const QString &filename); +bool Copy(QIODevice *source, QIODevice *destination); +bool CopyRecursive(const QString &source, const QString &destination); +bool RemoveRecursive(const QString &path); + +} // namespace Utilities + +#endif // FILEUTILS_H diff --git a/src/core/imageutils.cpp b/src/utilities/imageutils.cpp similarity index 99% rename from src/core/imageutils.cpp rename to src/utilities/imageutils.cpp index 297625e3..5ecd29d8 100644 --- a/src/core/imageutils.cpp +++ b/src/utilities/imageutils.cpp @@ -17,8 +17,6 @@ * */ -#include "config.h" - #include #include #include @@ -32,7 +30,8 @@ #include #include "imageutils.h" -#include "core/utilities.h" +#include "fileutils.h" +#include "mimeutils.h" #include "core/tagreaderclient.h" QStringList ImageUtils::kSupportedImageMimeTypes; diff --git a/src/core/imageutils.h b/src/utilities/imageutils.h similarity index 98% rename from src/core/imageutils.h rename to src/utilities/imageutils.h index 257f3178..29cb8400 100644 --- a/src/core/imageutils.h +++ b/src/utilities/imageutils.h @@ -20,8 +20,6 @@ #ifndef IMAGEUTILS_H #define IMAGEUTILS_H -#include "config.h" - #include #include #include diff --git a/src/utilities/macaddrutils.cpp b/src/utilities/macaddrutils.cpp new file mode 100644 index 00000000..44f9f0b0 --- /dev/null +++ b/src/utilities/macaddrutils.cpp @@ -0,0 +1,54 @@ +/* + * Strawberry Music Player + * Copyright 2019-2021, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#include +#include +#include + +#include "macaddrutils.h" + +namespace Utilities { + +QString MacAddress() { + + QString ret; + + for (QNetworkInterface &netif : QNetworkInterface::allInterfaces()) { + if ( + (netif.hardwareAddress() == "00:00:00:00:00:00") || + (netif.flags() & QNetworkInterface::IsLoopBack) || + !(netif.flags() & QNetworkInterface::IsUp) || + !(netif.flags() & QNetworkInterface::IsRunning) + ) { continue; } + if (ret.isEmpty() +#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)) + || netif.type() == QNetworkInterface::Ethernet || netif.type() == QNetworkInterface::Wifi +#endif + ) { + ret = netif.hardwareAddress(); + } + } + + if (ret.isEmpty()) ret = "00:00:00:00:00:00"; + + return ret; + +} + +} // namespace Utilities diff --git a/src/core/mac_utilities.mm b/src/utilities/macaddrutils.h similarity index 74% rename from src/core/mac_utilities.mm rename to src/utilities/macaddrutils.h index 3e441cf1..67fc34eb 100644 --- a/src/core/mac_utilities.mm +++ b/src/utilities/macaddrutils.h @@ -17,20 +17,15 @@ * */ -#include "config.h" +#ifndef MACADDRUTILS_H +#define MACADDRUTILS_H -#include - -#import -#import +#include namespace Utilities { -qint32 GetMacOsVersion() { - - NSOperatingSystemVersion version = [ [NSProcessInfo processInfo] operatingSystemVersion]; - return version.minorVersion; - -} +QString MacAddress(); } // namespace Utilities + +#endif // MACADDRUTILS_H diff --git a/src/core/mac_utilities.h b/src/utilities/macosutils.h similarity index 74% rename from src/core/mac_utilities.h rename to src/utilities/macosutils.h index 1b1f9c6e..2e111cf6 100644 --- a/src/core/mac_utilities.h +++ b/src/utilities/macosutils.h @@ -19,26 +19,14 @@ * */ -#include "config.h" - -#include -#include - -#include - -#ifdef __OBJC__ -@class NSEvent; -#else -class NSEvent; -#endif - -namespace mac { - -QKeySequence KeySequenceFromNSEvent(NSEvent *event); -void DumpDictionary(CFDictionaryRef dict); - -} // namespace mac +#ifndef MACOSUTILS_H +#define MACOSUTILS_H namespace Utilities { + qint32 GetMacOsVersion(); -} +void IncreaseFDLimit(); + +} // namespace Utilities + +#endif // MACOSUTILS_H diff --git a/src/utilities/macosutils.mm b/src/utilities/macosutils.mm new file mode 100644 index 00000000..543cf88d --- /dev/null +++ b/src/utilities/macosutils.mm @@ -0,0 +1,62 @@ +/* + * Strawberry Music Player + * Copyright 2019-2021, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#include + +#include +#include +#include + +#import +#import + +#include "macosutils.h" + +#include "core/logging.h" + +namespace Utilities { + +qint32 GetMacOsVersion() { + + NSOperatingSystemVersion version = [ [NSProcessInfo processInfo] operatingSystemVersion]; + return version.minorVersion; + +} + +void IncreaseFDLimit() { + + // Bump the soft limit for the number of file descriptors from the default of 256 to the maximum (usually 10240). + struct rlimit limit; + getrlimit(RLIMIT_NOFILE, &limit); + + // getrlimit() lies about the hard limit so we have to check sysctl. + int max_fd = 0; + size_t len = sizeof(max_fd); + sysctlbyname("kern.maxfilesperproc", &max_fd, &len, nullptr, 0); + + limit.rlim_cur = max_fd; + int ret = setrlimit(RLIMIT_NOFILE, &limit); + + if (ret == 0) { + qLog(Debug) << "Max fd:" << max_fd; + } + +} + +} // namespace Utilities diff --git a/src/utilities/mimeutils.cpp b/src/utilities/mimeutils.cpp new file mode 100644 index 00000000..63721315 --- /dev/null +++ b/src/utilities/mimeutils.cpp @@ -0,0 +1,36 @@ +/* + * Strawberry Music Player + * Copyright 2018-2021, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#include +#include +#include + +#include "mimeutils.h" + +namespace Utilities { + +QString MimeTypeFromData(const QByteArray &data) { + + if (data.isEmpty()) return QString(); + + return QMimeDatabase().mimeTypeForData(data).name(); + +} + +} // namespace Utilities diff --git a/src/utilities/mimeutils.h b/src/utilities/mimeutils.h new file mode 100644 index 00000000..f20c1ae4 --- /dev/null +++ b/src/utilities/mimeutils.h @@ -0,0 +1,32 @@ +/* + * Strawberry Music Player + * Copyright 2018-2021, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#ifndef MIMEUTILS_H +#define MIMEUTILS_H + +#include +#include + +namespace Utilities { + +QString MimeTypeFromData(const QByteArray &data); + +} // namespace Utilities + +#endif // MIMEUTILS_H diff --git a/src/utilities/randutils.cpp b/src/utilities/randutils.cpp new file mode 100644 index 00000000..6556f3bc --- /dev/null +++ b/src/utilities/randutils.cpp @@ -0,0 +1,63 @@ +/* + * Strawberry Music Player + * Copyright 2018-2021, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#include +#include + +#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) +# include +#endif + +#include "randutils.h" + +namespace Utilities { + +QString GetRandomStringWithChars(const int len) { + const QString UseCharacters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); + return GetRandomString(len, UseCharacters); +} + +QString GetRandomStringWithCharsAndNumbers(const int len) { + const QString UseCharacters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"); + return GetRandomString(len, UseCharacters); +} + +QString CryptographicRandomString(const int len) { + const QString UseCharacters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~"); + return GetRandomString(len, UseCharacters); +} + +QString GetRandomString(const int len, const QString &UseCharacters) { + + QString randstr; + for (int i = 0; i < len; ++i) { +#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) + const qint64 index = QRandomGenerator::global()->bounded(0, UseCharacters.length()); +#else + const int index = qrand() % UseCharacters.length(); +#endif + QChar nextchar = UseCharacters.at(index); + randstr.append(nextchar); + } + + return randstr; + +} + +} // namespace Utilities diff --git a/src/utilities/randutils.h b/src/utilities/randutils.h new file mode 100644 index 00000000..ced3f868 --- /dev/null +++ b/src/utilities/randutils.h @@ -0,0 +1,34 @@ +/* + * Strawberry Music Player + * Copyright 2018-2021, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#ifndef RANDUTILS_H +#define RANDUTILS_H + +#include + +namespace Utilities { + +QString GetRandomStringWithChars(const int len); +QString GetRandomStringWithCharsAndNumbers(const int len); +QString CryptographicRandomString(const int len); +QString GetRandomString(const int len, const QString &UseCharacters); + +} // namespace Utilities + +#endif // RANDUTILS_H diff --git a/src/utilities/strutils.cpp b/src/utilities/strutils.cpp new file mode 100644 index 00000000..c254b982 --- /dev/null +++ b/src/utilities/strutils.cpp @@ -0,0 +1,204 @@ +/* + * Strawberry Music Player + * Copyright 2010, David Sansome + * Copyright 2018-2021, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#include +#include +#include +#include +#include + +#include "strutils.h" +#include "core/song.h" + +namespace Utilities { + +QString PrettySize(const quint64 bytes) { + + QString ret; + + if (bytes > 0) { + if (bytes <= 1000) { + ret = QString::number(bytes) + " bytes"; + } + else if (bytes <= 1000 * 1000) { + ret = QString::asprintf("%.1f KB", static_cast(bytes) / 1000.0F); + } + else if (bytes <= 1000 * 1000 * 1000) { + ret = QString::asprintf("%.1f MB", static_cast(bytes) / (1000.0F * 1000.0F)); + } + else { + ret = QString::asprintf("%.1f GB", static_cast(bytes) / (1000.0F * 1000.0F * 1000.0F)); + } + } + return ret; + +} + +QString PrettySize(const QSize size) { + return QString::number(size.width()) + "x" + QString::number(size.height()); +} + +QString PathWithoutFilenameExtension(const QString &filename) { + if (filename.section('/', -1, -1).contains('.')) return filename.section('.', 0, -2); + return filename; +} + +QString FiddleFileExtension(const QString &filename, const QString &new_extension) { + return PathWithoutFilenameExtension(filename) + "." + new_extension; +} + +const char *EnumToString(const QMetaObject &meta, const char *name, const int value) { + + int index = meta.indexOfEnumerator(name); + if (index == -1) return "[UnknownEnum]"; + QMetaEnum metaenum = meta.enumerator(index); + const char *result = metaenum.valueToKey(value); + if (!result) return "[UnknownEnumValue]"; + return result; + +} + +QStringList Prepend(const QString &text, const QStringList &list) { + + QStringList ret(list); + for (int i = 0; i < ret.count(); ++i) ret[i].prepend(text); + return ret; + +} + +QStringList Updateify(const QStringList &list) { + + QStringList ret(list); + for (int i = 0; i < ret.count(); ++i) ret[i].prepend(ret[i] + " = :"); + return ret; + +} + +QString DecodeHtmlEntities(const QString &text) { + + QString copy(text); + copy.replace("&", "&") + .replace("&", "&") + .replace(""", "\"") + .replace(""", "\"") + .replace("'", "'") + .replace("'", "'") + .replace("<", "<") + .replace("<", "<") + .replace(">", ">") + .replace(">", ">") + .replace("'", "'"); + + return copy; + +} + +QString ReplaceMessage(const QString &message, const Song &song, const QString &newline, const bool html_escaped) { + + QRegularExpression variable_replacer("[%][a-z]+[%]"); + QString copy(message); + + // Replace the first line + qint64 pos = 0; + QRegularExpressionMatch match; + for (match = variable_replacer.match(message, pos); match.hasMatch(); match = variable_replacer.match(message, pos)) { + pos = match.capturedStart(); + QStringList captured = match.capturedTexts(); + copy.replace(captured[0], ReplaceVariable(captured[0], song, newline, html_escaped)); + pos += match.capturedLength(); + } + + qint64 index_of = copy.indexOf(QRegularExpression(" - (>|$)")); + if (index_of >= 0) copy = copy.remove(index_of, 3); + + return copy; + +} + +QString ReplaceVariable(const QString &variable, const Song &song, const QString &newline, const bool html_escaped) { + + QString value = variable; + + if (variable == "%title%") { + value = song.PrettyTitle(); + } + else if (variable == "%album%") { + value = song.album(); + } + else if (variable == "%artist%") { + value = song.artist(); + } + else if (variable == "%albumartist%") { + value = song.effective_albumartist(); + } + else if (variable == "%track%") { + value.setNum(song.track()); + } + else if (variable == "%disc%") { + value.setNum(song.disc()); + } + else if (variable == "%year%") { + value = song.PrettyYear(); + } + else if (variable == "%originalyear%") { + value = song.PrettyOriginalYear(); + } + else if (variable == "%genre%") { + value = song.genre(); + } + else if (variable == "%composer%") { + value = song.composer(); + } + else if (variable == "%performer%") { + value = song.performer(); + } + else if (variable == "%grouping%") { + value = song.grouping(); + } + else if (variable == "%length%") { + value = song.PrettyLength(); + } + else if (variable == "%filename%") { + value = song.basefilename(); + } + else if (variable == "%url%") { + value = song.url().toString(); + } + else if (variable == "%playcount%") { + value.setNum(song.playcount()); + } + else if (variable == "%skipcount%") { + value.setNum(song.skipcount()); + } + else if (variable == "%rating%") { + value = song.PrettyRating(); + } + else if (variable == "%newline%") { + return QString(newline); // No HTML escaping, return immediately. + } + + if (html_escaped) { + value = value.toHtmlEscaped(); + } + return value; + +} + +} // namespace Utilities diff --git a/src/utilities/strutils.h b/src/utilities/strutils.h new file mode 100644 index 00000000..621a64be --- /dev/null +++ b/src/utilities/strutils.h @@ -0,0 +1,54 @@ +/* + * Strawberry Music Player + * Copyright 2010, David Sansome + * Copyright 2018-2021, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#ifndef STRUTILS_H +#define STRUTILS_H + +#include +#include +#include + +#include "core/song.h" + +namespace Utilities { + +QString PrettySize(const quint64 bytes); +QString PrettySize(const QSize size); + +// Get the path without the filename extension +QString PathWithoutFilenameExtension(const QString &filename); +QString FiddleFileExtension(const QString &filename, const QString &new_extension); + +// Replaces some HTML entities with their normal characters. +QString DecodeHtmlEntities(const QString &text); + +// Shortcut for getting a Qt-aware enum value as a string. +// Pass in the QMetaObject of the class that owns the enum, the string name of the enum and a valid value from that enum. +const char *EnumToString(const QMetaObject &meta, const char *name, int value); + +QStringList Prepend(const QString &text, const QStringList &list); +QStringList Updateify(const QStringList &list); + +QString ReplaceMessage(const QString &message, const Song &song, const QString &newline, const bool html_escaped = false); +QString ReplaceVariable(const QString &variable, const Song &song, const QString &newline, const bool html_escaped = false); + +} // namespace Utilities + +#endif // STRUTILS_H diff --git a/src/utilities/threadutils.cpp b/src/utilities/threadutils.cpp new file mode 100644 index 00000000..334ee4d9 --- /dev/null +++ b/src/utilities/threadutils.cpp @@ -0,0 +1,59 @@ +/* + * Strawberry Music Player + * Copyright 2010, David Sansome + * Copyright 2018-2021, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#include + +#ifdef Q_OS_LINUX +# include +# include +#endif + +#ifdef Q_OS_MACOS +# include +#endif + +#include "threadutils.h" + +namespace Utilities { + +long SetThreadIOPriority(const IoPriority priority) { + +#ifdef Q_OS_LINUX + return syscall(SYS_ioprio_set, IOPRIO_WHO_PROCESS, GetThreadId(), 4 | priority << IOPRIO_CLASS_SHIFT); +#elif defined(Q_OS_MACOS) + return setpriority(PRIO_DARWIN_THREAD, 0, priority == IOPRIO_CLASS_IDLE ? PRIO_DARWIN_BG : 0); +#else + Q_UNUSED(priority); + return 0; +#endif + +} + +long GetThreadId() { + +#ifdef Q_OS_LINUX + return syscall(SYS_gettid); +#else + return 0; +#endif + +} + +} // namespace Utilities diff --git a/src/utilities/threadutils.h b/src/utilities/threadutils.h new file mode 100644 index 00000000..78f41a5c --- /dev/null +++ b/src/utilities/threadutils.h @@ -0,0 +1,45 @@ +/* + * Strawberry Music Player + * Copyright 2010, David Sansome + * Copyright 2018-2021, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#ifndef THREADUTILS_H +#define THREADUTILS_H + +namespace Utilities { + +// Borrowed from schedutils +enum IoPriority { + IOPRIO_CLASS_NONE = 0, + IOPRIO_CLASS_RT, + IOPRIO_CLASS_BE, + IOPRIO_CLASS_IDLE, +}; +enum { + IOPRIO_WHO_PROCESS = 1, + IOPRIO_WHO_PGRP, + IOPRIO_WHO_USER, +}; +static const int IOPRIO_CLASS_SHIFT = 13; + +long SetThreadIOPriority(const IoPriority priority); +long GetThreadId(); + +} // namespace Utilities + +#endif // THREADUTILS_H diff --git a/src/core/timeconstants.h b/src/utilities/timeconstants.h similarity index 100% rename from src/core/timeconstants.h rename to src/utilities/timeconstants.h diff --git a/src/utilities/timeutils.cpp b/src/utilities/timeutils.cpp new file mode 100644 index 00000000..6afcf024 --- /dev/null +++ b/src/utilities/timeutils.cpp @@ -0,0 +1,152 @@ +/* + * Strawberry Music Player + * Copyright 2010, David Sansome + * Copyright 2018-2021, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "timeconstants.h" +#include "timeutils.h" + +namespace Utilities { + +QString PrettyTime(int seconds) { + + // last.fm sometimes gets the track length wrong, so you end up with negative times. + seconds = qAbs(seconds); + + int hours = seconds / (60 * 60); + int minutes = (seconds / 60) % 60; + seconds %= 60; + + QString ret; + if (hours > 0) ret = QString::asprintf("%d:%02d:%02d", hours, minutes, seconds); + else ret = QString::asprintf("%d:%02d", minutes, seconds); + + return ret; + +} + +QString PrettyTimeDelta(const int seconds) { + return (seconds >= 0 ? "+" : "-") + PrettyTime(seconds); +} + +QString PrettyTimeNanosec(const qint64 nanoseconds) { + return PrettyTime(static_cast(nanoseconds / kNsecPerSec)); +} + +QString WordyTime(const quint64 seconds) { + + quint64 days = seconds / (60 * 60 * 24); + + // TODO: Make the plural rules translatable + QStringList parts; + + if (days > 0) parts << (days == 1 ? QObject::tr("1 day") : QObject::tr("%1 days").arg(days)); + parts << PrettyTime(static_cast(seconds - days * 60 * 60 * 24)); + + return parts.join(" "); + +} + +QString WordyTimeNanosec(const quint64 nanoseconds) { + return WordyTime(nanoseconds / kNsecPerSec); +} + +QString Ago(const qint64 seconds_since_epoch, const QLocale &locale) { + + const QDateTime now = QDateTime::currentDateTime(); + const QDateTime then = QDateTime::fromSecsSinceEpoch(seconds_since_epoch); + const qint64 days_ago = then.date().daysTo(now.date()); + const QString time = then.time().toString(locale.timeFormat(QLocale::ShortFormat)); + + if (days_ago == 0) return QObject::tr("Today") + " " + time; + if (days_ago == 1) return QObject::tr("Yesterday") + " " + time; + if (days_ago <= 7) return QObject::tr("%1 days ago").arg(days_ago); + + return then.date().toString(locale.dateFormat(QLocale::ShortFormat)); + +} + +QString PrettyFutureDate(const QDate date) { + + const QDate now = QDate::currentDate(); + const qint64 delta_days = now.daysTo(date); + + if (delta_days < 0) return QString(); + if (delta_days == 0) return QObject::tr("Today"); + if (delta_days == 1) return QObject::tr("Tomorrow"); + if (delta_days <= 7) return QObject::tr("In %1 days").arg(delta_days); + if (delta_days <= 14) return QObject::tr("Next week"); + + return QObject::tr("In %1 weeks").arg(delta_days / 7); + +} + +QDateTime ParseRFC822DateTime(const QString &text) { + + QRegularExpression regexp("(\\d{1,2}) (\\w{3,12}) (\\d+) (\\d{1,2}):(\\d{1,2}):(\\d{1,2})"); + QRegularExpressionMatch re_match = regexp.match(text); + if (!re_match.hasMatch()) { + return QDateTime(); + } + + enum class MatchNames { DAYS = 1, MONTHS, YEARS, HOURS, MINUTES, SECONDS }; + + QMap monthmap; + monthmap["Jan"] = 1; + monthmap["Feb"] = 2; + monthmap["Mar"] = 3; + monthmap["Apr"] = 4; + monthmap["May"] = 5; + monthmap["Jun"] = 6; + monthmap["Jul"] = 7; + monthmap["Aug"] = 8; + monthmap["Sep"] = 9; + monthmap["Oct"] = 10; + monthmap["Nov"] = 11; + monthmap["Dec"] = 12; + monthmap["January"] = 1; + monthmap["February"] = 2; + monthmap["March"] = 3; + monthmap["April"] = 4; + monthmap["May"] = 5; + monthmap["June"] = 6; + monthmap["July"] = 7; + monthmap["August"] = 8; + monthmap["September"] = 9; + monthmap["October"] = 10; + monthmap["November"] = 11; + monthmap["December"] = 12; + + const QDate date(re_match.captured(static_cast(MatchNames::YEARS)).toInt(), monthmap[re_match.captured(static_cast(MatchNames::MONTHS))], re_match.captured(static_cast(MatchNames::DAYS)).toInt()); + + const QTime time(re_match.captured(static_cast(MatchNames::HOURS)).toInt(), re_match.captured(static_cast(MatchNames::MINUTES)).toInt(), re_match.captured(static_cast(MatchNames::SECONDS)).toInt()); + + return QDateTime(date, time); + +} + +} // namespace Utilities diff --git a/src/utilities/timeutils.h b/src/utilities/timeutils.h new file mode 100644 index 00000000..78efb967 --- /dev/null +++ b/src/utilities/timeutils.h @@ -0,0 +1,42 @@ +/* + * Strawberry Music Player + * Copyright 2010, David Sansome + * Copyright 2018-2021, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#ifndef TIMEUTILS_H +#define TIMEUTILS_H + +#include +#include +#include +#include + +namespace Utilities { + +QString PrettyTime(int seconds); +QString PrettyTimeDelta(const int seconds); +QString PrettyTimeNanosec(const qint64 nanoseconds); +QString WordyTime(const quint64 seconds); +QString WordyTimeNanosec(const quint64 nanoseconds); +QString Ago(const qint64 seconds_since_epoch, const QLocale &locale); +QString PrettyFutureDate(const QDate date); +QDateTime ParseRFC822DateTime(const QString &text); + +} // namespace Utilities + +#endif // TIMEUTILS_H diff --git a/src/utilities/transliterate.cpp b/src/utilities/transliterate.cpp new file mode 100644 index 00000000..c413ac6c --- /dev/null +++ b/src/utilities/transliterate.cpp @@ -0,0 +1,94 @@ +/* + * Strawberry Music Player + * Copyright 2018-2021, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#include "config.h" + +#include +#include +#include + +#ifdef HAVE_ICU +# include +#else +# include +#endif + +#include +#include + +#include "transliterate.h" + +namespace Utilities { + +QString Transliterate(const QString &accented_str) { + +#ifdef HAVE_ICU + + UErrorCode errorcode = U_ZERO_ERROR; + std::unique_ptr transliterator; + transliterator.reset(icu::Transliterator::createInstance("Any-Latin; Latin-ASCII;", UTRANS_FORWARD, errorcode)); + + if (!transliterator) return accented_str; + + QByteArray accented_data = accented_str.toUtf8(); + icu::UnicodeString ustring = icu::UnicodeString(accented_data.constData()); + transliterator->transliterate(ustring); + + std::string unaccented_str; + ustring.toUTF8String(unaccented_str); + + return QString::fromStdString(unaccented_str); + +#else + +#ifdef LC_ALL + setlocale(LC_ALL, ""); +#endif + + iconv_t conv = iconv_open("ASCII//TRANSLIT", "UTF-8"); + if (conv == reinterpret_cast(-1)) return accented_str; + + QByteArray utf8 = accented_str.toUtf8(); + + size_t input_len = utf8.length() + 1; + char *input_ptr = new char[input_len]; + char *input = input_ptr; + + size_t output_len = input_len * 2; + char *output_ptr = new char[output_len]; + char *output = output_ptr; + + snprintf(input, input_len, "%s", utf8.constData()); + + iconv(conv, &input, &input_len, &output, &output_len); + iconv_close(conv); + + QString ret(output_ptr); + ret = ret.replace('?', '_'); + + delete[] input_ptr; + delete[] output_ptr; + + return ret; + +#endif // HAVE_ICU + +} // Transliterate + +} // namespace Utilities diff --git a/src/utilities/transliterate.h b/src/utilities/transliterate.h new file mode 100644 index 00000000..0f806b24 --- /dev/null +++ b/src/utilities/transliterate.h @@ -0,0 +1,31 @@ +/* + * Strawberry Music Player + * Copyright 2018-2021, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#ifndef TRANSLITERATE_H +#define TRANSLITERATE_H + +#include + +namespace Utilities { + +QString Transliterate(const QString &accented_str); + +} // namespace Utilities + +#endif // TRANSLITERATE_H diff --git a/src/utilities/winutils.cpp b/src/utilities/winutils.cpp new file mode 100644 index 00000000..50772bb1 --- /dev/null +++ b/src/utilities/winutils.cpp @@ -0,0 +1,84 @@ +/* + * Strawberry Music Player + * Copyright 2018-2021, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#include + +#include +#include + +#include +#include + +#include "winutils.h" + +namespace Utilities { + +HRGN qt_RectToHRGN(const QRect &rc); +HRGN qt_RectToHRGN(const QRect &rc) { + return CreateRectRgn(rc.left(), rc.top(), rc.right() + 1, rc.bottom() + 1); +} + +HRGN toHRGN(const QRegion ®ion); +HRGN toHRGN(const QRegion ®ion) { + +# if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + return region.toHRGN(); +# else + + const int rect_count = region.rectCount(); + if (rect_count == 0) { + return nullptr; + } + + HRGN resultRgn = nullptr; + QRegion::const_iterator rects = region.begin(); + resultRgn = qt_RectToHRGN(rects[0]); + for (int i = 1; i < rect_count; ++i) { + HRGN tmpRgn = qt_RectToHRGN(rects[i]); + const int res = CombineRgn(resultRgn, resultRgn, tmpRgn, RGN_OR); + if (res == ERROR) qWarning("Error combining HRGNs."); + DeleteObject(tmpRgn); + } + + return resultRgn; + +# endif // Qt 6 +} + +void enableBlurBehindWindow(QWindow *window, const QRegion ®ion) { + + DWM_BLURBEHIND dwmbb = { 0, 0, nullptr, 0 }; + dwmbb.dwFlags = DWM_BB_ENABLE; + dwmbb.fEnable = TRUE; + HRGN rgn = nullptr; + if (!region.isNull()) { + rgn = toHRGN(region); + if (rgn) { + dwmbb.hRgnBlur = rgn; + dwmbb.dwFlags |= DWM_BB_BLURREGION; + } + } + DwmEnableBlurBehindWindow(reinterpret_cast(window->winId()), &dwmbb); + if (rgn) { + DeleteObject(rgn); + } + +} + +} // namespace Utilities diff --git a/src/utilities/winutils.h b/src/utilities/winutils.h new file mode 100644 index 00000000..cdf562c0 --- /dev/null +++ b/src/utilities/winutils.h @@ -0,0 +1,33 @@ +/* + * Strawberry Music Player + * Copyright 2018-2021, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#ifndef WINUTILS_H +#define WINUTILS_H + +#include + +class QWindow; + +namespace Utilities { + +void enableBlurBehindWindow(QWindow *window, const QRegion ®ion); + +} // namespace Utilities + +#endif // WINUTILS_H diff --git a/src/utilities/xmlutils.cpp b/src/utilities/xmlutils.cpp new file mode 100644 index 00000000..54a21d2b --- /dev/null +++ b/src/utilities/xmlutils.cpp @@ -0,0 +1,69 @@ +/* + * Strawberry Music Player + * Copyright 2010, David Sansome + * Copyright 2018-2021, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#include +#include + +#include "xmlutils.h" + +namespace Utilities { + +void ConsumeCurrentElement(QXmlStreamReader *reader) { + + int level = 1; + while (level != 0 && !reader->atEnd()) { + switch (reader->readNext()) { + case QXmlStreamReader::StartElement: ++level; break; + case QXmlStreamReader::EndElement: --level; break; + default: break; + } + } + +} + +bool ParseUntilElement(QXmlStreamReader *reader, const QString &name) { + + while (!reader->atEnd()) { + QXmlStreamReader::TokenType type = reader->readNext(); + if (type == QXmlStreamReader::StartElement && reader->name() == name) { + return true; + } + } + return false; + +} + +bool ParseUntilElementCI(QXmlStreamReader *reader, const QString &name) { + + while (!reader->atEnd()) { + QXmlStreamReader::TokenType type = reader->readNext(); + if (type == QXmlStreamReader::StartElement) { + QString element = reader->name().toString().toLower(); + if (element == name) { + return true; + } + } + } + + return false; + +} + +} // namespace Utilities diff --git a/src/utilities/xmlutils.h b/src/utilities/xmlutils.h new file mode 100644 index 00000000..b5e7bf27 --- /dev/null +++ b/src/utilities/xmlutils.h @@ -0,0 +1,40 @@ +/* + * Strawberry Music Player + * Copyright 2010, David Sansome + * Copyright 2018-2021, Jonas Kvinge + * + * Strawberry is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Strawberry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Strawberry. If not, see . + * + */ + +#ifndef XMLUTILS_H +#define XMLUTILS_H + +#include +#include + +namespace Utilities { + +// Reads all children of the current element, +// and returns with the stream reader either on the EndElement for the current element, or the end of the file - whichever came first. +void ConsumeCurrentElement(QXmlStreamReader *reader); + +// Advances the stream reader until it finds an element with the given name. +// Returns false if the end of the document was reached before finding a matching element. +bool ParseUntilElement(QXmlStreamReader *reader, const QString &name); +bool ParseUntilElementCI(QXmlStreamReader *reader, const QString &name); + +} // namespace Utilities + +#endif // XMLUTILS_H diff --git a/src/widgets/fileviewlist.cpp b/src/widgets/fileviewlist.cpp index 6c803df4..fd8da176 100644 --- a/src/widgets/fileviewlist.cpp +++ b/src/widgets/fileviewlist.cpp @@ -32,7 +32,7 @@ #include "core/iconloader.h" #include "core/mimedata.h" -#include "core/utilities.h" +#include "utilities/filemanagerutils.h" #include "fileviewlist.h" FileViewList::FileViewList(QWidget *parent) diff --git a/src/widgets/freespacebar.cpp b/src/widgets/freespacebar.cpp index 41e400fd..c39bd9d3 100644 --- a/src/widgets/freespacebar.cpp +++ b/src/widgets/freespacebar.cpp @@ -37,7 +37,7 @@ #include #include -#include "core/utilities.h" +#include "utilities/strutils.h" #include "freespacebar.h" class QPaintEvent; diff --git a/src/widgets/playingwidget.cpp b/src/widgets/playingwidget.cpp index 535bd369..6a7c9143 100644 --- a/src/widgets/playingwidget.cpp +++ b/src/widgets/playingwidget.cpp @@ -40,7 +40,7 @@ #include #include "core/application.h" -#include "core/imageutils.h" +#include "utilities/imageutils.h" #include "covermanager/albumcoverchoicecontroller.h" #include "playingwidget.h" diff --git a/src/widgets/trackslider.cpp b/src/widgets/trackslider.cpp index 0d53d062..f580e721 100644 --- a/src/widgets/trackslider.cpp +++ b/src/widgets/trackslider.cpp @@ -29,8 +29,8 @@ #include #include -#include "core/timeconstants.h" -#include "core/utilities.h" +#include "utilities/timeutils.h" +#include "utilities/timeconstants.h" #include "trackslider.h" #include "ui_trackslider.h" #include "clickablelabel.h" diff --git a/src/widgets/tracksliderslider.cpp b/src/widgets/tracksliderslider.cpp index cd91f7b0..b18159d5 100644 --- a/src/widgets/tracksliderslider.cpp +++ b/src/widgets/tracksliderslider.cpp @@ -30,8 +30,8 @@ #include #include -#include "core/timeconstants.h" -#include "core/utilities.h" +#include "utilities/timeutils.h" +#include "utilities/timeconstants.h" #ifndef Q_OS_MACOS # include "tracksliderpopup.h" #endif