EsaDev

aaaaaaaaaaaaaaaAAAAAAAAAAAAimlosingmymind

Jul 13th, 2020
1,522
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.25 KB | None | 0 0
  1. '''
  2. Handles connecting to a chromecast device and playing music on the device via Spotify
  3. '''
  4. import argparse
  5. import logging
  6. import sys
  7. import time
  8. import nfc
  9.  
  10. import pychromecast
  11. from pychromecast.controllers.spotify import SpotifyController
  12. import spotify_token as st
  13. import spotipy
  14. from spotipy.oauth2 import SpotifyOAuth
  15.  
  16. import constants
  17.  
  18. CAST_NAME = constants.CAST_NAME
  19. CAST_IP = constants.CAST_IP
  20.  
  21. SP_DC = constants.SP_DC
  22. SP_KEY = constants.SP_KEY
  23. CLIENT_ID = constants.CLIENT_ID
  24. CLIENT_SECRET = constants.CLIENT_SECRET
  25. SPOTIPY_REDIRECT_URI = constants.REDIRECT_URI
  26. SPOTIFY_USERNAME = constants.USERNAME
  27.  
  28. ALLOW_EXPLICIT = constants.ALLOW_EXPLICIT
  29. SHUFFLE_DEFAULT = constants.SHUFFLE_DEFAULT
  30. PLAYLISTS_SHUFFLE = constants.PLAYLIST_SHUFFLE
  31.  
  32. parser = argparse.ArgumentParser(description="Cast songs/albums to Google Home via nfc controls.")
  33. parser.add_argument("--show-debug", help="Enable debug log", action="store_true")
  34. parser.add_argument("--cast", help='Name of cast device (default: "%(default)s")', default=CAST_NAME)
  35. args = parser.parse_args()
  36.  
  37. if args.show_debug:
  38. logging.basicConfig(level=logging.DEBUG)
  39.  
  40. print('Version: ' + constants.VERSION)
  41.  
  42. def n():
  43. '''
  44. prints a new line
  45. '''
  46. print("\n")
  47.  
  48.  
  49. def isSameSongPlaying(dictionary, tag_uri):
  50. '''
  51. returns True if the same song is playing and False if it is not.
  52.  
  53. params:
  54. dictionary: dictionary returned from "client.current_playback('US')"
  55.  
  56. tag_uri: the URI of the song being comapared to the currently playing song
  57. '''
  58. if dictionary == None: #If no song is playing
  59. return False
  60.  
  61. context_dictionary = dictionary.get('context')
  62. if context_dictionary == None:
  63. return False
  64. current_uri = context_dictionary.get('uri')
  65. if current_uri == None:
  66. return False
  67.  
  68. if current_uri == tag_uri: #If the song is playing
  69. return True
  70. else: #If a different song is playing
  71. return False
  72.  
  73.  
  74. def find(string, search_term):
  75. '''
  76. returns True if 'search_term' is found anywhere in 'string'
  77. '''
  78. if string.find(search_term) != -1:
  79. return True
  80. else:
  81. return False
  82.  
  83.  
  84. chromecasts, browser = pychromecast.get_listed_chromecasts(friendly_names=[args.cast])
  85. home = None
  86. for _cast in chromecasts:
  87. if _cast.name == args.cast:
  88. home = _cast
  89. break
  90.  
  91. if not home:
  92. print('No chromecast with name "{}" discovered'.format(args.cast))
  93. print("Discovered casts: {}".format(chromecasts))
  94. print("Attempting to connect to cast devie via IP")
  95. n()
  96. home = pychromecast.Chromecast(CAST_IP)
  97.  
  98. if not home:
  99. print("Failure. Exiting.")
  100. sys.exit(1)
  101. else:
  102. print("Success!")
  103. n()
  104.  
  105. print("cast {}".format(home))
  106.  
  107. home.wait() # Start a new worker thread/wait for connection
  108.  
  109. # Log device and status
  110. n()
  111. print(home.device)
  112. n()
  113. print(home.status)
  114. n()
  115.  
  116. spotify_device_id = None
  117.  
  118. # Create a spotify token
  119. data = st.start_session(SP_DC, SP_KEY)
  120. access_token = data[0]
  121. expires = data[1] - int(time.time())
  122.  
  123. # Create a spotify client
  124. scope = "streaming user-read-playback-state user-modify-playback-state"
  125.  
  126. client = spotipy.Spotify(auth_manager=SpotifyOAuth(client_id=CLIENT_ID, client_secret=CLIENT_SECRET, scope=scope, redirect_uri=SPOTIPY_REDIRECT_URI, username=SPOTIFY_USERNAME))
  127. if args.show_debug:
  128. spotipy.trace = True
  129. spotipy.trace_out = True
  130.  
  131. # Launch the spotify app on the home
  132. sp = SpotifyController(access_token, expires)
  133. home.register_handler(sp)
  134. sp.launch_app()
  135.  
  136. n()
  137. print(home.status)
  138. n()
  139.  
  140. if not sp.is_launched and not sp.credential_error:
  141. print("Failed to launch spotify controller due to timeout")
  142. sys.exit(1)
  143. if not sp.is_launched and sp.credential_error:
  144. print("Failed to launch spotify controller due to credential error")
  145. sys.exit(1)
  146.  
  147. # Query spotify for active devices
  148. devices_available = client.devices()
  149.  
  150. # Match active spotify devices with the spotify controller's device id
  151. for device in devices_available["devices"]:
  152. if device["id"] == sp.device:
  153. spotify_device_id = device["id"]
  154. break
  155.  
  156. if not spotify_device_id:
  157. print('No device with id "{}" known by Spotify'.format(sp.device))
  158. print("Known devices: {}".format(devices_available["devices"]))
  159. sys.exit(1)
  160.  
  161. #Set up NFC reader
  162. n()
  163. print("Setting up the NFC reader")
  164. reader = nfc.ContactlessFrontend(constants.PATH)
  165. print(reader)
  166. n()
  167.  
  168. shuffle_state = SHUFFLE_DEFAULT
  169. explicit_filter = ALLOW_EXPLICIT
  170.  
  171. def get_record(tag_data):
  172. shuffle_state = SHUFFLE_DEFAULT
  173. explicit_filter = ALLOW_EXPLICIT
  174.  
  175. if tag_data.ndef:
  176. for record in tag_data.ndef.records:
  177. nfc_data = record.text
  178. print("Read from NFC tag: " + record.text)
  179. nfc_data = nfc_data.lower() #make it lowercase
  180.  
  181. reset_shuffle = False
  182. command = nfc_data
  183. if type(command) == type('string-example'):
  184. if command.startswith('spotify'):
  185. playback_data = client.current_playback('US')
  186. tag_uri = command #These variables have the same exact value
  187.  
  188. # Overide shuffle based on media type
  189. if find(command, 'playlist'):
  190. client.shuffle(PLAYLISTS_SHUFFLE, spotify_device_id)
  191. reset_shuffle = True
  192. elif find(command, 'show'):
  193. client.shuffle(False, spotify_device_id)
  194. reset_shuffle = True
  195.  
  196. if not isSameSongPlaying(playback_data, tag_uri):
  197. client.start_playback(device_id=spotify_device_id, context_uri=tag_uri)
  198. time.sleep(0.1)
  199.  
  200. # If we overid the shuffle state, change it back to normal
  201. if reset_shuffle:
  202. client.shuffle(shuffle_state, spotify_device_id)
  203. elif command == 'command:skip':
  204. client.next_track(spotify_device_id)
  205. elif command == 'command:previous':
  206. client.previous_track(spotify_device_id)
  207. elif command == 'command:pause':
  208. client.pause_playback(spotify_device_id)
  209. elif command == 'command:shuffle':
  210. shuffle_state = not shuffle_state
  211. client.shuffle(shuffle_state, spotify_device_id)
  212. elif command == 'command:explicit':
  213. explicit_filter = not explicit_filter
  214. else:
  215. n()
  216. print('Oopsies, that NFC tag has an invalid command.')
  217.  
  218. time.sleep(0.1)
  219.  
  220. else:
  221. n()
  222. print("The NFC reader could not read this tag.")
  223. n()
  224. print("This may be because:")
  225. print("- You are using a Mifare Classic NFC tag, which is not supported by your reader.")
  226. print("- The NFC tag you are trying to read is not storing URI's or commands at text.")
  227.  
  228.  
  229. # Start playback
  230. while True:
  231. reader.connect(rdwr={'on-connect': get_record, 'beep-on-connect': constants.BEEP})
  232.  
  233. # Shut down discovery
  234. pychromecast.discovery.stop_discovery(browser)
Add Comment
Please, Sign In to add comment