commit f73ef71f9681619deb6024273d1926c1fbd9c3cc Author: mathayay Date: Tue Sep 16 11:44:32 2025 +0200 first commit diff --git a/.cache b/.cache new file mode 100644 index 0000000..387f693 --- /dev/null +++ b/.cache @@ -0,0 +1 @@ +{"access_token": "BQDeVV_yylewo72n9ZtSMTn1WNhJKSbUBDKv18Cl-QY7dphidwC9jDuGuZWKaIWZv-fVIG1uuP1XvJFKwcj3GOxgRxYJbaWOLtogCHkAxC-iOaZe6uphn-vCy5rbX6Xlx9XVUG-jHNu0jaCf1-ueTRUQuyF0Btu4_aAcIktTnYyofSUJuk_Mdi1J6V3hmARkCl34Rv-4hgfXcIqQ_rpdCFHGheEU1rSL5oME", "token_type": "Bearer", "expires_in": 3600, "scope": "user-modify-playback-state user-read-playback-state", "expires_at": 1757966041, "refresh_token": "AQAxD3wm_8aDlK9w2ZsibKsrPY0SxUJb2UaqiT2ygxK-pEq2ojxPzgLa6DNt9EpP3mjFDCLmGO5glj5fSpR3ZnqEa26belG4EQv5FOeee38ix31o2xuxPbDsY44KR5Uj1KE"} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b477fbc --- /dev/null +++ b/.gitignore @@ -0,0 +1,29 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# Distribution / packaging +build/ +dist/ +*.egg-info/ + +# Virtual environment folders +.env +.venv +env/ +venv/ +ENV/ + +# Jupyter Notebook checkpoints +.ipynb_checkpoints + +# PyCharm +.idea/ + +# VS Code +.vscode/ + +# Logs and databases +*.log +*.sqlite3 diff --git a/boonepeter.github.io-code b/boonepeter.github.io-code new file mode 160000 index 0000000..4a272a4 --- /dev/null +++ b/boonepeter.github.io-code @@ -0,0 +1 @@ +Subproject commit 4a272a48e0d7f57e7116cadacfa468d4444fe929 diff --git a/main.py b/main.py new file mode 100644 index 0000000..852fbfe --- /dev/null +++ b/main.py @@ -0,0 +1,53 @@ +import spotipy +from spotipy.oauth2 import SpotifyOAuth +import sys + +# Replace these with your Spotify developer app credentials +CLIENT_ID = 'a1b29f64bef643b5ade0944830637510' +CLIENT_SECRET = '1d74196e6fec41f9986917afd57df3da' +REDIRECT_URI = 'https://vinyly.couraud.xyz' +SCOPE = 'user-modify-playback-state user-read-playback-state' + + +def main(): + auth_manager = SpotifyOAuth(client_id=CLIENT_ID, + client_secret=CLIENT_SECRET, + redirect_uri=REDIRECT_URI, + scope=SCOPE, + open_browser=False) + + # Check if token already cached; if not, do manual auth + token_info = auth_manager.get_cached_token() + if not token_info: + print("Please scan the QR code and paste the full redirect URL after authorization:") + redirect_response = input("Redirect URL: ").strip() + token_info = auth_manager.get_access_token(code=auth_manager.parse_response_code(redirect_response)) + auth_manager.cache_token(token_info) + + sp = spotipy.Spotify(auth_manager=auth_manager) + + if len(sys.argv) < 2: + print('Usage: python play_spotify.py "song name"') + sys.exit(1) + + song_name = ' '.join(sys.argv[1:]) + + results = sp.search(q=song_name, type='track', limit=1) + if not results['tracks']['items']: + print(f'No track found for: {song_name}') + sys.exit(1) + + track_uri = results['tracks']['items'][0]['uri'] + + devices = sp.devices() + if not devices['devices']: + print('No active Spotify devices found. Please start playback on a device.') + sys.exit(1) + + active_device_id = devices['devices'][0]['id'] + + sp.start_playback(device_id=active_device_id, uris=[track_uri]) + print(f'Playing "{song_name}" on device ID: {active_device_id}') + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/test/compose.yml b/test/compose.yml new file mode 100644 index 0000000..a3aba0e --- /dev/null +++ b/test/compose.yml @@ -0,0 +1,11 @@ +services: + spotifyd: + container_name: spotify + restart: always + image: hvalev/spotifyd-alsa-dbus + network_mode: host + # Keep in mind to keep the ports for zeroconf and mdns open on the host + devices: + - /dev/snd:/dev/snd + volumes: + - ./spotifyd.conf:/etc/spotifyd.conf \ No newline at end of file diff --git a/test/spotifyd.conf b/test/spotifyd.conf new file mode 100644 index 0000000..74d6fcc --- /dev/null +++ b/test/spotifyd.conf @@ -0,0 +1,115 @@ +[global] + +#---------# +# GENERAL # +#---------# + +# The name that gets displayed under the connect tab on +# official clients. +#device_name = "device_name_in_spotify_connect" + +# The displayed device type in Spotify clients. +# Can be unknown, computer, tablet, smartphone, speaker, t_v, +# a_v_r (Audio/Video Receiver), s_t_b (Set-Top Box), and audio_dongle. +#device_type = "speaker" + +# The directory used to store credentials and audio cache. +# Default: infers a sensible cache directory (e.g. on Linux: $XDG_CACHE_HOME) +# +# Note: The file path does not get expanded. Environment variables and +# shell placeholders like $HOME or ~ don't work! +#cache_path = "/full/path/to/cache/directory" + +# If set to true, audio data does NOT get cached. +# In this case, the cache is only used for credentials. +#no_audio_cache = true + +# The maximal size of the cache directory in bytes +# The example value corresponds to ~ 1GB +#max_cache_size = 1000000000 + +# If set to true, `spotifyd` tries to bind to dbus (default is the session bus) +# and expose MPRIS controls. When running headless, without the session bus, +# you should set this to false, to avoid errors. If you still want to use MPRIS, +# have a look at the `dbus_type` option. +#use_mpris = true + +# The bus to bind to with the MPRIS interface. +# Possible values: "session", "system" +# The system bus can be used if no graphical session is available +# (e.g. on headless systems) but you still want to be able to use MPRIS. +# NOTE: You might need to add appropriate policies to allow spotifyd to +# own the name. +#dbus_type = "session" + +#-----------# +# DISCOVERY # +#-----------# + +# If set to true, this disables zeroconf discovery. +# This can be useful, if one prefers to run a single-user instance. +#disable_discovery = false + +# The port at which `spotifyd` is going to offer its service over the network (TCP). +# If not set, a random port > 1024 is used. For the service to be discoverable on the +# local network via mDNS, both the mDNS port (5353 UDP) and the random or fixed +# zeroconf port need to be allowed through any active firewall. +#zeroconf_port = 1234 + +#-------# +# AUDIO # +#-------# + +# The audio backend used to play music. To get +# a list of possible backends, run `spotifyd --help`. +#backend = "alsa" # use portaudio for macOS [homebrew] + +# The alsa audio device to stream audio. To get a +# list of valid devices, run `aplay -L`, +#device = "default" # omit for macOS + +# The PCM sample format to use. Possible values +# are F32, S32, S24, S24_3, S16. +# Change this value if you encounter errors like +# "Alsa error PCM open ALSA function 'snd_pcm_hw_params_set_format' failed with error 'EINVAL: Invalid argument'" +#audio_format = "S16" + +# The volume controller. Each one behaves different to +# volume increases. For possible values, run +# `spotifyd --help`. +#volume_controller = "softvol" # use softvol for macOS + +# ! Only relevant for ALSA ! +# The alsa control device. By default this is the same +# name as the `device` field. +#control = "default" + +# ! Only relevant for ALSA ! +# The alsa mixer used by `spotifyd`. +#mixer = "PCM" # omit for macOS + +# The audio bitrate. 96, 160 or 320 kbit/s +#bitrate = 160 + +# Volume on startup between 0 and 100 +#initial_volume = 90 + +# If set to true, enables volume normalisation between songs. +#volume_normalisation = true + +# The normalisation pregain that is applied for each song. +#normalisation_pregain = -10 + +#-------รค +# OTHER # +#-------# + +# After the music playback has ended, start playing similar songs based on the previous tracks. +# By default, `spotifyd` infers this setting from the user settings. +#autoplay = true + +# A command that gets executed in your shell after each song changes. +#on_song_change_hook = "echo \"hook executed on $PLAYER_EVENT\"" + +# The proxy `spotifyd` will use to connect to spotify. +#proxy = "http://proxy.example.org:8080" \ No newline at end of file diff --git a/video.py b/video.py new file mode 100644 index 0000000..7f235c9 --- /dev/null +++ b/video.py @@ -0,0 +1,41 @@ +import cv2 +from pyzbar import pyzbar +import subprocess + +def detect_qr_code(frame): + detected_barcodes = pyzbar.decode(frame) + for barcode in detected_barcodes: + if barcode.type == 'QRCODE': + return barcode.data.decode('utf-8') + return None + +def main(): + cap = cv2.VideoCapture(0) # open default USB camera (index 0) + if not cap.isOpened(): + print('Error: Cannot access camera') + return + + print('Starting camera. Press q to quit.') + + while True: + ret, frame = cap.read() + if not ret: + print('Error: Cannot read frame') + break + + qr_data = detect_qr_code(frame) + if qr_data: + print(f'Detected QR Code: {qr_data}') + # Call the play script with this QR code data as argument + subprocess.Popen(['python3', 'play_spotify.py', qr_data]) + break + + cv2.imshow('QR Code Detector', frame) + if cv2.waitKey(1) & 0xFF == ord('q'): + break + + cap.release() + cv2.destroyAllWindows() + +if __name__ == '__main__': + main()