Consume libakgl 0.3.0: every workaround deleted, two capabilities gained
0.3.0 closed all ten API gaps this port had filed. The four workarounds go with them: the CMake block that declared libakgl's vendored dependencies by hand, the akgl/actor.h include in three files, and the six vtable pointers assigned by hand in two more, now akgl_render_bind2d(). Two gaps were capabilities rather than inconveniences, and both are now real: The line editor takes the composed UTF-8 text the ring carries in preference to the keycode, so shifted characters, keyboard layouts, compose keys and dead keys all work. A double quote can be typed, which means a BASIC string literal can be typed -- the sharp end of the old limitation. Letters are no longer folded to upper case. SOUND's dir/min/step reach akgl_audio_sweep instead of being refused. dir 3 sweeps once rather than oscillating and TODO.md section 5 says so. A backend with no sweep still refuses the swept note and plays the held one. The adaptors now carry an AKGL_VERSION_AT_LEAST(0, 3, 0) floor, verified by temporarily demanding 0.4.0 and watching it fire. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -131,20 +131,58 @@ static void test_sound(void)
|
||||
harness_stop();
|
||||
|
||||
/*
|
||||
* The frequency sweep is refused rather than faked. Faking it would mean
|
||||
* re-issuing tones from step(), which would tie audible pitch to how often
|
||||
* the host calls us -- a tune that changes key with the frame rate.
|
||||
* The frequency sweep reaches the device, which it could not until libakgl
|
||||
* 0.3.0 grew akgl_audio_sweep -- it was refused outright before, because
|
||||
* faking it would have meant re-issuing tones from step() and tying audible
|
||||
* pitch to how often the host calls us.
|
||||
*
|
||||
* Sweeping *down*: register 1000 is below register 16777, so the endpoints
|
||||
* decide the direction and both the SID and akgl_audio_sweep read them that
|
||||
* way.
|
||||
*/
|
||||
TEST_REQUIRE_OK(run_program("10 SOUND 1, 1000, 60, 1, 500, 10\n"));
|
||||
TEST_REQUIRE(strstr(HARNESS_OUTPUT, "frequency sweep") != NULL,
|
||||
"a sweep should be refused, got \"%s\"", HARNESS_OUTPUT);
|
||||
TEST_REQUIRE_OK(run_program("10 SOUND 1, 16777, 60, 2, 1000, 10\n"));
|
||||
TEST_REQUIRE(strstr(MOCK.log, "sweep v0 ") != NULL,
|
||||
"a sweep should reach the device, got \"%s\"", MOCK.log);
|
||||
TEST_REQUIRE(strstr(MOCK.log, "1000ms") != NULL,
|
||||
"60 jiffies should still be 1000 ms on a sweep, got \"%s\"", MOCK.log);
|
||||
TEST_REQUIRE(strstr(HARNESS_OUTPUT, "") != NULL && HARNESS_OUTPUT[0] == '\0',
|
||||
"a sweep should not be refused, got \"%s\"", HARNESS_OUTPUT);
|
||||
harness_stop();
|
||||
|
||||
/* A sweep direction of zero is "no sweep" and must still play. */
|
||||
/* A direction outside 0..3 is a typo worth catching. */
|
||||
TEST_REQUIRE_OK(run_program("10 SOUND 1, 1000, 60, 9, 500, 10\n"));
|
||||
TEST_REQUIRE(strstr(HARNESS_OUTPUT, "SOUND direction 9") != NULL,
|
||||
"direction 9 should be refused, got \"%s\"", HARNESS_OUTPUT);
|
||||
harness_stop();
|
||||
|
||||
/* A sweep needs all three of its arguments. */
|
||||
TEST_REQUIRE_OK(run_program("10 SOUND 1, 1000, 60, 1\n"));
|
||||
TEST_REQUIRE(strstr(HARNESS_OUTPUT, "direction, a minimum and a step") != NULL,
|
||||
"a partial sweep should be refused, got \"%s\"", HARNESS_OUTPUT);
|
||||
harness_stop();
|
||||
|
||||
/* A sweep direction of zero is "no sweep" and must still play a held note. */
|
||||
TEST_REQUIRE_OK(run_program("10 SOUND 1, 1000, 60, 0\n"));
|
||||
TEST_REQUIRE(strstr(MOCK.log, "tone v0 ") != NULL,
|
||||
"direction 0 is not a sweep and should play, got \"%s\"", MOCK.log);
|
||||
harness_stop();
|
||||
|
||||
/*
|
||||
* A backend with no sweep is still a valid backend -- that is what a host
|
||||
* written against libakgl 0.2.0 looks like -- and SOUND refuses the swept
|
||||
* note rather than dereferencing a NULL entry point.
|
||||
*/
|
||||
TEST_REQUIRE_OK(harness_start(NULL));
|
||||
mock_devices_init();
|
||||
MOCK_AUDIO.sweep = NULL;
|
||||
TEST_REQUIRE_OK(akbasic_runtime_set_devices(&HARNESS_RUNTIME, &MOCK_GRAPHICS,
|
||||
&MOCK_AUDIO, &MOCK_INPUT));
|
||||
TEST_REQUIRE_OK(akbasic_runtime_load(&HARNESS_RUNTIME, "10 SOUND 1, 1000, 60, 1, 500, 10\n"));
|
||||
TEST_REQUIRE_OK(akbasic_runtime_start(&HARNESS_RUNTIME, AKBASIC_MODE_RUN));
|
||||
TEST_REQUIRE_OK(akbasic_runtime_run(&HARNESS_RUNTIME, 0));
|
||||
TEST_REQUIRE(strstr(HARNESS_OUTPUT, "audio device that can sweep") != NULL,
|
||||
"a backend without sweep should refuse, got \"%s\"", HARNESS_OUTPUT);
|
||||
harness_stop();
|
||||
}
|
||||
|
||||
/** @brief ENVELOPE maps the SID rate numbers, and sustain is a level not a time. */
|
||||
|
||||
Reference in New Issue
Block a user