def silence(self, duration, **kwargs): '''stream silence audio for the given duration, used by spotify connect player''' duration = int(duration) wave_header, filesize = create_wave_header(duration) output_buffer = StringIO() output_buffer.write(wave_header) output_buffer.write('\0' * (filesize - output_buffer.tell())) return cherrypy.lib.static.serve_fileobj(output_buffer, content_type="audio/wav", name="%s.wav" % duration, filesize=output_buffer.tell())
def send_audio_stream(self, track_id, filesize, wave_header, range_l): '''chunked transfer of audio data from spotty binary''' log_msg("start transfer for track %s - range: %s" % (track_id, range_l), xbmc.LOGDEBUG) spotty_bin = None try: # Initialize some loop vars max_buffer_size = 1024000 output_buffer = StringIO() bytes_written = 0 has_frames = True # Write wave header output_buffer.write(wave_header) bytes_written = output_buffer.tell() if not range_l: yield wave_header output_buffer.truncate(0) # get pcm data from spotty stdout and append to our buffer args = ["-n", "temp", "--single-track", track_id] spotty_bin = self.__spotty.run_spotty(args) # ignore the first x bytes to match the range request if range_l: spotty_bin.stdout.read(range_l - bytes_written) # Loop as long as there's something to output frame = spotty_bin.stdout.read(max_buffer_size) while has_frames: if cherrypy.response.timed_out: log_msg("response timeout !", xbmc.LOGDEBUG) break try: if not frame or len(frame) < max_buffer_size: has_frames = False output_buffer.write(frame) bytes_written += len(frame) frame = spotty_bin.stdout.read(max_buffer_size) except Exception as exc: log_exception(__name__, exc) has_frames = False finally: # Check if the current buffer needs to be flushed if not has_frames or output_buffer.tell() > max_buffer_size: yield output_buffer.getvalue() output_buffer.truncate(0) # Add some silence padding until the end is reached (if needed) while bytes_written < filesize: if bytes_written + max_buffer_size < filesize: # The buffer size fits into the file size yield '\0' * max_buffer_size bytes_written += max_buffer_size else: # Does not fit, just generate the remaining bytes yield '\0' * (filesize - bytes_written) memory_buffer.write(frame) bytes_written = filesize except Exception as exc: log_msg(__name__, exc) finally: # make sure spotty always gets terminated if spotty_bin: spotty_bin.terminate() log_msg("FINISH transfer for track %s - range %s" % (track_id, range_l), xbmc.LOGDEBUG)