denemo-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Scheme Interface (was Re: [Denemo-devel] Staff menu transpose)


From: Richard Shann
Subject: Scheme Interface (was Re: [Denemo-devel] Staff menu transpose)
Date: Mon, 22 Sep 2008 09:58:37 +0100

On Sun, 2008-09-21 at 23:49 -0500, Jeremiah Benham wrote:
> On Sat, 2008-09-20 at 15:39 +0100, Richard Shann wrote:
> > I notice there is alread a transpose menu item in the staff menu. I
> > guess this is the abortive attempt to do transposition directly in C
> > that Jeremiah started? If so, I guess it should be reverted as there is
> > no obvious way to get it working.
> 
> It actually works. 
Sorry - I meant the display. What it does is (I guess) the similar to
the DiatonicShift function I wrote (see under action/menus/...).
What *could* be done to create a transpose would be to create an
upgraded version of
the function
 SCM diatonic_shift (SCM optional)
in view.c
taking a more elaborate parameter (e.g. it could take two notes to
specify the interval to be transposed) and doing something more
elaborate than the simple
 gui->si->curmeasureaccs[offsettonumber(thenote->mid_c_offset+shift)]
which diatonic_shift() does. *However* I think there is a better way to
go (see below).
A complete version would also have to find and modify all the keysigs
AND would need to cope with chords. 
This last is not trivial, because Denemo does not have an entity
currentnote (the notes in a chord are not DenemoObjects, ultimately
because DenemoObjects are things spread horizontally along the stave).
I've done some thinking about this and I think it is best not to try to
introduce such a field - a si->currentnote - (even one to be used purely
from  scheme).
I think it would be better to write a transpose function in scheme:

(transpose note from-note to-note)

where note is the note to be transposed e.g. "cisis,," and from-note is
an arbitrary note (say "c") and to-note gives the desired transpostion
by giving the note that from-note should become (e.g. "bes," for down a
major second). The function returns a string - another note, that is -
in my example it would return "bis,,," (I think - it is a bit of an
extreme example!).
(we could insist on the first parameter always being "c" but that is not
so good, people don't think that way, they think "I want Bb to become
Eb", and LilyPond does not restrict the user in this respect. You can
write "\transpose c d" or "\transpose d e" and it means the same thing.)

If this were done we could iterate from chord to chord using the code as
in DiatonicShift, and to fetch the list of notes in the chord into
Scheme, transpose it and put it back. This would be an improvement over
how DiatonicShift is written, because I wrote the transformation of the
note in C, which is not the best, since that then gets compiled in and
can't be easily changed. So if we had the whole thing working in Scheme,
we could chuck out my C-routine and replace it with a simple
modification of the new Scheme transpose routine.

There is still one C function lacking before this can be actually got
working, namely the function to return the notes of the current chord. I
can write this very easily - I'll try and do it today. I would be really
glad if you could do the transpose function in Scheme.

> The display does not refresh though. If you save the
> file and reload it after transposition it loads up in the new key. 
> 
> I would like to rewrite it in scheme though as you suggested. Is is
> possible to enter edit mode in scheme?
Yes, I believe I wrote an extra bit of code so that you can do this and
preserve the correct setting of the check-box, HOWEVER, I have come to
the conclusion that it is not the way to go. There are a set of modeless
functions in Denemo, and using these you can do anything that can be
done in any mode but with the advantage that when the script is finished
the user's mode has not been upset. And, indeed the semantics of the
modal commands are more complex, and hence more difficult to program
against. For example, Edit mode either changes a note or inserts one
depending if you are in the appending position - it would be horrible to
have to test all this, and quite pointless: you know what you want to
do, and there is a function to do it regardless of the user's mode. (I
haven't written anything to store/restore the user's mode, which could
be done, but we would be going the wrong way).

>  Is there a list of scheme
> functions other then the actually menu itself?
Not yet. But I think I know what it will be like now.
First, for every command (i.e. the things listed in the right hand
column of the Command Management dialog, which are in fact the name
field of the GtkActions, and equivalently the names in denemoui.xml
following "<menuitem action=")
        for every command, as I say, there is a Scheme function
d-CommandName
which can take an optional parameter.
The parameter is omitted to get the same effect as pressing the menuitem
button, but can be set to a string to pass data to the C-routines.
The string passed in can be a series of C strings concatenated together.
That is (in Scheme notation) "midi_instrument=Piano\0number_of_lines=5"
would be valid input to the (d-StaffProperties) function.
I have not yet written code in all the dialog functions to respond to
being set from Scheme - in fact there is just a bit done in
d-StaffProperties to support some of the scripts I have been putting
into git. But this is just filling the dots.

You can get the names of the scheme functions for the menu item commands
by view->Show Scheme->Record Scheme, which appends each Scheme function
each time you press a menu item. In fact, someone with no knowledge of
scheme could write a script by setting recording going and clicking on
the things to be done and saving the result as a menu item. Basically -
we have a macro recording/playback facility, with persistent storage.

In addition to the complete set of menuitem commands there are some
access functions for the utilities. These are all collected together
near the top of view.c
  install_scm_function ("d-GetNoteName",  scheme_get_note_name);
  install_scm_function ("d-GetNote",  scheme_get_note);
  install_scm_function ("d-PutNoteName",  scheme_put_note_name);
  install_scm_function ("d-DiatonicShift", diatonic_shift);//deprecated
  install_scm_function ("d-NextObject", next_object);
  install_scm_function ("d-NextChord", next_chord);
  install_scm_function ("d-NextNote", next_note);//deprecated!!!! just
does next_chord
  install_scm_function3 ("d-getUserInput", scheme_get_user_input);
  install_scm_function ("d-GetChar", scheme_get_char);

The last one is the real killer - it lets a scheme script get a keypress
from the user. For example, guitar fingerings could be scripted to take
a two-key sequence Alt-f 1 for finger 1, Alt-f 2 for finger 2 etc.
Note that the d-getUserInput takes three parameters - it would perhaps
be better for it to take three C-strings packed in a Scheme string, to
make it uniform with everything else. Also, I notice I haven't finally
settled on whether all return values should be strings, or whether most
should return a boolean and those that are specifically doing a "get"
should return strings.
(By the way, the Scheme strings, with embedded NULLs map straight on to
GString type, which is nice).

Any constructive thoughts, from anyone, would be most welcome. I've been
thinking this all through on my own, and there are surely improvements
to be made.






reply via email to

[Prev in Thread] Current Thread [Next in Thread]