Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spotify extension #43

Closed
wants to merge 14 commits into from
Closed

Conversation

BlueManCZ
Copy link

@BlueManCZ BlueManCZ commented Jan 27, 2021

New plugin available here: #138

Old extension:

I created a Spotify extension for Albert launcher. It allows user to search and play tracks, add them to the queue and choose particular Spotify client.

This code needs review and testing. It works without any problems for me, but there may be unpredictable situational problems, that I'm currently not aware of.

For all people willing to use this extension, please read README.md first. I describe there how to configure Spotify Web API connection in this extension.

It is QueryHandler::ExecutionType::Realtime and currently contains spotify and play triggers.

YouTube video: https://youtu.be/fCpvYUWIsBs

Spotify extension

Instructions for building and running this PR:

# Clone repositories
git clone --recursive https://github.com/albertlauncher/albert.git

# Switch to this PR branch
cd albert/plugins
git fetch origin pull/43/head:spotify
git checkout spotify

# Build
mkdir ../build
cd ../build
cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug
make -j5

# Run
./bin/albert -p "$(pwd)/lib/"

@Bierchermuesli
Copy link

Bierchermuesli commented Jul 19, 2021

nice! but do this extension depends on QT 5.15?

tmp/albert-source/plugins/spotify/src/extension.cpp:104:65: error: ‘textChanged’ is not a member of ‘QSpinBox’
  104 |     connect(d->widget->ui.spinBox_number_of_results, &QSpinBox::textChanged, [this](const QString &s){

qmake -v
QMake version 3.1
Using Qt version 5.12.8 in /usr/lib/x86_64-linux-gnu

lsb_release -a
No LSB modules are available.
Distributor ID:	Linuxmint
Description:	Linux Mint 20.2
Release:	20.2
Codename:	ulyssa


@BlueManCZ
Copy link
Author

Hello! To be honest I don't know right now. I'm on vacation and I will take a look when I come back. 😉

@BlueManCZ
Copy link
Author

@Bierchermuesli According to the docs, textChanged was introduced in Qt 5.14. Do you think it's a problem?

@Bierchermuesli
Copy link

just a Problem of outdated Qt version in some distros :-)
≤ Debian 10 or ≤ Ubuntu 20.04 (LTS) still have Qt 5.11.3.

Debian 11 (soon stable) has Qt 5.14 and Ubuntu >20.10 has Qt5.14

@BlueManCZ
Copy link
Author

Is there anything I can do to help you merge this @ManuelSchneid3r? Or are you working on some breaking changes in the core that will require adaptation?

I've used this extension for more than one year and didn't notice a single problem.

@ManuelSchneid3r
Copy link
Member

ManuelSchneid3r commented Oct 8, 2022

Do you think it's a problem?

currently albert is backward compatible until ubuntu 18.04 i.e. 5.9. 20.04 uses 5.12.. I strive to be one or two years backward compatible. Therefore I decided to always support the latest two ubuntu LTS. Unfortunately this means that the newest lib you can use is 5.12.

Copy link
Contributor

@idkCpp idkCpp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm very sorry, but this is in bad shape.

}

SpotifyWebAPI::~SpotifyWebAPI() {
delete manager;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You pass this as parent which should then take care of this. (Except when you leak it in the query handler)

if (query->string().trimmed().isEmpty())
return;

d->api->manager = new QNetworkAccessManager();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this happening? Also there is no parent specified. I strongly suspect a memory leak here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use unique_ptr to avoid memory leaks

d->api->manager = new QNetworkAccessManager();

// If there is no internet connection, make one alerting item to let the user know.
if (!d->api->testInternetConnection()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ManuelSchneid3r When do we like network access in the handler? Is this an acceptable case? Wasn't there something about async queries? I forgot.

Also on a separate note; why test the connection? Nothing is gained here. Better to handle connection errors when they occur.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well it is accessing a web api, hence it's necessary. I agree please use (short) timeouts

auto filename = QString("%1/%2.jpeg").arg(d->cacheDirectory, track.albumId);

// Download cover image of the album.
d->api->downloadImage(track.imageUrl, filename);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There sure is a lot happening in the query handler...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately yes, but in this case we can't get better than the lag introduces by the requests

d->spotifyExecutable = settings().value("spotify_executable").toString();
d->cacheDirectory = settings().value("cache_directory").toString();

if (d->numberOfResults == 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

QSettings::value supports a default argument

connect(this, SIGNAL(deviceReady(QString, QString)), this, SLOT(play(QString, QString)));

QtConcurrent::run([=]() {
manager = new QNetworkAccessManager();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume you just plaster this line everywhere where you had a threading problem when testing... This really needs to be fixed. (Last time I mention threads and managers, but there are still more occurrences)

return jsonObject;
}

void SpotifyWebAPI::waitForSignal_(const QObject *sender, const char *signal) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like you don't want to go async.

}

QString SpotifyWebAPI::getFirstDeviceId() {
QVector<Device> *devices_ = getDevices();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is leaked.

auto results = d->api->searchTracks(query->string(), d->numberOfResults);

// Get available Spotify devices.
auto *devices = d->api->getDevices();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not only leaked, but its ownership is all over the place.

QString SEARCH_URL = "https://api.spotify.com/v1/search?q=%1&type=%2&limit=%3";
QString PLAY_URL = "https://api.spotify.com/v1/me/player/play?device_id=%1";
QString ADD_ITEM_URL = "https://api.spotify.com/v1/me/player/queue?uri=%1";
QString DEVICES_URL = "https://api.spotify.com/v1/me/player/devices";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These all look very const despite none of them are.

@ManuelSchneid3r
Copy link
Member

Please port it to 0.18. Looking forward to finally use this one :D

@ManuelSchneid3r
Copy link
Member

Will a subset of features work withou a premium account?

@ManuelSchneid3r
Copy link
Member

@BlueManCZ do you still want this plugin to be merged?

@BlueManCZ
Copy link
Author

Excuse me for not replying sooner.

I'm very sorry, but this is in bad shape.

Thank you for the code review @idkCpp, I will try to refactor this when porting to the new Albert core. You were right, that ton of managers was indeed a threading problem.

Please port it to 0.18. Looking forward to finally use this one :D

As soon as I get Qt6 and build working on Gentoo, I will try to port it.

Will a subset of features work without a premium account?

I'm not sure. I can't imagine what that subset would be. Based on the sentence from API documentation:
"This tutorial assumes you have a Spotify account (free or premium)."
maybe some will work. But you can't select a specific song to play without Spotify premium.

@BlueManCZ do you still want this plugin to be merged?

I do, but I still don't have Qt6 on Gentoo to port this to the new Albert core. But I keep this in mind and watch Telegram for news.

@CaseOf
Copy link
Contributor

CaseOf commented Mar 29, 2023

@BlueManCZ my ebuild for Qt6 Albert is ready and working. I just have to commit it, and do a pull request on gentoo repository.
It wont be merged quickly as I know them, and they have to review ebuilds for qtscxml and qhotkey too in the same PR.
You can manually add it to a local overlay for testing.

@CaseOf
Copy link
Contributor

CaseOf commented Mar 29, 2023

Here is my pull request on gentoo repository gentoo/gentoo#30405

@ManuelSchneid3r
Copy link
Member

@BlueManCZ ill close this one for now. Please reopen or make a new one if it is time for it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

5 participants