/** * @relates texteditor * @brief Play any ZZM music found in the editor. * * @param slurflag Slur notes together when true (ZZT-style). */ void texteditZZMPlay(texteditor * editor, int slurflag) { /** @TODO: do a damn good job of testing music */ /* Idea: create a copy of *editor so that we can mess around with curline and * pos and such, using existing functions to do the bulk of the display. */ #if 0 editor->text->cur = editor->curline; testMusic(editor->text, slurflag, editor->linewidth, flags, editor->d); #endif /* Create a new view of the editor data. This allows us to move the cursor * and change display settings for the new view without affecting editor. */ const char* playString = "#play "; const int playStringLen = 6; texteditor editorCopy = *editor; texteditor* view = &editorCopy; int done; #ifdef SDL SDL_AudioSpec spec; #endif /* Display everything, in case the editor has not been displayed recently. */ view->updateflags |= TUD_ALL; #ifdef SDL /* IF opening the audio device fails, return now before we crash something. */ if (OpenSynth(&spec)) return; #endif done = 0; /* Loop through the stringvector looking for #play statements */ while (view->curline != NULL && !done) { char* tune = strstr(view->curline->s, "#"); if (tune != NULL && str_equ(tune, playString, STREQU_UNCASE | STREQU_RFRONT)) { /* Current note and settings */ musicalNote note = zzmGetDefaultNote(); musicSettings settings = zzmGetDefaultSettings(); int xoffset = tune - view->curline->s + playStringLen; tune += playStringLen; /* Advance to notes! */ /* Change the slur setting */ note.slur = slurflag; while (note.src_pos < strlen(tune) && !done) { if (view->d->getkey() != DKEY_NONE) done = 1; /* Move the cursor and re-display before playing note. */ view->pos = note.src_pos + xoffset; texteditUpdateDisplay(view); note = zzmGetNote(tune, note); #ifdef DOS pcSpeakerPlayNote(note, settings); #elif defined SDL SynthPlayNote(spec, note, settings); #endif } } view->curline = view->curline->next; /* Re-display edit area since the current line has changed. */ view->updateflags |= TUD_EDITAREA; } #ifdef SDL /* TODO: instead of just sitting here, display the progress of playback */ /* Wait until the music is done or the user presses a key */ while (!IsSynthBufferEmpty() && view->d->getkey() == DKEY_NONE) ; CloseSynth(); #elif defined DOS pcSpeakerFinish(); #endif /* No need to free the view, it only exists on the stack. */ /* The edit area needs to be redisplayed now. */ editor->updateflags |= TUD_EDITAREA; }
void testMusic(stringvector* sv, int slur, int editwidth, int flags, displaymethod* d) { int done; #ifdef SDL SDL_AudioSpec spec; /* IF opening the audio device fails, return now before we crash something. */ if (OpenSynth(&spec)) return; #endif done = 0; /* Loop through the stringvector looking for #play statements */ while (sv->cur != NULL && !done) { char* tune = strstr(sv->cur->s, "#"); if (tune != NULL && str_equ(tune, "#play ", STREQU_UNCASE | STREQU_RFRONT)) { /* Current note and settings */ musicalNote note = zzmGetDefaultNote(); musicSettings settings = zzmGetDefaultSettings(); #ifdef DOS int xoff = tune - sv->cur->s; #endif tune += 6; /* Advance to notes! */ /* Change the slur setting */ note.slur = slur; /* Update everything because we have likely shifted to a new line. */ updateditbox(d, sv, U_EDITAREA, editwidth, flags, "", 1); while (note.src_pos < strlen(tune) && !done) { #ifdef DOS int oldpos = note.src_pos; char* strpart; #endif if (d->getkey() != DKEY_NONE) done = 1; note = zzmGetNote(tune, note); #ifdef DOS /* In DOS, display everything as we go along */ /* Display the whole line */ updateditbox(d, sv, U_CENTER, editwidth, flags, "", 1); /* Display the part of the string which will be played now */ strpart = str_duplen(tune + oldpos, note.src_pos - oldpos); d->print(oldpos + 15 + xoff, 13, ZOC_MPLAY_COLOUR, strpart); free(strpart); d->cursorgo(oldpos + 15 + xoff, 13); pcSpeakerPlayNote(note, settings); #elif defined SDL SynthPlayNote(spec, note, settings); #endif } } sv->cur = sv->cur->next; } #ifdef SDL /* TODO: instead of just sitting here, display the progress of playback */ /* Wait until the music is done or the user presses a key */ while (!IsSynthBufferEmpty() && d->getkey() == DKEY_NONE) ; CloseSynth(); #elif defined DOS pcSpeakerFinish(); #endif }
void Stop() { CloseSynth ();}