Passed
Push — master ( d23365...8cfbab )
by Quentin
01:17
created

player.Player.run()   A

Complexity

Conditions 1

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 6
nop 1
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
# -*- coding: utf-8 -*-
2
#
3
# Copyright © 2020 Quentin Kniep <[email protected]>
4
# Distributed under terms of the MIT license.
5
"""Manages playback through multiple audio players.
6
Currently supports: Spotify, MPV (for YouTube)
7
"""
8
9
import json
10
import os.path
11
import time
12
from threading import Thread
13
14
import ffmpeg_normalize
15
import googleapiclient.discovery as google
16
from mpv import MPV
17
import pafy
18
import spotipy
19
20
import config
21
22
23
class Player:
24
    def __init__(self):
25
        self.queue = [['_KhsQ3nn6Kw', 'Wankelmut & Emma Louise - My Head Is A Jungle (MK Remix)', '', True]]
26
        self.currently_playing = ['vzYYW8V3Ibc', 'Nothing', 'Nothing', False]
27
28
        self.player = MPV(ytdl=True, video=False)
29
        self.youtube = google.build('youtube', 'v3', developerKey=config.YOUTUBE_API_KEY)
30
31
        sp_oauth = spotipy.oauth2.SpotifyOAuth(scope=config.SPOTIPY_SCOPE,
32
                                               cache_path=config.SPOTIPY_CACHE)
33
34
        self.spotify = spotipy.Spotify(auth_manager=sp_oauth)
35
36
        devices = self.spotify.devices()
37
        print(json.dumps(devices, sort_keys=True, indent=4))
38
        device_id = devices['devices'][0]['id']
39
40
        results = self.spotify.search(q='Airwaves', type='track')
41
        print(json.dumps(results['tracks']['items'][0], sort_keys=True, indent=4))
42
        self.spotify.start_playback(device_id, uris=[results['tracks']['items'][0]['uri']])
43
44
    def play_loop(self):
45
        while True:
46
            if not self.queue:
47
                next_track = self.youtube_search(self.current_track[0], 1, recs=True)[0]
48
                self.current_track = next_track
49
                self.play(next_track[0])
50
            else:
51
                if not self.queue[0][3]:  # wait for download to finish
52
                    time.sleep(1)
53
                    continue
54
                self.current_track = self.queue[0]
55
                del self.queue[0]
56
                self.play(self.current_track[0])
57
58
    def download_loop(self):
59
        while True:
60
            for entry in self.queue:
61
                if not entry[3]:
62
                    self.download(entry[0])
63
                    entry[3] = True
64
            time.sleep(1)
65
66
    def download(self, ytid):
67
        v = pafy.new(ytid)
68
        s = v.getbest()
69
        filename = None
70
        while filename is None:
71
            try:
72
                filename = s.download(filepath='downloads/'+ytid)
73
            except:
74
                pass
75
        print('DOWNLOADED ' + ytid + ' into ' + filename)
76
77
        if config.ENABLE_VOLUME_NORMALIZATION:
78
            ffmpnorm = ffmpeg_normalize._ffmpeg_normalize.FFmpegNormalize(
79
                audio_codec='libmp3lame', output_format='mp3',
80
                video_disable=True, subtitle_disable=True, target_level=-13)
81
            ffmpnorm.add_media_file('downloads/'+ytid, 'downloads/'+ytid)
82
            ffmpnorm.run_normalization()
83
            print('NORMALIZED ' + ytid)
84
85
        return filename
86
87
    def play(self, ytid):
88
        path = 'downloads/' + ytid
89
        if not os.path.isfile(path):
90
            self.download(ytid)
91
        self.player.play(path)
92
        self.player.wait_for_playback()
93
94
    def run(self):
95
        play_thread = Thread(target=self.play_loop)
96
        play_thread.start()
97
98
        download_thread = Thread(target=self.download_loop)
99
        download_thread.start()
100
101
        pafy.set_api_key(config.YOUTUBE_API_KEY)
102