def _ask_synth_to_play_segment(self, segment, channel, pan): if self.synth: logger.debug("asking synth to play %s" % segment) file_info = self.tr_log.files[segment["filenum"]] if self.output == self.SSR: segment["sound_source_id"] = self.ssr.allocate_source() if segment["sound_source_id"] and not self._warned_about_max_sources: channel = segment["sound_source_id"] - 1 pan = None else: print "WARNING: max sources exceeded, skipping segment playback (this warning will not be repeated)" self._warned_about_max_sources = True return self.synth.play_segment( segment["id"], segment["audio_filenum"], segment["relative_start_time_in_file"], segment["relative_end_time_in_file"], segment["duration"], self.looped_duration, channel, pan) self._scheduler_queue.put( (segment["playback_duration"], 1, self.stopped_playing, [segment]))
def set_time_cursor(self, log_time): assert not self.realtime logger.debug("setting time cursor at %f" % log_time) self.log_time_played_from = log_time if self._playing: self.stopwatch.restart() self.current_chunk_index = self._get_current_chunk_index() self.current_segment_index = self._get_current_segment_index()
def _decode_and_process_file(self, source_filename, target_filename): if os.path.isfile(source_filename): temp = tempfile.NamedTemporaryFile(suffix=".wav") self._decode_file(source_filename, temp.name) self._process_file(temp.name, target_filename) # self._decode_file(source_filename, target_filename) else: logger.debug("file not downloaded - not decoding")
def process_chunks_from_queue(): while True: logger.debug("waiting for chunk") chunk = get_chunk_from_queue() if chunk == TrLogReader.NO_MORE_CHUNKS: logger.debug("no more chunks") return orchestra.handle_chunk(chunk)
def _decode_file_unless_already_decoded(self, file_info, force): if self._location: source_filename = self._location + os.sep + file_info["name"] else: source_filename = file_info["name"] if self._extension(source_filename) == "wav": file_info["decoded_name"] = source_filename elif self._decodable(source_filename): logger.debug("decoding %s" % source_filename) target_filename = self._target_filename(source_filename) file_info["decoded_name"] = target_filename if self._already_decoded(target_filename) and not force: logger.debug("file already decoded") else: self._decode_and_process_file(source_filename, target_filename)
def _process_files_info(self): if not self.realtime: self.logfile.seek(0) file_info_re = re.compile('^TID=%d file=(\d+) offset=(\d+) length=(\d+) firstPiece=(\d+) lastPiece=(\d+) name=(.*)$' % self.id) logger.debug("starting to search for file info in log") for line in self.logfile: line = line.rstrip("\r\n") logger.debug("processing: %s" % line) m = file_info_re.search(line) if m: self._process_file_info_line(m) if len(self.files) == self.numfiles: return raise Exception("failed to find file info about all %d files (only found %d)" % ( self.numfiles, len(self.files)))
def _process_chunks(self): self.numdata = 0 self.time_offset = None self._chunk_re = re.compile('^\[(\d+)\] TID=%d peer=([^ ]+) got (\d+) bytes for block (\d+) at offset (\d+) in file (\d+) at offset (\d+) \.\.\. remaining (\d+) of (\d+)$' % self.id) self.filenummax = 0 if not self.realtime: self.chunks = [] logger.debug("starting to search for chunk info in log") for line in self.logfile: line = line.rstrip("\r\n") logger.debug("processing: %s" % line) self._process_chunk_line(line) if self.realtime: self.chunks_queue.put_nowait(self.NO_MORE_CHUNKS) elif self.pretend_sequential: self.chunks = self.sort_chunks_sequentially(self.chunks)
def _get_wav_files_info(cls, tr_log, include_non_playable=False): playable_file_index = 0 for filenum in range(len(tr_log.files)): file_info = tr_log.files[filenum] file_info["playable_file_index"] = -1 if "decoded_name" in file_info: file_info["duration"] = cls._get_file_duration(file_info) if file_info["duration"] > 0: file_info["playable_file_index"] = playable_file_index logger.debug("duration for %r: %r\n" % (file_info["name"], file_info["duration"])) playable_file_index += 1 if include_non_playable: file_info["index"] = filenum else: file_info["index"] = file_info["playable_file_index"] return playable_file_index
def handle_chunk(self, chunk): logger.debug("handling chunk %s" % chunk) player = self.get_player_for_chunk(chunk) logger.debug("get_player_for_chunk returned %s" % player) if self.fast_forwarding: self._stop_ff_if_necessary() else: now = self.get_current_log_time() time_margin = chunk["t"] - now logger.debug("time_margin=%f-%f=%f" % (chunk["t"], now, time_margin)) if not self.realtime and time_margin > 0: sleep_time = time_margin logger.debug("sleeping %f" % sleep_time) time.sleep(sleep_time) if player: logger.debug("player.enabled=%s" % player.enabled) if player and player.enabled: player.visualize(chunk) self._log_time_for_last_handled_event = chunk["t"]
def _create_player(self, addr): count = len(self.players) logger.debug("creating player number %d" % count) player = self._player_class(self, count) player.addr = addr if self.server.options.locate_peers and self._peer_location[addr] is not None: x, y, place_name = self._peer_location[addr] if place_name: place_name = place_name.encode("unicode_escape") else: place_name = "" player.location_str = "%s,%s,%s" % (x, y, place_name) if x < self._peers_center_location_x: player.spatial_position.pan = -1.0 else: player.spatial_position.pan = 1.0 else: player.location_str = "" return player
def handle_segment(self, segment): logger.debug("handling segment %s" % segment) player = self.get_player_for_segment(segment) if not player: logger.debug("get_player_for_segment returned None - skipping playback") if self.fast_forwarding: self._stop_ff_if_necessary() else: now = self.get_current_log_time() time_margin = segment["onset"] - now logger.debug("time_margin=%f-%f=%f" % (segment["onset"], now, time_margin)) if not self.realtime and time_margin > 0: sleep_time = time_margin logger.debug("sleeping %f" % sleep_time) time.sleep(sleep_time) if player: logger.debug("player.enabled=%s" % player.enabled) if player and player.enabled: player.play(segment, pan=0.5) self._log_time_for_last_handled_event = segment["onset"]
def interpret_sonically(self, segment): if self.orchestra.options.pretend_audio_filename: segment["audio_filenum"] = 0 file_info = self.orchestra.tr_log.files[segment["audio_filenum"]] begin = segment["begin"] end = segment["end"] else: segment["audio_filenum"] = segment["filenum"] file_info = self.orchestra.tr_log.files[segment["audio_filenum"]] begin = segment["begin"] - file_info["offset"] end = segment["end"] - file_info["offset"] filename = file_info["decoded_name"] start_time_in_file = self._bytecount_to_secs(begin, file_info) end_time_in_file = self._bytecount_to_secs(end, file_info) logger.debug("playing %s at position %fs with duration %fs" % ( filename, start_time_in_file, segment["duration"])) audio_file_duration = file_info["duration"] segment["relative_start_time_in_file"] = start_time_in_file / audio_file_duration segment["relative_end_time_in_file"] = end_time_in_file / audio_file_duration self.orchestra.play_segment(segment, self) return True
def _process_until_selected_torrent(self): logger.debug("selecting torrent") initialized_re = re.compile('initialized torrent (\d+): name=(.*) totalSize=(\d+) fileCount=(\d+) pieceSize=(\d+) pieceCount=(\d+)( fileLocation=(.+))?') for line in self.logfile: line = line.rstrip("\r\n") logger.debug("processing: %s" % line) m = initialized_re.search(line) if m: (id,name,totalsize,filecount,piecesize,piececount,foo,file_location) = m.groups() if self.torrent_name == "" or re.search(self.torrent_name, name): self.id = int(id) self.name = name self.totalsize = int(totalsize) self.numfiles = int(filecount) self.piecesize = int(piecesize) if file_location: self.file_location = file_location break if self.id == None: logger.debug("no torrent found") raise Exception("no torrent found") logger.debug("selected torrent '%s' (TID=%d totalsize=%d piecesize=%d)" % \ (self.name, self.id, self.totalsize, self.piecesize))
def _get_next_chunk_or_segment(self): logger.debug("chunk index = %d, segment index = %d" % ( self.current_chunk_index, self.current_segment_index)) chunk = self._get_next_chunk() segment = self._get_next_segment() logger.debug("next chunk: %s" % chunk) logger.debug("next segment: %s" % segment) if chunk and segment: return self._choose_nearest_chunk_or_segment(chunk, segment) elif chunk: return {"type": "chunk", "chunk": chunk} elif segment: return {"type": "segment", "segment": segment} else: return None
def _decode_file(self, source_filename, target_filename): extension = self._extension(source_filename) decoder = self._decoders[extension] cmd = decoder.command(source_filename, target_filename, self._sample_rate) logger.debug("decode command: %s" % cmd) subprocess.call(cmd, shell=True)
def _handle_visualizing_message(self, path, args, types, src, data): segment_id = args[0] segment = self.segments_by_id[segment_id] logger.debug("visualizing segment %s" % segment) player = self.get_player_for_segment(segment) self._ask_synth_to_play_segment(segment, channel=0, pan=player.spatial_position.pan)
def stopped_playing(self, segment): logger.debug("stopped segment %s" % segment) if self.gui: self.gui.unhighlight_segment(segment) if self.output == self.SSR and segment["sound_source_id"]: self.ssr.free_source(segment["sound_source_id"])
def __init__(self, server, sessiondir, tr_log, options): self.server = server self.options = options self.sessiondir = sessiondir self.tr_log = tr_log self.realtime = options.realtime self.timefactor = options.timefactor self.quiet = options.quiet self._loop = options.loop self.looped_duration = options.looped_duration self.output = options.output self.include_non_playable = options.include_non_playable self._leading_pause = options.leading_pause if server.options.locate_peers: self._peer_location = {} for peeraddr in tr_log.peers: self._peer_location[peeraddr] = server.ip_locator.locate(peeraddr) self._peers_center_location_x = self._get_peers_center_location_x() if options.pretend_audio_filename: self._pretended_file = self._fileinfo_for_pretended_audio_file() self._pretended_file["duration"] = self._get_file_duration(self._pretended_file) self._pretended_files = [self._pretended_file] self._files_to_play = self._pretended_files else: self._files_to_play = self.tr_log.files self.predecode = server.options.predecode if self.predecode: predecoder = Predecoder( tr_log.files, sample_rate=self.SAMPLE_RATE, location=tr_log.file_location) predecoder.decode(server.options.force_predecode) if options.pretend_audio_filename: predecoder = Predecoder( self._pretended_files, sample_rate=self.SAMPLE_RATE) predecoder.decode(server.options.force_predecode) if options.selected_files: tr_log.select_files(options.selected_files) self.playback_enabled = True self.fast_forwarding = False self.gui = None self._check_which_files_are_audio() self._player_class = WavPlayer self.players = [] self._player_for_peer = dict() self._prepare_playable_files() self.stopwatch = Stopwatch() self.playable_chunks = self._filter_playable_chunks(tr_log, tr_log.chunks) if self.include_non_playable: self.chunks = tr_log.chunks self._num_selected_files = len(self.tr_log.files) else: self.chunks = self.playable_chunks self._num_selected_files = self._num_playable_files logger.debug("total num chunks: %s" % len(tr_log.chunks)) logger.debug("num playable chunks: %s" % len(self.playable_chunks)) logger.debug("num selected chunks: %s" % len(self.chunks)) self.score = self._interpret_chunks_to_score(tr_log, self.playable_chunks, options) self.estimated_duration = self._estimated_playback_duration(self.score, options) print "playback duration: %s" % datetime.timedelta(seconds=self.estimated_duration) self._chunks_by_id = {} self.segments_by_id = {} self._playing = False self._quitting = False self._was_stopped = False self.space = Space() self._scheduler_queue = Queue.Queue() self.scheduler = sched.scheduler(time.time, time.sleep) self._run_scheduler_thread() if self.output == self.SSR: self.ssr = SsrControl() self._warned_about_max_sources = False