Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b4683db900 | ||
|
|
5a90643ba8 | ||
|
|
4a1ab2f004 | ||
|
|
36be755a78 | ||
|
|
ffd8c88b1f | ||
|
|
84ff163b34 | ||
|
|
811e625618 | ||
|
|
037b0d7dea | ||
|
|
d578d3c66d | ||
|
|
2644dbd5ab | ||
|
|
245103dc30 |
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@@ -628,7 +628,7 @@ jobs:
|
||||
|
||||
upload-ubuntu-ppa:
|
||||
name: Upload Ubuntu PPA
|
||||
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && (github.event_name == 'release' || (github.event_name == 'push' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci')))
|
||||
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && (github.event_name == 'release' || (github.event_name == 'push' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci' || github.ref == 'refs/heads/1.1')))
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -1548,7 +1548,7 @@ jobs:
|
||||
upload_path="${{secrets.RELEASES_PATH}}/"
|
||||
else
|
||||
distro=$(echo "$i" | cut -d '/' -f 2)
|
||||
if [ "$(echo "$i" | grep '-' || true)" = "" ]; then
|
||||
if [ -z "$(echo "${distro}" | grep '-' || true)" ]; then
|
||||
upload_path="${{secrets.BUILDS_PATH}}/${distro}/"
|
||||
else
|
||||
distro_name=$(echo "${distro}" | cut -d '-' -f 1)
|
||||
|
||||
@@ -2,6 +2,15 @@ Strawberry Music Player
|
||||
=======================
|
||||
ChangeLog
|
||||
|
||||
Version 1.1.3 (2024.09.21):
|
||||
|
||||
Bugfixes:
|
||||
* Fixed gstreamer registry lookup leak in Spotify settings.
|
||||
* Fixed all songs in a CUE sheet starting playback at the zero position (#1549).
|
||||
* Fixed playback going to pause and back to play on song change.
|
||||
* Fixed Genius Lyrics login not working (#1554).
|
||||
* Fixed slow collection filter search.
|
||||
|
||||
Version 1.1.2 (2024.09.12):
|
||||
|
||||
Bugfixes:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
set(STRAWBERRY_VERSION_MAJOR 1)
|
||||
set(STRAWBERRY_VERSION_MINOR 1)
|
||||
set(STRAWBERRY_VERSION_PATCH 2)
|
||||
set(STRAWBERRY_VERSION_PATCH 3)
|
||||
#set(STRAWBERRY_VERSION_PRERELEASE rc1)
|
||||
|
||||
set(INCLUDE_GIT_REVISION ON)
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<content_rating type="oars-1.1" />
|
||||
<description>
|
||||
<p>
|
||||
Strawberry is a music player and music collection organizer. It is aimed at music collectors and audiophiles. With Strawberry you can play and manage your digital music collection, or stream your favorite radios. It also has unofficial streaming support for Tidal and Qobuz. Strawberry is free software released under GPL. The source code is available on GitHub. It's written in C++ using the Qt toolkit and GStreamer. Strawberry is compatible with both Qt version 5 and 6.
|
||||
Strawberry is a music player and music collection organizer. It is aimed at music collectors and audiophiles. Strawberry is free software released under GPL. It's written in C++ using the Qt framework and GStreamer.
|
||||
</p>
|
||||
<p>Features:</p>
|
||||
<ul>
|
||||
@@ -52,6 +52,7 @@
|
||||
</screenshots>
|
||||
<update_contact>eclipseo@fedoraproject.org</update_contact>
|
||||
<releases>
|
||||
<release version="1.1.3" date="2024-09-21"/>
|
||||
<release version="1.1.2" date="2024-09-12"/>
|
||||
<release version="1.1.1" date="2024-07-22"/>
|
||||
<release version="1.1.0" date="2024-07-14"/>
|
||||
|
||||
@@ -259,7 +259,7 @@ bool GstEngine::Play(const bool pause, const quint64 offset_nanosec) {
|
||||
|
||||
EnsureInitialized();
|
||||
|
||||
if (!current_pipeline_ || current_pipeline_->is_buffering()) return false;
|
||||
if (!current_pipeline_ || current_pipeline_->is_buffering() || current_pipeline_->state() == GstState::GST_STATE_PLAYING) return false;
|
||||
|
||||
if (OldExclusivePipelineActive()) {
|
||||
qLog(Debug) << "Delaying play because a exclusive pipeline is already active...";
|
||||
@@ -284,7 +284,7 @@ bool GstEngine::Play(const bool pause, const quint64 offset_nanosec) {
|
||||
watcher->deleteLater();
|
||||
PlayDone(ret, pause, offset_nanosec, pipeline_id);
|
||||
});
|
||||
QFuture<GstStateChangeReturn> future = current_pipeline_->Play(pause, offset_nanosec);
|
||||
QFuture<GstStateChangeReturn> future = current_pipeline_->Play(pause, beginning_nanosec_ + offset_nanosec);
|
||||
watcher->setFuture(future);
|
||||
|
||||
return true;
|
||||
|
||||
@@ -235,123 +235,125 @@ FilterTree *FilterParser::createSearchTermTreeNode(const QString &column, const
|
||||
|
||||
FilterParserSearchTermComparator *cmp = nullptr;
|
||||
|
||||
if (Song::kTextSearchColumns.contains(column, Qt::CaseInsensitive)) {
|
||||
if (prefix == QLatin1Char('=') || prefix == QLatin1String("==")) {
|
||||
cmp = new FilterParserTextEqComparator(value);
|
||||
}
|
||||
else if (prefix == QLatin1String("!=") || prefix == QLatin1String("<>")) {
|
||||
cmp = new FilterParserTextNeComparator(value);
|
||||
}
|
||||
else {
|
||||
cmp = new FilterParserDefaultComparator(value);
|
||||
}
|
||||
}
|
||||
else if (Song::kIntSearchColumns.contains(column, Qt::CaseInsensitive)) {
|
||||
bool ok = false;
|
||||
int number = value.toInt(&ok);
|
||||
if (ok) {
|
||||
if (!column.isEmpty()) {
|
||||
if (Song::kTextSearchColumns.contains(column, Qt::CaseInsensitive)) {
|
||||
if (prefix == QLatin1Char('=') || prefix == QLatin1String("==")) {
|
||||
cmp = new FilterParserIntEqComparator(number);
|
||||
cmp = new FilterParserTextEqComparator(value);
|
||||
}
|
||||
else if (prefix == QLatin1String("!=") || prefix == QLatin1String("<>")) {
|
||||
cmp = new FilterParserIntNeComparator(number);
|
||||
}
|
||||
else if (prefix == QLatin1Char('>')) {
|
||||
cmp = new FilterParserIntGtComparator(number);
|
||||
}
|
||||
else if (prefix == QLatin1String(">=")) {
|
||||
cmp = new FilterParserIntGeComparator(number);
|
||||
}
|
||||
else if (prefix == QLatin1Char('<')) {
|
||||
cmp = new FilterParserIntLtComparator(number);
|
||||
}
|
||||
else if (prefix == QLatin1String("<=")) {
|
||||
cmp = new FilterParserIntLeComparator(number);
|
||||
cmp = new FilterParserTextNeComparator(value);
|
||||
}
|
||||
else {
|
||||
cmp = new FilterParserIntEqComparator(number);
|
||||
cmp = new FilterParserTextContainsComparator(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (Song::kUIntSearchColumns.contains(column, Qt::CaseInsensitive)) {
|
||||
bool ok = false;
|
||||
uint number = value.toUInt(&ok);
|
||||
if (ok) {
|
||||
else if (Song::kIntSearchColumns.contains(column, Qt::CaseInsensitive)) {
|
||||
bool ok = false;
|
||||
int number = value.toInt(&ok);
|
||||
if (ok) {
|
||||
if (prefix == QLatin1Char('=') || prefix == QLatin1String("==")) {
|
||||
cmp = new FilterParserIntEqComparator(number);
|
||||
}
|
||||
else if (prefix == QLatin1String("!=") || prefix == QLatin1String("<>")) {
|
||||
cmp = new FilterParserIntNeComparator(number);
|
||||
}
|
||||
else if (prefix == QLatin1Char('>')) {
|
||||
cmp = new FilterParserIntGtComparator(number);
|
||||
}
|
||||
else if (prefix == QLatin1String(">=")) {
|
||||
cmp = new FilterParserIntGeComparator(number);
|
||||
}
|
||||
else if (prefix == QLatin1Char('<')) {
|
||||
cmp = new FilterParserIntLtComparator(number);
|
||||
}
|
||||
else if (prefix == QLatin1String("<=")) {
|
||||
cmp = new FilterParserIntLeComparator(number);
|
||||
}
|
||||
else {
|
||||
cmp = new FilterParserTextContainsComparator(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (Song::kUIntSearchColumns.contains(column, Qt::CaseInsensitive)) {
|
||||
bool ok = false;
|
||||
uint number = value.toUInt(&ok);
|
||||
if (ok) {
|
||||
if (prefix == QLatin1Char('=') || prefix == QLatin1String("==")) {
|
||||
cmp = new FilterParserUIntEqComparator(number);
|
||||
}
|
||||
else if (prefix == QLatin1String("!=") || prefix == QLatin1String("<>")) {
|
||||
cmp = new FilterParserUIntNeComparator(number);
|
||||
}
|
||||
else if (prefix == QLatin1Char('>')) {
|
||||
cmp = new FilterParserUIntGtComparator(number);
|
||||
}
|
||||
else if (prefix == QLatin1String(">=")) {
|
||||
cmp = new FilterParserUIntGeComparator(number);
|
||||
}
|
||||
else if (prefix == QLatin1Char('<')) {
|
||||
cmp = new FilterParserUIntLtComparator(number);
|
||||
}
|
||||
else if (prefix == QLatin1String("<=")) {
|
||||
cmp = new FilterParserUIntLeComparator(number);
|
||||
}
|
||||
else {
|
||||
cmp = new FilterParserInt64EqComparator(number);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (Song::kInt64SearchColumns.contains(column, Qt::CaseInsensitive)) {
|
||||
qint64 number = 0;
|
||||
if (column == QLatin1String("length")) {
|
||||
number = ParseTime(value);
|
||||
}
|
||||
else {
|
||||
number = value.toLongLong();
|
||||
}
|
||||
if (prefix == QLatin1Char('=') || prefix == QLatin1String("==")) {
|
||||
cmp = new FilterParserUIntEqComparator(number);
|
||||
cmp = new FilterParserInt64EqComparator(number);
|
||||
}
|
||||
else if (prefix == QLatin1String("!=") || prefix == QLatin1String("<>")) {
|
||||
cmp = new FilterParserUIntNeComparator(number);
|
||||
cmp = new FilterParserInt64NeComparator(number);
|
||||
}
|
||||
else if (prefix == QLatin1Char('>')) {
|
||||
cmp = new FilterParserUIntGtComparator(number);
|
||||
cmp = new FilterParserInt64GtComparator(number);
|
||||
}
|
||||
else if (prefix == QLatin1String(">=")) {
|
||||
cmp = new FilterParserUIntGeComparator(number);
|
||||
cmp = new FilterParserInt64GeComparator(number);
|
||||
}
|
||||
else if (prefix == QLatin1Char('<')) {
|
||||
cmp = new FilterParserUIntLtComparator(number);
|
||||
cmp = new FilterParserInt64LtComparator(number);
|
||||
}
|
||||
else if (prefix == QLatin1String("<=")) {
|
||||
cmp = new FilterParserUIntLeComparator(number);
|
||||
cmp = new FilterParserInt64LeComparator(number);
|
||||
}
|
||||
else {
|
||||
cmp = new FilterParserUIntEqComparator(number);
|
||||
cmp = new FilterParserInt64EqComparator(number);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (Song::kInt64SearchColumns.contains(column, Qt::CaseInsensitive)) {
|
||||
qint64 number = 0;
|
||||
if (column == QLatin1String("length")) {
|
||||
number = ParseTime(value);
|
||||
}
|
||||
else {
|
||||
number = value.toLongLong();
|
||||
}
|
||||
if (prefix == QLatin1Char('=') || prefix == QLatin1String("==")) {
|
||||
cmp = new FilterParserInt64EqComparator(number);
|
||||
}
|
||||
else if (prefix == QLatin1String("!=") || prefix == QLatin1String("<>")) {
|
||||
cmp = new FilterParserInt64NeComparator(number);
|
||||
}
|
||||
else if (prefix == QLatin1Char('>')) {
|
||||
cmp = new FilterParserInt64GtComparator(number);
|
||||
}
|
||||
else if (prefix == QLatin1String(">=")) {
|
||||
cmp = new FilterParserInt64GeComparator(number);
|
||||
}
|
||||
else if (prefix == QLatin1Char('<')) {
|
||||
cmp = new FilterParserInt64LtComparator(number);
|
||||
}
|
||||
else if (prefix == QLatin1String("<=")) {
|
||||
cmp = new FilterParserInt64LeComparator(number);
|
||||
}
|
||||
else {
|
||||
cmp = new FilterParserInt64EqComparator(number);
|
||||
}
|
||||
}
|
||||
else if (Song::kFloatSearchColumns.contains(column, Qt::CaseInsensitive)) {
|
||||
const float rating = ParseRating(value);
|
||||
if (prefix == QLatin1Char('=') || prefix == QLatin1String("==")) {
|
||||
cmp = new FilterParserFloatEqComparator(rating);
|
||||
}
|
||||
else if (prefix == QLatin1String("!=") || prefix == QLatin1String("<>")) {
|
||||
cmp = new FilterParserFloatNeComparator(rating);
|
||||
}
|
||||
else if (prefix == QLatin1Char('>')) {
|
||||
cmp = new FilterParserFloatGtComparator(rating);
|
||||
}
|
||||
else if (prefix == QLatin1String(">=")) {
|
||||
cmp = new FilterParserFloatGeComparator(rating);
|
||||
}
|
||||
else if (prefix == QLatin1Char('<')) {
|
||||
cmp = new FilterParserFloatLtComparator(rating);
|
||||
}
|
||||
else if (prefix == QLatin1String("<=")) {
|
||||
cmp = new FilterParserFloatLeComparator(rating);
|
||||
}
|
||||
else {
|
||||
cmp = new FilterParserFloatEqComparator(rating);
|
||||
else if (Song::kFloatSearchColumns.contains(column, Qt::CaseInsensitive)) {
|
||||
const float rating = ParseRating(value);
|
||||
if (prefix == QLatin1Char('=') || prefix == QLatin1String("==")) {
|
||||
cmp = new FilterParserFloatEqComparator(rating);
|
||||
}
|
||||
else if (prefix == QLatin1String("!=") || prefix == QLatin1String("<>")) {
|
||||
cmp = new FilterParserFloatNeComparator(rating);
|
||||
}
|
||||
else if (prefix == QLatin1Char('>')) {
|
||||
cmp = new FilterParserFloatGtComparator(rating);
|
||||
}
|
||||
else if (prefix == QLatin1String(">=")) {
|
||||
cmp = new FilterParserFloatGeComparator(rating);
|
||||
}
|
||||
else if (prefix == QLatin1Char('<')) {
|
||||
cmp = new FilterParserFloatLtComparator(rating);
|
||||
}
|
||||
else if (prefix == QLatin1String("<=")) {
|
||||
cmp = new FilterParserFloatLeComparator(rating);
|
||||
}
|
||||
else {
|
||||
cmp = new FilterParserFloatEqComparator(rating);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -359,7 +361,7 @@ FilterTree *FilterParser::createSearchTermTreeNode(const QString &column, const
|
||||
return new FilterColumnTerm(column, cmp);
|
||||
}
|
||||
|
||||
return new FilterTerm(Song::kTextSearchColumns, new FilterParserDefaultComparator(value));
|
||||
return new FilterTerm(new FilterParserTextContainsComparator(value));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -38,16 +38,16 @@ class FilterParserSearchTermComparator {
|
||||
};
|
||||
|
||||
// "compares" by checking if the field contains the search term
|
||||
class FilterParserDefaultComparator : public FilterParserSearchTermComparator {
|
||||
class FilterParserTextContainsComparator : public FilterParserSearchTermComparator {
|
||||
public:
|
||||
explicit FilterParserDefaultComparator(const QString &search_term) : search_term_(search_term) {}
|
||||
explicit FilterParserTextContainsComparator(const QString &search_term) : search_term_(search_term) {}
|
||||
bool Matches(const QVariant &value) const override {
|
||||
return value.toString().contains(search_term_, Qt::CaseInsensitive);
|
||||
}
|
||||
private:
|
||||
QString search_term_;
|
||||
|
||||
Q_DISABLE_COPY(FilterParserDefaultComparator)
|
||||
Q_DISABLE_COPY(FilterParserTextContainsComparator)
|
||||
};
|
||||
|
||||
class FilterParserTextEqComparator : public FilterParserSearchTermComparator {
|
||||
|
||||
@@ -67,19 +67,27 @@ class NopFilter : public FilterTree {
|
||||
// Filter that applies a SearchTermComparator to all fields
|
||||
class FilterTerm : public FilterTree {
|
||||
public:
|
||||
explicit FilterTerm(const QStringList &columns, FilterParserSearchTermComparator *comparator) : columns_(columns), cmp_(comparator) {}
|
||||
explicit FilterTerm(FilterParserSearchTermComparator *comparator) : cmp_(comparator) {}
|
||||
|
||||
FilterType type() const override { return FilterType::Term; }
|
||||
|
||||
bool accept(const Song &song) const override {
|
||||
for (const QString &column : columns_) {
|
||||
if (cmp_->Matches(DataFromColumn(column, song))) return true;
|
||||
}
|
||||
|
||||
if (cmp_->Matches(song.PrettyTitle())) return true;
|
||||
if (cmp_->Matches(song.album())) return true;
|
||||
if (cmp_->Matches(song.artist())) return true;
|
||||
if (cmp_->Matches(song.albumartist())) return true;
|
||||
if (cmp_->Matches(song.composer())) return true;
|
||||
if (cmp_->Matches(song.performer())) return true;
|
||||
if (cmp_->Matches(song.grouping())) return true;
|
||||
if (cmp_->Matches(song.genre())) return true;
|
||||
if (cmp_->Matches(song.comment())) return true;
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
const QStringList columns_;
|
||||
QScopedPointer<FilterParserSearchTermComparator> cmp_;
|
||||
};
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@ void GeniusLyricsProvider::Authenticate() {
|
||||
}
|
||||
|
||||
QUrlQuery url_query;
|
||||
url_query.addQueryItem(QStringLiteral("client_id"), QString::fromLatin1(QUrl::toPercentEncoding(QLatin1String(kClientIDB64))));
|
||||
url_query.addQueryItem(QStringLiteral("client_id"), QString::fromLatin1(QUrl::toPercentEncoding(QString::fromLatin1(QByteArray::fromBase64(kClientIDB64)))));
|
||||
url_query.addQueryItem(QStringLiteral("redirect_uri"), QString::fromLatin1(QUrl::toPercentEncoding(redirect_url.toString())));
|
||||
url_query.addQueryItem(QStringLiteral("scope"), QStringLiteral("me"));
|
||||
url_query.addQueryItem(QStringLiteral("state"), QString::fromLatin1(QUrl::toPercentEncoding(code_challenge_)));
|
||||
@@ -197,8 +197,8 @@ void GeniusLyricsProvider::RequestAccessToken(const QUrl &url, const QUrl &redir
|
||||
|
||||
QUrlQuery new_url_query;
|
||||
new_url_query.addQueryItem(QStringLiteral("code"), QString::fromLatin1(QUrl::toPercentEncoding(code)));
|
||||
new_url_query.addQueryItem(QStringLiteral("client_id"), QString::fromLatin1(QUrl::toPercentEncoding(QLatin1String(kClientIDB64))));
|
||||
new_url_query.addQueryItem(QStringLiteral("client_secret"), QString::fromLatin1(QUrl::toPercentEncoding(QLatin1String(kClientSecretB64))));
|
||||
new_url_query.addQueryItem(QStringLiteral("client_id"), QString::fromLatin1(QUrl::toPercentEncoding(QString::fromLatin1(QByteArray::fromBase64(kClientIDB64)))));
|
||||
new_url_query.addQueryItem(QStringLiteral("client_secret"), QString::fromLatin1(QUrl::toPercentEncoding(QString::fromLatin1(QByteArray::fromBase64(kClientSecretB64)))));
|
||||
new_url_query.addQueryItem(QStringLiteral("redirect_uri"), QString::fromLatin1(QUrl::toPercentEncoding(redirect_url.toString())));
|
||||
new_url_query.addQueryItem(QStringLiteral("grant_type"), QStringLiteral("authorization_code"));
|
||||
new_url_query.addQueryItem(QStringLiteral("response_type"), QStringLiteral("code"));
|
||||
|
||||
@@ -69,6 +69,7 @@ SpotifySettingsPage::SpotifySettingsPage(SettingsDialog *dialog, QWidget *parent
|
||||
if (reg) {
|
||||
GstPluginFeature *spotifyaudiosrc = gst_registry_lookup_feature(reg, "spotifyaudiosrc");
|
||||
if (spotifyaudiosrc) {
|
||||
gst_object_unref(spotifyaudiosrc);
|
||||
ui_->widget_warning->hide();
|
||||
}
|
||||
else {
|
||||
|
||||
Reference in New Issue
Block a user