Giter Site home page Giter Site logo

retro-ipod-spotify-client's Introduction

sPot

This code is meant to accompany this project in which a Spotify client is built into an iPod "Classic" from 2004. Everything is meant to run on a Raspberry Pi Zero W.

Since we are using the lite version of raspbian, some extra packages need to be installed:

Instructions

  1. Install updates
sudo apt-get update 
sudo apt-get upgrade
  1. Install Required Packages.

Installation for python3-pip, raspotify, python3-tk, openbox


sudo apt install python-setuptools python3-setuptools

sudo apt install python3-pip

sudo curl -sL https://dtcooper.github.io/raspotify/install.sh | sh

sudo apt-get install python3-tk 

sudo apt-get install redis-server

sudo apt-get install openbox

sudo apt install xorg

sudo apt-get install lightdm

sudo apt-get install x11-xserver-utils

  1. Install Dependencies
pip3 install -r requirements.txt
  1. Install pi-btaudio
git clone https://github.com/bablokb/pi-btaudio.git
cd pi-btaudio
sudo tools/install
  1. Install PiGPIO
wget https://github.com/joan2937/pigpio/archive/master.zip
unzip master.zip
cd pigpio-master
make
sudo make install
  1. Setup Spotify API

First Create an App at https://developer.spotify.com/dashboard/applications/

https://accounts.spotify.com/authorize?client_id=XXXXXXXXXXXXXXXXXXXXXXXXXXXXX&response_type=code&redirect_uri=http%3A%2F%2F127.0.0.1&scope=user-read-playback-state%20user-modify-playback-state%20user-read-currently-playing%20	app-remote-control%20streaming%20playlist-modify-public%20playlist-modify-private%20playlist-read-private%20playlist-read-collaborative
  1. raspi-config

sudo raspi-config

Console Autologin

Display Option -> Screen Blanking -> Off if you want to avoid the screen turning black after a few seconds.

  1. bash_profile

In .bash_profile added the following (if the file is not htere, you must create it)

#!/bin/bash

[[ -z $DISPLAY && $XDG_VTNR -eq 1 ]] && startx -- -nocursor

# Disable any form of screen saver / screen blanking / power management

xset s off

xset s noblank
  1. Configure xinitrc

sudo nano /etc/X11/xinit/xinitrc

Inside, make sure the following is there:

#!/bin/sh

# /etc/X11/xinit/xinitrc

# global xinitrc file, used by all X sessions started by xinit (startx)

# invoke global X session script

#. /etc/X11/Xsession

exec openbox-session #-> This is the one that launches Openbox ;)
  1. Run "spotifypod.py" with autostart

sudo nano /etc/xdg/openbox/autostart

and add the following command to launch spotifypod.py:

cd /home/pi/fork/retro-ipod-spotify-client/frontend/

sudo -H -u pi python3 spotifypod.py &

sudo /home/pi/fork/retro-ipod-spotify-client/clickwheel/click &

Make sure that the paths are ok with your setup!!

in sudo nano /etc/xdg/openbox/environment all the variables needed to run spotifypod.py are set( SPOTIPY_CLIENT_ID, SPOTIPY_CLIENT_SECRET,SPOTIPY_REDIRECT_URI)

export SPOTIPY_CLIENT_ID='your_SPOTIPY_CLIENT_ID'

export SPOTIPY_CLIENT_SECRET='your_SPOTIPY_CLIENT_SECRET'

export SPOTIPY_REDIRECT_URI='your_SPOTIPY_REDIRECT_URI'
  1. Synchronizing Spotify data! Last but not least, if you want to make sure all your playlists artists, etc are synchronized every time you turn on your Spotypod, you can simply modify the script view_model.py with the following at line 16:

#spotify_manager.refresh_devices()

spotify_manager.refresh_data()

instead of calling refresh_device, you can execute refresh_data. This will sync all your data and then will eceute refresh.devices. This will make the boot up way slower! but it will synchronize every single time you switch on :). If you dont run at least once refresh_data() no playlist, artist or anything related with your account will be displayed!

  1. Configure Raspotify

sudo nano /etc/default/raspotify

Uncomment and fill the following line:

OPTIONS="--username <USERNAME> --password <PASSWORD>"

And maybe you want also to consider the following:

# The displayed device type in Spotify clients. 

# Can be "unknown", "computer", "tablet", "smartphone", "speaker", "tv",

# "avr" (Audio/Video Receiver), "stb" (Set-Top Box), and "audiodongle".

DEVICE_TYPE="smartphone"

Wiring

Here is the wiring of the hardware, as of revision 1. Note that the pin numbers correlate to those referenced in click.c

Wiring Diagram

retro-ipod-spotify-client's People

Contributors

3urobeat avatar dupontgu avatar elcapitandre avatar mightea avatar mitchlui avatar rsappia avatar tomaculum avatar utkut avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

retro-ipod-spotify-client's Issues

Button

Hello i have a question i want to use your nice project in my diy bluetooth boombox
But for that i want to use a clickable potentiometer (Incremental encoders( instead of the normal ipod wheel how can i do that

Thanks in Advance

error when running spotifypod.py

First when I manually run spotifypod.py I get error
spotipy.oauth2.SpotifyOauthError: No client_id. Pass it or set a SPOTIPY_CLIENT_ID environment variable.
I already set up my variables and I can't get it to run, also i'm trying to get this to run on a raspberry pi zero w on a monitor as a test.
Another thing is I set this to autorun but it just boots into the terminal. Any help? This is my first project.

Edit: fixed it all i did was in issue #41 theres a program that Authenticates the client id and secret id

Running retro-ipod-spotify-client/spot on clockwork gameshell portable console

1024-1811

Following the documentation I got it running in a few minutes (congrats on the documentation!) https://www.clockworkpi.com/ is a pi compute module based device with a 320x240 screen.

As you can see in the picture there probably will be some tweaks need to get it working properly. But just wanted to let you (and the community) know that I'm hacking away at this... You might see some patches coming from me if I manage to modify the code.

Debian Boot Screen with Errno98 Address Already in Use?

About at my wits end here. Not sure where to go, here's my issue. My pi boots into a debian login screen. If I do enter my login information the prompt disappears and nothing else happens. This is all before I even login to the pi over ssh. When I run spotifypod.py, my output is as follows:
`
Traceback (most recent call last):
File "spotifypod.py", line 12, in
from view_model import *
File "/home/pi/retro-ipod-spotify-client/frontend/view_model.py", line 17, in

spotify_manager.refresh_data()
File "/home/pi/retro-ipod-spotify-client/frontend/spotify_manager.py", line 15
9, in refresh_data
results = sp.current_user_saved_tracks(limit=pageSize, offset=0)
File "/home/pi/.local/lib/python3.7/site-packages/spotipy/client.py", line 122
6, in current_user_saved_tracks
return self._get("me/tracks", limit=limit, offset=offset, market=market)
File "/home/pi/.local/lib/python3.7/site-packages/spotipy/client.py", line 291
, in _get
return self._internal_call("GET", url, payload, kwargs)
File "/home/pi/.local/lib/python3.7/site-packages/spotipy/client.py", line 221
, in _internal_call
headers = self._auth_headers()
File "/home/pi/.local/lib/python3.7/site-packages/spotipy/client.py", line 212
, in _auth_headers
token = self.auth_manager.get_access_token(as_dict=False)
File "/home/pi/.local/lib/python3.7/site-packages/spotipy/oauth2.py", line 518
, in get_access_token
"code": code or self.get_auth_response(),
File "/home/pi/.local/lib/python3.7/site-packages/spotipy/oauth2.py", line 473
, in get_auth_response
return self._get_auth_response_local_server(redirect_port)
File "/home/pi/.local/lib/python3.7/site-packages/spotipy/oauth2.py", line 439
, in _get_auth_response_local_server
server = start_local_http_server(redirect_port)
File "/home/pi/.local/lib/python3.7/site-packages/spotipy/oauth2.py", line 130
3, in start_local_http_server
server = HTTPServer(("127.0.0.1", port), handler)
File "/usr/lib/python3.7/socketserver.py", line 452, in init
self.server_bind()
File "/usr/lib/python3.7/http/server.py", line 137, in server_bind
socketserver.TCPServer.server_bind(self)
File "/usr/lib/python3.7/socketserver.py", line 466, in server_bind
self.socket.bind(self.server_address)
OSError: [Errno 98] Address already in use

I attached a picture of the debian screen as well. Sorry in advance if my code copy/paste is hard to read, this is literally my first github post haha. Thanks!!
20210414_210512

`

Openbox and Tkinter driving me crazy :s

Do not take the following steps below as reference, since all these steps are probably not 100% ok. The right steps have been updated in the main Readme file!


Hi there, I am having a hard time trying to setup Openbox tu show the Tkinter output. Has anyone managend to configure this properly on a raspberry pi zero?

So far I have manage to get running a small 2." SPI display using fbcp-ili9341

This is what I have done so far:

Since I am using the lite version of raspbien, I installed some extra packages:
sudo apt install xorg
sudo apt-get install lightdm

In raspi-config: Console Autologin

In rc.local added before exit 0 the following line:
startx &

Configure xinitrc

sudo nano /etc/X11/xinit/xinitrc

Comment this line

. /etc/X11/xsession

and add this line to start openbox
exec openbox-session

Run "spotifypod.py" with autostart

sudo nano /etc/xdg/openbox/autostart

and add the following command to launch spotifypod.py

sudo -H -u pi python3 /somewhere/over/the/rainbow/spotifypod.py &

in sudo nano /etc/xdg/openbox/environment I set all the variables needed to run spotifypod.py ( SPOTIPY_CLIENT_ID, SPOTIPY_CLIENT_SECRET,SPOTIPY_REDIRECT_URI)

As result I get the following:

X.Org X Server 1.20.4
X Protocol Version 11, Revision 0
Build Operating System: Linux 5.4.0-54-generic armv8l Raspbian
Current Operating System: Linux raspberrypi 5.10.11+ #1399 Thu Jan 28 12:02:28 GMT 2021 armv6l
Kernel command line: coherent_pool=1M 8250.nr_uarts=0 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1 bcm2708_fb.fbwidth=320 bcm2708_fb.fbheight=240 bcm2708_fb.fbswap=1 smsc95xx.macaddr=HI:TH:ER:EC:DD:E9 vc_mem.mem_base=0x1ec00000 vc_mem.mem_size=0x20000000 console=ttyS0,115200 console=tty1 root=PARTUUID=2386ac2f-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
Build Date: 15 January 2021 02:03:57PM
xorg-server 2:1.20.4-1+rpt2+deb10u3 (https://www.debian.org/support)
Current version of pixman: 0.36.0
Before reporting problems, check http://wiki.x.org
to make sure that you have the latest version.
Markers: (--) probed, (**) from config file, (==) default setting,
(++) from command line, (!!) notice, (II) informational,
(WW) warning, (EE) error, (NI) not implemented, (??) unknown.
(==) Log file: "/var/log/Xorg.1.log", Time: Mon Feb 8 22:27:43 2021
(==) Using system config directory "/usr/share/X11/xorg.conf.d"
InitSPI done
Relevant source display area size with overscan cropped away: 320x240.
Source GPU display is 320x240. Output SPI display is 320x240 with a drawable area of 320x240. Applying scaling factor horiz=1.00x & vert=1.00x, xOffset: 0, yOffset: 0, scaledWidth: 320, scaledHeight: 240
Creating dispmanX resource of size 320x240 (aspect ratio=1.333333).
GPU grab rectangle is offset x=0,y=0, size w=320xh=240, aspect ratio=1.333333
All initialized, now running main loop...
Openbox-Message: Unable to find a valid menu file "/var/lib/openbox/debian-menu.xml"

** (process:627): WARNING **: 22:27:46.829: xdg-autostart.vala:125: Error: Error opening directory ?/root/.config/autostart?: No such file or directory

** Message: 22:27:46.838: xdg-autostart.vala:39: Processing /etc/xdg/autostart/at-spi-dbus-bus.desktop file.
** Message: 22:27:46.855: xdg-autostart.vala:94: Launching: /usr/lib/at-spi2-core/at-spi-bus-launcher --launch-immediately (at-spi-dbus-bus.desktop)
** Message: 22:27:46.858: xdg-autostart.vala:39: Processing /etc/xdg/autostart/xdg-user-dirs.desktop file.
** Message: 22:27:46.896: xdg-autostart.vala:94: Launching: xdg-user-dirs-update (xdg-user-dirs.desktop)
Failed to launch bus: Failed to connect to session busNo protocol specified
No protocol specified

All what I get is a black screen with a mouse pointer... In my PC I have managed to make it run and get to see the manues an navigate. With tthe RPI Zero, it looks like I am missing one or several pconfigurations to link Tkinter properly with openbox..
Any help would be very appreciated!!

Search infinitely loading.

After battling for a weekend I'm finally nearing the end of the software side of things.

The only thing that I cannot seem to get working is the search function.

I was originally having issues with actually playing any songs from my playlists until I modified the scope array in spotify_manager.py. Am I missing anything from my scope that is causing my search issues?

Here's my current scope:

 scope = "user-follow-read," \
        "user-library-read," \
        "user-library-modify," \
        "user-modify-playback-state," \
        "user-read-playback-state," \
        "user-read-currently-playing," \
        "app-remote-control," \
        "playlist-read-private," \
        "playlist-read-collaborative," \
        "playlist-modify-public," \
        "playlist-modify-private," \
        "streaming," \
        "user-read-private"

I am able to play music from my playlists, and at this stage, I'm happy to just leave it at that, but if I could get the search function working too, that would be great.

Cannot Generate .cache file

Hi there. After following some guides from other posts, I have gotten to the part where you need to let the Spotipy program have access to my Spotify account. After loading up a VNC and going to the localhost:8080 site, and allowing it access to my account, it takes me to a site that Midori cannot load. I was told to paste this into the console, but there is no prompt to do so, and nothing happens when I do. Any leads? Here is a screenshot of after I authorize it through spotify:
121064308-04379600-c78d-11eb-89bf-fb27b8075fc6

5th generation ipod

would a 5th generation ipod classic be possible?
i would guess the newer clickwheel would be the only obstacle.

Enable Discussions Tab

Hi @dupontgu,

could you please enable the Discussions tab in the repository settings? Instead of creating new issues, this would be a better place to ask questions.

Blank Screen

Got everything mostly working (even the clickwheel) but I get nothing but a blank screen after X11 starts.

While I'm usually fine using X11, this openbox stuff is all new to me and it just doesn't seem to be working.

If I startx manually I get the following:

** (process:879): WARNING **: 20:40:13.509: xdg-autostart.vala:125: Error: Error opening directory ?/home/pi/.config/autostart?: No such file or directory

** Message: 20:40:13.544: xdg-autostart.vala:39: Processing /etc/xdg/autostart/gnome-keyring-secrets.desktop file.
** Message: 20:40:13.550: xdg-autostart.vala:64: Not found in OnlyShowIn list, aborting.
** Message: 20:40:13.555: xdg-autostart.vala:39: Processing /etc/xdg/autostart/gnome-keyring-ssh.desktop file.
** Message: 20:40:13.559: xdg-autostart.vala:64: Not found in OnlyShowIn list, aborting.
** Message: 20:40:13.564: xdg-autostart.vala:39: Processing /etc/xdg/autostart/at-spi-dbus-bus.desktop file.
** Message: 20:40:13.584: xdg-autostart.vala:94: Launching: /usr/lib/at-spi2-core/at-spi-bus-launcher --launch-immediately (at-spi-dbus-bus.desktop)
** Message: 20:40:13.587: xdg-autostart.vala:39: Processing /etc/xdg/autostart/xdg-user-dirs.desktop file.
** Message: 20:40:13.630: xdg-autostart.vala:94: Launching: xdg-user-dirs-update (xdg-user-dirs.desktop)
** Message: 20:40:13.638: xdg-autostart.vala:39: Processing /etc/xdg/autostart/gnome-keyring-pkcs11.desktop file.
** Message: 20:40:13.640: xdg-autostart.vala:64: Not found in OnlyShowIn list, aborting.
2021-03-15 20:40:13 initInitialise: Can't lock /var/run/pigpio.pid

Any help is appreciated.

(Request) Help Porting Clickwheel Code to PocketBeagle

Hey everyone,

I was holding off on posting here for a while, but I've banged my head against the wall for so long that I need a bit of guidance.

Like Guy, I had been working on a similar project since last summer, but decided to try to switch over to the PocketBeagle instead of a Raspberry Pi (mainly due to it's alleged support for very low power sleep modes).

Getting things like Wi-Fi/Bluetooth/SPI displays working on this was a battle and a half, but I managed to work through them. One thing I'm still stuck on, however, is the clickwheel code.

From what I can tell, he's got a few callback functions triggered to run whenever either the clock or data line changes, then does a bit of bit-banging. What I'm struggling with is the switch to the IOBB library to get similar behavior up and running on a PocketBeagle.

// Nate added these for PocketBeagle to make hack-y callback functions
int CURRENTCLOCKSTATE = 0;
int CURRENTDATASTATE = 0;
int PASTCLOCKSTATE = 0;
int PASTDATASTATE = 0;

iolib_init();

iolib_setdir(1, 28, DigitalIn);  // Set clock pin GPIO13 (P1,28) as input
iolib_setdir(1, 26, DigitalIn);  // Set data pin GPIO12 (P1,26) as input

// Back to Guy's code
if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) { 
    perror("socket creation failed"); 
    exit(EXIT_FAILURE); 
} 
  
memset(&servaddr, 0, sizeof(servaddr)); 
      
servaddr.sin_family = AF_INET; 
servaddr.sin_port = htons(PORT); 
servaddr.sin_addr.s_addr = INADDR_ANY;

// I also removed the pulses/haptic code, as I wasn't planning on integrating that

while(running) {
    
    CURRENTCLOCKSTATE = (is_low(1, 28)) ? 0 : 1;
    CURRENTDATASTATE = (is_low(1, 26)) ? 0 : 1;

    //printf("Did clock state change?");
    if(CURRENTCLOCKSTATE != PASTCLOCKSTATE) {
        printf("Clock state changed!\n");
        onClockEdge(28, CURRENTCLOCKSTATE);  // Runs his original functions
        PASTCLOCKSTATE = CURRENTCLOCKSTATE;
    }

    //printf("Did data state change?");
    if(CURRENTDATASTATE != PASTDATASTATE) {
        printf("Data state changed!\n");
        onDataEdge(26, CURRENTDATASTATE);  // Runs his original functions
        PASTDATASTATE = CURRENTDATASTATE;
    }
}

The idea is that I'm creating my own callback functions if the current data/clock pin state changes compared to the previous one. However, it perpetually reads the state of those pins as 0, which makes me think I'm just not polling correctly.

I'm not a programmer by trade (especially not this low level of programming), and unfortunately I've exhausted my list of resources for i2c reading/bit-banging.

Potential UI improvements

First of all, @dupontgu thank you for this amazing project.

  • What do you think to add a potential UI for switching output for music playback, such as audio jack, bluetooth. Perhaps this can be added to music playback section with a custom action such as holding home button for 2 or more seconds?
  • What do you think to add another root menu option called settings, where the user can pair bluetooth accessories, or other personalized options, like wifi and other properties of the device?

How to add a new option on the menu page

Where you would usually find playlists, albums, and podcasts I want to make a new one called Pair Audio so when it's clicked it will run subprocess.run(["btaudio-connect"]) which will run a bash command in python that connects my headphones.

My headphones already connect upon boot, But sometimes they don't or they are connected to my phone so I wanted an easy option to connect my headphones. I already have the code displaying the option but can't get it to run when clicked, I have no experience in python just messing around and looking at how the other classes get processed.

Here's what I already got working:
pair_head
with this code
Code_head
run_head
When I click on it, it freezes the program and I have to restart and it's back to normal. Any ideas?

No License?

Hey,
Unless I missed it, there is no open source license for the code?
If that's the case then the code is technically proprietary (I assume that's not what you want). I am not a lawyer but from what I know right now people can't legally modify, distribute, or use your code (incl. to make contributions) without your written consent each time (See this github doc).

Personally, I'd use the GNU GPL (so people can't take your code and create a closed source version) but you may prefer something else ๐Ÿ˜„

Q: High click.c CPU usage

Hi everyone,

I noticed a very high CPU usage if I run just click even without the UI. Did anyone else notice this and did anyone find a better solution?

So far I have tried to rewrite the click.c code into a python class which could be used by the frontend directly, which was much worse performance wise.

Afterwards I have tried to adjust the sampling rate of the gpios but this resulted in only detecting up and down commands:

gpioCfgClock(8, 0, 0);

My latest effort was to make use of the pigpio daemon sudo pigpiod (add this command to /etc/xdg/openbox/autostart). And the following rewritten code but it does not seem to be any better.

click.c code
// To compile on the pi (after installing pigpio):
// gcc -Wall -pthread -o click click.c -lpigpiod_if2 -lrt

#include <pigpiod_if2.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

#define CLOCK_PIN 23
#define DATA_PIN 17
#define HAPTIC_PIN 26
#define BIT_COUNT 32
#define PORT 9090
#define MAXLINE 1024

#define CENTER_BUTTON_BIT 7
#define LEFT_BUTTON_BIT 9
#define RIGHT_BUTTON_BIT 8
#define UP_BUTTON_BIT 11
#define DOWN_BUTTON_BIT 10
#define WHEEL_TOUCH_BIT 29

#define BUFFER_SIZE 3
#define BUTTON_INDEX 0
#define BUTTON_STATE_INDEX 1
#define WHEEL_POSITION_INDEX 2

// used to store the current packet
uint32_t bits = 0;
// used to store the previous full packet
uint32_t lastBits = 0;
uint8_t bitIndex = 0;
uint8_t oneCount = 0;
uint8_t recording = 0;
// indicates whether the data pin is high or low
uint8_t dataBit = 1;
uint8_t lastPosition = 255;
int pi = -1;
int hapticWaveId = -1;

char buttons[] = {
    CENTER_BUTTON_BIT,
    LEFT_BUTTON_BIT,
    RIGHT_BUTTON_BIT,
    UP_BUTTON_BIT,
    DOWN_BUTTON_BIT,
    WHEEL_TOUCH_BIT
};

// all valid click wheel packets start with this
const uint32_t PACKET_START = 0b01101;

int sockfd;
char buffer[BUFFER_SIZE];
char prev_buffer[BUFFER_SIZE];
struct sockaddr_in servaddr;

// helper function to print packets as binary
void printBinary(uint32_t value) {
    for(uint8_t i = 0; i < 32; i++) {
        if (value & 1)
            printf("1");
        else
            printf("0");

        value >>= 1;
    }
    printf("\n");
}

// parse packet and broadcast data
void sendPacket() {
    if ((bits & PACKET_START) != PACKET_START) {
        return;
    }
    for (size_t i = 0; i < BUFFER_SIZE; i++) {
        buffer[i] = -1;
    }

    for (size_t i = 0; i < sizeof(buttons); i++) {
        char buttonIndex = buttons[i];
        if ((bits >> buttonIndex) & 1 && !((lastBits >> buttonIndex) & 1)) {
            buffer[BUTTON_INDEX] = buttonIndex;
            buffer[BUTTON_STATE_INDEX] = 1;
            printf("button pressed: %d\n", buttonIndex);
        } else if (!((bits >> buttonIndex) & 1) && (lastBits >> buttonIndex) & 1) {
            buffer[BUTTON_INDEX] = buttonIndex;
            buffer[BUTTON_STATE_INDEX] = 0;
            printf("button released: %d\n", buttonIndex);
        }
    }
    uint8_t wheelPosition = (bits >> 16) & 0xFF;
    // send haptics every other position. too sensitive otherwise
    if (wheelPosition != lastPosition && wheelPosition % 2 == 0) {
        if (hapticWaveId != -1) {
            wave_send_once(pi, hapticWaveId);
        }
        lastPosition = wheelPosition;
    }
    buffer[WHEEL_POSITION_INDEX] = wheelPosition;
    if (memcmp(prev_buffer, buffer, BUFFER_SIZE) == 0) {
        return;
    }
    printf("position %d\n", wheelPosition);
    lastBits = bits;
    sendto(sockfd, (const char *)buffer, BUFFER_SIZE,
        MSG_CONFIRM, (const struct sockaddr *) &servaddr,
            sizeof(servaddr));
    memcpy(prev_buffer, buffer, BUFFER_SIZE);
}

// Function to set the kth bit of n
int setBit(int n, int k) {
    return (n | (1 << (k - 1)));
}

// Function to clear the kth bit of n
int clearBit(int n, int k) {
    return (n & (~(1 << (k - 1))));
}

void onClockEdge(int pi, unsigned int gpio, unsigned int edge, unsigned int tick) {
    if (!edge) {
        // only care about rising edge
        return;
    }
    if (dataBit == 0) {
        recording = 1;
        oneCount = 0;
    } else {
        // 32 1's in a row means we're definitely not in the middle of a packet
        if (++oneCount >= BIT_COUNT) {
            recording = 0;
            bitIndex = 0;
        }
    }
    // in the middle of the packet
    if (recording == 1) {
        if (dataBit) {
            bits = setBit(bits, bitIndex);
        } else {
            bits = clearBit(bits, bitIndex);
        }
        // we've collected the whole packet
        if (++bitIndex == 32) {
            bitIndex = 0;
            sendPacket();
        }
    }
}

void onDataEdge(int pi, unsigned int gpio, unsigned int edge, unsigned int tick) {
    dataBit = edge;
}

int main(int argc, char** argv){

    // Creating socket file descriptor
    if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }

    memset(&servaddr, 0, sizeof(servaddr));

    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(PORT);
    servaddr.sin_addr.s_addr = INADDR_ANY;

    pi = pigpio_start(0, 0);

    // haptic waveform - just a simple on-off pulse
    set_mode(pi, HAPTIC_PIN, PI_OUTPUT);

    gpioPulse_t pulse[2];
    pulse[0].gpioOn = (1<<HAPTIC_PIN);
    pulse[0].gpioOff = 0;
    pulse[0].usDelay = 8000;

    pulse[1].gpioOn = 0;
    pulse[1].gpioOff = (1<<HAPTIC_PIN);
    pulse[1].usDelay = 2000;

    wave_add_new(pi);
    wave_add_generic(pi, 2, pulse);
    hapticWaveId = wave_create(pi);

    set_pull_up_down(pi, CLOCK_PIN, PI_PUD_UP);
    set_pull_up_down(pi, DATA_PIN, PI_PUD_UP);
    callback(pi, CLOCK_PIN, RISING_EDGE, onClockEdge);
    callback(pi, DATA_PIN, EITHER_EDGE, onDataEdge);

    while(1) {
    };

    pigpio_stop(pi);
}

Is there a better or more efficient way to read the serial data from our clickwheel?

On the one hand I am a bit concerned by the heat generated by the CPU even while not even running anything else but click on the other hand I kind of want to avoid adding another component as such as an Arduino if it is not necessary.

Search and Get_Playlist() Issues

Hey, I've been working on this project for a while now and am almost all the way through. I have only two major issues left on the software side and wanted to see if anyone could help me solve them.
1: When I try to use the search feature I get the following error and on the frontend the screen in just left with "loading..."

requests.exceptions.HTTPError: 400 Client Error: Bad Request for url: https://api.spotify.com/v1/search?q=&limit=5&offset=0&type=track

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/usr/lib/python3.9/threading.py", line 954, in _bootstrap_inner
self.run()
File "/usr/lib/python3.9/threading.py", line 892, in run
self._target(*self._args, **self._kwargs)
File "/home/pi/retro-ipod-spotify-client/frontend/view_model.py", line 155, in
spotify_manager.run_async(lambda: self.run_search(self.live_render.query))
File "/home/pi/retro-ipod-spotify-client/frontend/view_model.py", line 150, in run_search
self.live_render.results = spotify_manager.search(query)
File "/home/pi/retro-ipod-spotify-client/frontend/spotify_manager.py", line 418, in search
track_results = sp.search(query, limit=5, type='track')
File "/home/pi/.local/lib/python3.9/site-packages/spotipy/client.py", line 553, in search
return self._get(
File "/home/pi/.local/lib/python3.9/site-packages/spotipy/client.py", line 297, in _get
return self._internal_call("GET", url, payload, kwargs)
File "/home/pi/.local/lib/python3.9/site-packages/spotipy/client.py", line 267, in _internal_call
raise SpotifyException(
spotipy.exceptions.SpotifyException: http status: 400, code:-1 - https://api.spotify.com/v1/search?q=&limit=5&offset=0&type=track:
No search query, reason: None

That was me searching just 'q'

2: I can never fetch any of my playlists
I'm not sure what else to put here but the only lead I have are that, if I'm actively listening to a playlist while booting it up it will have it saved. I have no clue what is the problem here but it seems like there were a lot more steps that needed to be taken around the coding for the playlist function after looking at the comments next to them.

If anyone could help fill me in on anything I may be missing or doing wrong please let me know and thank you in advance!

Tutorial: Get a SPI Display working (Waveshare 320x240 using fbcp-ili9341)

You are wondering on how to get a SPI display to work? Yeah me too so I hope this quick guide will help you.
I did this using a Waveshare 320x240 LCD IPS screen. This is the pinout I used which is provided by Waveshare themselves.

I'm sorry if an issue isn't the right place but I figured most people with this question would see it here first. If it fits into the README (as a shortened version) I would gladly open a pull request.

If I'm missing something or got something wrong please comment down below.

Stuff on your computer:
First of all open config.txt which is located in the boot partition while having the SD card mounted on your computer.
I didn't need to follow these few steps which tell you to remove any dtoverlay or dtparam=spi=on parameter as I didn't have them in my config.

As described here, add these lines to your config.txt (or uncomment and modify the existing ones but hdmi_cvt didn't exist for me yet):

hdmi_group=2
hdmi_mode=87
hdmi_cvt=320 240 60 1 0 0 0
hdmi_force_hotplug=1

Note: You will need to change the first two hdmi_cvt values based on the resolution of your screen. As I mentioned already, I used a 320x240 screen in this example.

Stuff on the pi:
You can now eject your SD card and boot the pi.
When you are in a terminal (for example using ssh), follow these steps as documented here:

sudo apt install cmake git
cd ~
git clone https://github.com/juj/fbcp-ili9341.git
cd fbcp-ili9341

Open st7735r.h using a text editor:
nano st7735r.h

Go to line 18 which defines the values for the controller the display in this example uses: ST7789
Change DISPLAY_NATIVE_HEIGHT from 240 to 320 as described here.
Then save (CTRL+S) and exit (CTRL+X).

Yes, in my experience you need to change height and not width even though the width should be 320. Idk, this is a bit weird but maybe I just don't understand it correctly.

Now we need to compile the driver.
Create a build folder:
mkdir build
and open it:
cd build

If you have used the same pinout as in the image in the beginning then these values should be right.
If not then you need to change TFT_DATA_CONTROL and TFT_RESET_PIN. Remember that these numbers are the GPIO pin names and not counted. Image to see which GPIO Pin has which number

Note: The BUS_CLOCK_DIVISOR is not a pin but a value that defines the speed of the clock together with the value 60 we set in the config.txt. I don't really understand this value myself but I read that most people recommend using 30 here first before changing it and it worked for me just fine.

cmake -DST7789=ON -DGPIO_TFT_DATA_CONTROL=25 -DGPIO_TFT_RESET_PIN=27 -DSPI_BUS_CLOCK_DIVISOR=30 -DSTATISTICS=0 -DUSE_DMA_TRANSFERS=OFF ..

Since I had to mount my display with the ribbon cable on the right side, so basically upside down from the original orientation the manufacturer intended, I had to flip the image by including this option before the two dots at the end: -DDISPLAY_ROTATE_180_DEGREES=ON

Now wait for that to finish and then type:
make -j

When that is done we are almost done. You can test the driver now by running sudo ./fbcp-ili9341 but since the driver should start automatically on boot we have to do one last change.
Open /etc/rc.local with a text editor with sudo privileges:
sudo nano /etc/rc.local

Add these lines before exit:

# Start display driver
/home/pi/fbcp-ili9341/build/fbcp-ili9341 &

Thats it!

I hope this helped you to figure out on how to get your display running. I had many questions for a few days but these were all the steps I had to take to get my display up and running. I credited every source where I got my information from in this post.
(I hope I didn't forget anything, wasn't the only one having this problem and that it works for you.)

error when I run spotifpod.py

When I Spotifypod.py manually it in the terminal it just spams 'no ints' and I've looked on every issue and read the comments and I can't seem to find a solution for this problem any help im kind of a noob to all this.

Selecting track to play from playlist doesn't seem to work

What a great project. I saw it featured on hackaday and have got it mostly setup and running locally (on my PC running uBuntu 20.04 via WSL2 in Windows).

When browsing playlist tracks, are you supposed to be able to hit the "play/pause" button a track (or hit next on the track item) to start playing that instead of whatever is currently playing?

When I do this nothing happens, it just pushes in the Now Playing view and the existing track that is currently playing will just continue. See GIF for demonstration of what I mean:

Example GIF

Just wondering if this is expected, or if it is indeed meant to start playing the selected track? I'm not using Raspotify as a Connect Device as I'm running local on my desktop for now. Just a standard Spotify Windows App (also tried with spotify web player), but I'm not sure if this should make a difference or not.

BTW, a couple of things I found along the way that might trip up others:

  • I found I needed to change the keycodes for uBuntu Linux. I used xev to test what codes were used for my directional arrows and P / N which I assigned to previous/next.
  • I found the default spotify API scopes were not enough, and I would get a 401 response from the API in an exception when trying to run the frontend. To fix this I added user-read-playback-state (key to finding this was 'devices' API call to spotify returning 401 response. There may have been one or two other scopes needed, but when you see the exceptions its usually pretty clear which other scopes need adding ๐Ÿ‘

I have some hardware on order and will attempt a full build once it arrives :]

Thanks!

Raspotify no longer supported

So it appears they dropped support for the raspberry pi zero. So that step does not work. Can someone help me solve this?

How I fixed [Errno 98], NoneType, Scope, and StartX blank screen

Hey everyone,

I want to show everyone what I did to resolve some of the major issues I've been running into during the installation @dupontgu's amazing project.

Some background: I don't have an iPod or anything, and this was all done on my Raspberry Pi 4 in a PiBoy DMG. My plan for this is to be able to launch spotipy via RetroPie.

[Errno 98] Address already in use

After going through the installation I tried running spotipy.py, but I ran into a couple of issues with the [Errno 98] Address in use. I went out of my mind thinking it was related to the UDP_PORT or even the OAuth port. Maybe it was the server address or redis? Nah, throw all of that out the window. This issue is because of a .cache not being found.

python3 spotifypod.py
Traceback (most recent call last):
File "spotifypod.py", line 12, in
from view_model import *
File "/home/pi/retro-ipod-spotify-client/frontend/view_model.py", line 17, in
spotify_manager.refresh_data()
File "/home/pi/retro-ipod-spotify-client/frontend/spotify_manager.py", line 159, in refresh_data
results = sp.current_user_saved_tracks(limit=pageSize, offset=0)
File "/home/pi/.local/lib/python3.7/site-packages/spotipy/client.py", line 1183, in current_user_saved_tracks
return self._get("me/tracks", limit=limit, offset=offset)
File "/home/pi/.local/lib/python3.7/site-packages/spotipy/client.py", line 291, in _get
return self._internal_call("GET", url, payload, kwargs)
File "/home/pi/.local/lib/python3.7/site-packages/spotipy/client.py", line 221, in _internal_call
headers = self._auth_headers()
File "/home/pi/.local/lib/python3.7/site-packages/spotipy/client.py", line 212, in _auth_headers
token = self.auth_manager.get_access_token(as_dict=False)
File "/home/pi/.local/lib/python3.7/site-packages/spotipy/oauth2.py", line 481, in get_access_token
"code": code or self.get_auth_response(),
File "/home/pi/.local/lib/python3.7/site-packages/spotipy/oauth2.py", line 436, in get_auth_response
return self._get_auth_response_local_server(redirect_port)
File "/home/pi/.local/lib/python3.7/site-packages/spotipy/oauth2.py", line 402, in _get_auth_response_local_server
server = start_local_http_server(redirect_port)
File "/home/pi/.local/lib/python3.7/site-packages/spotipy/oauth2.py", line 1300, in start_local_http_server
server = HTTPServer(("127.0.0.1", port), handler)
File "/usr/lib/python3.7/socketserver.py", line 452, in init
self.server_bind()
File "/usr/lib/python3.7/http/server.py", line 137, in server_bind
socketserver.TCPServer.server_bind(self)
File "/usr/lib/python3.7/socketserver.py", line 466, in server_bind
self.socket.bind(self.server_address)
OSError: [Errno 98] Address already in use

sebakitzing's post (#22) led me to the right path with this issue.
You can verify if the .cache folder exists by going to /retro-ipod-spotify-client/frontend and typing ls -a
I was able to authorize spotipy through Midori browser, but for some reason, the .cache file would not create. I looked around and found Perelin's solution for Spotipy's OAuth (https://github.com/perelin/spotipy_oauth_demo). With a little modification to the spotipy_oauth_demo, I was able to create a cache folder to the /home/pi/ folder:

Please note: you will have to add your own client ID and secret from your Spotify Developer Dashboard. You will also need to add http://localhost:8080 to your Redirect URIs in the dashboard. I will explain the scoping modifications in the next topic.

SPOTIPY_CLIENT_ID = 'XXXXXXX'
SPOTIPY_CLIENT_SECRET = 'XXXXXX'
SPOTIPY_REDIRECT_URI = 'http://localhost:8080'

SCOPE = "user-follow-read," \
        "user-library-read," \
        "user-library-modify," \
        "user-modify-playback-state," \
        "user-read-playback-state," \
        "user-read-currently-playing," \
        "app-remote-control," \
        "playlist-modify," \
        "playlist-read-private," \
        "playlist-read-collaborative," \
        "playlist-modify-public," \
        "playlist-modify-private," \
        "streaming," \
        "user-follow-modify," \
        "user-follow-read"


CACHE = '/home/pi/.spotipyoauthcache'

sp_oauth = oauth2.SpotifyOAuth( SPOTIPY_CLIENT_ID, SPOTIPY_CLIENT_SECRET,SPOTIPY_REDIRECT_URI,scope=SCOPE,cache_path=CACHE)

With this modification, a cache folder was successfully made! I then
sudo cp /home/pi/.spotipyoauthcache /retro-ipod-spotify-client/frontend/.cache
This will copy the cache folder into the folder to allow spotipypod.py to work. This will also bypass the "Enter the URL you were redirected to:" prompt.
Note: I use cp instead of mv because I wanted to have a backup of the cache folder in case of a disaster.

After copying this cache folder over, I ran into another issue where spotipypod.py cannot write into the cache folder due to permission issues. This can easily be resolved with
sudo chomod 777 /retro-ipod-spotify-client/frontend/.cache
This command opens the permission rights to the .cache folder.

After that, I was able to run spotipypod.py...into another issue.

Scope Errors

Another issue occurred when running spotipypod.py, somewhere along the line of:

https://api.spotify.com/v1/me/following?type=artist&limit=50
spotipy.client.SpotifyException: http status: 403, code:-1 - https://api.spotify.com/v1/me/albums?limit=100&offset=0:
     Insufficient client scope

This can be resolved by adding more scopes into spotify_manager.py

scope = "user-follow-read," \
        "user-library-read," \
        "user-library-modify," \
        "user-modify-playback-state," \
        "user-read-playback-state," \
        "user-read-currently-playing," \
        "app-remote-control," \
        "playlist-modify," \
        "playlist-read-private," \
        "playlist-read-collaborative," \
        "playlist-modify-public," \
        "playlist-modify-private," \
        "streaming," \
        "user-follow-modify," \
        "user-follow-read"

This fixed pretty much my scope issues.

NoneType Error

This part was tricky. As a person of many many... many playlists, some tracks become unavailable or null. spotipypod.py doesn't know what to do with these null tracks and will end up in an error before even starting. I had to modify some code around spotify_manager.py to skip null tracks. Here are the instances and their code:

!!Oh yeah before doing this, make sure to fix the playlist order first according to HerrEurobeat's post (#26).

def get_playlist_tracks(id):
    tracks = []
    results = sp.playlist_tracks(id, limit=pageSize)
    while(results['next']):
        for _, item in enumerate(results['items']):
            track = item['track']
            if track is None:
                continue
            else:
                tracks.append(UserTrack(track['name'], track['artists'][0]['nam$
        results = sp.next(results)
    for _, item in enumerate(results['items']):
        if item['track'] is None:
            continue
        else:
            track = item['track']
            tracks.append(UserTrack(track['name'], track['artists'][0]['name'],$
    return tracks


def refresh_data():
  <--code skip--->
    results = sp.current_user_playlists(limit=pageSize)
    totalindex = 0 # variable to preserve playlist sort index when calling offset loop down below
    while(results['next']):
        offset = results['offset']
        for idx, item in enumerate(results['items']):
            if item['uri'] is None:
                continue
            else:
                tracks = get_playlist_tracks(item['id'])
                DATASTORE.setPlaylist(UserPlaylist(item['name'], totalindex, item['uri'], len(tracks)), tracks, inde$
                totalindex = totalindex + 1
        results = sp.next(results)

We're not done yet!

StartX

I kept running into an issue with the Xauth: xauth: timeout in locking authority file /home/pi/.Xauthority. I was not sure what could be causing it, but I read that this was not really needed and safe to deleted. So I did, I ran sudo rm /home/pi/.Xauthority I ran into another issue where when using startx, it will not launch and returns an error
Cannot Open /dev/tty0 (Permission Denied) to resolve this, I had to use sudo chown pi /dev/tty0. This works, but resets when after rebooting. So I created a script:

sudo chown pi /dev/tty0
sudo chown pi /dev/tty1
sudo chown pi /dev/tty2
sudo chown pi /dev/tty3
sudo chown pi /dev/tty4
sudo chown pi /dev/tty5
sudo chown pi /dev/tty6
sudo chown pi /dev/tty7


startx

The reason why I repeated this step all the way until tty7 was because of the virtual consoles. If you already have a startx console running, using startx again will create another virtual console, which is a different ttyX set. Setting chown for 8 tty will make it safe to load in any one of these. I know this is a bit of a mess, but I have not run into any issues as of yet. I am open for optimizations and improvements.

make sure to use sudo chmod +x [yourscript].sh to allow running ./[yourscript].sh

!!Please note using sudo startx will launch it in root, which will not launch spotipypod.py at all. It'll just give you a blank screen. Just remove sudo and it should launch correctly.

After tackling these issues, I was able to load spotipypod.py at last.

Side note: During this process, I followed HerrEurobeat's other post (#24) on removing emoticons from playlist names so it doesn't error. I have a couple of playlists with this and for 'future-proofing this definitely did the job.

Cheers

Program keeps crashing

All I get is "x set" errors each time I run it. I've tried this countless times, word for word and it just isn't working.

Clickwheel feedback

Hi, I have the following problem: when I run de comand sudo ./click to see if I recive feedback from the clickwheel I only recive when the menu button or the center button are pressed nothing happens with the others. Any suggestions?, thank you very much!

Song only plays first few seconds & How to use bluetooth audio?

So I almost have everything fully working now. I am down to two issues.

  1. When selecting a song, it "plays" the first 3 or so seconds and then pauses on 00:03. Hitting play wont do anything and i just have to select the song again.
  2. When it's playing I don't get any audio. Bluetooth is connected and shows the following for status:
    [Galaxy Buds2 (C0C4)]# info 60:3A:AF:4D:C0:C4
    Device 60:3A:AF:4D:C0:C4 (public)
    Name: Galaxy Buds2 (C0C4)
    Alias: Galaxy Buds2 (C0C4)
    Class: 0x00240404
    Icon: audio-card
    Paired: yes
    Trusted: no
    Blocked: no
    Connected: yes
    LegacyPairing: no
    UUID: Serial Port (00001101-0000-1000-8000-00805f9b34fb)
    UUID: Audio Sink (0000110b-0000-1000-8000-00805f9b34fb)
    UUID: A/V Remote Control Target (0000110c-0000-1000-8000-00805f9b34fb)
    UUID: A/V Remote Control (0000110e-0000-1000-8000-00805f9b34fb)
    UUID: Handsfree (0000111e-0000-1000-8000-00805f9b34fb)
    UUID: PnP Information (00001200-0000-1000-8000-00805f9b34fb)
    UUID: Vendor specific (2e73a4ad-332d-41fc-90e2-16bef06523f2)
    UUID: Vendor specific (a23d00bc-217c-123b-9c00-fc44577136ee)
    UUID: Vendor specific (b4a9d6a0-b2e3-4e40-976d-a69f167ea895)
    UUID: Vendor specific (e7ab2241-ca64-4a69-ac02-05f5c6fe2d62)
    UUID: Vendor specific (f8620674-a1ed-41ab-a8b9-de9ad655729d)

Also, how to auto connect bluetooth on startup? I have to manually connect via terminal over SSH each time.

TclError: no display name and no $DISPLAY environment variable

Hello, Firstly thanks for sharing this awesome project.

I receive the error below after trying to run python3 spotifypod.py
This error appeared after I entered the redirected URL

Can anyone point me in the right direction to get past this?

Traceback (most recent call last): File "spotifypod.py", line 543, in <module> app = tkinterApp() File "spotifypod.py", line 88, in __init__ tk.Tk.__init__(self, *args, **kwargs) File "/usr/lib/python3.7/tkinter/__init__.py", line 2023, in __init__ self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use) _tkinter.TclError: no display name and no $DISPLAY environment variable

Thanks

How I fixed Cache, env variables and got everything running

Just a few notes on how I got things working, mostly based on what I have read in various issue threads. Credit to #22 #30

/boot/config.txt if you bought the screen from the tutorial
comment out hdmi_force_hotplug=1
#hdmi_force_hotplug=1

uncomment sdtv_mode
sdtv_mode=0

uncomment disable overscan
disable_overscan=1

also want to put in your wpa_supplicant.conf in the boot directory as well at this time

Install git:
Step 2.
Add sudo apt install git

Clone repo
Step 3
add git clone https://github.com/dupontgu/retro-ipod-spotify-client before installing requirements

add env variables to bash profile
Step 8
sudo nano ~/.bash_profile

#!/bin/bash

[[ -z $DISPLAY && $XDG_VTNR -eq 1 ]] && startx -- -nocursor

# Disable any form of screen saver / screen blanking / power management

xset s off

xset s noblank

export SPOTIPY_CLIENT_ID='your_SPOTIPY_CLIENT_ID'

export SPOTIPY_CLIENT_SECRET='your_SPOTIPY_CLIENT_SECRET'

export SPOTIPY_REDIRECT_URI='http://localhost:8080'

export DISPLAY=:0.0

pass env variables to spotify ipod script
Step 10
replace sudo -H -u pi python3 spotifypod.py & with sudo -H -u pi --preserve-env=SPOTIPY_REDIRECT_URI,SPOTIPY_CLIENT_ID,SPOTIPY_CLIENT_SECRET python3 spotifypod.py &

Also need to compile click.c

cd /home/pi/retro-spotify-client/clickwheel
gcc -Wall -pthread -o click click.c -lpigpio -lrt

Post install
We need to generate a .cache file for the spotify token. I suggest doing this on a pi 3 or 4 and using VNC.

sudo apt install midori
git clone https://github.com/perelin/spotipy_oauth_demo
sudo apt install python python-pip
cd ~/spotipy_oauth_demo
pip install -r requirements.txt

modify spotipy_oauth_demo.py and add your client id and secret
run the oauth demo with python spotipy_oauth_demo.py

using Midori, navigate to http://localhost:8080, you should see a hyperlink that says login to spotify, click it, you will be redirected to spotify login, just login and accept the terms

cp ~/.spotipyautocache ~/retro-ipod-spotify/frontend/.cache
chmod 777 ~/retro-ipod-spotify/frontend/.cache

Run raspi-config one more time to disable VNC from the interface menu, reboot and now you should be good.

As a side note, be careful with the ipod case being metal it is really easy to short the various solder points you have made. I lined mine with electrical tape to avoid it, in the future I plan on 3d printing something to hold the various components in place and keep them from shorting.

An overheating Power Boost (& wiring schematic)

IMG_2915
the schematic posted on the github was SUPER useful
i am a novice to the soldering aspect of this project
in the attached image - my adafruit powerboost overheats - the little 6R8 component gets wickedly hot
then the power boost low power light flickers
and i am never able to get the screen nor the PI to actually turn on

in the photo
you will see that the white and black cables from the charger to the power boost
have been cut
obviously when connected
the overheating occurs

what am i missing in my attempt to mimic the schematic?
do i have some polarity issue
am i using a proper charger (using a different usb charger than in dupontgu's setup)

sincerely
and thanks in advance to all the comments and such here
wonderful project
paulo

Having Problems with Spotipy...

For whatever reason when I run python3 spotifypod.py I get the error: No module named 'spotipy'

I was able to run spotifypod.py before and was even able to get spotify to recognize everything but for some reason now the spotipy module wont show up.

I am super confused and also fairly new to this so forgive my ignorance.

Thanks

How I got everything working

Installing SpotifyPod (The code is modified for Ricardo's Alternate Build)

What you need to do before installing SpotifyPod

You need raspberry pi lite os legacy version We will also be using raspotify version 0.14 which we will be installing later

IMPORTANT This code works 2inch LCD Module ST7789V controller 240 x 320 Pixels For more hardware instructions please follow Ricardo's Alternate Build)

Installing updates

sudo apt-get update -y
sudo apt-get upgrade -y

Install Required Packages

sudo apt install python-setuptools python3-setuptools -y

sudo apt install python3-pip -y

sudo wget https://github.com/dtcooper/raspotify/releases/download/0.14.0/raspotify_0.14.0.librespot.20200130T014147Z.3672214_armhf.deb

sudo apt-get install python3-tk -y

sudo apt-get install redis-server -y

sudo apt-get install openbox -y

sudo apt install xorg -y

sudo apt-get install lightdm -y

sudo apt-get install x11-xserver-utils -y

sudo apt-get install git -y

Change directory to home

cd ~

Clone this repo and Install Dependencies

sudo dpkg -i raspotify_0.14.0.librespot.20200130T014147Z.3672214_armhf.deb

git clone https://github.com/dupontgu/retro-ipod-spotify-client

cd retro-ipod-spotify-client/frontend

pip3 install -r requirements.txt

Installing Pi-btaudio

git clone https://github.com/bablokb/pi-btaudio.git

cd pi-btaudio

sudo tools/install

Install PigPio

wget https://github.com/joan2937/pigpio/archive/master.zip

unzip master.zip

cd pigpio-master

make

sudo make install

Setup spotify API

Create a Spotify Developer Account, then create an app where you will get your Client ID, Client Secret, and create a Redirect URI

https://developer.spotify.com/dashboard/applications/
Create_app

Add an app name and description can be anything

Add_app_name
Add_host_uri
Add_uri_2
add_uri_3
add_rui_4

Save Client id and Save Secret id

Secret_and_client

Disable screen blanking

sudo raspi-config
Display Option > Screen Blanking > OFF / Disable

Disable Cursor and Screen Savers

Add or Create and Add this:

sudo nano ~/.bash_profile

Then:

'#!/bin/bash'

[[ -z $DISPLAY && $XDG_VTNR -eq 1 ]] && startx -- -nocursor

# Disable any form of screen saver / screen blanking / power management

xset s off

xset s noblank

export SPOTIPY_CLIENT_ID='your_SPOTIPY_CLIENT_ID'

export SPOTIPY_CLIENT_SECRET='your_SPOTIPY_CLIENT_SECRET'

export SPOTIPY_REDIRECT_URI='http://localhost:8080'

export DISPLAY=:0.0

Configure Xintric

sudo nano /etc/X11/xinit/xinitrc

#!/bin/sh

# /etc/X11/xinit/xinitrc
# global xinitrc file, used by all X sessions started by xinit (startx)
# invoke global X session script 
#. /etc/X11/Xsession' 

exec openbox-session #-> This is the one that launches Openbox ;)`

Run "spotifypod.py" with Autostart

sudo nano /etc/xdg/openbox/autostart

Then paste this before exit

#cd /home/pi/retro-ipod-spotify-client/frontend/
#sudo -H -u pi --preserve-env=SPOTIPY_REDIRECT_URI,SPOTIPY_CLIENT_ID,SPOTIPY_CLIENT_SECRET python3 spotifypod.py &
#sudo /home/pi/retro-ipod-spotify-client/clickwheel/click &

Please comment this out until I remind you to uncomment it, save the file and exit, then we are now going to make the the program that makes the clickwheel work an executable

cd /home/pi/retro-ipod-spotify-client/clickwheel
nano click.c

change #define DATA_PIN 25 to #define DATA_PIN 5

gcc -Wall -pthread -o click click.c -lpigpio -lrt

when were running "gcc -Wall -pthread -o click click.c -lpigpio -lrt" just leave it alone till you see a blinking text box

sudo chmod +x click

Spotify credentials

sudo nano /etc/xdg/openbox/environment

export SPOTIPY_CLIENT_ID='your_SPOTIPY_CLIENT_ID'

export SPOTIPY_CLIENT_SECRET='your_SPOTIPY_CLIENT_SECRET'

export SPOTIPY_REDIRECT_URI='http://localhost:8080'

Synchronize Spotify Data

Synchronizing Spotify data! Last but not least, if you want to make sure all your playlists artists, etc are synchronized every time you turn on your Spotypod, you can simply modify the script view_model.py

sudo nano view_model.py

go to line 16

#spotify_manager.refresh_devices()

spotify_manager.refresh_data()

Configure Raspotify

sudo nano /etc/default/raspotify

Uncomment and fill the following line:

OPTIONS="--username XXXXXXXX --password XXXXXXXXX"

Enter your spotify login details, In the first XXX add your email address, and in the second XXX add your password

Ex:

OPTIONS="--username [email protected] --password thisismypassword"

Paste the following

# The displayed device type in Spotify clients.
# Can be "unknown", "computer", "tablet", "smartphone", "speaker", "tv",
# "avr" (Audio/Video Receiver), "stb" (Set-Top Box), and "audiodongle".
DEVICE_TYPE="smartphone"

Entering Device id

To obtain your device id you first have to go to https://developer.spotify.com/console/get-users-available-devices/
when you go the the website your ipod may not appear connect to it using the spotify app on the device list then retry the website and it should show up

cd /home/pi/retro-ipod-spotify-client/frontend/

nano spotify_manager.py

Go to line 173 using ctrl+shift+_ and type 173 You can comment out the entire refresh_device def and replace it with

def refresh_devices():
    device = UserDevice('xxxxxxxxxxxxxxxxxxxxxxxxxxxxx','raspotify', True)
    DATASTORE.setUserDevice(device)

Replace the XXXXXXX with your device id
Ex:
def refresh_devices():
device = UserDevice(โ€˜123456789','raspotify', True)
DATASTORE.setUserDevice(device)
After that you want to go save and exit the file then

cd ~/.local/lib/python3.7/site-packages/spotipy/

nano client.py

Go to line 1734 using ctrl+shift+_
Paste this in:

data = {"device_ids": ["xxxxxxxxxxxxxxxxxxxxxxxxxx"], "play": force_play}
    return self._put("me/player", payload=data)

Replace the xxxxxx with your device id

Post Install

Generate .cache files

sudo apt install midori

cd ~

git clone https://github.com/perelin/spotipy_oauth_demo

cd ~/spotipy_oauth_demo

sudo apt-get install python-pip python-dev

sudo apt-get install python3-pip python-dev

pip install -r requirements.txt

Before running it modify the client id and secret also your scopes in with:

nano spotipy_oauth_demo.py

Scope:

SCOPE = "user-follow-read," \
        "user-library-read," \
        "user-library-modify," \
        "user-modify-playback-state," \
        "user-read-playback-state," \
        "user-read-currently-playing," \
        "app-remote-control," \
        "playlist-modify," \
        "playlist-read-private," \
        "playlist-read-collaborative," \
        "playlist-modify-public," \
        "playlist-modify-private," \
        "streaming," \
        "user-follow-modify," \
        "user-follow-read"

Now you can save and exit the file

before reboot do the following:

sudo raspi-config

system options --> boot / auto login --> console autologin

Turn on vnc or connect a mouse to the pi, then reboot

Then you can run this program:

python spotipy_oauth_demo.py

Recommend using a Pi 4 or anything faster than a zero w, but if this is the only pi you have you should be fine but it will take a while. Your pi should be displaying a black screen then right click and click on browser then go to internet/ browser (midori). Once you did that go to http://localhost:8080/ There should be a spotify sign in page, sign in, once signed in it should redirect you to a page with gibberish code and spotify credits. Once you're on that screen exit the page and in your terminal stop running the program.

Now move your cache file to the one in spotifypod

cp ~/spotipy_oauth_demo/.spotipyoauthcache ~/retro-ipod-spotify-client/frontend/.cache

chmod 777 ~/retro-ipod-spotify-client/frontend/.cache

Once your done you can turn off vnc
If you get ERNO98 already in use go to issue 30

Install Display code

ssh into the pi and edit the config file

sudo nano /boot/config.txt

Add the code below:

DIsplay code

hdmi_group=2
hdmi_mode=87
hdmi_cvt=320 240 60 1 0 0 0
hdmi_force_hotplug=1

Also you have to comment out this code:

dtoverlay=vc4-kms-v3d

Then save it, after that download the display code:

sudo apt install cmake git
cd ~
git clone https://github.com/juj/fbcp-ili9341.git
cd fbcp-ili9341

Then we want to change the native resolution to take advantage of the whole display.

nano st7735r.h

Go to line 18 which is ST7789
Change DISPLAY_NATIVE_HEIGHT from 240 to 320
After that save it and then nano into st7735r.cpp

nano st7735r.cpp

Go to line 95 with ctrl+shift+_
Comment out the line beginning with SPI_TRANSFER with // then below it add this:

SPI_TRANSFER(0x37, 0, 0);

Then exit the file then run this command:

mkdir build

cd build

cmake -DST7789=ON -DGPIO_TFT_DATA_CONTROL=24 -DGPIO_TFT_RESET_PIN=25 -DSPI_BUS_CLOCK_DIVISOR=30 -DSTATISTICS=0 -DDISPLAY_BREAK_ASPECT_RATIO_WHEN_SCALING=ON -DUSE_DMA_TRANSFERS=OFF ..

Once finished run:

make -j

After that is finished we want to make it run on boot:

sudo nano /etc/rc.local

Enter this before exit:

sudo /home/pi/fbcp-ili9341/build/fbcp-ili9341 &

Uncomment the Autostart things:

sudo nano /etc/xdg/openbox/autostart

cd /home/pi/retro-ipod-spotify-client/frontend/

sudo -H -u pi --preserve-env=SPOTIPY_REDIRECT_URI,SPOTIPY_CLIENT_ID,SPOTIPY_CLIENT_SECRET python3 spotifypod.py &

sudo /home/pi/retro-ipod-spotify-client/clickwheel/click &

Bluetooth

For bluetooth I these instructions:
To install blue-alsa link
To set up auto connect link

Use this to pair bluetooth device:

pairing

Please only follow the configuration instructions you already downloaded it in the previous link. link

When Done

Reboot and whenever you need to use the pod connect to it from your phone/ computer on the device list as if it were a speaker. It might take a while but it should connect eventually then you're free to exit the app and play songs from the pod.

Issues

Trying to recreate the Bluetooth settings (If you want to try and figure it out, I suggest going to #66 near the bottom there should be some links doris put)
If you have any issues please feel free to comment them below ๐Ÿ˜„

Resources:

Couldn't have done this without doris, they've helped me out so much.
https://hackaday.io/project/177034-spot-spotify-in-a-4th-gen-ipod-2004
https://github.com/dupontgu/retro-ipod-spotify-client
https://www.youtube.com/watch?v=KciKqGX8g94
#41
#22
#34
#65
#23
#66
http://rsflightronics.com/spotifypod
https://sigmdel.ca/michel/ha/rpi/bluetooth_n_buster_01_en.html
https://github.com/dtcooper/raspotify/wiki/Play-via-Bluetooth-Speaker
https://github.com/bablokb/pi-btaudio

Cannot access `.cache` file

I have setup env vars but still getting this error

โฏ python3 spotifypod.py
Couldn't read cache at: .cache
Couldn't read cache at: .cache
Enter the URL you were redirected to: http://google.com
Enter the URL you were redirected to: no ints
Couldn't read cache at: .cache

Multilanguage string of py script

@dupontgu

First of all thank you for your intersting project.

What do you think to modify your source code about .py scritps to have external strings that enable a multilanguage project?

Thanks.

Just boots to command line

I have been over this very carefully and my ipod just boots to a command line. I cant get it to run anything else. Anyone have any ideas?

Can't play music (error no devices)

Hello I've finally got Spot to auto start and a bunch of other problems fixed but when I try to play a song it gives me this error

"playing spotify:album:6Bp2ojsBc8CtNaYipdxCLt spotify:track:3ZcLmonVVD1MTQtmQb8yf3
error! no devices"

I saw in the Github issue #4 someone had this error but they fixed it so I applied the fix to mine and it didn't do anything. Got a solution or an idea?

when i boot up i get the sign in page

When I was done with the settings and i reset it takes me to a sign in to debian i'm using raspberry pi os lite, and i'm using ssh. This is my first ever project and I can't get this working. Any help?

Can't connect to Spotify API

Hey, I saw your video on YouTube. Really cool project!
I remember my iPod mini fondly :) I remember flashing some alternative OS on it as a kid, probably breaking it with that, but that was so cool. I would write notes on it to cheat on a topography test ๐Ÿ˜„

So I wanted to take a look at your sPod interface. But I can't seem to connect to the Spotify API.

I set the spotipy variables correctly I think:

export SPOTIPY_CLIENT_ID=123 (not my real id)
export SPOTIPY_CLIENT_SECRET=abc (not my real secret)
export SPOTIPY_REDIRECT_URI=http://foo.bar

But getting stuck after pasting the redirect URL:

$ python spotifypod.py    
Couldn't read cache at: .cache
Couldn't read cache at: .cache
Enter the URL you were redirected to: http://foo.bar/?code=AQB95fJ1ctCgK2sst8VCmMvxGQOdU878Ob6l9hHodiv54CICwbVFXw8ZLz00chlVDl34mCU-udeEdWSsrw5_rxW3RGVN45k-iMq-0AuBcLshVbIet-h6DROk17QiXrb8KbJR9IjeXGFjPCMBn2V4q_gOye-EXU6YxMbDKQI91PIHmsa-q54zs5sME8nMnANU26uCKYOCxg
Enter the URL you were redirected to: HTTP Error for GET to https://api.spotify.com/v1/me/player/devices returned 401 due to Permissions missing
Traceback (most recent call last):
  File "/home/stan/Misc/retro-ipod-spotify-client/frontend/venv/lib/python3.8/site-packages/spotipy/client.py", line 245, in _internal_call
    response.raise_for_status()
  File "/home/stan/Misc/retro-ipod-spotify-client/frontend/venv/lib/python3.8/site-packages/requests/models.py", line 943, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 401 Client Error: Unauthorized for url: https://api.spotify.com/v1/me/player/devices

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "spotifypod.py", line 12, in <module>
    from view_model import *
  File "/home/stan/Misc/retro-ipod-spotify-client/frontend/view_model.py", line 16, in <module>
    spotify_manager.refresh_devices()
  File "/home/stan/Misc/retro-ipod-spotify-client/frontend/spotify_manager.py", line 129, in refresh_devices
    results = sp.devices()
  File "/home/stan/Misc/retro-ipod-spotify-client/frontend/venv/lib/python3.8/site-packages/spotipy/client.py", line 1633, in devices
    return self._get("me/player/devices")
  File "/home/stan/Misc/retro-ipod-spotify-client/frontend/venv/lib/python3.8/site-packages/spotipy/client.py", line 291, in _get
    return self._internal_call("GET", url, payload, kwargs)
  File "/home/stan/Misc/retro-ipod-spotify-client/frontend/venv/lib/python3.8/site-packages/spotipy/client.py", line 261, in _internal_call
    raise SpotifyException(
spotipy.exceptions.SpotifyException: http status: 401, code:-1 - https://api.spotify.com/v1/me/player/devices:
 Permissions missing, reason: None

Do you have any idea what could be wrong here? The .cache file is being created and populated correctly as far as I can see.

Scopes

Hi all,

what are the minimum scopes that are required for this codebase?

it looks like it requires more than

scope = "user-library-read,user-follow-read"

Insufficient client scope, reason: None

Thanks
Nick

AutoStart seems to not work

Hello when I start my pi up the display is black. I think I've looked every on the page and can't seem to find an answer

have any suggestions?

No environmental variables, playback and refresh issues

Greetings! I'm excited about this project and I'm attempting to ensure the software is running smoothly before starting on the hardware. This means I have the raspberry pi zero outputting display to a monitor, and I'm either testing using an attached keyboard or via SSH.

Setup

I followed the base README instructions including the following suggested steps:

  1. Installed GIT and cloned this repo before installing requirements (see #22)
  2. Compiled the click wheel code (see #22)
  3. Created the .cache file when launching "sPot" failed (see #30)
  4. Added export DISPLAY=:0.0 to .bash_profile to stop it complaining about the xset commands in the console ๐Ÿคท
  5. Added preserve-env argument to the autostart command because ENV variables were not being set (see #21)

In addition I have the following changes:

  • SPOTIPY_REDIRECT_URI is set to http://127.0.0.1 with no port specified because I can't determine what else is correct.
  • I replaced spotify_manager.refresh_devices() with spotify_manager.refresh_data() in view_model.py as the instructions suggested, but found out that this caused "sPot" to take exactly 5 minutes to start at launch! SO - I commented out both commands for now.

Problems

So these are already somewhat stated, but I've run into a couple of issues that I can't seem to resolve and I'm open to suggestion. They all seem to be related to authentication, but I'm really not certain.

  1. I only realized by accident that "sPot" was taking 5 minutes (almost exactly) to launch at start. In that time, I could interact with the desktop, so it wasn't frozen. I solved this delay by commenting out spotify_manager.refresh_data(), but this is not a long term solution. My guess is that this request has to time out before the interface displays eventually.
  2. When trying to manually run spotifypod.py from the desktop, I get the error "spotipy.oauth2.SpotifyOauthError: No client_id". I can't run from SSH at all.
  3. When taking a look at openbox environmental variables, I found that they are never set. I doubled checked everything and I could only get the SPOTIPY vars set by sourcing /etc/xdg/openbox/environment manually. Even then, it doesn't seem to affect anything - I get the same client_id error.
  4. I can tell the program is communicating with my Spotify account because it has my albums and such in the menu. That said, when selecting any song, it just sits at 0:00 and doesn't play anything or display the title or display play length.

I feel like I'm close to a correctly functioning program, but I'm just missing a detail or two. Any feedback here would be most assuredly appreciated. Cheers and many thanks to @dupontgu for the challenge!

Autostart, Clickwheel, Spotify Credentials... How I made the screen work

So, I've spent more nights than I should have working on this, my first Raspberry Pi project.

Here are the things I've done following the README file and trying to make it work for myself...

For the ones that don't know, you can code everything from your PC/Mac terminal and you can copy/paste the codes. I didn't know for the first days.

Details on what works and what doesn't at the end of this...

So:

Install Raspberry Pi OS Lite to your Pi and then configure your WiFi on first boot

  1. Install Updates
    sudo apt-get update
    sudo apt-get upgrade

  2. Install Dependencies
    sudo apt install python-setuptools python3-setuptools
    sudo apt install python3-pip
    sudo curl-sL https://dtcooper.github.io/raspotify/install.sh | sh
    sudo apt install install xorg
    sudo apt-get install python3-tk
    sudo apt-get install redis-server
    sudo apt-get install openbox
    sudo apt-get install lightdm
    sudo apt-get install x11-xserver-utils

  3. Install Dependencies
    pip3 install -r requirements.txt
    This command didn't work. So I ran the following:
    sudo apt-get install git
    git clone https://github.com/dupontgu/retro-ipod-spotify-client
    After this:
    cd /home/pi/retro-ipod-spotify-client/frontend/
    To finally run this...
    pip3 install -r requirements.txt

  4. Install pi-btaudio
    git clone https://github.com/bablokb/pi-btaudio.git
    cd pi-btaudio
    sudo tools/install

All worked fine. For bluetooth pairing and instructions, go to https://github.com/bablokb/pi-btaudio

  1. Install PiGPIO
    wget https://github.com/joan2937/pigpio/archive/master.zip
    unzip master.zip
    cd pigpio-master
    make
    sudo make install

I don't know if it works because I haven't been able to use the Clickwheel. Still don't know it it's a hardware or software issue...

  1. Setup Spotify API
    Create a Spotify Developer Account, then create an app where you will get your Client ID, Client Secret, and create a Redirect URI.
    I recommend watching this video and try to make something like the link on README. I think it hasn't worked 100% right for me though...

  2. Disable Screen Blanking
    sudo raspi-config
    Display Option > Screen Blanking > OFF / Disable

  3. Disable Cursor and Screen Savers
    Add or Create and Add this:
    sudo nano /root/.bash_profile
    Then:
    '#!/bin/bash'
    [[ -z $DISPLAY && $XDG_VTNR -eq 1 ]] && startx -- -nocursor
    # Disable any form of screen saver / screen blanking / power management
    xset s off
    xset s noblank

  4. Configure xinitrc
    sudo nano /etc/X11/xinit/xinitrc
    Inside, make sure the following is there:
    #!/bin/sh
    # /etc/X11/xinit/xinitrc
    # global xinitrc file, used by all X sessions started by xinit (startx)
    # invoke global X session script
    #. /etc/X11/Xsession' exec openbox-session #-> This is the one that launches Openbox ;)`

  5. Run "spotifypod.py" with Autostart
    sudo nano /etc/xdg/openbox/autostart
    and add the following command to launch spotifypod.py:
    I made some changes and didn't use the /fork/ folder as in README
    cd /home/pi/retro-ipod-spotify-client/frontend/
    sudo -H -u pi python3 spotifypod.py &
    sudo /home/pi/retro-ipod-spotify-client/clickwheel/click &
    There is no clickso in order to get that:
    cd /home/pi/retro-spotify-client/clickwheel
    gcc -Wall -pthread -o click click.c -lpigpio -lrt
    It returns some warnings but everything is fine. I guess...

  6. Spotify Credentials
    'sudo nano /etc/xdg/openbox/environment'
    Add you credentials:
    export SPOTIPY_CLIENT_ID='your_SPOTIPY_CLIENT_ID'
    export SPOTIPY_CLIENT_SECRET='your_SPOTIPY_CLIENT_SECRET'
    export SPOTIPY_REDIRECT_URI='your_SPOTIPY_REDIRECT_URI'

  7. Syncronize Spotify Data
    Synchronizing Spotify data! Last but not least, if you want to make sure all your playlists artists, etc are synchronized every time you turn on your Spotypod, you can simply modify the script view_model.py
    with the following at line 16:
    #spotify_manager.refresh_devices()
    spotify_manager.refresh_data()

instead of calling refresh_device, you can execute refresh_data. This will sync all your data and then will execute refresh.devices. This will make the boot up way slower! but it will synchronize every single time you switch on :). If you don't run at least once refresh_data() no playlist, artist or anything related with your account will be displayed!

I had errors with this part so I left it as it was...

  1. Configure Raspotify
    sudo nano /etc/default/raspotify
    Uncomment and fill the following line:
    OPTIONS="--username <USERNAME> --password <PASSWORD>"
    And maybe you want also to consider the following:
    # The displayed device type in Spotify clients.
    # Can be "unknown", "computer", "tablet", "smartphone", "speaker", "tv",
    # "avr" (Audio/Video Receiver), "stb" (Set-Top Box), and "audiodongle".
    DEVICE_TYPE="smartphone"

All good. I also changed the Device Name

  1. Display Configuration!
    sudo nano /boot/config.txt
    uncomment (erase #):
    sdtv_mode=2
    comment add (#)
    hdmi_force_hotplug=1
    then add:
    hdmi_ignore_hotplug=1

After this if it throws error for displaying spotifypod.py try the following command:
export DISPLAY=:0.0

So that's what I've got.
The app doesn't autostart. When I start it I get the frontend screen that shows NOW PLAYING when I play a song on my phone. I still haven't been able to work with the clickwheel, it is running with no errors apparently, but it doesn't work with my clickwheel at least so I haven't tried the app on itself.
I connected the Pi to my bluetooth speaker and from my phone I used the Pi as a Remote Device and I got Spotify audio out of it. Is it able to choose it's own songs and play them, I still don't know.
I hope this works for someone and if anybody has any info on how to solve the rest of this, please share hahaha.

Cheers and thanks @dupontgu for this fun project.

Compiling click.c warnings

Hello, so I tried compiling the click.c with the command supplied in the file :'gcc -Wall -pthread -o click click.c -lpigpio -lrt'.
The problem is I'm getting two error messages and I don't know anything about C, so I don't know how to fix them.
The errors are:
click.c:160:5: warning: first argument of 'main' should be 'int' [-Wmain]
int main(void *args){
^~~~
click.c:160:5: warning: 'main' takes only zero or two arguments [-Wmain]

Can somebody help me, Pigpio is installed and I'm guessing it has to do something with the main function, but I don't know how to fix this.

electric schemes

You did a great job congratulations! , I was wondering if you can add connection schemes so maybe we can too.

Black screen issues & Raspotify - Pi Zero 1

Hi, Trying to get the project working on my Pi z W with waveshare screen.

I followed the instructions in the readme, but I had to install the older version of raspotify:
raspotify_0.31.8.1.librespot.v0.3.1-54-gf4be9bb_armhf

First issue, on step 12 this file does not exist
sudo nano /etc/default/raspotify

However it does seem raspotify is running because I can see it as a a device in my spotify app. But not sure how to edit the config now.

Second issue:
I get a black screen when the desktop loads, which then eventually crashes back to desktop. When i SSH in I get this:

xset: unable to open display ""
xset: unable to open display ""

When I try to run sudo -H -u pi python3 spotifypod.py I get this:

pi@pipod:~/retro-ipod-spotify-client/frontend$ sudo -H -u pi python3 spotifypod.py Traceback (most recent call last): File "/home/pi/retro-ipod-spotify-client/frontend/spotifypod.py", line 12, in <module> from view_model import * File "/home/pi/retro-ipod-spotify-client/frontend/view_model.py", line 1, in <module> import spotify_manager File "/home/pi/retro-ipod-spotify-client/frontend/spotify_manager.py", line 102, in <module> sp = spotipy.Spotify(auth_manager=SpotifyOAuth(scope=scope)) File "/home/pi/.local/lib/python3.9/site-packages/spotipy/oauth2.py", line 332, in __init__ self.client_id = client_id File "/home/pi/.local/lib/python3.9/site-packages/spotipy/oauth2.py", line 94, in client_id self._client_id = _ensure_value(val, "client_id") File "/home/pi/.local/lib/python3.9/site-packages/spotipy/oauth2.py", line 70, in _ensure_value raise SpotifyOauthError(msg) spotipy.oauth2.SpotifyOauthError: No client_id. Pass it or set a SPOTIPY_CLIENT_ID environment variable.

I did set the IDs in /etc/xdg/openbox/environment

Not sure what to do next

*UNTESTED* PCB design

Hello, I've been working on a pcb design. This design is untested and I'm unsure if works, this pcb cost around $40 - $50. The 3.7v to 5v might not work, I'm going to provide the gerber file if you'd like to take a look at it. I want this to be a starting point if anyone wants to modify it go for it!

image
image
image

Spotifypod.zip

I got nothing when running click

I make the click.c file, and then run sudo ./click, but I got nothing when touching or clicking the clickwheel.
I connect the clickwheel and the gpio as the picture in README.md, am I missing the steps, or the clickwheel I bought is broken

I have no idea to figure out this problem, please give some suggestions, thank you very much!

Spotifypod Doesnt Pull Content - Variables are not being stored - and token always expires

hi

so my issues at this juncture

  1. the autostart for spotifypod does not work for me - simply goes to Pi desktop - all the steps are taken in this readme and beyond but it just doesnt autostart

so i end up running - python3 Spotifypod.py
and each time i will get the same series of errors

ERROR 1- it will say the access token has expired
so i take the steps to "https://accounts.spotify.com/authorize?client_id=....." in PI BROWSER - it returns the callback to the REDIRECT URL - and I can ENTER THE URL into the Spotifypod.py when it requests "what is the URL Spotify redirected you to"

I have a .CACHE file - and it reads logically - showing the Access Token, Refresh Token, Timeout, Scopes.

i have also generated an access token through "Curl -h Authorization" direct to spotify/api/token
this will deliver an access token as well - and i can replace the contents of the .cache file in FRONTEND folder and it will resolve the expired token issue

but again - within the hour i will experience the same error - "invalid access token"

ERROR 2 - once i am past the invalid token error - i will get an error that states i must declare my CLIENT ID

here is the error
"spotipy.oauth2.SpotifyOauthError: No client_id. Pass it or set a SPOTIPY_CLIENT_ID environment variable."

so set these AGAIN
export SPOTIPY_CLIENT_ID='XXXXX'
export SPOTIPY_CLIENT_SECRET='XXXXX'
export SPOTIPY_REDIRECT_URI='XXXXX'

  • and it resolves the issue for this moment -
    but i have these variables already declared in the necessary areas - and i can check
    env | grep SPOTIPY
    and the variables are there

so why does it forget each time i do the SPOTIFYPOD.PY?

ERROR 3 - tkinter cannot display on localhost:10.1

so i AGAIN enter the following

"export DISPLAY=:0.0"
and this resolves this issue

ERROR 4 - so now i run the Spotifypod.py
and the SPOT screen renders and i see the following - see screenshot

STRW4547

this is great - i finally get this SPOT to function and display
however when you navigate to the any of these items - for example PLAYLISTS - everything is EMPTY
there is nothing underneath

meanwhile - the Spotifypod.py is still running in PUTTY
and
these errors are generating

"return SinglePlaylistPage(self.playlists[index], self)
IndexError: list index out of range"

or other times

"no ints
no ints
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python3.7/tkinter/init.py", line 1705, in call
return self.func(*args)
File "spotifypod.py", line 454, in onKeyPress
onSelectPressed()
File "spotifypod.py", line 517, in onSelectPressed
page = page.nav_select()
File "/home/pi/retro-ipod-spotify-client/frontend/view_model.py", line 260, in nav_select
return self.page_at(self.index)
File "/home/pi/retro-ipod-spotify-client/frontend/view_model.py", line 384, in page_at
artist = spotify_manager.DATASTORE.getArtist(index)
File "/home/pi/retro-ipod-spotify-client/frontend/datastore.py", line 103, in getArtist
return pickle.loads(pickled_pl)
TypeError: a bytes-like object is required, not 'NoneType'
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python3.7/tkinter/init.py", line 1705, in call
return self.func(*args)
File "spotifypod.py", line 454, in onKeyPress
onSelectPressed()
File "spotifypod.py", line 517, in onSelectPressed
page = page.nav_select()
File "/home/pi/retro-ipod-spotify-client/frontend/view_model.py", line 260, in nav_select
return self.page_at(self.index)
File "/home/pi/retro-ipod-spotify-client/frontend/view_model.py", line 384, in page_at
artist = spotify_manager.DATASTORE.getArtist(index)
File "/home/pi/retro-ipod-spotify-client/frontend/datastore.py", line 103, in getArtist
return pickle.loads(pickled_pl)
TypeError: a bytes-like object is required, not 'NoneType'"

does anyone have any clues as to how to resolve the above ?

thanks in advance
paulo

click wheel question

Not really an issue with the code, just a question, if somebody explored this idea:
Does anybody know if you can fit the click wheel of a 4g classic into the front case of a 5g? Do these two share the same dimensions? I'm thinking that I might 3d print some kind of inner holder, but then I could use the 5g case with the buttons of the 4g.

Unable to open display

16186091114226054285710309907953
Please help, I don't know what to do... :(

Please break everything down since I am new to all of this and am struggling with both software and hardware

Import error randomly started appearing.

Hello, So I am trying to get this going on my Pi 4b and I had everything going ok(ish) last night.

I was able to get the gui going and go into playlists, artists, albums, etc. when I tried clicking on a song the "now playing" screen would appear with the progress bar in the middle and it would kick back a 401 spotify api error.

I couldn't figure out what was causing that so I decided to start from scratch with a fresh sd card.

I reinstall everything, set everything up and get to the point I have gotten to before where i reboot my pi to the command line.
openbox starts up on reboot (I assume it doesnt launch spotifypod.py automatically because of the errors i am getting?) and I have to rightclick on the black screen and pull up the terminal. When i navigate to my /retro-ipod-spotify-client/frontend folder and run python3 spotifypod.py I see it fetch my tracks, artists, playlists, albums and new releases, it sees my device and then it kicks back this error:

File "spotifypod.py", line 13, in
from PIL import ImageTK, Image
ImportError: cannot import name 'ImageTK' from 'PIL' (/usr/lib/python3/dist-packages/PIL/init.py)

Did I install something in the wrong place? I am a bit confused as to where I should be installing some of the required software, specifically pigpio and pi-btaudio.

By the way, I am not using ssh. (some people have said that that can cause issues.
Thanks in advance for any guidance.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.