From 4b5220ce0a52c246af1a38b9613504ac89b186cc Mon Sep 17 00:00:00 2001
From: Philip Chimento <philip.chimento@gmail.com>
Date: Wed, 6 Jul 2011 22:39:14 +0200
Subject: [PATCH] Add new glk.h and dispatch code

---
 libchimara/gi_dispa.c |  49 ++++++++++++++++++-
 libchimara/gi_dispa.h |   2 +-
 libchimara/glk.h      | 111 ++++++++++++++++++++++++------------------
 3 files changed, 113 insertions(+), 49 deletions(-)

diff --git a/libchimara/gi_dispa.c b/libchimara/gi_dispa.c
index 4c4b553..f38eff0 100644
--- a/libchimara/gi_dispa.c
+++ b/libchimara/gi_dispa.c
@@ -1,4 +1,4 @@
-/* gi_dispa.c: Dispatch layer for Glk API, version 0.7.2.
+/* gi_dispa.c: Dispatch layer for Glk API, version 0.7.3.
     Designed by Andrew Plotkin <erkyrath@eblong.com>
     http://eblong.com/zarf/glk/
 
@@ -49,6 +49,7 @@ static gidispatch_intconst_t intconstant_table[] = {
     { "evtype_Redraw", (6) },
     { "evtype_SoundNotify", (7) },
     { "evtype_Timer", (1) },
+    { "evtype_VolumeNotify", (9) },
 
     { "filemode_Read", (0x02) },
     { "filemode_ReadWrite", (0x03) },
@@ -80,6 +81,7 @@ static gidispatch_intconst_t intconstant_table[] = {
     { "gestalt_LineTerminators", (18) },
     { "gestalt_MouseInput", (4) },
     { "gestalt_Sound", (8) },
+    { "gestalt_Sound2", (21) },
     { "gestalt_SoundMusic", (13) },
     { "gestalt_SoundNotify", (10) },
     { "gestalt_SoundVolume", (9) },
@@ -260,6 +262,13 @@ static gidispatch_function_t function_table[] = {
     { 0x00FA, glk_schannel_stop, "schannel_stop" },
     { 0x00FB, glk_schannel_set_volume, "schannel_set_volume" },
     { 0x00FC, glk_sound_load_hint, "sound_load_hint" },
+#ifdef GLK_MODULE_SOUND2
+    { 0x00F4, glk_schannel_create_ext, "schannel_create_ext" },
+    { 0x00F7, glk_schannel_play_multi, "schannel_play_multi" },
+    { 0x00FD, glk_schannel_set_volume_ext, "schannel_set_volume_ext" },
+    { 0x00FE, glk_schannel_pause, "schannel_pause" },
+    { 0x00FF, glk_schannel_unpause, "schannel_unpause" },
+#endif /* GLK_MODULE_SOUND2 */
 #endif /* GLK_MODULE_SOUND */
 #ifdef GLK_MODULE_HYPERLINKS
     { 0x0100, glk_set_hyperlink, "set_hyperlink" },
@@ -544,6 +553,19 @@ char *gidispatch_prototype(glui32 funcnum)
             return "2QdIu:";
         case 0x00FC: /* sound_load_hint */
             return "2IuIu:";
+
+#ifdef GLK_MODULE_SOUND2
+        case 0x00F4: /* schannel_create_ext */
+            return "3IuIu:Qd";
+        case 0x00F7: /* schannel_play_multi */
+            return "4>+#Qd>+#IuIu:Iu";
+        case 0x00FD: /* schannel_set_volume_ext */
+            return "4QdIuIuIu:";
+        case 0x00FE: /* schannel_pause */
+            return "1Qd:";
+        case 0x00FF: /* schannel_unpause */
+            return "1Qd:";
+#endif /* GLK_MODULE_SOUND2 */
 #endif /* GLK_MODULE_SOUND */
 
 #ifdef GLK_MODULE_HYPERLINKS
@@ -1081,6 +1103,31 @@ void gidispatch_call(glui32 funcnum, glui32 numargs, gluniversal_t *arglist)
         case 0x00FC: /* sound_load_hint */
             glk_sound_load_hint(arglist[0].uint, arglist[1].uint);
             break;
+
+#ifdef GLK_MODULE_SOUND2
+        case 0x00F4: /* schannel_create_ext */
+            arglist[3].opaqueref = glk_schannel_create_ext(arglist[0].uint, arglist[1].uint);
+            break;
+        case 0x00F7: /* schannel_play_multi */
+            if (arglist[0].ptrflag && arglist[3].ptrflag)
+                arglist[8].uint = glk_schannel_play_multi(arglist[1].array, arglist[2].uint, arglist[4].array, arglist[5].uint, arglist[6].uint);
+            else if (arglist[0].ptrflag)
+                arglist[6].uint = glk_schannel_play_multi(arglist[1].array, arglist[2].uint, NULL, 0, arglist[4].uint);
+            else if (arglist[1].ptrflag)
+                arglist[6].uint = glk_schannel_play_multi(NULL, 0, arglist[2].array, arglist[3].uint, arglist[4].uint);
+            else
+                arglist[4].uint = glk_schannel_play_multi(NULL, 0, NULL, 0, arglist[2].uint);
+            break;
+        case 0x00FD: /* schannel_set_volume_ext */
+            glk_schannel_set_volume_ext(arglist[0].opaqueref, arglist[1].uint, arglist[2].uint, arglist[3].uint);
+            break;
+        case 0x00FE: /* schannel_pause */
+            glk_schannel_pause(arglist[0].opaqueref);
+            break;
+        case 0x00FF: /* schannel_unpause */
+            glk_schannel_unpause(arglist[0].opaqueref);
+            break;
+#endif /* GLK_MODULE_SOUND2 */
 #endif /* GLK_MODULE_SOUND */
 
 #ifdef GLK_MODULE_HYPERLINKS
diff --git a/libchimara/gi_dispa.h b/libchimara/gi_dispa.h
index 6ea045c..6ec3b96 100644
--- a/libchimara/gi_dispa.h
+++ b/libchimara/gi_dispa.h
@@ -1,7 +1,7 @@
 #ifndef _GI_DISPA_H
 #define _GI_DISPA_H
 
-/* gi_dispa.h: Header file for dispatch layer of Glk API, version 0.7.2.
+/* gi_dispa.h: Header file for dispatch layer of Glk API, version 0.7.3.
     Designed by Andrew Plotkin <erkyrath@eblong.com>
     http://www.eblong.com/zarf/glk/index.html
 
diff --git a/libchimara/glk.h b/libchimara/glk.h
index d6ca327..3bcbc3d 100644
--- a/libchimara/glk.h
+++ b/libchimara/glk.h
@@ -1,41 +1,43 @@
 #ifndef GLK_H
 #define GLK_H
 
-/* glk.h: Header file for Glk API, version 0.7.2.
- Designed by Andrew Plotkin <erkyrath@eblong.com>
- http://eblong.com/zarf/glk/
- 
- This file is copyright 1998-2011 by Andrew Plotkin. You may copy,
- distribute, and incorporate it into your own programs, by any means
- and under any conditions, as long as you do not modify it. You may
- also modify this file, incorporate it into your own programs,
- and distribute the modified version, as long as you retain a notice
- in your program or documentation which mentions my name and the URL
- shown above.
- */
+/* glk.h: Header file for Glk API, version 0.7.3.
+    Designed by Andrew Plotkin <erkyrath@eblong.com>
+    http://eblong.com/zarf/glk/
+
+    This file is copyright 1998-2011 by Andrew Plotkin. You may copy,
+    distribute, and incorporate it into your own programs, by any means
+    and under any conditions, as long as you do not modify it. You may
+    also modify this file, incorporate it into your own programs,
+    and distribute the modified version, as long as you retain a notice
+    in your program or documentation which mentions my name and the URL
+    shown above.
+*/
 
 /* If your system does not have <stdint.h>, you'll have to remove this
- include line. Then edit the definition of glui32 to make sure it's
- really a 32-bit unsigned integer type, and glsi32 to make sure
- it's really a 32-bit signed integer type. If they're not, horrible
- things will happen. */
+    include line. Then edit the definition of glui32 to make sure it's
+    really a 32-bit unsigned integer type, and glsi32 to make sure
+    it's really a 32-bit signed integer type. If they're not, horrible
+    things will happen. */
 #include <stdint.h>
 typedef uint32_t glui32;
 typedef int32_t glsi32;
 
 /* These are the compile-time conditionals that reveal various Glk optional
- modules. */
+    modules. Note that if GLK_MODULE_SOUND2 is defined, GLK_MODULE_SOUND
+    must be also. */
 #define GLK_MODULE_LINE_ECHO
 #define GLK_MODULE_LINE_TERMINATORS
 #define GLK_MODULE_UNICODE
 #define GLK_MODULE_UNICODE_NORM
 #define GLK_MODULE_IMAGE
 #define GLK_MODULE_SOUND
+#define GLK_MODULE_SOUND2
 #define GLK_MODULE_HYPERLINKS
 #define GLK_MODULE_DATETIME
 
 /* These types are opaque object identifiers. They're pointers to opaque
- C structures, which are defined differently by each library. */
+    C structures, which are defined differently by each library. */
 typedef struct glk_window_struct  *winid_t;
 typedef struct glk_stream_struct  *strid_t;
 typedef struct glk_fileref_struct *frefid_t;
@@ -65,6 +67,7 @@ typedef struct glk_schannel_struct *schanid_t;
 #define gestalt_LineTerminators (18)
 #define gestalt_LineTerminatorKey (19)
 #define gestalt_DateTime (20)
+#define gestalt_Sound2 (21)
 
 #define evtype_None (0)
 #define evtype_Timer (1)
@@ -75,6 +78,7 @@ typedef struct glk_schannel_struct *schanid_t;
 #define evtype_Redraw (6)
 #define evtype_SoundNotify (7)
 #define evtype_Hyperlink (8)
+#define evtype_VolumeNotify (9)
 
 typedef struct event_struct {
     glui32 type;
@@ -185,7 +189,7 @@ typedef struct stream_result_struct {
 #define   stylehint_just_RightFlush (3)
 
 /* glk_main() is the top-level function which you define. The Glk library
- calls it. */
+    calls it. */
 extern void glk_main(void);
 
 extern void glk_exit(void);
@@ -194,21 +198,21 @@ extern void glk_tick(void);
 
 extern glui32 glk_gestalt(glui32 sel, glui32 val);
 extern glui32 glk_gestalt_ext(glui32 sel, glui32 val, glui32 *arr,
-							  glui32 arrlen);
+    glui32 arrlen);
 
 extern unsigned char glk_char_to_lower(unsigned char ch);
 extern unsigned char glk_char_to_upper(unsigned char ch);
 
 extern winid_t glk_window_get_root(void);
 extern winid_t glk_window_open(winid_t split, glui32 method, glui32 size,
-							   glui32 wintype, glui32 rock);
+    glui32 wintype, glui32 rock);
 extern void glk_window_close(winid_t win, stream_result_t *result);
 extern void glk_window_get_size(winid_t win, glui32 *widthptr,
-								glui32 *heightptr);
+    glui32 *heightptr);
 extern void glk_window_set_arrangement(winid_t win, glui32 method,
-									   glui32 size, winid_t keywin);
+    glui32 size, winid_t keywin);
 extern void glk_window_get_arrangement(winid_t win, glui32 *methodptr,
-									   glui32 *sizeptr, winid_t *keywinptr);
+    glui32 *sizeptr, winid_t *keywinptr);
 extern winid_t glk_window_iterate(winid_t win, glui32 *rockptr);
 extern glui32 glk_window_get_rock(winid_t win);
 extern glui32 glk_window_get_type(winid_t win);
@@ -223,9 +227,9 @@ extern strid_t glk_window_get_echo_stream(winid_t win);
 extern void glk_set_window(winid_t win);
 
 extern strid_t glk_stream_open_file(frefid_t fileref, glui32 fmode,
-									glui32 rock);
+    glui32 rock);
 extern strid_t glk_stream_open_memory(char *buf, glui32 buflen, glui32 fmode,
-									  glui32 rock);
+    glui32 rock);
 extern void glk_stream_close(strid_t str, stream_result_t *result);
 extern strid_t glk_stream_iterate(strid_t str, glui32 *rockptr);
 extern glui32 glk_stream_get_rock(strid_t str);
@@ -248,19 +252,19 @@ extern glui32 glk_get_line_stream(strid_t str, char *buf, glui32 len);
 extern glui32 glk_get_buffer_stream(strid_t str, char *buf, glui32 len);
 
 extern void glk_stylehint_set(glui32 wintype, glui32 styl, glui32 hint,
-							  glsi32 val);
+    glsi32 val);
 extern void glk_stylehint_clear(glui32 wintype, glui32 styl, glui32 hint);
 extern glui32 glk_style_distinguish(winid_t win, glui32 styl1, glui32 styl2);
 extern glui32 glk_style_measure(winid_t win, glui32 styl, glui32 hint,
-								glui32 *result);
+    glui32 *result);
 
 extern frefid_t glk_fileref_create_temp(glui32 usage, glui32 rock);
 extern frefid_t glk_fileref_create_by_name(glui32 usage, char *name,
-										   glui32 rock);
+    glui32 rock);
 extern frefid_t glk_fileref_create_by_prompt(glui32 usage, glui32 fmode,
-											 glui32 rock);
+    glui32 rock);
 extern frefid_t glk_fileref_create_from_fileref(glui32 usage, frefid_t fref,
-												glui32 rock);
+    glui32 rock);
 extern void glk_fileref_destroy(frefid_t fref);
 extern frefid_t glk_fileref_iterate(frefid_t fref, glui32 *rockptr);
 extern glui32 glk_fileref_get_rock(frefid_t fref);
@@ -273,7 +277,7 @@ extern void glk_select_poll(event_t *event);
 extern void glk_request_timer_events(glui32 millisecs);
 
 extern void glk_request_line_event(winid_t win, char *buf, glui32 maxlen,
-								   glui32 initlen);
+    glui32 initlen);
 extern void glk_request_char_event(winid_t win);
 extern void glk_request_mouse_event(winid_t win);
 
@@ -287,17 +291,17 @@ extern void glk_set_echo_line_event(winid_t win, glui32 val);
 
 #ifdef GLK_MODULE_LINE_TERMINATORS
 extern void glk_set_terminators_line_event(winid_t win, glui32 *keycodes, 
-										   glui32 count);
+    glui32 count);
 #endif /* GLK_MODULE_LINE_TERMINATORS */
 
 #ifdef GLK_MODULE_UNICODE
 
 extern glui32 glk_buffer_to_lower_case_uni(glui32 *buf, glui32 len,
-										   glui32 numchars);
+    glui32 numchars);
 extern glui32 glk_buffer_to_upper_case_uni(glui32 *buf, glui32 len,
-										   glui32 numchars);
+    glui32 numchars);
 extern glui32 glk_buffer_to_title_case_uni(glui32 *buf, glui32 len,
-										   glui32 numchars, glui32 lowerrest);
+    glui32 numchars, glui32 lowerrest);
 
 extern void glk_put_char_uni(glui32 ch);
 extern void glk_put_string_uni(glui32 *s);
@@ -311,22 +315,22 @@ extern glui32 glk_get_buffer_stream_uni(strid_t str, glui32 *buf, glui32 len);
 extern glui32 glk_get_line_stream_uni(strid_t str, glui32 *buf, glui32 len);
 
 extern strid_t glk_stream_open_file_uni(frefid_t fileref, glui32 fmode,
-										glui32 rock);
+    glui32 rock);
 extern strid_t glk_stream_open_memory_uni(glui32 *buf, glui32 buflen,
-										  glui32 fmode, glui32 rock);
+    glui32 fmode, glui32 rock);
 
 extern void glk_request_char_event_uni(winid_t win);
 extern void glk_request_line_event_uni(winid_t win, glui32 *buf,
-									   glui32 maxlen, glui32 initlen);
+    glui32 maxlen, glui32 initlen);
 
 #endif /* GLK_MODULE_UNICODE */
 
 #ifdef GLK_MODULE_UNICODE_NORM
 
 extern glui32 glk_buffer_canon_decompose_uni(glui32 *buf, glui32 len,
-											 glui32 numchars);
+    glui32 numchars);
 extern glui32 glk_buffer_canon_normalize_uni(glui32 *buf, glui32 len,
-											 glui32 numchars);
+    glui32 numchars);
 
 #endif /* GLK_MODULE_UNICODE_NORM */
 
@@ -340,15 +344,15 @@ extern glui32 glk_buffer_canon_normalize_uni(glui32 *buf, glui32 len,
 
 extern glui32 glk_image_draw(winid_t win, glui32 image, glsi32 val1, glsi32 val2);
 extern glui32 glk_image_draw_scaled(winid_t win, glui32 image,
-									glsi32 val1, glsi32 val2, glui32 width, glui32 height);
+    glsi32 val1, glsi32 val2, glui32 width, glui32 height);
 extern glui32 glk_image_get_info(glui32 image, glui32 *width, glui32 *height);
 
 extern void glk_window_flow_break(winid_t win);
 
 extern void glk_window_erase_rect(winid_t win,
-								  glsi32 left, glsi32 top, glui32 width, glui32 height);
+    glsi32 left, glsi32 top, glui32 width, glui32 height);
 extern void glk_window_fill_rect(winid_t win, glui32 color,
-								 glsi32 left, glsi32 top, glui32 width, glui32 height);
+    glsi32 left, glsi32 top, glui32 width, glui32 height);
 extern void glk_window_set_background_color(winid_t win, glui32 color);
 
 #endif /* GLK_MODULE_IMAGE */
@@ -362,12 +366,25 @@ extern glui32 glk_schannel_get_rock(schanid_t chan);
 
 extern glui32 glk_schannel_play(schanid_t chan, glui32 snd);
 extern glui32 glk_schannel_play_ext(schanid_t chan, glui32 snd, glui32 repeats,
-									glui32 notify);
+    glui32 notify);
 extern void glk_schannel_stop(schanid_t chan);
 extern void glk_schannel_set_volume(schanid_t chan, glui32 vol);
 
 extern void glk_sound_load_hint(glui32 snd, glui32 flag);
 
+#ifdef GLK_MODULE_SOUND2
+/* Note that this section is nested inside the #ifdef GLK_MODULE_SOUND.
+   GLK_MODULE_SOUND must be defined if GLK_MODULE_SOUND2 is. */
+
+extern schanid_t glk_schannel_create_ext(glui32 rock, glui32 volume);
+extern glui32 glk_schannel_play_multi(schanid_t *chanarray, glui32 chancount,
+    glui32 *sndarray, glui32 soundcount, glui32 notify);
+extern void glk_schannel_pause(schanid_t chan);
+extern void glk_schannel_unpause(schanid_t chan);
+extern void glk_schannel_set_volume_ext(schanid_t chan, glui32 vol,
+    glui32 duration, glui32 notify);
+
+#endif /* GLK_MODULE_SOUND2 */
 #endif /* GLK_MODULE_SOUND */
 
 #ifdef GLK_MODULE_HYPERLINKS
@@ -403,9 +420,9 @@ extern glsi32 glk_current_simple_time(glui32 factor);
 extern void glk_time_to_date_utc(glktimeval_t *time, glkdate_t *date);
 extern void glk_time_to_date_local(glktimeval_t *time, glkdate_t *date);
 extern void glk_simple_time_to_date_utc(glsi32 time, glui32 factor, 
-										glkdate_t *date);
+    glkdate_t *date);
 extern void glk_simple_time_to_date_local(glsi32 time, glui32 factor, 
-										  glkdate_t *date);
+    glkdate_t *date);
 extern void glk_date_to_time_utc(glkdate_t *date, glktimeval_t *time);
 extern void glk_date_to_time_local(glkdate_t *date, glktimeval_t *time);
 extern glsi32 glk_date_to_simple_time_utc(glkdate_t *date, glui32 factor);
-- 
2.30.2