Exemplo n.º 1
0
def update(_list, conn_text: TextInput, instance) -> None:
    # ping(conn_text.text)
    # is_connected(conn_text.text, 2307)
    try:
        conn = rpr.connect(conn_text.text)
        with rpr.inside_reaper():
            print(f'connected to {conn_text.text}')
    except (rpr.errors.DisabledDistAPIError, AttributeError):
        print('cannot connect to "{}"'.format(conn_text.text))
        # conn_text.background_color = (1, 0, 0)
        return
    # else:
    #     conn_text.background_color = (1, 1, 1)
    Config.set(SECTION, 'IP', conn_text.text)
    Config.write()
    print(f'SECTION, "IP" to {conn_text.text}')

    with rpr.inside_reaper():
        items_list = get_items_list()

        pr = rpr.Project()
        ts = pr.time_selection
        ts.start = 0
        ts.end = pr.length
        rpr.perform_action(40420)
        ts.end = 0

        for item in items_list:
            item_ = item.item
            pr.add_marker(item_.position + item_.length - .1, name='!1016')

        print(items_list)
        update_list(_list, items_list)
Exemplo n.º 2
0
    def sync_recarm(self) -> None:
        """Synchronize recarm state of all childs with target childs.

        Raises
        ------
        SessionError
            If no childs matched to slave.
        """
        if self.target is None:
            raise SessionError(f'no target for track {self.name} ({self})')
        if not self._childs_matched_primary:
            raise SessionError(f'no matched childs for {self.name} ({self})')
        childs = self._return_matched_childs(TrackChildsSet.both)
        t_host = self.s_project.last_ip
        Targets = te.TypedDict('Targets', {'target': Track, 'recarm': bool})

        with rpr.inside_reaper():
            targets: ty.Dict[Track.ID, Targets] = {}
            for child in childs.values():
                recarm = child.recarm
                assert child.target, f'no target for child: {child}'
                target = child.target
                if target.id not in targets:
                    targets[target.id] = {'target': target, 'recarm': recarm}
                elif recarm is True:
                    targets[target.id]['recarm'] = True
        with rpr.connect(t_host):
            with rpr.inside_reaper():
                # with self.target.make_current_project():
                for t_dict in targets.values():
                    target = t_dict['target']
                    recarm = t_dict['recarm']
                    target.recarm = recarm
Exemplo n.º 3
0
 def read(self, event: str, values: ValuesType) -> ty.Optional[Exception]:
     if not event.startswith(self.key_ns):
         return None
     if event != self.key_ns + 'make_loop':
         return None
     assert isinstance(values, ty.Dict)
     with rpr.inside_reaper():
         rpr.Project().begin_undo_block()
         try:
             ih = ItemsHandler(sr=values[self.key_ns +
                                         'samplerate']  # type:ignore
                               )
             lf = LoopFinder(ih)
             st_ofst, end_ofst = lf.get_loop(
                 corr_wind_sec=values[self.key_ns +
                                      'corr_wind'],  # type:ignore
                 slide_wind_sec=values[self.key_ns +
                                       'slide_wind'],  # type:ignore
                 corr_treshold=values[self.key_ns +
                                      'corr_max_treshold'],  # type:ignore
                 corr_min_treshold=values[self.key_ns +  # type:ignore
                                          'corr_min_treshold'],
             )
         except (ItemsError, LoopError) as e:
             return e
         ls = LoopSlicer(ih, lf)
         ls.cut_and_fade(
             st_ofst,
             end_ofst,
             crs_length=values[self.key_ns + 'cross_length'],  # type:ignore
             crs_shape=self.cross_shapes[values[
                 self.key_ns + 'cross_shape']  # type:ignore
                                         ])
         rpr.Project().end_undo_block('make loop')
     return None
Exemplo n.º 4
0
    def get_all_regions(
            self) -> ty.List[ty.Tuple[rpr.Region, ty.Dict[str, object]]]:
        """Get all regions with articulation metadata.

        Returns
        -------
        List[Tuple[reapy.Region, Dict[str, object]]]
        """
        retvals: ty.List[ty.Tuple[rpr.Region, ty.Dict[str, object]]] = []
        with rpr.inside_reaper():
            regions, keys = self._all_regions_with_keys()
            metadatas = pickle.loads(rpr.Project().map(
                'get_ext_state', {
                    'key': keys
                },
                defaults={
                    'section': GUI_SECTION,
                    'pickled': True
                },
                pickled_out=True).encode('latin-1'))
            for reg, metadata in zip(regions, metadatas):
                if metadata:
                    retvals.append((reg, metadata))
        pprint(retvals)
        return retvals
Exemplo n.º 5
0
def get_host_midi_ports(
    host: ty.Optional[str] = None
) -> ty.Tuple[ty.List[_RMidiPort], ty.List[_RMidiPort]]:
    """Get all MIDI devices of the particular host.

    Parameters
    ----------
    host : ty.Optional[str], optional
        'localhost' or IPV4 address

    No Longer Returned
    ------------------
    jack_in_ports: _JMidiPort
    jack_out_ports _JMidiPort

    """
    if host == 'localhost':
        host = None

    ins, outs = [], []
    with rpr.connect(host):
        with rpr.inside_reaper():
            for i, port in enumerate(rpr.midi.get_input_names()):
                ins.append(_RMidiPort(idx=i, name=port))
            for i, port in enumerate(rpr.midi.get_output_names()):
                outs.append(_RMidiPort(idx=i, name=port))
    return ins, outs
Exemplo n.º 6
0
def get_host_jack_ports(
    host: ty.Optional[str] = None
) -> ty.Tuple[ty.List[_JMidiPort], ty.List[_JMidiPort]]:
    """Return all Jack midi ports of Reaper on the specified host.

    Note
    ----
    reascript 'Levitanus: (session_management) get_system_jack_ports'
    has to be registered in action editor.

    Parameters
    ----------
    host : ty.Optional[str], optional
        'localhost' or IPV4 address

    No Longer Returned
    ------------------
    jack_in_ports: _JMidiPort
    jack_out_ports _JMidiPort

    """
    if host == 'localhost':
        host = None
    with rpr.connect(host):
        with rpr.inside_reaper():
            a_id: int = RPR.NamedCommandLookup(
                '_RSc3a0868bee74abaf333ac661af9a4a27257c37c1')
            rpr.perform_action(a_id)
            ports = prs.loads('slave_ports')
            # print(ports)
            return ports
Exemplo n.º 7
0
    def in_measure(self, measure):
        """
        Returns a list of Note contained in the specified measure.

        Parameters
        ----------
        measure : int

        Returns
        -------
        notes : List[Note]
            Notes in the measure.
        """
        notes = []
        with reapy.inside_reaper():
            measure = int(measure)
            for n in self:
                n_measure = n.measure
                if n_measure < measure:
                    continue
                elif n_measure == measure:
                    notes.insert(0,n)
                else:
                    break
        return notes
Exemplo n.º 8
0
    def _from_name(name):
        """Return project with corresponding name.

        Parameters
        ----------
        name : str
            Project file name. Including the extension ('.rpp')
            is optional.

        Returns
        -------
        Project

        Raises
        ------
        NameError
            If no project with the corresponding name is open.
        """
        if not name.lower().endswith('.rpp'):
            name += '.rpp'
        with reapy.inside_reaper():
            for project in reapy.get_projects():
                project_name = project.name[:-4] + '.rpp'
                if project_name == name:
                    return project
        raise NameError('"{}" is not currently open.'.format(name))
    def load_audio(self, reaper_vol: bool = True) -> ty.Iterable[float]:
        """Get np.array of Item audiodata in mono.

        Parameters
        ----------
        reaper_vol : bool, optional
            Default to True
            Sohuld audio be normalized to the Reaper item*take level or not

        Returns
        -------
        ty.Iterable[float]

        """
        with rpr.inside_reaper():
            source = self.source
            filename = source.filename
            sr = self.sr
            offset, duration = self._get_item_bounds()
        loaded = lr.load(
            filename,
            sr=sr,
            mono=True,
            offset=offset,
            duration=duration,
        )[0]
        if reaper_vol:
            loaded *= self.vol
        return loaded  # type:ignore
Exemplo n.º 10
0
def glue_all_items_on_track(project: R_project, track: R_track) -> None:
    with reapy.inside_reaper():
        for i, item in enumerate(track.items):
            #make unique selection if it's the first item in the loop
            make_unique = i == 0
            project.select_item(item, makeUnique=make_unique)
        #glue items
        project.perform_action(41588)
Exemplo n.º 11
0
    def visible_fx(self):
        """
        Visible FX in FX chain if any, else None.

        :type: FX or NoneType
        """
        with reapy.inside_reaper():
            return self.fxs[RPR.TrackFX_GetChainVisible(self.id)]
Exemplo n.º 12
0
 def __enter__(self) -> Track:
     pr = self.track.s_project
     self.connect = rpr.connect(pr.last_ip)
     self.connect.__enter__()
     self.ir = rpr.inside_reaper()
     self.ir.__enter__()
     self.curr_proj = pr.make_current_project()
     self.curr_proj.__enter__()
     return self.track
Exemplo n.º 13
0
    def cut_and_fade(
        self,
        st_ofst: float,
        end_ofst: float,
        crs_length: float = .1,
        crs_shape: int = 0,
    ) -> rpr.Region:
        """Cut and fade items to make loop.

        Note
        ----
        units in seconds

        Parameters
        ----------
        st_ofst : float
            Start offset from time selection
        end_ofst : float
            End offset from time selection
        crs_length : float, optional
            Crossfade length

        Returns
        -------
        reapy.Region
            loop region
        """
        with rpr.inside_reaper():
            self._pr.begin_undo_block()
            region_ofst = 0.1
            start, duration = self._handler.item_handlers[
                0].get_item_bounds_within_ts()

            main_part, tail = self._handler.split(start + duration - end_ofst)
            tail.position += end_ofst + region_ofst
            tail.start_offset += end_ofst
            tail.length -= end_ofst + region_ofst

            end_part = main_part.make_copy(main_part.position)
            del_part, end_part = end_part.split(start + st_ofst)
            del_part.delete()

            end_part.position += duration - st_ofst - end_ofst
            end_part.length = crs_length + region_ofst

            main_part.length += crs_length
            reg = self._pr.add_region(start + st_ofst + end_part.length,
                                      end_part.position + end_part.length,
                                      color=0xff0000,
                                      name='#')
            self._pr.loop_points = (start + st_ofst + end_part.length,
                                    end_part.position + end_part.length)
            main_part.fade_out(crs_length, crs_shape)
            end_part.fade_in(crs_length, crs_shape)
            self._pr.end_undo_block('cut and fade loop')
        return reg
Exemplo n.º 14
0
 def __setitem__(self, i, value):
     with reapy.inside_reaper():
         if isinstance(i, str):
             i = self._get_param_index(i)
         n_params = len(self)
         if i >= n_params:
             raise IndexError("{} has only {} params".format(
                 self.parent_fx, n_params))
         i = i % n_params  # Allows for negative values
     self.functions["SetParam"](self.parent_id, self.fx_index, i, value)
Exemplo n.º 15
0
 def __getitem__(self, i):
     with reapy.inside_reaper():
         if isinstance(i, str):
             i = self._get_fx_index(name=i)
         n_fxs = self.parent.n_fxs
     if i >= n_fxs:
         raise IndexError("{} has only {} fxs".format(self.parent, n_fxs))
     i = i % n_fxs  # Allows for negative values
     fx = FX(self.parent, i)
     return fx
Exemplo n.º 16
0
def combine_items_from_track_group(group_name: str,
                                   tracks: R_tracks) -> R_tracks:
    unused_tracks = []
    with reapy.inside_reaper():
        if len(tracks):
            main_track = tracks.pop()
            main_track.name = group_name
            for t in tracks:
                t.items[0].track = main_track
                unused_tracks.append(t)
    return unused_tracks
Exemplo n.º 17
0
 def erase_metadata(self) -> None:
     with rpr.inside_reaper():
         regions, keys = self._all_regions_with_keys()
         keys = list(keys)
         pprint(('erasing metadata for keys:', keys))
         rpr.Project().map('set_ext_state', {'key': keys},
                           defaults={
                               'section': GUI_SECTION,
                               'pickled': False,
                               'value': '',
                           })
Exemplo n.º 18
0
def get_nested_tracks(project: R_project, track: R_track) -> R_tracks:
    with reapy.inside_reaper():
        child_tracks = []
        n_track_left = project.n_tracks - track.index
        last_track_id = n_track_left + track.index
        new_track_id = track.index

        for track_id in range(last_track_id, new_track_id + 1, -1):
            track = project.tracks[track_id - 1]
            if new_track_id == track.parent_track.index:
                child_tracks.insert(0, track)
    return child_tracks
Exemplo n.º 19
0
    def cut_and_fade_deprecated(self,
                                st_ofst: float,
                                end_ofst: float,
                                crs_length: float = .1) -> rpr.Region:
        """Cut and fade items to make loop.

        Note
        ----
        units in seconds

        Parameters
        ----------
        st_ofst : float
            Start offset from time selection
        end_ofst : float
            End offset from time selection
        crs_length : float, optional
            Crossfade length

        Returns
        -------
        reapy.Region
            loop region
        """
        with rpr.inside_reaper():
            self._pr.begin_undo_block()
            region_ofst = 0.1
            start, duration = self._handler.item_handlers[
                0].get_item_bounds_within_ts()
            itms_hdlr_l, itms_hdlr_r = self._handler.split(start + st_ofst)
            _, del_part = itms_hdlr_r.split(start + duration - end_ofst)
            del_part.delete()
            itms_hdlr_end = itms_hdlr_r.make_copy(
                itms_hdlr_r.position + itms_hdlr_r.length,
                length=crs_length + region_ofst)
            itms_hdlr_r.length += crs_length
            reg = self._pr.add_region(
                itms_hdlr_r.position + itms_hdlr_end.length,
                itms_hdlr_end.position + itms_hdlr_end.length,
                color=0xff0000,
                name='#')
            self._pr.loop_points = (itms_hdlr_r.position +
                                    itms_hdlr_end.length,
                                    itms_hdlr_end.position +
                                    itms_hdlr_end.length)
            itms_hdlr_r.fade_out(crs_length)
            itms_hdlr_end.fade_in(crs_length)
            self._pr.end_undo_block('cut and fade loop')
        return reg
def make_region_from_selected_items_or_ts(
        name: str,
        tracks_in_matrix: ty.Optional[ty.List[rpr.Track]] = None
) -> rpr.Region:
    with rpr.inside_reaper():
        pr = rpr.Project()
        ts = pr.time_selection
        # if no time selection
        start, end = (ts.start, ts.end)
        if (start, end) == (0, 0):
            start, end = ItemsHandler().get_bounds(check_for_indentity=False)
        region = pr.add_region(start, end, name=name)
        if tracks_in_matrix:
            region.add_rendered_tracks(tracks_in_matrix)
    return region
Exemplo n.º 21
0
def update_list(layout: GridLayout, itemlist: ty.List[Item]):
    layout.clear_widgets()
    try:
        rpr.Project()
    except (rpr.errors.DisabledDistAPIError, AttributeError):
        print('cannot connect')
        return
    with rpr.inside_reaper():
        for item in itemlist:
            btn = Button(
                text=item.name, size_hint_y=None, height=Window.height / 10
            )
            btn.bind(
                on_press=lambda instance, time=item.time:
                on_track(time, instance)
            )
            layout.add_widget(btn)
Exemplo n.º 22
0
def get_track_by_CC_pitch(pitch_list: List[int], tracks: R_tracks) -> R_tracks:
    with reapy.inside_reaper():
        pitch_tracks = []
        #loop tracks
        for t in tracks:
            #skip if there's no item on the track
            if not len(t.items):
                continue
            CC_notes = t.items[0].takes[0].notes
            #skip if there's no note on the track
            if not len(CC_notes):
                continue
            #get pitch of the first note
            CC_note = t.items[0].takes[0].notes[0].pitch
            if CC_note in pitch_list:
                pitch_tracks.append(t)

    return pitch_tracks
Exemplo n.º 23
0
    def buses_unpacked(self) -> bool:
        """Whether MIDI BUSes are unpacked from one channel or not.

        Note
        ----
        currently it's made by the custom JSFX

        Returns
        -------
        bool
        """
        with rpr.inside_reaper():
            fxlist = self.fxs
            try:
                fx = fxlist[self._BUS_FX_NAME]
                par = fx.params[self._BUS_PAR_IDX]
            except KeyError:
                return False
            return par == 1
        return False
    def load_audio(self,
                   mono: bool = True,
                   reaper_vol: bool = True) -> ty.List[ty.Iterable[float]]:
        """Load audio of items to the np.array.

        Parameters
        ----------
        mono : bool, optional
            Default to True
        reaper_vol : bool, optional
            Default to True
            Sohuld audio be normalized to the Reaper item*take level or not

        Returns
        -------
        ty.Iterable[ty.Iterable[float]]

        Raises
        ------
        ItemsError
            If items are not identical
        """
        if mono and self._audio_mono is not None:
            return self._audio_mono
        if not mono and self._audios is not None:
            return self._audios
        with rpr.inside_reaper():
            items_handler = self
            if not self.are_bounds_identical:
                items_handler = self.get_longest_items_on_each_track()
                if not items_handler.are_bounds_identical:
                    raise ItemsError('bounds of items are not identical')
            audios: ty.List[ty.Iterable[float]] = []
            for ih in items_handler.item_handlers:
                y = ih.load_audio(reaper_vol=reaper_vol)
                audios.append(y)
        if mono:
            self._audio_mono = [np.sum(audios, 0)]
            return self._audio_mono
        self._audios = np.column_stack(audios)
        return self._audios  # type:ignore
Exemplo n.º 25
0
    def get_module_status(self):
        if not self.is_connected:
            return DISCONNECTED

        with reapy.inside_reaper():
            project = reapy.Project()
            if project.name == '':
                return CONNECTED

            channels = []
            # levels = []
            for i in range(RAW_TRACK_COUNT):
                command = ACTION_TOGGLE_CHANNEL_1 + (FIRST_RAW_TRACK +
                                                     i) * COMMANDS_PER_CHANNEL
                channels.append(
                    reapy.reascript_api.GetToggleCommandState(command))

                # track_id = project.tracks[i + FIRST_RAW_TRACK].id
                # levels.append(reapy.reascript_api.Track_GetPeakHoldDB(track_id, 0, False))
                # reapy.reascript_api.Track_GetPeakHoldDB(track_id, 0, True)

            metronome = reapy.reascript_api.GetToggleCommandState(40364)

            state = 'ready'
            position = 0
            if project.is_recording:
                state = 'recording'
                position = project.play_position - project.cursor_position
            elif project.is_playing:
                state = 'playing'
                position = project.play_position - project.time_selection.start

        return {
            'position': position,
            'state': state,
            'channels': channels,
            # 'levels': levels,
            'metronome': metronome
        }
Exemplo n.º 26
0
def detect_onsets(
    items_handler: ItemsHandler,
    pre_max: float,
    wait: float,
    fmin: ty.Optional[int] = None,
    pre_avg: ty.Optional[float] = None,
    post_max: ty.Optional[float] = None,
    post_avg: ty.Optional[float] = None,
    delta: float = 1.0,
    onset_markers: str = '',
    backtrack_markers: str = '',
    units: LengthUnit = LengthUnit.ms,
) -> ty.Tuple[ty.List[float], ty.List[float], ty.List[float]]:
    """Detect onsets and place markers if needed.

    Parameters
    ----------
    items_handler : ItemsHandler
    pre_max : float
        time to seek peacks before onset
    wait : float
        time to skip after detected onset
    fmin : ty.Optional[int], optional
        minimum frequency if filtering is needed
    pre_avg : ty.Optional[float], optional
        time to seek mean before offset (if None — pre_max is used)
    post_max : ty.Optional[float], optional
        time so seek peak after offset (if None — wait or post_avg are used)
    post_avg : ty.Optional[float], optional
        time to seek mean after onset (if None — wait of post_max are used)
    delta : float, optional
        threshold offset for mean (ambiguos parameter)
    onset_markers : str, optional
        If not null string — markers with the same name will be placed
    backtrack_markers : str, optional
        If not null string — markers with the same name will be placed
    units : LengthUnit, optional
        length units for onsets and backtrack return (ms are default)

    Returns
    -------
    Tuple[List[float], List[float], List[float]]
        onsets, backtracks, onset_envelope(in frames)
    """
    with rpr.inside_reaper():
        audio = items_handler.load_audio()[0]
        sr = items_handler.sr
        if fmin:
            Spc = lr.feature.mfcc(audio, sr, fmin=fmin)
            onset_envelope = lr.onset.onset_strength(sr, S=Spc)
        else:
            onset_envelope = lr.onset.onset_strength(audio, sr)
        if post_avg is None and post_max is None:
            post_max, post_avg = wait, wait
        if post_avg is None:
            post_avg = post_max
        if post_max is None:
            post_max = post_avg
        if pre_avg is None:
            pre_avg = pre_max
        (pre_max, wait, pre_avg, post_max, post_avg) = lr.time_to_frames(
            (pre_max, wait, pre_avg, post_max, post_avg), sr)
        onsets = lr.util.peak_pick(
            onset_envelope,
            pre_max,
            post_max,
            pre_avg,
            post_avg,
            delta,
            wait,
        )
        backtrack = lr.onset.onset_backtrack(onsets, onset_envelope)
        if backtrack_markers:
            for bck in lr.frames_to_time(backtrack, sr=sr):
                pos = items_handler.get_bounds(count_ts=True)[0] + bck
                rpr.Project().add_marker(pos, name=backtrack_markers)
        if onset_markers:
            for onst in lr.frames_to_time(onsets, sr=sr):
                pos = items_handler.get_bounds(count_ts=True)[0] + onst
                rpr.Project().add_marker(pos, name=onset_markers)
        if units == LengthUnit.ms:
            onsets, backtrack = (lr.frames_to_time(onsets, sr),
                                 lr.frames_to_time(backtrack, sr))
        if units == LengthUnit.samples:
            onsets, backtrack = (lr.frames_to_samples(onsets, sr),
                                 lr.frames_to_samples(backtrack, sr))
    return onsets, backtrack, onset_envelope
Exemplo n.º 27
0
 def __enter__(self) -> Host:
     self._connect = rpr.connect(self.ip)
     self._connect.__enter__()
     self._ir = rpr.inside_reaper()
     self._ir.__enter__()
     return self
Exemplo n.º 28
0
 def midi_note_names(self):
     with reapy.inside_reaper():
         names = [
             RPR.GetTrackMIDINoteName(self.id, i, 0) for i in range(128)
         ]
     return names
Exemplo n.º 29
0
 def __getitem__(self, key):
     with reapy.inside_reaper():
         if key >= len(self):
             raise IndexError
         return self._elements_class(self.parent, key)
Exemplo n.º 30
0
        print(hostname, 'is up!')
    else:
        print(hostname, 'is down!')


if __name__ == '__main__':
    is_connected('8.8.8.8')
    is_connected('ya.ru')
    Config.adddefaultsection(SECTION)
    Config.setdefault(SECTION, 'IP', "192.168.0.1")
    grid = GridLayout(cols=1, spacing=20)

    conn_text = TextInput(text=Config.get(SECTION, 'IP'))
    try:
        conn = rpr.connect(conn_text.text)
        with rpr.inside_reaper():
            print(f'connected to {conn_text.text}')
    except (rpr.errors.DisabledDistAPIError, AttributeError):
        print('cannot connect to "{}"'.format(conn_text.text))
    itemlist = get_items_list()
    print(*(item.name for item in itemlist), sep=' | ')
    scroll, layout = get_layouts()
    update_list(layout, itemlist)

    connection_grid = GridLayout(cols=2, spacing=10, size_hint_y=.5)
    upd_btn = Button(text='update')
    upd_btn.bind(on_press=lambda instance: update(layout, conn_text, instance))
    connection_grid.add_widget(conn_text)
    connection_grid.add_widget(upd_btn)
    grid.add_widget(connection_grid)