class Player: async_queue_size = 3 # larger is less chance of getting skips, but latency increases update_rate = 40 # larger is less cpu usage but more chance of getting skips levelmeter_lowest = -40 # dB def __init__(self, app): self.app = app self.app.after(self.update_rate, self.tick) self.app.firstTrackFrame.play() self.stopping = False self.mixer = StreamMixer([], endless=True) self.output = Output(self.mixer.samplerate, self.mixer.samplewidth, self.mixer.nchannels, queuesize=self.async_queue_size) self.mixed_samples = iter(self.mixer) self.levelmeter = LevelMeter(rms_mode=False, lowest=self.levelmeter_lowest) def stop(self): self.stopping = True self.app.firstTrackFrame.close_stream() self.app.secondTrackFrame.close_stream() self.mixer.close() self.output.close() def switch_player(self): """ The actual switching of the main track player. Note that it can be playing already because of the fade-in mixing. """ first_is_playing = self.app.firstTrackFrame.playing self.app.firstTrackFrame.play(not first_is_playing) self.app.secondTrackFrame.play(first_is_playing) def tick(self): if self.output.queue_size() <= self.async_queue_size / 2: self.app.firstTrackFrame.tick(self.mixer) self.app.secondTrackFrame.tick(self.mixer) _, sample = next(self.mixed_samples) if sample and sample.duration > 0: self.output.play_sample(sample, async=True) left, _, right, _ = self.levelmeter.update(sample) self.app.update_levels(left, right) else: self.levelmeter.reset() self.app.update_levels(self.levelmeter.level_left, self.levelmeter.level_right) if not self.stopping: self.app.after(self.update_rate, self.tick) def play_sample(self, sample): if sample and sample.duration > 0: self.mixer.add_sample(sample) def start_play_other(self): # @todo fix the track switching and fadein/fadeout, it's a bit of a mess if self.app.firstTrackFrame.playing: other_track = self.app.secondTrackFrame else: other_track = self.app.firstTrackFrame other_track.start_fadein()