Skip to content

Commit 97b45ae

Browse files
MarioalexsaneXpl0it3r
authored andcommitted
Allow overriding protected methods on sfMusic and sfSoundStream
1 parent 08b22ee commit 97b45ae

File tree

9 files changed

+284
-3
lines changed

9 files changed

+284
-3
lines changed

include/CSFML/Audio/Music.h

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include <CSFML/Audio/SoundChannel.h>
3434
#include <CSFML/Audio/SoundSourceCone.h>
3535
#include <CSFML/Audio/SoundStatus.h>
36+
#include <CSFML/Audio/SoundStream.h>
3637
#include <CSFML/Audio/Types.h>
3738
#include <CSFML/System/InputStream.h>
3839
#include <CSFML/System/Time.h>
@@ -41,6 +42,16 @@
4142
#include <stddef.h>
4243

4344

45+
typedef bool (*sfMusicOnGetDataOriginal)(sfMusic* music, sfSoundStreamChunk* data); ///< sf::Music::onGetData callback
46+
typedef bool (*sfMusicOnGetDataMixin)(sfMusicOnGetDataOriginal originalImpl, sfMusic* music, sfSoundStreamChunk* data); ///< sf::Music::onGetData mixin
47+
48+
typedef void (*sfMusicOnSeekOriginal)(sfMusic* music, sfTime data); ///< sf::Music::onSeek callback
49+
typedef void (*sfMusicOnSeekMixin)(sfMusicOnSeekOriginal originalImpl, sfMusic* music, sfTime timeOffset); ///< sf::Music::onSeek mixin
50+
51+
typedef bool (*sfMusicOnLoopOriginal)(sfMusic* music, uint64_t* position); ///< sf::Music::onLoop callback
52+
typedef bool (*sfMusicOnLoopMixin)(sfMusicOnLoopOriginal originalImpl, sfMusic* music, uint64_t* position); ///< sf::Music::onLoop mixin
53+
54+
4455
////////////////////////////////////////////////////////////
4556
/// \brief Structure defining a time range
4657
///
@@ -52,6 +63,46 @@ typedef struct
5263
} sfTimeSpan;
5364

5465

66+
////////////////////////////////////////////////////////////
67+
/// \brief Override the behaviour of requesting a new chunk
68+
/// of audio samples from the stream source
69+
///
70+
/// This function fills the chunk from the next samples
71+
/// to read from the audio file.
72+
///
73+
/// \param music Music object
74+
/// \param mixin Method override to set, a null override restores the original behaviour
75+
///
76+
////////////////////////////////////////////////////////////
77+
CSFML_AUDIO_API void sfMusic_setOnGetData(sfMusic* music, sfMusicOnGetDataMixin mixin);
78+
79+
80+
////////////////////////////////////////////////////////////
81+
/// \brief Override the behaviour of changing the current
82+
/// playing position in the stream source
83+
///
84+
/// \param music Music object
85+
/// \param mixin Method override to set, a null override restores the original behaviour
86+
///
87+
////////////////////////////////////////////////////////////
88+
CSFML_AUDIO_API void sfMusic_setOnSeek(sfMusic* music, sfMusicOnSeekMixin mixin);
89+
90+
91+
////////////////////////////////////////////////////////////
92+
/// \brief Override the behaviour of changing the current
93+
/// playing position in the stream source to the loop offset
94+
///
95+
/// This is called by the underlying `SoundStream` whenever it needs us to reset
96+
/// the seek position for a loop. We then determine whether we are looping on a
97+
/// loop point or the end-of-file, perform the seek, and return the new position.
98+
///
99+
/// \param music Music object
100+
/// \param mixin Method override to set, a null override restores the original behaviour
101+
///
102+
////////////////////////////////////////////////////////////
103+
CSFML_AUDIO_API void sfMusic_setOnLoop(sfMusic* music, sfMusicOnLoopMixin mixin);
104+
105+
55106
////////////////////////////////////////////////////////////
56107
/// \brief Create a new music and load it from a file
57108
///

include/CSFML/Audio/SoundStream.h

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,20 +40,38 @@
4040
#include <stddef.h>
4141

4242

43+
typedef bool (*sfSoundStreamOnLoopOriginal)(sfSoundStream* soundStream, uint64_t* position); ///< sf::SoundStream::onLoop callback
44+
typedef bool (*sfSoundStreamOnLoopMixin)(sfSoundStreamOnLoopOriginal, sfSoundStream* soundStream, uint64_t* position); ///< sf::SoundStream::onLoop mixin
45+
46+
4347
////////////////////////////////////////////////////////////
4448
/// \brief defines the data to fill by the OnGetData callback
4549
///
4650
////////////////////////////////////////////////////////////
4751
typedef struct
4852
{
49-
int16_t* samples; ///< Pointer to the audio samples
50-
unsigned int sampleCount; ///< Number of samples pointed by Samples
53+
const int16_t* samples; ///< Pointer to the audio samples
54+
size_t sampleCount; ///< Number of samples pointed by Samples
5155
} sfSoundStreamChunk;
5256

5357
typedef bool (*sfSoundStreamGetDataCallback)(sfSoundStreamChunk*, void*); ///< Type of the callback used to get a sound stream data
5458
typedef void (*sfSoundStreamSeekCallback)(sfTime, void*); ///< Type of the callback used to seek in a sound stream
5559

5660

61+
////////////////////////////////////////////////////////////
62+
/// \brief Override the behaviour of changing the current
63+
/// playing position in the stream source to the loop offset
64+
///
65+
/// This function can be overridden to allow implementation of
66+
/// custom loop points. Otherwise, it just calls `onSeek(Time::Zero)` and returns 0.
67+
///
68+
/// \param soundStream SoundStream object
69+
/// \param mixin Method override to set, a null override restores the original behaviour
70+
///
71+
////////////////////////////////////////////////////////////
72+
CSFML_AUDIO_API void sfSoundStream_setOnLoop(sfSoundStream* soundStream, sfSoundStreamOnLoopMixin mixin);
73+
74+
5775
////////////////////////////////////////////////////////////
5876
/// \brief Create a new sound stream
5977
///

src/CSFML/Audio/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ set(SRC
1010
${INCROOT}/Listener.h
1111
${SRCROOT}/Music.cpp
1212
${SRCROOT}/MusicStruct.hpp
13+
${SRCROOT}/MusicStruct.cpp
1314
${INCROOT}/Music.h
1415
${SRCROOT}/Sound.cpp
1516
${SRCROOT}/SoundStruct.hpp
@@ -27,6 +28,7 @@ set(SRC
2728
${INCROOT}/SoundSourceCone.h
2829
${INCROOT}/SoundStatus.h
2930
${SRCROOT}/SoundStream.cpp
31+
${SRCROOT}/SoundStreamStruct.cpp
3032
${SRCROOT}/SoundStreamStruct.hpp
3133
${INCROOT}/SoundStream.h
3234
${INCROOT}/Types.h

src/CSFML/Audio/Music.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,28 @@
3434

3535
#include <cstring>
3636

37+
38+
////////////////////////////////////////////////////////////
39+
void sfMusic_setOnGetData(sfMusic* music, sfMusicOnGetDataMixin mixin)
40+
{
41+
music->OnGetDataMixin = mixin;
42+
}
43+
44+
45+
////////////////////////////////////////////////////////////
46+
void sfMusic_setOnSeek(sfMusic* music, sfMusicOnSeekMixin mixin)
47+
{
48+
music->OnSeekMixin = mixin;
49+
}
50+
51+
52+
////////////////////////////////////////////////////////////
53+
void sfMusic_setOnLoop(sfMusic* music, sfMusicOnLoopMixin mixin)
54+
{
55+
music->OnLoopMixin = mixin;
56+
}
57+
58+
3759
////////////////////////////////////////////////////////////
3860
sfMusic* sfMusic_createFromFile(const char* filename)
3961
{

src/CSFML/Audio/MusicStruct.cpp

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
////////////////////////////////////////////////////////////
2+
//
3+
// SFML - Simple and Fast Multimedia Library
4+
// Copyright (C) 2007-2024 Laurent Gomila ([email protected])
5+
//
6+
// This software is provided 'as-is', without any express or implied warranty.
7+
// In no event will the authors be held liable for any damages arising from the use of this software.
8+
//
9+
// Permission is granted to anyone to use this software for any purpose,
10+
// including commercial applications, and to alter it and redistribute it freely,
11+
// subject to the following restrictions:
12+
//
13+
// 1. The origin of this software must not be misrepresented;
14+
// you must not claim that you wrote the original software.
15+
// If you use this software in a product, an acknowledgment
16+
// in the product documentation would be appreciated but is not required.
17+
//
18+
// 2. Altered source versions must be plainly marked as such,
19+
// and must not be misrepresented as being the original software.
20+
//
21+
// 3. This notice may not be removed or altered from any source distribution.
22+
//
23+
////////////////////////////////////////////////////////////
24+
25+
////////////////////////////////////////////////////////////
26+
// Headers
27+
////////////////////////////////////////////////////////////
28+
#include <CSFML/Audio/MusicStruct.hpp>
29+
30+
31+
////////////////////////////////////////////////////////////
32+
bool sfMusic::onGetDataOriginal(sfMusic* music, sfSoundStreamChunk* data)
33+
{
34+
sf::SoundStream::Chunk cppData;
35+
36+
cppData.samples = data->samples;
37+
cppData.sampleCount = data->sampleCount;
38+
39+
bool result = music->sf::Music::onGetData(cppData);
40+
41+
data->samples = cppData.samples;
42+
data->sampleCount = cppData.sampleCount;
43+
44+
return result;
45+
}
46+
47+
48+
////////////////////////////////////////////////////////////
49+
bool sfMusic::onGetData(sf::SoundStream::Chunk& data)
50+
{
51+
if (!OnGetDataMixin)
52+
return sf::Music::onGetData(data);
53+
54+
sfSoundStreamChunk cData;
55+
56+
cData.samples = data.samples;
57+
cData.sampleCount = data.sampleCount;
58+
59+
bool result = OnGetDataMixin(onGetDataOriginal, this, &cData);
60+
61+
data.samples = cData.samples;
62+
data.sampleCount = cData.sampleCount;
63+
64+
return result;
65+
}
66+
67+
68+
////////////////////////////////////////////////////////////
69+
void sfMusic::onSeekOriginal(sfMusic* music, sfTime timeOffset)
70+
{
71+
return music->sf::Music::onSeek(sf::microseconds(timeOffset.microseconds));
72+
}
73+
74+
75+
////////////////////////////////////////////////////////////
76+
void sfMusic::onSeek(sf::Time timeOffset)
77+
{
78+
if (!OnSeekMixin)
79+
return sf::Music::onSeek(timeOffset);
80+
81+
return OnSeekMixin(onSeekOriginal, this, {timeOffset.asMicroseconds()});
82+
}
83+
84+
85+
////////////////////////////////////////////////////////////
86+
bool sfMusic::onLoopOriginal(sfMusic* music, uint64_t* position)
87+
{
88+
auto result = music->sf::Music::onLoop();
89+
90+
if (!result)
91+
{
92+
return false;
93+
}
94+
95+
*position = *result;
96+
return true;
97+
}
98+
99+
100+
////////////////////////////////////////////////////////////
101+
std::optional<std::uint64_t> sfMusic::onLoop()
102+
{
103+
if (!OnLoopMixin)
104+
return sf::Music::onLoop();
105+
106+
std::uint64_t data = 0;
107+
108+
bool noLoop = OnLoopMixin(onLoopOriginal, this, &data);
109+
110+
return noLoop ? std::nullopt : std::optional(data);
111+
}

src/CSFML/Audio/MusicStruct.hpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
////////////////////////////////////////////////////////////
2828
// Headers
2929
////////////////////////////////////////////////////////////
30+
#include <CSFML/Audio/Music.h>
3031
#include <CSFML/Audio/SoundChannel.h>
3132
#include <CSFML/CallbackStream.hpp>
3233

@@ -42,4 +43,16 @@ struct sfMusic : sf::Music
4243
{
4344
mutable std::vector<sfSoundChannel> Channels;
4445
CallbackStream Stream;
46+
47+
sfMusicOnGetDataMixin OnGetDataMixin = nullptr;
48+
static bool onGetDataOriginal(sfMusic* music, sfSoundStreamChunk* data);
49+
bool onGetData(Chunk& data) override;
50+
51+
sfMusicOnSeekMixin OnSeekMixin = nullptr;
52+
static void onSeekOriginal(sfMusic* music, sfTime timeOffset);
53+
void onSeek(sf::Time timeOffset) override;
54+
55+
sfMusicOnLoopMixin OnLoopMixin = nullptr;
56+
static bool onLoopOriginal(sfMusic* music, uint64_t* position);
57+
std::optional<std::uint64_t> onLoop() override;
4558
};

src/CSFML/Audio/SoundStream.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@
3333
#include <cstring>
3434

3535

36+
////////////////////////////////////////////////////////////
37+
void sfSoundStream_setOnLoop(sfSoundStream* soundStream, sfSoundStreamOnLoopMixin mixin)
38+
{
39+
soundStream->OnLoopMixin = mixin;
40+
}
41+
42+
3643
////////////////////////////////////////////////////////////
3744
sfSoundStream* sfSoundStream_create(
3845
sfSoundStreamGetDataCallback onGetData,

src/CSFML/Audio/SoundStreamStruct.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
////////////////////////////////////////////////////////////
2+
//
3+
// SFML - Simple and Fast Multimedia Library
4+
// Copyright (C) 2007-2024 Laurent Gomila ([email protected])
5+
//
6+
// This software is provided 'as-is', without any express or implied warranty.
7+
// In no event will the authors be held liable for any damages arising from the use of this software.
8+
//
9+
// Permission is granted to anyone to use this software for any purpose,
10+
// including commercial applications, and to alter it and redistribute it freely,
11+
// subject to the following restrictions:
12+
//
13+
// 1. The origin of this software must not be misrepresented;
14+
// you must not claim that you wrote the original software.
15+
// If you use this software in a product, an acknowledgment
16+
// in the product documentation would be appreciated but is not required.
17+
//
18+
// 2. Altered source versions must be plainly marked as such,
19+
// and must not be misrepresented as being the original software.
20+
//
21+
// 3. This notice may not be removed or altered from any source distribution.
22+
//
23+
////////////////////////////////////////////////////////////
24+
25+
////////////////////////////////////////////////////////////
26+
// Headers
27+
////////////////////////////////////////////////////////////
28+
#include <CSFML/Audio/SoundStreamStruct.hpp>
29+
30+
bool sfSoundStream::onLoopOriginal(sfSoundStream* music, uint64_t* position)
31+
{
32+
auto result = music->sf::SoundStream::onLoop();
33+
34+
if (!result)
35+
{
36+
return false;
37+
}
38+
39+
*position = *result;
40+
return true;
41+
}
42+
43+
std::optional<std::uint64_t> sfSoundStream::onLoop()
44+
{
45+
if (!OnLoopMixin)
46+
return sf::SoundStream::onLoop();
47+
48+
std::uint64_t data = 0;
49+
50+
bool noLoop = OnLoopMixin(onLoopOriginal, this, &data);
51+
52+
return noLoop ? std::nullopt : std::optional(data);
53+
}

src/CSFML/Audio/SoundStreamStruct.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
// Headers
2929
////////////////////////////////////////////////////////////
3030
#include <CSFML/Audio/SoundChannel.h>
31+
#include <CSFML/Audio/SoundStream.h>
3132

3233
#include <SFML/Audio/SoundStream.hpp>
3334

@@ -57,7 +58,6 @@ struct sfSoundStream : sf::SoundStream
5758

5859
mutable std::vector<sfSoundChannel> Channels;
5960

60-
private:
6161
bool onGetData(Chunk& data) override
6262
{
6363
sfSoundStreamChunk chunk = {nullptr, 0};
@@ -78,6 +78,10 @@ struct sfSoundStream : sf::SoundStream
7878
}
7979
}
8080

81+
sfSoundStreamOnLoopMixin OnLoopMixin = nullptr;
82+
static bool onLoopOriginal(sfSoundStream* music, uint64_t* position);
83+
std::optional<std::uint64_t> onLoop() override;
84+
8185
sfSoundStreamGetDataCallback myGetDataCallback;
8286
sfSoundStreamSeekCallback mySeekCallback;
8387
void* myUserData;

0 commit comments

Comments
 (0)