Skip to content

Commit 4376d7b

Browse files
committed
Implement sound_playuntildone block
1 parent c8bdfac commit 4376d7b

File tree

3 files changed

+431
-10
lines changed

3 files changed

+431
-10
lines changed

src/blocks/soundblocks.cpp

Lines changed: 139 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ void SoundBlocks::registerBlocks(IEngine *engine)
1919
{
2020
// Blocks
2121
engine->addCompileFunction(this, "sound_play", &compilePlay);
22+
engine->addCompileFunction(this, "sound_playuntildone", &compilePlayUntilDone);
2223
engine->addCompileFunction(this, "sound_changevolumeby", &compileChangeVolumeBy);
2324
engine->addCompileFunction(this, "sound_setvolumeto", &compileSetVolumeTo);
2425
engine->addCompileFunction(this, "sound_volume", &compileVolume);
@@ -28,13 +29,13 @@ void SoundBlocks::registerBlocks(IEngine *engine)
2829
engine->addInput(this, "VOLUME", VOLUME);
2930
}
3031

31-
void SoundBlocks::compilePlay(Compiler *compiler)
32+
bool SoundBlocks::compilePlayCommon(Compiler *compiler, bool untilDone, bool *byIndex)
3233
{
3334
Target *target = compiler->target();
3435
assert(target);
3536

3637
if (!target)
37-
return;
38+
return false;
3839

3940
Input *input = compiler->input(SOUND_MENU);
4041

@@ -49,16 +50,46 @@ void SoundBlocks::compilePlay(Compiler *compiler)
4950

5051
if (v.type() == Value::Type::Integer) {
5152
compiler->addConstValue(v.toLong() - 1);
52-
compiler->addFunctionCall(&playByIndex);
53+
compiler->addFunctionCall(untilDone ? &playByIndexUntilDone : &playByIndex);
54+
55+
if (byIndex)
56+
*byIndex = true;
57+
58+
return true;
5359
}
5460
} else {
5561
compiler->addConstValue(index);
56-
compiler->addFunctionCall(&playByIndex);
62+
compiler->addFunctionCall(untilDone ? &playByIndexUntilDone : &playByIndex);
63+
64+
if (byIndex)
65+
*byIndex = true;
66+
67+
return true;
5768
}
5869
} else {
5970
compiler->addInput(input);
60-
compiler->addFunctionCall(&play);
71+
compiler->addFunctionCall(untilDone ? &playUntilDone : &play);
72+
73+
if (byIndex)
74+
*byIndex = false;
75+
76+
return true;
6177
}
78+
79+
return false;
80+
}
81+
82+
void SoundBlocks::compilePlay(Compiler *compiler)
83+
{
84+
compilePlayCommon(compiler, false);
85+
}
86+
87+
void SoundBlocks::compilePlayUntilDone(Compiler *compiler)
88+
{
89+
bool byIndex = false;
90+
91+
if (compilePlayCommon(compiler, true, &byIndex))
92+
compiler->addFunctionCall(byIndex ? &checkSoundByIndex : &checkSound);
6293
}
6394

6495
void SoundBlocks::compileChangeVolumeBy(Compiler *compiler)
@@ -92,7 +123,7 @@ Sound *SoundBlocks::getSoundByIndex(Target *target, long index)
92123
return target->soundAt(index).get();
93124
}
94125

95-
unsigned int SoundBlocks::play(VirtualMachine *vm)
126+
Sound *SoundBlocks::playCommon(VirtualMachine *vm)
96127
{
97128
Target *target = vm->target();
98129
assert(target);
@@ -101,30 +132,128 @@ unsigned int SoundBlocks::play(VirtualMachine *vm)
101132
if (target) {
102133
Sound *sound = target->soundAt(target->findSound(name->toString())).get();
103134

104-
if (sound)
135+
if (sound) {
105136
sound->start();
137+
return sound;
138+
}
139+
106140
else if (name->type() == Value::Type::Integer) {
107141
sound = getSoundByIndex(target, name->toLong() - 1);
108142

109-
if (sound)
143+
if (sound) {
110144
sound->start();
145+
return sound;
146+
}
111147
}
112148
}
113149

150+
return nullptr;
151+
}
152+
153+
Sound *SoundBlocks::playByIndexCommon(VirtualMachine *vm)
154+
{
155+
Target *target = vm->target();
156+
assert(target);
157+
158+
if (target) {
159+
Sound *sound = getSoundByIndex(target, vm->getInput(0, 1)->toInt());
160+
161+
if (sound) {
162+
sound->start();
163+
return sound;
164+
}
165+
}
166+
167+
return nullptr;
168+
}
169+
170+
unsigned int SoundBlocks::play(VirtualMachine *vm)
171+
{
172+
Sound *sound = playCommon(vm);
173+
174+
if (sound)
175+
m_waitingSounds.erase(sound);
176+
114177
return 1;
115178
}
116179

117180
unsigned int SoundBlocks::playByIndex(VirtualMachine *vm)
181+
{
182+
Sound *sound = playByIndexCommon(vm);
183+
184+
if (sound)
185+
m_waitingSounds.erase(sound);
186+
187+
return 1;
188+
}
189+
190+
unsigned int SoundBlocks::playUntilDone(VirtualMachine *vm)
191+
{
192+
Sound *sound = playCommon(vm);
193+
194+
if (sound)
195+
m_waitingSounds[sound] = vm;
196+
197+
return 0; // leave the register for checkSound()
198+
}
199+
200+
unsigned int SoundBlocks::playByIndexUntilDone(VirtualMachine *vm)
201+
{
202+
Sound *sound = playByIndexCommon(vm);
203+
204+
if (sound)
205+
m_waitingSounds[sound] = vm;
206+
207+
return 0; // leave the register for checkSoundByIndex()
208+
}
209+
210+
unsigned int SoundBlocks::checkSound(VirtualMachine *vm)
211+
{
212+
Target *target = vm->target();
213+
assert(target);
214+
const Value *name = vm->getInput(0, 1);
215+
216+
if (target) {
217+
Sound *sound = target->soundAt(target->findSound(name->toString())).get();
218+
219+
if (!sound && name->type() == Value::Type::Integer)
220+
sound = getSoundByIndex(target, name->toLong() - 1);
221+
222+
if (sound) {
223+
auto it = m_waitingSounds.find(sound);
224+
225+
if (it != m_waitingSounds.cend() && it->second == vm) {
226+
if (sound->isPlaying())
227+
vm->stop(true, true, true);
228+
else
229+
m_waitingSounds.erase(sound);
230+
}
231+
}
232+
}
233+
234+
return 1;
235+
}
236+
237+
unsigned int SoundBlocks::checkSoundByIndex(VirtualMachine *vm)
118238
{
119239
Target *target = vm->target();
120240
assert(target);
121241

122242
if (target) {
123243
auto sound = getSoundByIndex(target, vm->getInput(0, 1)->toInt());
124244

125-
if (sound)
126-
sound->start();
245+
if (sound) {
246+
auto it = m_waitingSounds.find(sound);
247+
248+
if (it != m_waitingSounds.cend() && it->second == vm) {
249+
if (sound->isPlaying())
250+
vm->stop(true, true, true);
251+
else
252+
m_waitingSounds.erase(sound);
253+
}
254+
}
127255
}
256+
128257
return 1;
129258
}
130259

src/blocks/soundblocks.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
#pragma once
44

5+
#include <unordered_map>
6+
#include <unordered_set>
7+
58
#include <scratchcpp/iblocksection.h>
69

710
namespace libscratchcpp
@@ -34,18 +37,30 @@ class SoundBlocks : public IBlockSection
3437

3538
void registerBlocks(IEngine *engine) override;
3639

40+
static bool compilePlayCommon(Compiler *compiler, bool untilDone, bool *byIndex = nullptr);
3741
static void compilePlay(Compiler *compiler);
42+
static void compilePlayUntilDone(Compiler *compiler);
3843
static void compileChangeVolumeBy(Compiler *compiler);
3944
static void compileSetVolumeTo(Compiler *compiler);
4045
static void compileVolume(Compiler *compiler);
4146

4247
static Sound *getSoundByIndex(Target *target, long index);
48+
static Sound *playCommon(VirtualMachine *vm);
49+
static Sound *playByIndexCommon(VirtualMachine *vm);
50+
4351
static unsigned int play(VirtualMachine *vm);
4452
static unsigned int playByIndex(VirtualMachine *vm);
4553

54+
static unsigned int playUntilDone(VirtualMachine *vm);
55+
static unsigned int playByIndexUntilDone(VirtualMachine *vm);
56+
static unsigned int checkSound(VirtualMachine *vm);
57+
static unsigned int checkSoundByIndex(VirtualMachine *vm);
58+
4659
static unsigned int changeVolumeBy(VirtualMachine *vm);
4760
static unsigned int setVolumeTo(VirtualMachine *vm);
4861
static unsigned int volume(VirtualMachine *vm);
62+
63+
static inline std::unordered_map<Sound *, VirtualMachine *> m_waitingSounds;
4964
};
5065

5166
} // namespace libscratchcpp

0 commit comments

Comments
 (0)