11// SPDX-License-Identifier: Apache-2.0
22
3+ #include < scratchcpp/iengine.h>
4+ #include < scratchcpp/compiler.h>
5+ #include < scratchcpp/target.h>
6+ #include < algorithm>
7+
38#include " soundblocks.h"
49
510using namespace libscratchcpp ;
@@ -21,4 +26,63 @@ Rgb SoundBlocks::color() const
2126
2227void SoundBlocks::registerBlocks (IEngine *engine)
2328{
29+ engine->addCompileFunction (this , " sound_play" , &compilePlay);
30+ }
31+
32+ CompilerValue *SoundBlocks::compilePlay (Compiler *compiler)
33+ {
34+ auto sound = compiler->addInput (" SOUND_MENU" );
35+ compiler->addTargetFunctionCall (" sound_play" , Compiler::StaticType::Void, { Compiler::StaticType::Unknown }, { sound });
36+ return nullptr ;
37+ }
38+
39+ int sound_wrap_clamp_index (Target *target, int index)
40+ {
41+ const long soundCount = target->sounds ().size ();
42+
43+ if (index < 0 )
44+ return (soundCount + index % (-soundCount)) % soundCount;
45+ else if (index >= soundCount)
46+ return index % soundCount;
47+ else
48+ return index;
49+ }
50+
51+ int sound_get_index (Target *target, const ValueData *sound)
52+ {
53+ if (!value_isString (sound)) {
54+ // Numbers should be treated as sound indices
55+ if (value_isNaN (sound) || value_isInfinity (sound) || value_isNegativeInfinity (sound))
56+ return -1 ;
57+ else
58+ return sound_wrap_clamp_index (target, value_toLong (sound) - 1 );
59+ } else {
60+ // Strings should be treated as sound names, where possible
61+ // TODO: Use UTF-16 in Target
62+ // StringPtr *nameStr = value_toStringPtr(sound);
63+ std::string nameStr;
64+ value_toString (sound, &nameStr);
65+ const int soundIndex = target->findSound (nameStr);
66+
67+ auto it = std::find_if (nameStr.begin (), nameStr.end (), [](char c) { return !std::isspace (c); });
68+ bool isWhiteSpace = (it == nameStr.end ());
69+
70+ if (soundIndex != -1 ) {
71+ return soundIndex;
72+ // Try to cast the string to a number (and treat it as a costume index)
73+ // Pure whitespace should not be treated as a number
74+ } else if (value_isValidNumber (sound) && !isWhiteSpace)
75+ return sound_wrap_clamp_index (target, value_toLong (sound) - 1 );
76+ }
77+
78+ return -1 ;
79+ }
80+
81+ extern " C" void sound_play (Target *target, const ValueData *soundName)
82+ {
83+ int index = sound_get_index (target, soundName);
84+ auto sound = target->soundAt (index);
85+
86+ if (sound)
87+ sound->start ();
2488}
0 commit comments