- Support for sound "release" (removal from active stream)

- Added `query_ports` method to MIDI plugin
This commit is contained in:
Fabio Manganiello 2018-12-27 00:09:05 +01:00
parent f2d2315610
commit c445763979
4 changed files with 74 additions and 3 deletions

View file

@ -24,13 +24,19 @@ class MidiBackend(Backend):
def __init__(self, device_name=None, port_number=None, def __init__(self, device_name=None, port_number=None,
midi_throttle_time=None, *args, **kwargs): midi_throttle_time=None, *args, **kwargs):
""" """
:param device_name: Name of the MIDI device. *N.B.* either `device_name` or `port_number` must be set :param device_name: Name of the MIDI device. *N.B.* either
`device_name` or `port_number` must be set.
Use :method:`platypush.plugins.midi.query_ports` to get the
available ports indices and names
:type device_name: str :type device_name: str
:param port_number: MIDI port number :param port_number: MIDI port number
:type port_number: int :type port_number: int
:param midi_throttle_time: If set, the MIDI events will be throttled - max one per selected time frame (in seconds). Set this parameter if you want to synchronize MIDI events with plugins that normally operate with a lower throughput. :param midi_throttle_time: If set, the MIDI events will be throttled -
max one per selected time frame (in seconds). Set this parameter if
you want to synchronize MIDI events with plugins that normally
operate with a lower throughput.
:type midi_throttle_time: int :type midi_throttle_time: int
""" """

View file

@ -120,5 +120,20 @@ class MidiPlugin(Plugin):
self.release_note(note) self.release_note(note)
@action
def query_ports(self):
"""
:returns: dict: A list of the available MIDI ports with index and name
"""
in_ports = rtmidi.MidiIn().get_ports()
out_ports = rtmidi.MidiOut().get_ports()
return {
'in': { i: port for i, port in enumerate(in_ports) },
'out': { i: port for i, port in enumerate(out_ports) },
}
# vim:sw=4:ts=4:et: # vim:sw=4:ts=4:et:

View file

@ -214,6 +214,15 @@ class Mix(object):
self._sounds.append(Sound.build(sound)) self._sounds.append(Sound.build(sound))
def remove(self, sound_index):
if sound_index >= len(self._sounds):
self.logger.error('No such sound index: {} in mix {}'.format(
sound_index, list(self)))
return
self._sounds.pop(sound_index)
def get_wave(self, t_start=0., t_end=0., normalize_range=(-1.0, 1.0), def get_wave(self, t_start=0., t_end=0., normalize_range=(-1.0, 1.0),
on_clip='scale', samplerate=Sound._DEFAULT_SAMPLERATE): on_clip='scale', samplerate=Sound._DEFAULT_SAMPLERATE):
""" """

View file

@ -325,7 +325,7 @@ class SoundPlugin(Plugin):
if duration is not None else t+blocktime if duration is not None else t+blocktime
data = mix.get_wave(t_start=t, t_end=next_t, data = mix.get_wave(t_start=t, t_end=next_t,
samplerate=samplerate) samplerate=samplerate)
t = next_t t = next_t
if duration is not None and t >= duration: if duration is not None and t >= duration:
@ -706,6 +706,47 @@ class SoundPlugin(Plugin):
self.logger.info('Recording paused state toggled') self.logger.info('Recording paused state toggled')
self.recording_paused_changed.set() self.recording_paused_changed.set()
@action
def release(self, stream, index=None, midi_note=None, frequency=None):
"""
Remove a sound from an active stream, either by sound index (use
:method:`platypush.sound.plugin.SoundPlugin.query_streams` to get
the sounds playing on the active streams), midi_note, frequency
or absolute file path.
:param stream: Stream index
:type stream: int
:param index: Sound index
:type index: int
:param midi_note: MIDI note
:type midi_note: int
:param frequency: Sound frequency
:type frequency: float
"""
if index is None and midi_note is None and frequency is None:
raise RuntimeError('Please specify either a sound index, ' +
'midi_note or frequency to release')
mix = self.stream_mixes.get(stream)
if not mix:
raise RuntimeError('No such stream: {}'.format(stream))
for i, sound in enumerate(mix):
if (index is not None and i == index) or \
(midi_note is not None
and sound.get('midi_note') == midi_note) or \
(frequency is not None
and sound.get('frequency') == frequency):
if len(list(mix)) == 1:
# Last sound in the mix
self.stop_playback([stream])
else:
mix.remove(i)
def _get_playback_state(self, stream_index): def _get_playback_state(self, stream_index):
with self.playback_state_lock: with self.playback_state_lock:
return self.playback_state[stream_index] return self.playback_state[stream_index]