denemo-devel
[Top][All Lists]
Advanced

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

Re: [Denemo-devel] Transpose


From: Jeremiah Benham
Subject: Re: [Denemo-devel] Transpose
Date: Tue, 12 Aug 2008 10:01:18 -0500

On Tue, 2008-08-12 at 10:24 +0100, Richard Shann wrote:
> On Mon, 2008-08-11 at 22:52 -0500, Jeremiah Benham wrote:
> > There
> > will need to be a header file containing something like
> > denemointerface.h:
> > 
> > void Denemo_InsertBflatmaj();
> > void Denemo_StaffUp();
> > etc ..... 
> OK, that's great. Swig is already doing most of what I was trying to do
> for it. So, forget what I was saying (which would anyway only apply to a
> scripting interface that accessed Denemo in the way that gdb does),
> here is two ways how we might get Swig working.
> 
> First suggestion (a bit tedious, but very straight forward, and indeed
> improving the current Denemo code):
> Define all the menu callbacks in the code-generation (helper) program
> and use that to generate the interface. In detail:
> 
>       Move all the entries in the array 
> menu_entries[] in view.c 
> into the array in the helper program generate_source.c
> for example the entry
> 
>   {"New", GTK_STOCK_NEW, N_("New"), NULL,  N_("Start a new musical
> score"),
>    G_CALLBACK (file_newwrapper)},
> 
> in view.c
> would go into the generate_source.c file as
> struct name_and_function unmenued_commands[] = {
> ...
>   {KBD_CATEGORY_OTHER, GTK_STOCK_NEW, "Start a new musical score",
> N_("New"), "file_newwrapper"},
> 
> 
> (Note the name of this array "unmenued_commands" is purely historical,
> they are the ones that used to be unmenued, and everything is now
> menued).
> Once this is done, the array menu_entries in view.c would just contain
> the #include "entries.h" that it has at present and no other entries.
> 
> 
> Then we just tweak the printf() statements in this program to output the
> declarations needed (ie fp=fopen("denemointerface.i"), fprintf(fp,"%%
> module denemointerface\n%%{\n.....  \nextern int %s(void *parameter);
> \n", unmenued_commands[i].function) etc which would output
> 
> %module denemointerface
> %{
> extern int file_newwrapper(void *parameter);
> 
> Note 1, we can use the callbacks to take a parameter which can be tested
> to see if it is a GtkAction*, in which case it is being called from the
> menu, or not, in which case it is the scripting language that is calling
> it. We can also return a status int - at the moment they are declared as
> void - the menu callback will ignore the return value.
> 
> 
> Note 2, generate_source.c is a self contained program (ie with its own
> main() function) that is compiled and executed by hand to generate the
> source code: the names of the source code files are hardwired into it
> (namely it generates entries.h and callbacks.h). So after doing all the
> work described above to expand the array unmenued_commands[] so that it
> contains all the callbacks you compile generate_source.c at the command
> prompt thus:
> 
> gcc generate_source.c -o generate_source
> and then execute
> ./generate_source
> 
> and it will create the source files you need, entries.h and callbacks.h
> which are included in view.c and your new output file denemointerface.i
> Only after doing this do you call make. The generated files you would
> put into git. (so generate_source.c is like lylexer.l etc, except that
> the make system has not been told how to generate entries.h from
> generate_source.c, and I am doing it by hand).
> 
> Note 3, all the callbacks would cease to be static, becoming externally
> visible (so the scripting language can link to them).
> Note 4, it would be nice to have the callbacks return a value to
> indicate success and perhaps to take a parameter, so that the callbacks
> that throw up dialogs can tell if that is an appropriate thing to do.
> But this is extra refinements.
> 
> Note 4, The name KBD_CATEGORY is just historical as well, of course. At
> the moment they are not being used.

The above seems easily doable. 


> ***********************************************************************
> Second suggestion: (a bit tricksy, but avoiding a lot of grunt, and
> allowing for the scripting language to access menu items added
> dynamically after the program starts),
> 
> In view.c at the end where the GtkActions are being traversed put the
> action and name into a hash table. The scripting language has only one
> function to call, passing the name in. So the interface is
> 
> %module denemointerface
> %{
> external int denemo(char *name);
> %}

Would this (in the long run) allow users to add their scripts as menu
items by placing their scripts in a directory like ~/.denemo/plugins or
~/.denemo/scripts or something.


> and in Denemo's source code we include
> 
> int denemo(char *name){
> GtkAction* action = get_action_from_store(name);
> activate_action(action); /* this is in view.c */
> /* well, if we want to pass in a parameter and get back a value we would
> need to execute the callback function directly ... */
> }

The script writer would only receive an int on return correct. The
writer would not be able to get anything like a structure back in this
way. In either option we would need to allow them to see some values in
DenemoGUI *gui. We can get started and test things without it at first.
Without being able to read values from DenemoGUI *gui the script would
be running blind.  Maybe new functions would need to be created to do
things like:
int denemo_print_currentmeasurenum()
   
> NOTE 1:
>     get_action_from_store() would be a new function written to look up a
> GtkAction* in a store created at runtime, towards the end of newview()
> in view.c
>       
> NOTE 2: The place in view.c where you would create the store which
> get_action_from_store() would access is this bit at the end:
> 
>    GtkActionGroup *action_group;
>    GList *groups = gtk_ui_manager_get_action_groups (Denemo.ui_manager);
>    action_group = GTK_ACTION_GROUP(groups->data); 
>    GList *g = gtk_action_group_list_actions(action_group);
>    for(;g;g=g->next) {
> GtkAction *action = g->data;
> 
> put this action and a suitable name e.g.
> "Denemo_"gtk_action_get_name(g->data)
> here put_action_in_store(action, name).

I think I get this. I don't have experience with these functions though.

> This would be a lot less grunt, and we would get to try out the idea
> quickly. In principle we have a slower interface here, but I doubt if
> anyone would notice.

Which option would you prefer. I am sure I can do option #1 very easily
but I don't want ease to be a deciding factor. Which option do you think
is the best for denemo? Maybe later we can use both ideas. Statical list
of menu items and additional dynamically generated if available. 

Thanks,
Jeremiah


> If there is anything unclear (difficult to avoid) please say,
> Richard
> 
> 
> 





reply via email to

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