There’s an I6 function called GGRecoverObjects that handles situations like this. I just took a look at Music.i7x and didn’t see any custom redefinition of that function, so I’m assuming your game is using the default definition in Glulx.i6t, which explicitly stops sounds currently playing on the channels.
Technical details
GGRecoverObjects is necessary because of the convoluted, poorly designed nature of the Glulx/Glk interface. References to Glk objects in the Glulx game are part of the game state, and thus are preserved in save files. However, the Glk objects themselves are usually part of the interpreter runtime state and are destroyed when the interpreter is closed. This asymmetry makes restores between different interpreter sessions complicated; to take sound channels as an example, some new sound channels will exist (created by the game when the second session started), but the restored state still has references to the channels created by the first session. GGRecoverObjects is supposed to allow the restored game to modify its references to point to the new Glk objects.
(Aside: I don’t think Music.i7x currently recovers gg_midgroundchan at all. Perhaps this is a bug or oversight, @Draconis?)
With 10.1.2 syntax, this is how you would replace it:
Include (-
[ GGRecoverObjects id;
! If GGRecoverObjects() has been called, all these stored IDs are
! invalid, so we start by clearing them all out.
! (In fact, after a restoreundo, some of them may still be good.
! For simplicity, though, we assume the general case.)
gg_mainwin = 0;
gg_statuswin = 0;
gg_quotewin = 0;
gg_scriptfref = 0;
gg_scriptstr = 0;
gg_savestr = 0;
statuswin_cursize = 0;
gg_foregroundchan = 0;
gg_midgroundchan = 0;
gg_backgroundchan = 0;
gg_commandstr = 0;
gg_command_reading = false;
! Also tell the game to clear its object references.
IdentifyGlkObject(0);
id = glk_stream_iterate(0, gg_arguments);
while (id) {
switch (gg_arguments-->0) {
GG_SAVESTR_ROCK: gg_savestr = id;
GG_SCRIPTSTR_ROCK: gg_scriptstr = id;
GG_COMMANDWSTR_ROCK: gg_commandstr = id;
gg_command_reading = false;
GG_COMMANDRSTR_ROCK: gg_commandstr = id;
gg_command_reading = true;
default: IdentifyGlkObject(1, 1, id, gg_arguments-->0);
}
id = glk_stream_iterate(id, gg_arguments);
}
id = glk_window_iterate(0, gg_arguments);
while (id) {
switch (gg_arguments-->0) {
GG_MAINWIN_ROCK: gg_mainwin = id;
GG_STATUSWIN_ROCK: gg_statuswin = id;
GG_QUOTEWIN_ROCK: gg_quotewin = id;
default: IdentifyGlkObject(1, 0, id, gg_arguments-->0);
}
id = glk_window_iterate(id, gg_arguments);
}
id = glk_fileref_iterate(0, gg_arguments);
while (id) {
switch (gg_arguments-->0) {
GG_SCRIPTFREF_ROCK: gg_scriptfref = id;
default: IdentifyGlkObject(1, 2, id, gg_arguments-->0);
}
id = glk_fileref_iterate(id, gg_arguments);
}
if (glk_gestalt(gestalt_Sound, 0)) {
id = glk_schannel_iterate(0, gg_arguments);
while (id) {
switch (gg_arguments-->0) {
GG_FOREGROUNDCHAN_ROCK: gg_foregroundchan = id;
GG_BACKGROUNDCHAN_ROCK: gg_backgroundchan = id;
GG_MIDGROUNDCHAN_ROCK: gg_midgroundchan = id;
default: IdentifyGlkObject(1, 3, id, gg_arguments-->0);
}
id = glk_schannel_iterate(id, gg_arguments);
}
! if (gg_foregroundchan ~= 0) { glk_schannel_stop(gg_foregroundchan); }
! if (gg_backgroundchan ~= 0) { glk_schannel_stop(gg_backgroundchan); }
}
! Tell the game to tie up any loose ends.
IdentifyGlkObject(2);
];
-) replacing "GGRecoverObjects".
The modified version above adds a line to recover the new midground channel, and comments out the code that’s supposed to stop currently playing sounds.
(I haven’t tested this idea with Draconis’s Music extension, but I tried the same thing with just the standard library and it seemed to work.)