- Support for sound "release" (removal from active stream)
- Added `query_ports` method to MIDI plugin
This commit is contained in:
parent
f2d2315610
commit
c445763979
4 changed files with 74 additions and 3 deletions
|
@ -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
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
||||||
|
|
|
@ -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):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -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]
|
||||||
|
|
Loading…
Reference in a new issue