|
| 1 | +//-- |
| 2 | +// This file is part of Sonic Pi: http://sonic-pi.net |
| 3 | +// Full project source: https://github.com/sonic-pi-net/sonic-pi |
| 4 | +// License: https://github.com/sonic-pi-net/sonic-pi/blob/main/LICENSE.md |
| 5 | +// |
| 6 | +// Copyright 2026 by Sam Aaron (http://sam.aaron.name). |
| 7 | +// All rights reserved. |
| 8 | +// |
| 9 | +// Permission is granted for use, copying, modification, and |
| 10 | +// distribution of modified versions of this work as long as this |
| 11 | +// notice is included. |
| 12 | +//++ |
| 13 | + |
| 14 | +// The window builds the Link panel before there is an engine, so anything it |
| 15 | +// sends then reaches nothing. Share Audio was sent only then: a fresh launch |
| 16 | +// with it On left the engine publishing nothing, and advertising no channels, |
| 17 | +// while the button said On. The panel sends it again whenever an engine is |
| 18 | +// ready: on first boot, and after every restart. |
| 19 | + |
| 20 | +#include <catch2/catch_test_macros.hpp> |
| 21 | + |
| 22 | +#include <QApplication> |
| 23 | +#include <QTemporaryDir> |
| 24 | + |
| 25 | +#include <memory> |
| 26 | +#include <string> |
| 27 | +#include <vector> |
| 28 | + |
| 29 | +#include "api/osc/osc_pkt.hh" |
| 30 | +#include "api/sonicpi_api.h" |
| 31 | +#include "utils/gui_settings.h" |
| 32 | +#include "widgets/linkaudiostreamswidget.h" |
| 33 | + |
| 34 | +namespace { |
| 35 | + |
| 36 | +using namespace SonicPi; |
| 37 | + |
| 38 | +struct NoClient : IAPIClient |
| 39 | +{ |
| 40 | + void Report(const MessageInfo&) override {} |
| 41 | + void Status(const StatusInfo&) override {} |
| 42 | + void Cue(const CueInfo&) override {} |
| 43 | + void Midi(const MidiInfo&) override {} |
| 44 | + void Version(const VersionInfo&) override {} |
| 45 | + void AudioDataAvailable(ProcessedAudioPtr) override {} |
| 46 | + void Buffer(const BufferInfo&) override {} |
| 47 | + void ActiveLinks(const int) override {} |
| 48 | + void BPM(const double) override {} |
| 49 | + void Scsynth(const ScsynthInfo&) override {} |
| 50 | + void AudioDevices(const AudioDevicesInfo&) override {} |
| 51 | + void AudioInputDevices(const AudioInputDevicesInfo&) override {} |
| 52 | + void AudioDeviceConfig(const AudioDeviceConfigInfo&) override {} |
| 53 | + void SupersonicSetup(int, int) override {} |
| 54 | + void SpiderReady() override {} |
| 55 | +}; |
| 56 | + |
| 57 | +// An engine that only listens: every message the GUI sends it, in order. |
| 58 | +struct ListeningEngine : SonicPiAPI |
| 59 | +{ |
| 60 | + explicit ListeningEngine(IAPIClient* client) : SonicPiAPI(client, APIProtocol::UDP, LogOption::Console) {} |
| 61 | + |
| 62 | + bool SupersonicSendOSC(oscpkt::Message m) override |
| 63 | + { |
| 64 | + sent.push_back(m); |
| 65 | + return true; |
| 66 | + } |
| 67 | + |
| 68 | + // The int the last message to `address` carried, or -1 if none came. |
| 69 | + int lastInt(const std::string& address) const |
| 70 | + { |
| 71 | + for (auto it = sent.rbegin(); it != sent.rend(); ++it) |
| 72 | + { |
| 73 | + int32_t v = 0; |
| 74 | + if (it->addressPattern() == address && it->arg().popInt32(v).isOkNoMoreArgs()) |
| 75 | + return v; |
| 76 | + } |
| 77 | + return -1; |
| 78 | + } |
| 79 | + |
| 80 | + std::vector<oscpkt::Message> sent; |
| 81 | +}; |
| 82 | + |
| 83 | +// A gui.ini of the test's own, put back as it was afterwards. |
| 84 | +struct OwnSettings |
| 85 | +{ |
| 86 | + QTemporaryDir dir; |
| 87 | + QString before = SonicPi::guiSettingsPath(); |
| 88 | + OwnSettings() { SonicPi::setGuiSettingsPath(dir.filePath("gui.ini")); } |
| 89 | + ~OwnSettings() { SonicPi::setGuiSettingsPath(before); } |
| 90 | +}; |
| 91 | + |
| 92 | +const std::string kPublish = "/clockwork/clock/audio/publish/set"; |
| 93 | + |
| 94 | +} // namespace |
| 95 | + |
| 96 | +TEST_CASE("Link Audio: Share Audio reaches every engine that comes up", "[link]") |
| 97 | +{ |
| 98 | + for (const bool share : { true, false }) |
| 99 | + { |
| 100 | + INFO("Share Audio " << (share ? "On" : "Off")); |
| 101 | + OwnSettings settings; |
| 102 | + SonicPi::guiSettings().setValue("link/audioPublish", share); |
| 103 | + NoClient client; |
| 104 | + auto engine = std::make_shared<ListeningEngine>(&client); |
| 105 | + LinkAudioStreamsWidget panel(engine); |
| 106 | + engine->sent.clear(); // built before the engine was up: nothing heard it |
| 107 | + |
| 108 | + panel.onEngineReady(); // first boot |
| 109 | + CHECK(engine->lastInt(kPublish) == (share ? 1 : 0)); |
| 110 | + |
| 111 | + engine->sent.clear(); |
| 112 | + panel.onEngineReady(); // a restarted engine starts with none of it |
| 113 | + CHECK(engine->lastInt(kPublish) == (share ? 1 : 0)); |
| 114 | + } |
| 115 | +} |
0 commit comments