def playback_data(self, data, num_samples, format, pending): global pending_data # Make sure we don't pass incomplete frames to alsa num_samples -= num_samples % CHANNELS buf = pending_data + ffi.buffer(data, num_samples * SAMPLESIZE)[:] try: total = 0 while len(buf) >= PERIODSIZE * CHANNELS * SAMPLESIZE: audio_queue.put(buf[:PERIODSIZE * CHANNELS * SAMPLESIZE], block=False) buf = buf[PERIODSIZE * CHANNELS * SAMPLESIZE:] total += PERIODSIZE * CHANNELS pending_data = buf return num_samples except Queue.Full: return total finally: pending[0] = audio_queue.qsize() * PERIODSIZE * CHANNELS
def playback_data(self, data, num_samples, format, pending): global pending_data play_event.set() # Make sure we don't pass incomplete frames to alsa num_samples -= num_samples % CHANNELS buf = pending_data + ffi.buffer(data, num_samples * SAMPLESIZE)[:] try: total = 0 while len(buf) >= PERIODSIZE * CHANNELS * SAMPLESIZE: audio_player.write(buf[:PERIODSIZE * CHANNELS * SAMPLESIZE]) buf = buf[PERIODSIZE * CHANNELS * SAMPLESIZE:] total += PERIODSIZE * CHANNELS pending_data = buf return num_samples except player.BufferFull: return total finally: pending[0] = audio_player.buffer_length() * PERIODSIZE * CHANNELS
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")
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 __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 __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='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")