start sketching
This commit is contained in:
parent
3bdf262068
commit
1d0a4cafe2
@ -102,6 +102,11 @@ target_sources(tomato PUBLIC
|
|||||||
|
|
||||||
./chat_gui4.hpp
|
./chat_gui4.hpp
|
||||||
./chat_gui4.cpp
|
./chat_gui4.cpp
|
||||||
|
|
||||||
|
./content/content.hpp
|
||||||
|
./content/stream_reader.hpp
|
||||||
|
./content/stream_reader_sdl_audio.hpp
|
||||||
|
./content/stream_reader_sdl_audio.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if (TOMATO_TOX_AV)
|
if (TOMATO_TOX_AV)
|
||||||
|
48
src/content/content.hpp
Normal file
48
src/content/content.hpp
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <entt/entity/registry.hpp>
|
||||||
|
#include <entt/entity/handle.hpp>
|
||||||
|
#include <entt/container/dense_set.hpp>
|
||||||
|
|
||||||
|
#include <solanaceae/contact/contact_model3.hpp>
|
||||||
|
#include <solanaceae/message3/registry_message_model.hpp>
|
||||||
|
|
||||||
|
#include <solanaceae/file/file2.hpp>
|
||||||
|
|
||||||
|
enum class Content1 : uint32_t {};
|
||||||
|
using ContentRegistry = entt::basic_registry<Content1>;
|
||||||
|
using ContentHandle = entt::basic_handle<ContentRegistry>;
|
||||||
|
|
||||||
|
namespace Content::Components {
|
||||||
|
|
||||||
|
// or something
|
||||||
|
struct TagFile {};
|
||||||
|
struct TagAudioStream {};
|
||||||
|
struct TagVideoStream {};
|
||||||
|
|
||||||
|
// the associated messages, if any
|
||||||
|
// useful if you want to update progress on the message
|
||||||
|
struct Messages {
|
||||||
|
std::vector<Message3Handle> messages;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ?
|
||||||
|
struct SuspectedParticipants {
|
||||||
|
entt::dense_set<Contact3> participants;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ReadHeadHint {
|
||||||
|
// points to the first byte we want
|
||||||
|
// this is just a hint, that can be set from outside
|
||||||
|
// to guide the sequential "piece picker" strategy
|
||||||
|
// the strategy *should* set this to the first byte we dont yet have
|
||||||
|
uint64_t offset_into_file {0u};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // Content::Components
|
||||||
|
|
||||||
|
// TODO: i have no idea
|
||||||
|
struct RawFile2ReadFromContentFactoryI {
|
||||||
|
virtual std::shared_ptr<File2I> open(ContentHandle h) = 0;
|
||||||
|
};
|
||||||
|
|
15
src/content/stream_reader.hpp
Normal file
15
src/content/stream_reader.hpp
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <solanaceae/util/span.hpp>
|
||||||
|
|
||||||
|
// most media that can be counted as "stream" comes in packets/frames/messages
|
||||||
|
// so this class provides an interface for ideal async fetching of frames
|
||||||
|
struct RawFrameStreamReaderI {
|
||||||
|
// return the number of ready frames in cache
|
||||||
|
// returns -1 if unknown
|
||||||
|
virtual int64_t have(void) = 0;
|
||||||
|
|
||||||
|
// get next frame, empty if none
|
||||||
|
virtual ByteSpan getNext(void) = 0;
|
||||||
|
};
|
||||||
|
|
39
src/content/stream_reader_sdl_audio.cpp
Normal file
39
src/content/stream_reader_sdl_audio.cpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#include "./stream_reader_sdl_audio.hpp"
|
||||||
|
|
||||||
|
SDLAudioFrameStreamReader::SDLAudioFrameStreamReader(int32_t buffer_size) : _buffer_size(buffer_size), _stream{nullptr, &SDL_DestroyAudioStream} {
|
||||||
|
_buffer.resize(_buffer_size);
|
||||||
|
|
||||||
|
const SDL_AudioSpec spec = { SDL_AUDIO_S16, 1, 48000 };
|
||||||
|
|
||||||
|
_stream = {
|
||||||
|
SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_CAPTURE, &spec, nullptr, nullptr),
|
||||||
|
&SDL_DestroyAudioStream
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Span<int16_t> SDLAudioFrameStreamReader::getNextAudioFrame(void) {
|
||||||
|
const int32_t needed_bytes = (_buffer.size() - _remaining_size) * sizeof(int16_t);
|
||||||
|
const auto read_bytes = SDL_GetAudioStreamData(_stream.get(), _buffer.data()+_remaining_size, needed_bytes);
|
||||||
|
if (read_bytes < 0) {
|
||||||
|
// error
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
if (read_bytes < needed_bytes) {
|
||||||
|
// HACK: we are just assuming here that sdl never gives us half a sample!
|
||||||
|
_remaining_size += read_bytes / sizeof(int16_t);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
_remaining_size = 0;
|
||||||
|
return Span<int16_t>{_buffer};
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t SDLAudioFrameStreamReader::have(void) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteSpan SDLAudioFrameStreamReader::getNext(void) {
|
||||||
|
auto next_frame_span = getNextAudioFrame();
|
||||||
|
return ByteSpan{reinterpret_cast<const uint8_t*>(next_frame_span.ptr), next_frame_span.size};
|
||||||
|
}
|
||||||
|
|
31
src/content/stream_reader_sdl_audio.hpp
Normal file
31
src/content/stream_reader_sdl_audio.hpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "./stream_reader.hpp"
|
||||||
|
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
struct SDLAudioFrameStreamReader : public RawFrameStreamReaderI {
|
||||||
|
// count samples per buffer
|
||||||
|
const int32_t _buffer_size {1024};
|
||||||
|
std::vector<int16_t> _buffer;
|
||||||
|
size_t _remaining_size {0}; // data still in buffer, that was remaining from last call and not enough to fill a full frame
|
||||||
|
|
||||||
|
// meh, empty default
|
||||||
|
std::unique_ptr<SDL_AudioStream, decltype(&SDL_DestroyAudioStream)> _stream;
|
||||||
|
|
||||||
|
// buffer_size in number of samples
|
||||||
|
SDLAudioFrameStreamReader(int32_t buffer_size = 1024);
|
||||||
|
|
||||||
|
// data owned by StreamReader, overwritten by next call to getNext*()
|
||||||
|
Span<int16_t> getNextAudioFrame(void);
|
||||||
|
|
||||||
|
public: // interface
|
||||||
|
int64_t have(void) override;
|
||||||
|
|
||||||
|
ByteSpan getNext(void) override;
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user