def __init__(self, error_cb = error_callback): pass_required = False if __name__ == "__main__": #Require username and password when used without a web server pass_required = True 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', default='spotify_appkey.key', type=file) arg_parser.add_argument('--username', '-u', help='your spotify username', required=pass_required) arg_parser.add_argument('--password', '-p', help='your spotify password', required=pass_required) 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() app_key = ffi.new('uint8_t *') self.args.key.readinto(ffi.buffer(app_key)) app_key_size = len(self.args.key.read()) + 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) 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'), 'deviceType': lib.kSpDeviceTypeAudioDongle, 'error_callback': error_cb, 'userdata': userdata, } init = ffi.new('SpConfig *' , self.config) print "SpInit: {}".format(lib.SpInit(init)) lib.SpRegisterConnectionCallbacks(connection_callbacks, userdata) if self.args.debug: lib.SpRegisterDebugCallbacks(debug_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'])
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")
@ffi.callback('void(uint16_t volume, void *userdata)') @userdata_wrapper def playback_volume(self, volume): print "playback_volume: {}".format(volume) if volume == 0: if mute_available: mixer.setmute(1) print "Mute activated" else: if mute_available and mixer.getmute()[0] == 1: mixer.setmute(0) print "Mute deactivated" corected_playback_volume = int(min_volume_range + ((volume / 655.35) * (100 - min_volume_range) / 100)) corected_playback_volume = int( 100 * math.pow(corected_playback_volume / 100.0, 1.0 / 3.0)) print "corected_playback_volume: {}".format(corected_playback_volume) mixer.setvolume(corected_playback_volume) connection_callbacks = ffi.new('SpConnectionCallbacks *', [connection_notify, connection_new_credentials]) debug_callbacks = ffi.new('SpDebugCallbacks *', [debug_message]) playback_callbacks = ffi.new( 'SpPlaybackCallbacks *', [playback_notify, playback_data, playback_seek, playback_volume])
def get_zeroconf_vars(): zeroconf_vars = ffi.new('struct vars_data *') lib.SpZeroConfGetVars(zeroconf_vars) return convert_to_python(zeroconf_vars[0])
finally: pending[0] = audio_player.buffer_length() * PERIODSIZE * CHANNELS @ffi.callback('void(uint32_t millis, void *userdata)') @userdata_wrapper def playback_seek(self, millis): print "playback_seek: {}".format(millis) @ffi.callback('void(uint16_t volume, void *userdata)') @userdata_wrapper def playback_volume(self, volume): print "playback_volume: {}".format(volume) if audio_player.mixer_loaded(): audio_player.volume_set(int(volume / 655.35)) connection_callbacks = ffi.new('SpConnectionCallbacks *', [ connection_notify, connection_new_credentials ]) debug_callbacks = ffi.new('SpDebugCallbacks *', [ debug_message ]) playback_callbacks = ffi.new('SpPlaybackCallbacks *', [ playback_notify, playback_data, playback_seek, playback_volume ])
def get_metadata(): metadata = ffi.new('struct SpMetadata *') lib.SpGetMetadata(metadata, 0) return convert_to_python(metadata[0])
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 __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 playback_data(frames, num_frames, format, userdata): # #audio_frame(frames, num_frames, format) # pass @ffi.callback('void(uint32_t millis, void *userdata)') def playback_seek(millis, userdata): print "playback_seek: {}".format(millis) @ffi.callback('void(uint16_t volume, void *userdata)') def playback_volume(volume, userdata): print "playback_volume: {}".format(volume) mixer.setvolume(int(volume / 655.35)) connection_callbacks = ffi.new('struct connection_callbacks *', [connection_notify, connection_message]) debug_callbacks = ffi.new('struct debug_callbacks *', [debug_message]) # playback_callbacks = ffi.new('struct playback_callbacks *', [ # playback_notify, # ffi.NULL, # playback_seek, # playback_volume # ]) lib.playback_notify = playback_notify lib.playback_seek = playback_seek lib.playback_volume = playback_volume
def __init__(self, error_cb=error_callback): pass_required = False if __name__ == "__main__": #Require username and password when used without a web server pass_required = True arg_parser = argparse.ArgumentParser( description='Web interface for Spotify Connect', parents=[mixer_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', default='spotify_appkey.key', type=file) arg_parser.add_argument('--username', '-u', help='your spotify username', required=pass_required) arg_parser.add_argument('--password', '-p', help='your spotify password', required=pass_required) 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) self.args = arg_parser.parse_args() app_key = ffi.new('uint8_t *') self.args.key.readinto(ffi.buffer(app_key)) app_key_size = len(self.args.key.read()) + 1 self.init_vars = { 'version': 4, 'buffer': C.malloc(1048576), 'buffer_size': 1048576, 'os_device_id': ffi.new('char[]', 'abcdef-{}'.format(os.getpid())), 'remoteName': ffi.new('char[]', self.args.name), 'brandName': ffi.new('char[]', 'DummyBrand'), 'modelName': ffi.new('char[]', 'DummyModel'), 'deviceType': lib.kSpDeviceTypeAudioDongle, 'error_callback': error_cb, 'zero1': 0, 'app_key': app_key, 'app_key_size': app_key_size } init = ffi.new('struct init_data *', self.init_vars) print "SpInit: {}".format(lib.SpInit(init)) lib.SpRegisterConnectionCallbacks(connection_callbacks, ffi.NULL) if self.args.debug: lib.SpRegisterDebugCallbacks(debug_callbacks, ffi.NULL) #lib.SpRegisterPlaybackCallbacks(playback_callbacks, ffi.NULL) lib.setup_audio_callbacks() mixer_volume = int(mixer.getvolume()[0] * 655.35) lib.SpPlaybackUpdateVolume(mixer_volume) bitrates = { 90: lib.kSpBitrate90, 160: lib.kSpBitrate160, 320: lib.kSpBitrate320 } lib.SpPlaybackSetBitrate(bitrates[self.args.bitrate]) print_zeroconf_vars() if self.args.username and self.args.password: lib.SpConnectionLoginPassword(self.args.username, self.args.password)
def get_zeroconf_vars(): zeroconf_vars = ffi.new('SpZeroConfVars *') lib.SpZeroConfGetVars(zeroconf_vars) return convert_to_python(zeroconf_vars[0])
def __init__(self, error_cb=error_callback): pass_required = False if __name__ == "__main__": #Require username and password when used without a web server pass_required = True 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', default='spotify_appkey.key', type=file) arg_parser.add_argument('--username', '-u', help='your spotify username', required=pass_required) arg_parser.add_argument('--password', '-p', help='your spotify password', required=pass_required) 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() app_key = ffi.new('uint8_t *') self.args.key.readinto(ffi.buffer(app_key)) app_key_size = len(self.args.key.read()) + 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) 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'), 'deviceType': lib.kSpDeviceTypeAudioDongle, 'error_callback': error_cb, 'userdata': userdata, } init = ffi.new('SpConfig *', self.config) print "SpInit: {}".format(lib.SpInit(init)) lib.SpRegisterConnectionCallbacks(connection_callbacks, userdata) if self.args.debug: lib.SpRegisterDebugCallbacks(debug_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'])
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 get_metadata(): metadata = ffi.new('SpMetadata *') lib.SpGetMetadata(metadata, 0) return convert_to_python(metadata[0])
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")