from flask import Flask, render_template, jsonify from flask_socketio import SocketIO, emit from flask_cors import CORS import yt_dlp import vlc import os import eyed3 import time home_directory = os.path.expanduser("~") music_directory = os.path.expanduser('~/Music') # Adjust path as necessary #app = Flask(__name__,template_folder=home_directory) app = Flask(__name__, template_folder=f"{home_directory}/Code/GR/GR-Jukebox") CORS(app, resources={r"/*": {"origins": "*"}}) socketio = SocketIO(app) player = vlc.MediaPlayer() music_queue = [] title_queue = [] @socketio.on('connect') def handle_connect(): emit('response', {'message': 'Connected to WebSocket server'}) @socketio.on('list_music') def handle_list_music(): music_files = [] for filename in os.listdir(music_directory): if filename.endswith('.mp3'): path = os.path.join(music_directory, filename) audiofile = eyed3.load(path) title = audiofile.tag.title if audiofile.tag else 'Unknown Title' music_files.append({'id': filename.split('.')[0], 'title': title}) print({'music_files':music_files}) emit('music_list', {'music_files': music_files}) @socketio.on('download') def handle_download(data): url = data['youtube_url'] if 'youtube.com' in url: video_id = url.split('=')[1][:11] # Extract the video ID from the YouTube URL elif 'youtu.be' in url: video_id = url.split('youtu.be/')[1][:11] else: #return jsonify({'status': 'error', 'message': 'Invalid YouTube URL'}) emit('download_status', {'status': 'error', 'message': 'Invalid YouTube URL'}) output_path = os.path.expanduser(f'{home_directory}/Music/{video_id}.mp3') # Path where the file will be saved if not os.path.exists(output_path): print("Downloading...") # Configure yt-dlp to download best audio quality ydl_opts = { 'format': 'bestaudio/best', 'postprocessors': [{ 'key': 'FFmpegExtractAudio', 'preferredcodec': 'mp3', 'preferredquality': '192', }], 'noplaylist': True, 'quiet': True, 'outtmpl': output_path[:-4] # Use the custom path as the output template } # Use yt-dlp to extract information and download the audio file with yt_dlp.YoutubeDL(ydl_opts) as ydl: info = ydl.extract_info(url, download=True) title = info.get('title') # Extract the title from video information # Load the downloaded file using eyed3 and add ID3 tags audiofile = eyed3.load(output_path) if audiofile.tag is None: # Create an ID3 tag if none exist audiofile.tag = eyed3.id3.Tag() audiofile.tag.file_info = eyed3.id3.FileInfo(output_path) print(f"Downloaded: {title}") audiofile.tag.title = title audiofile.tag.save() # Save the metadata emit('download_status', {'status': 'success', 'message': 'Song added successfully'}) playing_thread = False @socketio.on('play') def handle_play(data): global music_queue global title_queue global playing_thread global player music_queue.append(data['songId']) title_queue.append(data['songTitle']) if not playing_thread: while len(music_queue) > 0: playing_thread = True player = vlc.MediaPlayer(f'{home_directory}/Music/{music_queue[0]}.mp3') player.play() print(f"Playing: {title_queue[0]}") emit('current', {'title': title_queue[0]}) emit('queue', [{'id': idx, 'title': title} for idx, title in enumerate(title_queue)]) # Wait for the audio to start playing and check periodically if it is still playing time.sleep(1) # Short initial delay to allow playback to start while player.is_playing(): #print('Playing...') time.sleep(0.5) # Check every second if it is still playing #emit('time', {'time': player.get_time()}) #print(player.get_time()) #print(player.get_length()) #print((player.get_time()/player.get_length())) emit('time', {'time': (player.get_time()/player.get_length())}) player.stop() music_queue.pop(0) title_queue.pop(0) playing_thread = False emit('play_return', {'status': 'success', 'message': 'Playing song'}) @socketio.on('get_queue') def handle_get_queue(): emit('queue', [{'id': idx, 'title': title} for idx, title in enumerate(title_queue)]) @socketio.on('remove_from_queue') def handle_remove_from_queue(data): global music_queue global title_queue global player #data = request.json song_id = int(data['songId']) try: #del music_queue[song_id] #del title_queue[song_id] if song_id == 0: player.stop() else: music_queue.pop(song_id) title_queue.pop(song_id) #return jsonify({'status': 'success', 'message': 'Song removed successfully'}) emit('remove_return', {'status': 'success', 'message': 'Song removed successfully'}) except IndexError: #return jsonify({'status': 'error', 'message': 'Invalid song ID'}), 400 emit('remove_return', {'status': 'error', 'message': 'Invalid song ID'}) @socketio.on('current_song') def handle_current_song(): if title_queue: emit('current', {'title': title_queue[0]}) else: emit('current', {'title': 'Nothing is playing'}) @app.route('/') def index(): return render_template('manage2.html') @app.route('/display') def display(): return render_template('display2.html') if __name__ == '__main__': socketio.run(app, host='0.0.0.0', debug=True, port=5000)