コード例 #1
0
    def exec(self, symbols_scope: SymbolsScope, context: Context, *args,
             **kargs):
        forked = context.fork(symbols=symbols_scope.fork())

        forked.symbols.assign('__callerctx__', context, local=True)

        for variable_name in self.using:
            forked.symbols.using(variable_name)

        for i in range(len(self.arguments)):
            (name, arg_mod, default_value) = self.arguments[i]

            argument_node, default_node = None, default_value

            if len(args) > i:
                argument_node = args[i]
            elif name in kargs:
                argument_node = kargs[name]
            elif default_value == None:
                raise Exception(f"Mandatory argument { name } was not given.")

            if arg_mod == 'expr':
                forked.symbols.assign(name, argument_node)
            elif (arg_mod == 'ref'
                  or arg_mod == 'in') and argument_node is not None:
                is_variable = isinstance(argument_node, VariableExpressionNode)

                if arg_mod == 'ref' and not is_variable:
                    raise BaseException(
                        f"Only variable references can be passed to a function (function { self.name }, parameter { name })"
                    )

                # TODO: Should ref pointers be shallow? Since ref can mutate
                # the value, it could be sensible for them to be so
                if is_variable:
                    pointer = context.symbols.pointer(argument_node.name)

                    if pointer is None:
                        context.symbols.assign(argument_node.name, None)
                    else:
                        forked.symbols.using(pointer, name)
                else:
                    forked.symbols.assign(
                        name,
                        Value.assignment(argument_node.eval(context.fork())))
            else:
                if argument_node is not None:
                    value = Value.assignment(argument_node.eval(
                        context.fork()))
                else:
                    value = Value.assignment(default_node.eval(forked.fork()))

                value = forked.symbols.assign(name, value)

        return self.body.eval(forked)
コード例 #2
0
    def values(self, context: Context):
        condition_value = self.condition.eval(context)

        while condition_value:
            forked = context.fork(symbols=context.symbols.fork(opaque=False))

            yield self.body.eval(forked)

            context.join(forked)

            condition_value = self.condition.eval(context)
コード例 #3
0
    def __eval__(self, context: Context):
        forked = context.fork(symbols=context.symbols.fork(
            opaque=False)) if self.fork_context else context

        try:
            if self.create_stack_frame:
                return self.body.eval(forked)
            else:
                return self.body.child.eval(forked)
        finally:
            context.join(forked)
コード例 #4
0
    def __eval__(self, context: Context, assignment: bool = False):
        if self.expression is None:
            return None

        forked = context.fork()

        value = self.expression.eval(forked)

        if isinstance(value, Music):
            return Music(self.get_events(context, forked, value))
        else:
            context.join(forked)

            return value
コード例 #5
0
    def modify(self, context: Context):
        if self.upper != None or self.lower != None:
            context.voice = context.voice.clone(time_signature=(self.upper,
                                                                self.lower))
        elif self.upper != None:
            context.voice = context.voice.clone(
                time_signature=(self.upper, context.time_signature[1]))
        elif self.lower != None:
            context.voice = context.voice.clone(
                time_signature=(context.time_signature[0], self.lower))

        yield ContextChangeEvent(context.cursor, "timeSignature",
                                 context.voice.time_signature, context.voice,
                                 0)
コード例 #6
0
def function_to_mkl(context: Context,
                    music: Music,
                    ast: bool = False,
                    nameless_voices: bool = True,
                    declare_voices: bool = True,
                    base_voice: Voice = None) -> Union[str, Node]:
    source: Box[str] = Box("")

    inp, out = Transformer.pipeline2(
        VoiceIdentifierTransformer(),
        MusiklaNotationBuilderTransformer(only_final=True,
                                          ast=ast,
                                          context=context,
                                          nameless_voices=nameless_voices,
                                          declare_voices=declare_voices,
                                          base_voice=base_voice),
    )

    out.subscribe(lambda s: source.set(s))

    for ev in music.expand(context.fork(cursor=0)):
        inp.add_input(ev)

    inp.end_input()

    return source.value
コード例 #7
0
def function_save(context: Context, music: Music,
                  outputs: Union[str, Sequencer, List[SequencerLike]]) -> Any:
    # The single parameter specifies if only one sequencer was given
    # In that case, instead of returning an array, we return just the sequencer
    single: bool = False

    if type(outputs) is str or isinstance(outputs, Sequencer):
        sequencers: List[Sequencer] = [
            function_make_sequencer(context, outputs)
        ]

        single = True
    else:
        sequencers: List[Sequencer] = [
            function_make_sequencer(context, seq) for seq in outputs
        ]

    for seq in sequencers:
        seq.realtime = False

        seq.start()

    for ev in music.expand(context.fork(cursor=0)):
        for seq in sequencers:
            seq.register_event(ev)

    for seq in sequencers:
        seq.close()

    if single:
        return sequencers[0]

    return sequencers
コード例 #8
0
    def modify(self, context: Context):
        context.voice = context.voice.clone(
            instrument=Instrument.from_program(self.instrument))

        yield ContextChangeEvent(context.cursor, "instrument",
                                 context.voice.instrument.program,
                                 context.voice, 0)
コード例 #9
0
def function_make_sequencer(context: Context,
                            sequencer: SequencerLike) -> Sequencer:
    std = cast(StandardLibrary, context.library(StandardLibrary))

    format = None
    uri = None
    args = None

    if type(sequencer) is str:
        uri = sequencer
    elif type(sequencer) is list:
        args_start = 0

        if len(sequencer) >= args_start + 2 and sequencer[args_start] == '-o':
            uri = sequencer[args_start + 1]
            args_start += 2

        if len(sequencer) >= args_start + 2 and sequencer[args_start] == '-f':
            format = sequencer[args_start + 1]
            args_start += 2

        args = sequencer[args_start:]
    elif isinstance(sequencer, Sequencer):
        return sequencer

    if format is not None:
        return std.player.make_sequencer_from_format(format, uri or "", args
                                                     or [])

    return std.player.make_sequencer_from_uri(uri or "", args or [])
コード例 #10
0
    def __init__(self,
                 only_final: bool = False,
                 ast: bool = False,
                 context: Context = None,
                 nameless_voices: bool = True,
                 declare_voices: bool = True,
                 base_voice: Voice = None):
        """
        only_final          When true, the result is only emitted after the entire 
                            input (musical sequence) has been processed. When false,
                            intermediate notations are continuously emitted.
        
        ast                 When true, emits the Abstract Syntax Tree objects. When
                            false, transforms those objects into a string that can
                            be parsed, and emits the string instead

        nameless_voices     When true, it tries to produce notation that carries with
                            it any state that is needed, instead of prepending 
                            the names of the voices the events belonged to
        
        declare_voices      When `nameless_voices = False`, also include the 
                            definitions of the named voices used.
        
        base_voice          ...
        """
        super().__init__(only_final)

        self.ast: bool = ast
        self.context: Context = context or Context.create()
        self.nameless_voices: bool = nameless_voices
        self.declare_voices: bool = declare_voices
        self.base_voice: Voice = base_voice or Voice()
コード例 #11
0
def keyboard_close ( context : Context, keyboard : Keyboard ):
    if keyboard != None:
        keyboard.close()
    else:
        lib : KeyboardLibrary = cast( KeyboardLibrary, context.library( KeyboardLibrary ) )

        lib.close()
コード例 #12
0
def function_voices_create(context: Context,
                           name: str,
                           modifiers: Node = None,
                           inherit: Voice = None):
    if inherit != None:
        pass

    voice = Voice(name, Instrument(name, 1))
    forked = context.fork()
    forked.voice = voice

    if inherit != None:
        voice.instrument = inherit.instrument
        voice.time_signature = inherit.time_signature
        voice.velocity = inherit.velocity
        voice.octave = inherit.octave
        voice.value = inherit.value
        voice.tempo = inherit.tempo

    if modifiers != None:
        if isinstance(modifiers, MusicSequenceNode):
            for modifier in modifiers:
                if isinstance(modifier, ContextModifierNode):
                    modifier.apply(voice)
                else:
                    modifier.eval(forked)
        else:
            if isinstance(modifiers, ContextModifierNode):
                modifiers.apply(voice)
            else:
                modifiers.eval(forked)

    return voice
コード例 #13
0
    def create_context ( self, player : Player ):
        ctx = Context.create()

        ctx.link( StandardLibrary() )
        ctx.link( MusicLibrary() )
        ctx.link( KeyboardLibrary( player ) )

        return ctx
コード例 #14
0
def function_discard(context: Context, *expr):
    for e in expr:
        value = e.eval(context.fork())

        if isinstance(value, Music):
            for _ in value:
                pass

    return None
コード例 #15
0
def function_debug(context: Context, expr):
    value = expr.eval(context.fork())

    if value is None:
        print(None)
    elif isinstance(value, Music):
        print('<Music> ' +
              ' '.join(str(event) for event in value.expand(context)))
    else:
        print("<%s>%s" % (Value.typeof(value), value))
コード例 #16
0
def function_readmidi(context: Context,
                      file: str = None,
                      port: Union[str, List[str], bool] = None,
                      voices: List[Voice] = None,
                      cutoff_sequence=None,
                      ignore_message_types: List[str] = None):
    if file is not None:
        mid = mido.MidiFile(file)

        return read_midi_file(context, mid, voices, cutoff_sequence,
                              ignore_message_types)
    else:
        if port == True:
            default_port = context.library(
                MidiLibrary).get_midi_default_input()

            if default_port is None:
                port = mido.open_input()
            else:
                port = mido.open_input(default_port)
        elif type(port) == str:
            port = mido.open_input(port)
        elif type(port) == list:
            port = MultiPort([mido.open_input(p) for p in port])

        events = midi_stream_to_music(context, port, context.voice,
                                      ignore_message_types)

        events = ComposeNotesTransformer.iter(events)

        if cutoff_sequence != None:
            events = TerminationMelodyTransformer.iter(
                events, list(cutoff_sequence.expand(context.fork(cursor=0))))

        events = TeeTransformer.iter(
            events,
            Transformer.pipeline(
                VoiceIdentifierTransformer(),
                MusiklaNotationBuilderTransformer(),
                Transformer.subscriber(lambda n: print(n + '\n\n'))))

        return Music(list(events))
コード例 #17
0
    def __init__(self, event: Union[Music, NoteEvent, Note, None]):
        super().__init__()

        if isinstance(event, Music):
            event = event.first_note(Context())

        if isinstance(event, NoteEvent):
            event = event.note

        if event is None:
            raise Exception("Cannot create PianoKey of None")

        self.note: Note = event.timeless()
コード例 #18
0
def keyboard_filedialog ( context : Context, title : str = "File", text : str = "File Path:", default_value : str = None, cb = None ):
    from prompt_toolkit.patch_stdout import patch_stdout
    from prompt_toolkit.shortcuts import input_dialog
    from prompt_toolkit.completion import PathCompleter

    lib : KeyboardLibrary = cast( KeyboardLibrary, context.library( KeyboardLibrary ) )

    def _run ():
        with patch_stdout():
            application = input_dialog( title = title, text = text, completer = PathCompleter() )

            with application.input.raw_mode():
                application.input.read_keys()

            application.layout.current_control.buffer.insert_text(default_value or "")
            
            return application.run_async()

    lib.prompt( _run, cb )
コード例 #19
0
    def __eval__(self, context: Context):
        val = Value.assignment(self.right.eval(context.fork(cursor=0)))

        if self.operator is None or self.operator == "":
            self.left.assign(context, val, local=self.local)
        else:

            def _set(value):
                nonlocal val

                # value = context.symbols.lookup( self.name, recursive = not self.local )
                if self.operator == '*': value *= val
                elif self.operator == '/': value /= val
                elif self.operator == '+': value += val
                elif self.operator == '-': value -= val
                elif self.operator == '&': value &= val
                elif self.operator == '|': value |= val
                else: raise Exception("Invalid operator: " + self.operator)

                return value

            self.left.lookup_assign(context, _set, local=self.local)

        return None
コード例 #20
0
    def __eval__(self, context: Context):
        val = Value.assignment(self.right.eval(context.fork(cursor=0)))

        for i, op in enumerate(self.left):
            if self.operator is None or self.operator == "":
                op.assign(context, val[i], local=self.local)
            else:

                def _set(value):
                    nonlocal val

                    if self.operator == '*': value *= val[i]
                    elif self.operator == '/': value /= val[i]
                    elif self.operator == '+': value += val[i]
                    elif self.operator == '-': value -= val[i]
                    elif self.operator == '&': value &= val[i]
                    elif self.operator == '|': value |= val[i]
                    else: raise Exception("Invalid operator: " + self.operator)

                    return value

                op.lookup_assign(context, _set, local=self.local)

        return None
コード例 #21
0
def function_set_midi_input_name(context: Context, name: str):
    context.library(MidiLibrary).set_midi_default_input(name)
コード例 #22
0
def keyboard_readperf ( context : Context, file : str, keyboards : List[Keyboard] = None ) -> Music:
    lib : KeyboardLibrary = cast( KeyboardLibrary, context.library( KeyboardLibrary ) )

    return lib.readperf( context, file, keyboards )
コード例 #23
0
def function_get_midi_input_name(context: Context) -> str:
    return context.library(MidiLibrary).get_midi_default_input()
コード例 #24
0
 def setUp(self):
     self.parser = parser
     self.context = Context.create()
     self.context.link(StandardLibrary(None))
コード例 #25
0
    def modify(self, context: Context):
        context.voice = context.voice.clone(value=self.length)

        yield ContextChangeEvent(context.cursor, "length", context.voice.value,
                                 context.voice, 0)
コード例 #26
0
    def modify ( self, context : Context ):
        context.voice = context.voice.clone( tempo = self.tempo )

        yield ContextChangeEvent( context.cursor, "tempo", context.voice.tempo, context.voice, 0 )
コード例 #27
0
def keyboard_open_repl ( context : Context ):
    lib : KeyboardLibrary = cast( KeyboardLibrary, context.library( KeyboardLibrary ) )

    lib.eval( context )

    return None
コード例 #28
0
def function_setvoice(context: Context, voice: Voice):
    context.voice = voice
コード例 #29
0
def function_settime(context: Context, time: int):
    context.cursor = time
コード例 #30
0
def keyboard_replay ( context : Context, file : str ):
    lib : KeyboardLibrary = cast( KeyboardLibrary, context.library( KeyboardLibrary ) )

    lib.replay( file )