def get_info(): zeroconf_vars = get_zeroconf_vars() return jsonify({ 'status': 101, 'spotifyError': 0, 'activeUser': zeroconf_vars['activeUser'], 'brandDisplayName': ffi.string(connect_app.config['brandName']), 'accountReq': zeroconf_vars['accountReq'], #Doesn't have any specific format (I think) 'deviceID': zeroconf_vars['deviceId'], #Generated from SpZeroConfGetVars() #Used to encrypt the blob used for login 'publicKey': zeroconf_vars['publicKey'], 'version': '2.0.1', #Valid types are UNKNOWN, COMPUTER, TABLET, SMARTPHONE, SPEAKER, TV, AVR, STB and AUDIODONGLE 'deviceType': zeroconf_vars['deviceType'], 'modelDisplayName': ffi.string(connect_app.config['modelName']), #Status codes are ERROR-OK (not actually an error), ERROR-MISSING-ACTION, ERROR-INVALID-ACTION, ERROR-SPOTIFY-ERROR, ERROR-INVALID-ARGUMENTS, ERROR-UNKNOWN, and ERROR_LOG_FILE 'statusString': 'ERROR-OK', #Name that shows up in the Spotify client 'remoteName': zeroconf_vars['remoteName'] })
def convert_to_python(s): type = ffi.typeof(s) if type.kind == 'struct': return dict(__convert_struct_field(s, type.fields)) elif type.kind == 'array': if type.item.kind == 'primitive': if type.item.cname == 'char': return ffi.string(s) else: return [s[i] for i in range(type.length)] else: return [convert_to_python(s[i]) for i in range(type.length)] elif type.kind == 'primitive': return int(s)
def convert_to_python(s): type=ffi.typeof(s) if type.kind == 'struct': return dict(__convert_struct_field( s, type.fields ) ) elif type.kind == 'array': if type.item.kind == 'primitive': if type.item.cname == 'char': return ffi.string(s) else: return [ s[i] for i in range(type.length) ] else: return [ convert_to_python(s[i]) for i in range(type.length) ] elif type.kind == 'primitive': return int(s)
def debug_message(self, msg): print ffi.string(msg)
def connection_new_credentials(self, blob): print ffi.string(blob) self.credentials['blob'] = ffi.string(blob) with open(self.args.credentials, 'w') as f: f.write(json.dumps(self.credentials))
def __init__(self, error_cb=error_callback, web_arg_parser=None): arg_parsers = [audio_arg_parser] if web_arg_parser: arg_parsers.append(web_arg_parser) arg_parser = argparse.ArgumentParser( description="Deamon Spotify Connect", parents=arg_parsers) arg_parser.add_argument( "--debug", "-d", help="enable libspotify_embedded debug output", action="store_true", ) arg_parser.add_argument( "--key", "-k", help= "path to spotify_appkey.key (can be obtained from https://developer.spotify.com/my-account/keys )", default="spotify_appkey.key", ) arg_parser.add_argument("--username", "-u", help="your spotify username") arg_parser.add_argument("--password", "-p", help="your spotify password") arg_parser.add_argument( "--name", "-n", help="name that shows up in the spotify client", default="TestConnect", ) arg_parser.add_argument( "--bitrate", "-b", help="Sets bitrate of audio stream (may not actually work)", choices=[90, 160, 320], type=int, default=160, ) arg_parser.add_argument( "--credentials", "-c", help="File to load and save credentials from/to", default="credentials.json", ) self.args = arg_parser.parse_args() print("Using libspotify_embedded version: {}".format( ffi.string(lib.SpGetLibraryVersion()))) try: with open(self.args.key, "rb") as f: app_key = ffi.new("uint8_t *") f.readinto(ffi.buffer(app_key)) app_key_size = len(f.read()) + 1 except IOError as e: print("Error opening app key: {}.".format(e)) print( "If you don't have one, it can be obtained from https://developer.spotify.com/my-account/keys" ) sys.exit(1) self.credentials = dict({ "device-id": str(uuid.uuid4()), "username": None, "blob": None }) try: with open(self.args.credentials) as f: self.credentials.update(json.loads(f.read()).items()) except IOError: pass if self.args.username: self.credentials["username"] = self.args.username userdata = ffi.new_handle(self) if self.args.debug: lib.SpRegisterDebugCallbacks(debug_callbacks, userdata) self.config = { "version": 4, "buffer": C.malloc(0x100000), "buffer_size": 0x100000, "app_key": app_key, "app_key_size": app_key_size, "deviceId": ffi.new("char[]", self.credentials["device-id"].encode()), "remoteName": ffi.new("char[]", self.args.name.encode()), "brandName": ffi.new("char[]", "DummyBrand".encode()), "modelName": ffi.new("char[]", "DummyModel".encode()), "client_id": ffi.new("char[]", "0".encode()), "deviceType": lib.kSpDeviceTypeAudioDongle, "error_callback": error_cb, "userdata": userdata, } init = ffi.new("SpConfig *", self.config) init_status = lib.SpInit(init) print("SpInit: {}".format(init_status)) if init_status != 0: print("SpInit failed, exiting") sys.exit(1) lib.SpRegisterConnectionCallbacks(connection_callbacks, userdata) lib.SpRegisterPlaybackCallbacks(playback_callbacks, userdata) mixer_volume = int(mixer.getvolume()[0] * 655.35) lib.SpPlaybackUpdateVolume(mixer_volume) bitrates = { 90: lib.kSpBitrate90k, 160: lib.kSpBitrate160k, 320: lib.kSpBitrate320k, } lib.SpPlaybackSetBitrate(bitrates[self.args.bitrate]) playback_setup() if self.credentials["username"] and self.args.password: self.login(password=self.args.password) elif self.credentials["username"] and self.credentials["blob"]: self.login(blob=self.credentials["blob"]) else: raise ValueError("No username given, and none stored")
def connection_new_credentials(self, blob): print(ffi.string(blob)) self.credentials["blob"] = str(ffi.string(blob)) with open(self.args.credentials, "w") as f: f.write(json.dumps(self.credentials))
def get_image_url(uri): image_url = ffi.new('char[512]') #TODO: Change back to 640 lib.SpGetMetadataImageURL(uri, lib.kSpImageSize160, image_url, ffi.sizeof(image_url)) return ffi.string(image_url)
def debug_message(msg, userdata): print ffi.string(msg)
def connection_message(msg, userdata): print ffi.string(msg)
def __init__(self, error_cb=error_callback, web_arg_parser=None): arg_parser = argparse.ArgumentParser( description='Web interface for Spotify Connect', parents=[audio_arg_parser]) arg_parser.add_argument( '--debug', '-d', help='enable libspotify_embedded/flask debug output', action="store_true") arg_parser.add_argument( '--key', '-k', help= 'path to spotify_appkey.key (can be obtained from https://developer.spotify.com/my-account/keys )', default='spotify_appkey.key') arg_parser.add_argument('--username', '-u', help='your spotify username') arg_parser.add_argument('--password', '-p', help='your spotify password') arg_parser.add_argument( '--name', '-n', help='name that shows up in the spotify client', default='TestConnect') arg_parser.add_argument( '--bitrate', '-b', help='Sets bitrate of audio stream (may not actually work)', choices=[90, 160, 320], type=int, default=160) arg_parser.add_argument( '--credentials', '-c', help='File to load and save credentials from/to', default='credentials.json') self.args = arg_parser.parse_args() print "Using libspotify_embedded version: {}".format( ffi.string(lib.SpGetLibraryVersion())) try: with open(self.args.key) as f: app_key = ffi.new('uint8_t *') f.readinto(ffi.buffer(app_key)) app_key_size = len(f.read()) + 1 except IOError as e: print "Error opening app key: {}.".format(e) print "If you don't have one, it can be obtained from https://developer.spotify.com/my-account/keys" sys.exit(1) self.credentials = dict({ 'device-id': str(uuid.uuid4()), 'username': None, 'blob': None }) try: with open(self.args.credentials) as f: self.credentials.update({ k: v.encode('utf-8') if isinstance(v, unicode) else v for (k, v) in json.loads(f.read()).iteritems() }) except IOError: pass if self.args.username: self.credentials['username'] = self.args.username userdata = ffi.new_handle(self) if self.args.debug: lib.SpRegisterDebugCallbacks(debug_callbacks, userdata) self.config = { 'version': 4, 'buffer': C.malloc(0x100000), 'buffer_size': 0x100000, 'app_key': app_key, 'app_key_size': app_key_size, 'deviceId': ffi.new('char[]', self.credentials['device-id']), 'remoteName': ffi.new('char[]', self.args.name), 'brandName': ffi.new('char[]', 'DummyBrand'), 'modelName': ffi.new('char[]', 'DummyModel'), 'client_id': ffi.new('char[]', '0'), 'deviceType': lib.kSpDeviceTypeAudioDongle, 'error_callback': error_cb, 'userdata': userdata, } init = ffi.new('SpConfig *', self.config) init_status = lib.SpInit(init) print "SpInit: {}".format(init_status) if init_status != 0: print "SpInit failed, exiting" sys.exit(1) lib.SpRegisterConnectionCallbacks(connection_callbacks, userdata) lib.SpRegisterPlaybackCallbacks(playback_callbacks, userdata) mixer_volume = int(mixer.getvolume()[0] * 655.35) lib.SpPlaybackUpdateVolume(mixer_volume) bitrates = { 90: lib.kSpBitrate90k, 160: lib.kSpBitrate160k, 320: lib.kSpBitrate320k } lib.SpPlaybackSetBitrate(bitrates[self.args.bitrate]) playback_setup() print_zeroconf_vars() if self.credentials['username'] and self.args.password: self.login(password=self.args.password) elif self.credentials['username'] and self.credentials['blob']: self.login(blob=self.credentials['blob']) else: if __name__ == '__main__': raise ValueError("No username given, and none stored")
def get_image_url(uri): image_url = ffi.new('char[512]') #TODO: Change back to 640 lib.SpGetMetadataImageURL(uri, lib.kSpImageSizeSmall, image_url, ffi.sizeof(image_url)) return ffi.string(image_url)
def __init__(self, error_cb = error_callback, web_arg_parser = None): arg_parsers = [audio_arg_parser] if web_arg_parser: arg_parsers.append(web_arg_parser) arg_parser = argparse.ArgumentParser(description='Web interface for Spotify Connect', parents=arg_parsers) arg_parser.add_argument('--debug', '-d', help='enable libspotify_embedded/flask debug output', action="store_true") arg_parser.add_argument('--key', '-k', help='path to spotify_appkey.key (can be obtained from https://developer.spotify.com/my-account/keys )', default='spotify_appkey.key') arg_parser.add_argument('--username', '-u', help='your spotify username') arg_parser.add_argument('--password', '-p', help='your spotify password') arg_parser.add_argument('--name', '-n', help='name that shows up in the spotify client', default='TestConnect') arg_parser.add_argument('--bitrate', '-b', help='Sets bitrate of audio stream (may not actually work)', choices=[90, 160, 320], type=int, default=160) arg_parser.add_argument('--credentials', '-c', help='File to load and save credentials from/to', default='credentials.json') self.args = arg_parser.parse_args() print "Using libspotify_embedded version: {}".format(ffi.string(lib.SpGetLibraryVersion())) try: with open(self.args.key) as f: app_key = ffi.new('uint8_t *') f.readinto(ffi.buffer(app_key)) app_key_size = len(f.read()) + 1 except IOError as e: print "Error opening app key: {}.".format(e) print "If you don't have one, it can be obtained from https://developer.spotify.com/my-account/keys" sys.exit(1) self.credentials = dict({ 'device-id': str(uuid.uuid4()), 'username': None, 'blob': None }) try: with open(self.args.credentials) as f: self.credentials.update( { k: v.encode('utf-8') if isinstance(v, unicode) else v for (k,v) in json.loads(f.read()).iteritems() }) except IOError: pass if self.args.username: self.credentials['username'] = self.args.username userdata = ffi.new_handle(self) if self.args.debug: lib.SpRegisterDebugCallbacks(debug_callbacks, userdata) self.config = { 'version': 4, 'buffer': C.malloc(0x100000), 'buffer_size': 0x100000, 'app_key': app_key, 'app_key_size': app_key_size, 'deviceId': ffi.new('char[]', self.credentials['device-id']), 'remoteName': ffi.new('char[]', self.args.name), 'brandName': ffi.new('char[]', 'DummyBrand'), 'modelName': ffi.new('char[]', 'DummyModel'), 'client_id': ffi.new('char[]', '0'), 'deviceType': lib.kSpDeviceTypeAudioDongle, 'error_callback': error_cb, 'userdata': userdata, } init = ffi.new('SpConfig *' , self.config) init_status = lib.SpInit(init) print "SpInit: {}".format(init_status) if init_status != 0: print "SpInit failed, exiting" sys.exit(1) lib.SpRegisterConnectionCallbacks(connection_callbacks, userdata) lib.SpRegisterPlaybackCallbacks(playback_callbacks, userdata) mixer_volume = int(mixer.getvolume()[0] * 655.35) lib.SpPlaybackUpdateVolume(mixer_volume) bitrates = { 90: lib.kSpBitrate90k, 160: lib.kSpBitrate160k, 320: lib.kSpBitrate320k } lib.SpPlaybackSetBitrate(bitrates[self.args.bitrate]) playback_setup() print_zeroconf_vars() if self.credentials['username'] and self.args.password: self.login(password=self.args.password) elif self.credentials['username'] and self.credentials['blob']: self.login(blob=self.credentials['blob']) else: if __name__ == '__main__': raise ValueError("No username given, and none stored")