[Top][All Lists]

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

Re: [Denemo-devel] Transpose

From: Richard Shann
Subject: Re: [Denemo-devel] Transpose
Date: Tue, 12 Aug 2008 10:24:46 +0100

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
   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
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

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.

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);

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 ... */

    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.
here put_action_in_store(action, name).

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.

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

reply via email to

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