diff options
| author | 2025-01-17 12:12:01 -0500 | |
|---|---|---|
| committer | 2025-01-17 12:12:01 -0500 | |
| commit | 37684729283f62fd7f1e74bc2b318dc9ad2cb695 (patch) | |
| tree | 2f5be73bf64ac6573e35e8f499515659472a14c9 | |
| parent | d1f1eb9b3713a450c0736caad17febae0721af4d (diff) | |
| download | camu-37684729283f62fd7f1e74bc2b318dc9ad2cb695.tar.gz camu-37684729283f62fd7f1e74bc2b318dc9ad2cb695.tar.bz2 camu-37684729283f62fd7f1e74bc2b318dc9ad2cb695.zip | |
Account for dependency changes, platform testing
Signed-off-by: Andrew Opalach <andrew@akon.city>
59 files changed, 395 insertions, 347 deletions
@@ -27,6 +27,8 @@ subprojects/gperf/ subprojects/harfbuzz-*/ subprojects/jansson.wrap subprojects/jansson/ +subprojects/jsmn.wrap +subprojects/jsmn/ subprojects/libalabaster subprojects/libalabaster/ subprojects/libass-*/ diff --git a/docs/design.txt b/docs/design.txt index ef98961..9604efb 100644 --- a/docs/design.txt +++ b/docs/design.txt @@ -28,7 +28,7 @@ Nodes can be seen as distributed resource managers for the server. They each con Source Manager ^^^^^^^^^^^^^^ -A source manager implements any or all of browsing, searching, and custom resource actions. A big point of a source manager is to be able to work entirely behind a proxy. Some examples of sources may include a social media website, filesystem directory, dvd drive, or radio antenna. An example of browsing could be apple music's "New Music". An example of searching, youtube search. A custom action could be liking a post on twitter. +A source manager implements any or all of browsing, searching, and custom resource actions. A big point of a source manager is to be able to work entirely behind a proxy. Some examples of sources may include a social media website, filesystem directory, dvd drive, or radio antenna. An example of browsing could be Apple Music's "New Music". An example of searching, Youtube search. A custom action could be liking a post on Twitter. Database ^^^^^^^^ diff --git a/docs/style.css b/docs/style.css index f99c06c..f7722f7 100644 --- a/docs/style.css +++ b/docs/style.css @@ -1,13 +1,13 @@ body { font-family: serif; margin: 1em 35% 1em 5%; - background-color: #fef9fa; + background-color: #f9efe5; + color: #412f2d; } h3 { - text-decoration: underline; } strong { - color: #423152; + color: #934a5b; } @@ -16,24 +16,6 @@ "type": "github" } }, - "flake-utils": { - "inputs": { - "systems": "systems" - }, - "locked": { - "lastModified": 1731533236, - "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, "home-manager": { "inputs": { "nixpkgs": [ @@ -41,11 +23,11 @@ ] }, "locked": { - "lastModified": 1735925111, - "narHash": "sha256-/NptDI4njO5hH0ZVQ2yzbvTXmBOabZaGYkjhnMJ37TY=", + "lastModified": 1736883540, + "narHash": "sha256-dgPgoPUSg8cGAMqbhQRkww665sZtgzpWXxWjlyqhv94=", "owner": "nix-community", "repo": "home-manager", - "rev": "ef64efdbaca99f9960f75efab991e4c49e79a5f1", + "rev": "0dfec9deb275854a56c97c356c40ef72e3a2e632", "type": "github" }, "original": { @@ -57,11 +39,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1735388221, - "narHash": "sha256-e5IOgjQf0SZcFCEV/gMGrsI0gCJyqOKShBQU0iiM3Kg=", + "lastModified": 1736978406, + "narHash": "sha256-oMr3PVIQ8XPDI8/x6BHxsWEPBRU98Pam6KGVwUh8MPk=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "7c674c6734f61157e321db595dbfcd8523e04e19", + "rev": "b678606690027913f3434dea3864e712b862dde5", "type": "github" }, "original": { @@ -74,15 +56,14 @@ "nixos-wsl": { "inputs": { "flake-compat": "flake-compat", - "flake-utils": "flake-utils", "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1733854371, - "narHash": "sha256-K9qGHniYBbjqVcEiwXyiofj/IFf78L5F0/FCf+CKyr0=", + "lastModified": 1736095716, + "narHash": "sha256-csysw/Szu98QDiA2lhWk9seYOyCebeVEWL89zh1cduM=", "owner": "nix-community", "repo": "NixOS-WSL", - "rev": "dee4425dcee3149475ead0cb6a616b8a028c5888", + "rev": "63c3b4ed1712a3a0621002cd59bfdc80875ecbb0", "type": "github" }, "original": { @@ -110,11 +91,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1735834308, - "narHash": "sha256-dklw3AXr3OGO4/XT1Tu3Xz9n/we8GctZZ75ZWVqAVhk=", + "lastModified": 1736883708, + "narHash": "sha256-uQ+NQ0/xYU0N1CnXsa2zghgNaOPxWpMJXSUJJ9W7140=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "6df24922a1400241dae323af55f30e4318a6ca65", + "rev": "eb62e6aa39ea67e0b8018ba8ea077efe65807dc8", "type": "github" }, "original": { @@ -131,21 +112,6 @@ "nixos-wsl": "nixos-wsl", "nixpkgs": "nixpkgs_2" } - }, - "systems": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } } }, "root": "root", @@ -41,6 +41,7 @@ forAllDevSystems = function: nixpkgs.lib.genAttrs [ "x86_64-linux" + "i686-linux" ] (system: function (import nixpkgs { inherit system; @@ -89,15 +90,13 @@ ninja meson cmake - ant - jdk8 wayland-scanner ((python3.override { enableOptimizations = true; }).withPackages (python-pkgs: [ python-pkgs.setuptools python-pkgs.pip python-pkgs.cython ])) - ]; + ] ++ lib.optionals (system == "x86_64-linux") [ ant jdk8 ]; buildInputs = [ (curl.override { websocketSupport = true; }) jansson @@ -130,7 +129,6 @@ wayland-protocols wlr-protocols egl-wayland - libraspberrypi (notcurses.override { multimediaSupport = false; qrcodegenSupport = false; }) libsodium ]; diff --git a/meson.build b/meson.build index a1a4026..235b16a 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('camu', ['c', 'cpp'], version: '0.01', - default_options: ['warning_level=2', 'c_std=c99', 'cpp_std=c++20']) + default_options: ['warning_level=2', 'c_std=c99']) compiler = meson.get_compiler('c') cmake = import('cmake') @@ -10,10 +10,10 @@ is_linux = host_machine.system() == 'linux' is_windows = host_machine.system() == 'windows' is_android = host_machine.system() == 'android' -alabaster = subproject('libalabaster') +alabaster = subproject('libalabaster', default_options: ['tests=false']) naunet_opts = [] if not get_option('sink-only') - naunet_opts += ['json=enabled', 'curl=enabled'] + naunet_opts += ['json=enabled', 'curl=enabled', 'tests=false'] endif naunet = subproject('libnaunet', default_options: naunet_opts) naunet_has_curl = naunet.get_variable('naunet_has_curl') diff --git a/src/buffer/audio.c b/src/buffer/audio.c index 707219f..cf42840 100644 --- a/src/buffer/audio.c +++ b/src/buffer/audio.c @@ -5,13 +5,13 @@ #endif #include "audio.h" +#include "volume.h" #include "common.h" #include "common_internal.h" -#include "volume.h" -#define BUFFER_SIZE 4.0 -#define BUFFER_MARK_MIN 1.75 // Must be a most half of the buffer size. -#define BUFFER_MARK_BUFFERED 1.0 +#define BUFFER_SIZE 8.0 +#define BUFFER_MARK_MIN 3.25 // Must be a most half of the buffer size. +#define BUFFER_MARK_BUFFERED 1.25 #ifdef CAMU_AUDIO_BUFFER_FADE #define FADE_STEP(fmt) (1.75f / (fmt)->sample_rate) @@ -37,7 +37,7 @@ static void reset_buffer_state(struct camu_audio_buffer *buf) #endif buf->buffered = false; al_atomic_store(u8)(&buf->flow, FLOWING, AL_ATOMIC_RELAXED); - al_atomic_store(size_t)(&buf->uncork_at, 0, AL_ATOMIC_RELAXED); + al_atomic_store(ptrdiff_t)(&buf->uncork_at, 0, AL_ATOMIC_RELAXED); } bool camu_audio_buffer_init(struct camu_audio_buffer *buf, struct camu_clock *clock) @@ -77,12 +77,12 @@ bool camu_audio_buffer_configure(struct camu_audio_buffer *buf, struct camu_code in_format_name, buf->fmt.in.channel_count, buf->fmt.in.sample_rate, req_format_name, buf->fmt.req.channel_count, buf->fmt.req.sample_rate); - buf->size = camu_audio_format_sec_to_bytes(&buf->fmt.req, BUFFER_SIZE); + buf->size = (ptrdiff_t)camu_audio_format_sec_to_bytes(&buf->fmt.req, BUFFER_SIZE); buf->data = (u8 *)al_malloc(buf->size); al_ring_buffer_init(&buf->rb, buf->data, buf->size); - buf->mark.min = camu_audio_format_sec_to_bytes(&buf->fmt.req, BUFFER_MARK_MIN); - buf->mark.buffered = camu_audio_format_sec_to_bytes(&buf->fmt.req, BUFFER_MARK_BUFFERED); + buf->mark.min = (ptrdiff_t)camu_audio_format_sec_to_bytes(&buf->fmt.req, BUFFER_MARK_MIN); + buf->mark.buffered = (ptrdiff_t)camu_audio_format_sec_to_bytes(&buf->fmt.req, BUFFER_MARK_BUFFERED); camu_peak_buffer_init(&buf->peak, KB(16)); buf->stream = stream; @@ -118,12 +118,6 @@ void camu_audio_buffer_set_no_video(struct camu_audio_buffer *buf, bool no_video #define BUFFERED_SECONDS_DEBUG(buf) 0 #endif -static inline bool frame_is_late(struct camu_clock *clock, f64 base, f64 pts, f64 duration) -{ - if (base == -1.0) base = camu_clock_get_base_pts(clock); - return pts + duration < base; -} - // A return value of false signals that we pushed to the peak buffer. static bool push_internal(struct camu_audio_buffer *buf, f64 pts, u8 **data, s32 sample_count) { @@ -157,15 +151,15 @@ static bool push_internal(struct camu_audio_buffer *buf, f64 pts, u8 **data, s32 return true; } - size_t space = al_ring_buffer_space(&buf->rb); + ptrdiff_t space = al_ring_buffer_space(&buf->rb); if (!buf->buffered && buf->size - space > buf->mark.buffered) { al_log_debug("audio_buffer", "Buffered (mark: %.2fs).", BUFFERED_SECONDS_DEBUG(buf)); buf->callback(buf->userdata, CAMU_BUFFER_BUFFERED); buf->buffered = true; } - size_t have = camu_audio_format_samples_to_bytes(&buf->fmt.req, (size_t)sample_count); - size_t peak = camu_peak_buffer_get_size(&buf->peak); + ptrdiff_t have = (ptrdiff_t)camu_audio_format_samples_to_bytes(&buf->fmt.req, sample_count); + ptrdiff_t peak = camu_peak_buffer_get_size(&buf->peak); if (space < have + peak) { al_assert(have < buf->mark.min); camu_peak_buffer_push(&buf->peak, data[0], have); @@ -178,7 +172,7 @@ static bool push_internal(struct camu_audio_buffer *buf, f64 pts, u8 **data, s32 } al_assert(peak <= buf->mark.min); // We adjust the min mark by the peak buffer size just for consistency. - al_atomic_store(size_t)(&buf->uncork_at, buf->mark.min - peak, AL_ATOMIC_RELAXED); + al_atomic_store(ptrdiff_t)(&buf->uncork_at, buf->mark.min - peak, AL_ATOMIC_RELAXED); buf->callback(buf->userdata, CAMU_BUFFER_CORK); return false; } @@ -264,7 +258,7 @@ void camu_audio_buffer_unpause(struct camu_audio_buffer *buf) // PAUSE_PAUSED signifies that the last read was silence. Meaning we can skip // around in the buffer without worrying about pops. -size_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, size_t req) +ptrdiff_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, ptrdiff_t req) { if (al_atomic_load(s32)(&buf->volume.set, AL_ATOMIC_ACQUIRE) > 0) { buf->volume.user = al_atomic_load(f32)(&buf->volume.queued, AL_ATOMIC_RELAXED); @@ -315,8 +309,8 @@ size_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, size_t re } struct camu_audio_format *fmt = &buf->fmt.req; - size_t ret, signal = req; - size_t have = al_ring_buffer_occupied(&buf->rb); + ptrdiff_t ret, signal = req; + ptrdiff_t have = al_ring_buffer_occupied(&buf->rb); #ifdef CAMU_AUDIO_BUFFER_FADE // Cut off fade if it's reaching too far. if (have < buf->fade.offset) have = 0; @@ -329,16 +323,16 @@ size_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, size_t re if (!buf->ignore_desync) { pts -= base_pts; if (pts > 0.0) { // Skip. - ret = camu_audio_format_sec_to_bytes(fmt, pts); + ret = (ptrdiff_t)camu_audio_format_sec_to_bytes(fmt, pts); ret = MIN(ret, have); - al_log_info("audio_buffer", "Skipping %fs of audio (%zu bytes).", pts, ret); + al_log_info("audio_buffer", "Skipping %fs of audio (%zd bytes).", pts, ret); ret = al_ring_buffer_discard(&buf->rb, ret); have -= ret; base_pts += camu_audio_format_bytes_to_sec(fmt, ret); // Could go on to underrun. } else if (pts < 0.0) { // Delay. pts = -pts; - ret = camu_audio_format_sec_to_bytes(fmt, pts); + ret = (ptrdiff_t)camu_audio_format_sec_to_bytes(fmt, pts); ret = MIN(ret, req); al_log_info("audio_buffer", "Delaying audio by %fs.", pts); al_memset(data, 0, ret); @@ -366,7 +360,7 @@ size_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, size_t re // enough for this request. if (have < req) { signal = have; - al_log_debug("audio_buffer", "Flushed (signal: %zu).", signal); + al_log_debug("audio_buffer", "Flushed (signal: %zd).", signal); buf->callback(buf->userdata, CAMU_BUFFER_EOF); al_atomic_store(u8)(&buf->flow, SIGNALED, AL_ATOMIC_RELEASE); } @@ -377,7 +371,7 @@ size_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, size_t re // We hit an underrun because data wasn't coming in fast enough. // An underrun can also happen in the audio output if read() (this function) // takes too long. That isn't checked here. - al_log_warn("audio_buffer", "Underrun (req: %zu, have: %zu).", req, have); + al_log_warn("audio_buffer", "Underrun (req: %zd, have: %zd).", req, have); // If we have data by the next read(), try to skip ahead to maintain sync. // This might exacerbate the underrun issue but an underrun is already // unexpected behavior, trying to stay in sync comes first. @@ -435,7 +429,7 @@ size_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, size_t re #else if (flow == FLOWING) { #endif - ret = al_atomic_load(size_t)(&buf->uncork_at, AL_ATOMIC_RELAXED); + ret = al_atomic_load(ptrdiff_t)(&buf->uncork_at, AL_ATOMIC_RELAXED); if (ret && have - req <= ret) { buf->callback(buf->userdata, CAMU_BUFFER_UNCORK); } diff --git a/src/buffer/audio.h b/src/buffer/audio.h index ca2d405..901becf 100644 --- a/src/buffer/audio.h +++ b/src/buffer/audio.h @@ -27,15 +27,15 @@ struct camu_audio_buffer { struct camu_resampler *resampler; u8 *data; - size_t size; + ptrdiff_t size; struct al_ring_buffer rb; - struct { size_t min, buffered; } mark; + struct { ptrdiff_t min, buffered; } mark; bool buffered; atomic(u8) flow; struct camu_peak_buffer peak; - atomic(size_t) uncork_at; + atomic(ptrdiff_t) uncork_at; struct { f32 user; @@ -46,7 +46,7 @@ struct camu_audio_buffer { #ifdef CAMU_AUDIO_BUFFER_FADE struct { f32 volume; - size_t offset; + ptrdiff_t offset; } fade; #endif @@ -69,5 +69,5 @@ void camu_audio_buffer_push(struct camu_audio_buffer *buf, struct camu_codec_fra void camu_audio_buffer_flush(struct camu_audio_buffer *buf); void camu_audio_buffer_reset(struct camu_audio_buffer *buf); void camu_audio_buffer_unpause(struct camu_audio_buffer *buf); -size_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, size_t req); +ptrdiff_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, ptrdiff_t req); void camu_audio_buffer_free(struct camu_audio_buffer *buf); diff --git a/src/buffer/common_internal.h b/src/buffer/common_internal.h index e4cdd33..11caddc 100644 --- a/src/buffer/common_internal.h +++ b/src/buffer/common_internal.h @@ -1,5 +1,9 @@ #pragma once +#include <al/types.h> + +#include "clock.h" + enum { // Flowing. FLOWING, @@ -10,3 +14,9 @@ enum { // Errored. ERRORED }; + +static inline bool frame_is_late(struct camu_clock *clock, f64 base, f64 pts, f64 duration) +{ + if (base == -1.0) base = camu_clock_get_base_pts(clock); + return pts + duration < base; +} diff --git a/src/buffer/peak_buffer.c b/src/buffer/peak_buffer.c index 9687a1f..c1fe254 100644 --- a/src/buffer/peak_buffer.c +++ b/src/buffer/peak_buffer.c @@ -2,20 +2,22 @@ // https://github.com/MusicPlayerDaemon/MPD/blob/c71e586c530e1d066efde7c2ca40c363f74100c7/src/util/PeakBuffer.cxx -void camu_peak_buffer_init(struct camu_peak_buffer *buf, size_t size) +// We use ptrdiff_t here instead of nn_buffer's size_t just to map better to the types in audio_buffer. + +void camu_peak_buffer_init(struct camu_peak_buffer *buf, ptrdiff_t size) { nn_buffer_init(&buf->buf); - nn_buffer_ensure_space(&buf->buf, size); + nn_buffer_ensure_space(&buf->buf, (size_t)size); } -void camu_peak_buffer_push(struct camu_peak_buffer *buf, u8 *data, size_t size) +void camu_peak_buffer_push(struct camu_peak_buffer *buf, u8 *data, ptrdiff_t size) { - nn_buffer_append(&buf->buf, data, size); + nn_buffer_append(&buf->buf, data, (size_t)size); } -size_t camu_peak_buffer_get_size(struct camu_peak_buffer *buf) +ptrdiff_t camu_peak_buffer_get_size(struct camu_peak_buffer *buf) { - return nn_buffer_get_size(&buf->buf); + return (ptrdiff_t)nn_buffer_get_size(&buf->buf); } u8 *camu_peak_buffer_flush(struct camu_peak_buffer *buf) diff --git a/src/buffer/peak_buffer.h b/src/buffer/peak_buffer.h index 9bd3316..73465ec 100644 --- a/src/buffer/peak_buffer.h +++ b/src/buffer/peak_buffer.h @@ -7,8 +7,8 @@ struct camu_peak_buffer { struct nn_buffer buf; }; -void camu_peak_buffer_init(struct camu_peak_buffer *buf, size_t size); -void camu_peak_buffer_push(struct camu_peak_buffer *buf, u8 *data, size_t size); -size_t camu_peak_buffer_get_size(struct camu_peak_buffer *buf); +void camu_peak_buffer_init(struct camu_peak_buffer *buf, ptrdiff_t size); +void camu_peak_buffer_push(struct camu_peak_buffer *buf, u8 *data, ptrdiff_t size); +ptrdiff_t camu_peak_buffer_get_size(struct camu_peak_buffer *buf); u8 *camu_peak_buffer_flush(struct camu_peak_buffer *buf); void camu_peak_buffer_free(struct camu_peak_buffer *buf); diff --git a/src/buffer/video.c b/src/buffer/video.c index 47c1ea9..01f317e 100644 --- a/src/buffer/video.c +++ b/src/buffer/video.c @@ -10,9 +10,9 @@ #endif #endif -#define BUFFER_MARK_LOW ((1.0 / 30.0) * 4) +#define BUFFER_MARK_LOW ((1.0 / 30.0) * 6) #define BUFFER_MARK_BUFFERED ((1.0 / 30.0) * 5) -#define BUFFER_MARK_HIGH ((1.0 / 30.0) * 10) +#define BUFFER_MARK_HIGH ((1.0 / 30.0) * 12) #define BUFFER_MARK_RESET (BUFFER_MARK_HIGH * 2.0) bool camu_video_buffer_init(struct camu_video_buffer *buf, struct camu_clock *clock) @@ -46,11 +46,17 @@ bool camu_video_buffer_configure(struct camu_video_buffer *buf, struct camu_code struct camu_video_format *fmt = &buf->stream->video.fmt; switch (stream->mode) { case CAMU_NORMAL: { - buf->single_frame = true; camu_video_format_copy(&buf->fmt.in, fmt); + + buf->single_frame = true; + buf->avg_frame_duration = 0.0; + const char *format_name = camu_pixel_format_name(fmt->format); if (!format_name) format_name = "unknown"; - al_log_info("video_buffer", "Stream: %s (%dx%d) %s.", format_name, fmt->width, fmt->height, "IMAGE"); + + al_log_info("video_buffer", "Stream: %s (%dx%d) %s.", + format_name, fmt->width, fmt->height, "IMAGE"); + break; } #ifdef CAMU_HAVE_FFMPEG @@ -64,12 +70,16 @@ bool camu_video_buffer_configure(struct camu_video_buffer *buf, struct camu_code camu_video_format_copy(&buf->fmt.in, fmt); buf->single_frame = stream->duration == 0 || frame_rate.den == 0; - if (buf->single_frame) frame_rate = (AVRational){ 0, 1 }; buf->avg_frame_duration = buf->single_frame ? 0.0 : av_q2d(av_inv_q(frame_rate)); const char *format_name = av_get_pix_fmt_name(buf->fmt.in.format); - al_log_info("video_buffer", "Stream: %s (%dx%d) %s %.2ffps.", - format_name, fmt->width, fmt->height, buf->single_frame ? "IMAGE" : "VIDEO", av_q2d(frame_rate)); + if (buf->single_frame) { + al_log_info("video_buffer", "Stream: %s (%dx%d) %s.", + format_name, fmt->width, fmt->height, "IMAGE"); + } else { + al_log_info("video_buffer", "Stream: %s (%dx%d) %s %.3ffps.", + format_name, fmt->width, fmt->height, "VIDEO", av_q2d(frame_rate)); + } break; } @@ -129,13 +139,17 @@ static void after_push_internal(struct camu_video_buffer *buf) if (!buf->buffered && (buf->single_frame || have >= BUFFER_MARK_BUFFERED)) { // Preserve order of: flush -> callback -> set flow, for single frames. - if (buf->single_frame) buf->queue->flush(buf->queue); + if (buf->single_frame) { + buf->queue->flush(buf->queue); + } al_log_debug("video_buffer", "Buffered (mark: %.2fs).", have); buf->callback(buf->userdata, CAMU_BUFFER_BUFFERED); buf->buffered = true; - if (buf->single_frame) al_atomic_store(u8)(&buf->flow, FLUSHED, AL_ATOMIC_RELAXED); + if (buf->single_frame) { + al_atomic_store(u8)(&buf->flow, FLUSHED, AL_ATOMIC_RELAXED); + } } if (have >= BUFFER_MARK_RESET) { @@ -146,12 +160,6 @@ static void after_push_internal(struct camu_video_buffer *buf) } } -static inline bool frame_is_late(struct camu_clock *clock, f64 base, f64 pts, f64 duration) -{ - if (base == -1.0) base = camu_clock_get_base_pts(clock); - return pts + duration < base; -} - #ifdef CAMU_HAVE_FFMPEG static bool push_av_frame_internal(struct camu_video_buffer *buf, AVFrame *frame) { @@ -248,6 +256,7 @@ bool camu_video_buffer_read(struct camu_video_buffer *buf, void *out, bool *weig al_atomic_store(f64)(&buf->pts, base, AL_ATOMIC_RELEASE); } } + u8 ret = buf->queue->read(buf->queue, base, out); u8 flow = al_atomic_load(u8)(&buf->flow, AL_ATOMIC_ACQUIRE); if (ret == CAMU_QUEUE_ERR) { diff --git a/src/cache/backings/file_common.c b/src/cache/backings/file_common.c index 3914f95..0ee2574 100644 --- a/src/cache/backings/file_common.c +++ b/src/cache/backings/file_common.c @@ -9,7 +9,7 @@ static off_t file_backing_get_size_estimate(struct cch_backing *backing) static bool file_open_internal(struct cch_backing_file *file, str *path, size_t size) { - s32 flags = size != 0 ? NNWT_FILE_CREATE : 0; + s32 flags = size != 0 ? NNWT_FILE_CREATE : NNWT_FILE_READONLY; if (!nn_file_open(&file->file, path, flags)) return false; file->filesize = nn_file_get_filesize(&file->file); if (!size) { diff --git a/src/cache/handlers/cdio.c b/src/cache/handlers/cdio.c index ffaaa62..ac90c03 100644 --- a/src/cache/handlers/cdio.c +++ b/src/cache/handlers/cdio.c @@ -184,7 +184,7 @@ static bool open_cd_drive(struct cch_handler_cdio *cdio) struct cch_entry *cch_handler_cdio_create(void) { - struct cch_backing *backing = cch_backing_file_create(al_str_c("/tmp/camu_cd_data"), 4096); + struct cch_backing *backing = cch_backing_file_create(&al_str_c("/tmp/camu_cd_data"), 4096); if (!backing) return NULL; struct cch_handler_cdio *cdio = al_alloc_object(struct cch_handler_cdio); cdio->backing = backing; diff --git a/src/cache/handlers/http.c b/src/cache/handlers/http.c index b5f2504..3bbb751 100644 --- a/src/cache/handlers/http.c +++ b/src/cache/handlers/http.c @@ -8,7 +8,7 @@ #include "http.h" -#define USER_AGENT al_str_c("Mozilla/5.0 (Windows NT 10.0; rv:122.0) Gecko/20100101 Firefox/122.0") +static str USER_AGENT = al_str_c("Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:134.0) Gecko/20100101 Firefox/134.0"); static bool handler_http_can_seek(struct cch_handler *handler) { @@ -70,8 +70,9 @@ static void handler_http_maybe_spawn_worker(struct cch_handler *handler, size_t struct nn_http *request = &al_array_last(http->requests); nn_http_init(request); nn_http_set_url(request, &http->url); - nn_http_set_user_agent(request, USER_AGENT); + nn_http_set_user_agent(request, &USER_AGENT); nn_http_request_stream(request, NNWT_HTTP_GET, http->loop, http_callback, http); + al_log_debug("cache_handler_http", "Spawning worker for %.*s.", al_str_fmt(&http->url)); } static bool handler_http_wait_for_range(struct cch_handler *handler, struct cch_handler_wait *wait) diff --git a/src/codec/codec.h b/src/codec/codec.h index fac3be8..b70e3cb 100644 --- a/src/codec/codec.h +++ b/src/codec/codec.h @@ -248,10 +248,10 @@ static const char *camu_audio_format_name(s32 format) #endif } -static inline s32 camu_audio_format_bytes_per_sample(struct camu_audio_format *fmt) +static inline size_t camu_audio_format_bytes_per_sample(struct camu_audio_format *fmt) { #ifdef CAMU_HAVE_FFMPEG - return av_get_bytes_per_sample(fmt->format); + return (size_t)av_get_bytes_per_sample(fmt->format); #else switch (fmt->format) { case CAMU_SAMPLE_FORMAT_U8: @@ -271,15 +271,14 @@ static inline s32 camu_audio_format_bytes_per_sample(struct camu_audio_format *f case CAMU_SAMPLE_FORMAT_DBLP: return 8; default: - al_assert_and_return(-1); + al_assert_and_return(0); } #endif } static inline size_t camu_audio_format_samples_to_bytes(struct camu_audio_format *fmt, size_t samples) { - s32 bytes_per_sample = camu_audio_format_bytes_per_sample(fmt); - return samples * bytes_per_sample * fmt->channel_count; + return samples * camu_audio_format_bytes_per_sample(fmt) * fmt->channel_count; } static inline f64 camu_audio_format_samples_to_sec(struct camu_audio_format *fmt, size_t samples) diff --git a/src/fruits/cmc/cmc.c b/src/fruits/cmc/cmc.c index 35f2d9b..af3e567 100644 --- a/src/fruits/cmc/cmc.c +++ b/src/fruits/cmc/cmc.c @@ -58,7 +58,7 @@ static void client_callback(void *userdata, u8 op, void *opaque) case CLI_ADD: { str *arg; al_array_foreach_ptr(c->args, i, arg) { - camu_client_add_from_path(&c->client, al_str_c("default"), arg); + camu_client_add_from_path(&c->client, &al_str_c("default"), arg); al_str_free(arg); } camu_client_disconnect(&c->client); @@ -67,7 +67,7 @@ static void client_callback(void *userdata, u8 op, void *opaque) case CLI_SEARCH: { str *arg; al_array_foreach_ptr(c->args, i, arg) { - camu_client_create_search(&c->client, al_str_c("youtube"), arg); + camu_client_create_search(&c->client, &al_str_c("youtube"), arg); al_str_free(arg); } camu_client_disconnect(&c->client); @@ -106,7 +106,7 @@ static void client_callback(void *userdata, u8 op, void *opaque) al_array_push(page->list, s); } al_array_push(search->pages, page); - camu_client_add_from_post(&c->client, al_str_c("default"), &al_array_at(page->list, 0), 0); + camu_client_add_from_post(&c->client, &al_str_c("default"), &al_array_at(page->list, 0), 0); break; } } @@ -124,30 +124,32 @@ static bool parse_cmd(s32 argc, wchar_t **argv) c.command = CLI_OPEN_UI; return true; } - if (al_str_eq(al_str_cr(argv[1]), al_str_c("add"))) { + + if (al_str_eq(&al_str_cr(argv[1]), &al_str_c("add"))) { if (argc < 3) return false; c.command = CLI_ADD; char path[PATH_MAX]; str arg; for (s32 i = 2; i < argc; i++) { if (realpath(argv[i], path)) { - al_str_clone(&arg, al_str_cr(path)); + al_str_clone(&arg, &al_str_cs(path)); al_array_push(c.args, arg); } } - } else if (al_str_eq(al_str_cr(argv[1]), al_str_c("search"))) { + } else if (al_str_eq(&al_str_cr(argv[1]), &al_str_c("search"))) { if (argc < 3) return false; c.command = CLI_SEARCH; str query; al_str_from(&query, ""); for (s32 i = 2; i < argc; i++) { - al_str_cat(&query, al_str_cr(argv[i])); + al_str_cat(&query, &al_str_cr(argv[i])); if (i != argc - 1) { - al_str_cat(&query, al_str_c(" ")); + al_str_cat(&query, &al_str_c(" ")); } } al_array_push(c.args, query); } + return true; } @@ -169,7 +171,7 @@ s32 wmain(s32 argc, wchar_t **argv) c.client.callback = client_callback; c.client.userdata = &c; - if (!camu_client_login(&c.client, &c.loop, CAMU_TEST_TYPE, CAMU_TEST_ADDR, CAMU_PORT, al_str_c("andrew"))) { + if (!camu_client_login(&c.client, &c.loop, CAMU_TEST_TYPE, &CAMU_TEST_ADDR, CAMU_PORT, &al_str_c("andrew"))) { return EXIT_FAILURE; } diff --git a/src/fruits/cmc/ui/pane_search.c b/src/fruits/cmc/ui/pane_search.c index cc549e1..c3d1165 100644 --- a/src/fruits/cmc/ui/pane_search.c +++ b/src/fruits/cmc/ui/pane_search.c @@ -4,7 +4,7 @@ void cmc_sp_init(struct cmc_ui *ui) { - if (ui->c->searches.size > 0) { + if (ui->c->searches.count > 0) { ui->sp.search = al_array_at(ui->c->searches, 0); } cmc_sp_layout(ui, notcurses_stdplane(ui->nc)); diff --git a/src/fruits/cmsrv/cmsrv.c b/src/fruits/cmsrv/cmsrv.c index 6f00a05..4cd1691 100644 --- a/src/fruits/cmsrv/cmsrv.c +++ b/src/fruits/cmsrv/cmsrv.c @@ -39,19 +39,19 @@ static u8 server_line_callback(void *userdata, str *line) { struct cmsrv *s = (struct cmsrv *)userdata; struct lia_list *list = al_array_at(s->server.lists, 0); - if (al_str_eq(line, al_str_c(";PAUSE"))) { + if (al_str_eq(line, &al_str_c(";PAUSE"))) { lia_list_toggle_pause(list, LIANA_SEQUENCE_ANY, -1.0); - } else if (al_str_eq(line, al_str_c(";NEXT"))) { + } else if (al_str_eq(line, &al_str_c(";NEXT"))) { lia_list_skip(list, LIANA_SEQUENCE_ANY, 1); - } else if (al_str_eq(line, al_str_c(";PREV"))) { + } else if (al_str_eq(line, &al_str_c(";PREV"))) { lia_list_skip(list, LIANA_SEQUENCE_ANY, -1); - } else if (al_str_eq(line, al_str_c(";SHUFFLE"))) { + } else if (al_str_eq(line, &al_str_c(";SHUFFLE"))) { lia_list_shuffle(list); - } else if (al_str_eq(line, al_str_c(";SORT"))) { + } else if (al_str_eq(line, &al_str_c(";SORT"))) { lia_list_sort(list); - } else if (al_str_eq(line, al_str_c(";REVERSE"))) { + } else if (al_str_eq(line, &al_str_c(";REVERSE"))) { lia_list_reverse(list); - } else if (al_str_eq(line, al_str_c(";CLEAR"))) { + } else if (al_str_eq(line, &al_str_c(";CLEAR"))) { lia_list_clear(list); } else { struct nn_packet *packet = nn_packet_create(); @@ -63,7 +63,7 @@ static u8 server_line_callback(void *userdata, str *line) nn_packet_write_u8(packet, CAMU_RESOURCE_HTTP); #endif #if CACHE_HAVE_CDIO - } else if (al_str_cmp(line, al_str_c("cdda://"), 0, 7) == 0) { + } else if (al_str_cmp(line, &al_str_c("cdda://"), 0, 7) == 0) { nn_packet_write_u8(packet, CAMU_RESOURCE_CDIO); #endif } else { @@ -115,8 +115,8 @@ static s32 log_callback(void *userdata, u8 level, char *message) { struct cmsrv *s = (struct cmsrv *)userdata; (void)level; - cmsrv_ui_push_message(&s->ui, message); - return al_strlen(message); + cmsrv_ui_push_message(&s->ui, al_strndup(message, AL_LOG_MESSAGE_SIZE)); + return al_strnlen(message, AL_LOG_MESSAGE_SIZE); } #endif @@ -172,7 +172,7 @@ s32 wmain(s32 argc, wchar_t **argv) camu_server_init(&s.server, &s.loop); s.server.meta_callback = server_meta_callback; s.server.userdata = &s; - if (!camu_server_listen(&s.server, CAMU_TEST_TYPE, CAMU_TEST_ADDR, CAMU_PORT)) { + if (!camu_server_listen(&s.server, CAMU_TEST_TYPE, &CAMU_TEST_ADDR, CAMU_PORT)) { return EXIT_FAILURE; } @@ -181,9 +181,9 @@ s32 wmain(s32 argc, wchar_t **argv) nn_socket_init(&s.local.sock, NNWT_SOCKET_NONBLOCKING); s.local.cli.callback = server_line_callback; s.local.cli.userdata = &s; - nn_line_processor_init(&s.local.cli, al_str_c("\n")); + nn_line_processor_init(&s.local.cli, &al_str_c("\n")); nn_line_processor_open_socket(&s.local.cli, &s.local.sock); - if (nn_socket_bind(&s.local.sock, CAMU_TEST_CONTROL_PATH, 0) && nn_socket_listen(&s.local.sock)) { + if (nn_socket_bind(&s.local.sock, &CAMU_TEST_CONTROL_PATH, 0) && nn_socket_listen(&s.local.sock)) { nn_line_processor_run(&s.local.cli, &s.loop); } #endif diff --git a/src/fruits/cmsrv/ui.c b/src/fruits/cmsrv/ui.c index ba1f8b3..e64f580 100644 --- a/src/fruits/cmsrv/ui.c +++ b/src/fruits/cmsrv/ui.c @@ -82,15 +82,22 @@ static void render_log(struct cmsrv_ui *ui) u32 max_width = ncplane_dim_x(n) - 2; u32 max_height = ncplane_dim_y(n) - 2; - u64 c = 0; - ncchannels_set_fg_default(&c); - ncplane_rounded_box(n, NCSTYLE_NONE, c, max_height + 1, max_width + 1, 0); - - u32 size = ui->log.messages.size; + u32 size = ui->log.messages.count; u32 index = size > max_height ? size - max_height : 0; for (u32 i = index; i < size; i++) { - ncplane_putnstr_yx(n, (i - index) + 1, 1, max_width, al_array_at(ui->log.messages, i)); + // We can't use putnstr here to control the width because lots of + // these messages will have wide characters. + ncplane_putstr_yx(n, (i - index) + 1, 1, al_array_at(ui->log.messages, i)); + } + for (u32 i = 0; i < index; i++) { + al_free(al_array_at(ui->log.messages, i)); } + al_array_remove_range(ui->log.messages, 0, index); + + u64 c = 0; + ncchannels_set_fg_default(&c); + ncplane_cursor_move_yx(n, 0, 0); + ncplane_rounded_box(n, NCSTYLE_NONE, c, max_height + 1, max_width + 1, 0); } static void layout_lists(struct cmsrv_ui *ui, struct ncplane *parent) @@ -117,7 +124,7 @@ static void erase_lists(struct cmsrv_ui *ui) static void putnwstr_maxwidth_yx(struct ncplane *n, u32 y, u32 x, u32 maxwidth, wstr *w) { ncplane_cursor_move_yx(n, y, x); - u32 end = MIN(w->len, maxwidth); + u32 end = MIN(w->length, maxwidth); for (u32 i = 0; i < end; i++) { ncplane_putwc(n, al_wstr_at(w, i)); } @@ -135,11 +142,11 @@ static void render_lists(struct cmsrv_ui *ui) struct lia_list *list; al_array_foreach(ui->server->lists, i, list) { if (current_line++ >= max_height) break; - for (u32 j = 0; j < MIN(max_width, list->name.len); j++) { + for (u32 j = 0; j < MIN(max_width, list->name.length); j++) { ncplane_putchar_yx(n, i, j, al_str_at(&list->name, j)); } s32 index = MAX(list->current - (entries_per_list / 2), 0); - s32 size = (s32)list->entries.size; + s32 size = (s32)list->entries.count; s32 end = MIN(index + entries_per_list, size); for (s32 j = index; j < end; j++) { struct lia_list_entry *entry = al_array_at(list->entries, j); @@ -197,7 +204,7 @@ static void render_nodes(struct cmsrv_ui *ui) ncplane_putnstr_yx(n, i, 0, max_width, strbuf); struct lia_node_connection *conn; al_array_foreach(node->connections, j, conn) { - al_snprintf(strbuf, sizeof(strbuf), "%u", conn->pool.ready.size); + al_snprintf(strbuf, sizeof(strbuf), "%u", conn->pool.ready.count); ncplane_putnstr_yx(n, i + j + 1, 2, max_width, strbuf); } } diff --git a/src/fruits/cmv/cmv.c b/src/fruits/cmv/cmv.c index 02beffb..55d7d55 100644 --- a/src/fruits/cmv/cmv.c +++ b/src/fruits/cmv/cmv.c @@ -14,7 +14,7 @@ #ifndef CAMU_SINK_ONLY #ifndef _WIN32 -static str *CMV_UNIX_PATH = al_str_c("/tmp/cmv_sock"); +static str CMV_UNIX_PATH = al_str_c("/tmp/cmv_sock"); #endif #endif @@ -93,9 +93,9 @@ s32 wmain(s32 argc, wchar_t **argv) bool local = argc > 1; if (local) { #ifndef _WIN32 - type = NNWT_SOCKET_UNIX; addr = CMV_UNIX_PATH; + type = NNWT_SOCKET_UNIX; addr = &CMV_UNIX_PATH; #else - type = NNWT_SOCKET_TCP; addr = CAMU_LOCALHOST; + type = NNWT_SOCKET_TCP; addr = &CAMU_LOCALHOST; #endif camu_server_init(&c.server, &c.loop); c.server.meta_callback = server_meta_callback; @@ -109,7 +109,7 @@ s32 wmain(s32 argc, wchar_t **argv) #endif } else { type = CAMU_TEST_TYPE; - addr = CAMU_TEST_ADDR; + addr = &CAMU_TEST_ADDR; } #else type = NNWT_SOCKET_TCP; addr = CAMU_TEST_ADDR; @@ -129,10 +129,10 @@ s32 wmain(s32 argc, wchar_t **argv) if (local) { for (s32 i = 1; i < argc; i++) { #ifndef _WIN32 - str arg = *al_str_cr(argv[i]); + str arg = al_str_cr(argv[i]); #else str arg; - if (!al_wstr_to_str(al_wstr_cr(argv[i]), &arg)) { + if (!al_wstr_to_str(&al_wstr_cr(argv[i]), &arg)) { al_log_error("cmv", "Failed to parse argument #%i.", i); continue; } @@ -146,7 +146,7 @@ s32 wmain(s32 argc, wchar_t **argv) nn_packet_write_u8(packet, CAMU_RESOURCE_HTTP); #endif #if CACHE_HAVE_CDIO - } else if (al_str_cmp(&arg, al_str_c("cdda://"), 0, 7) == 0) { + } else if (al_str_cmp(&arg, &al_str_c("cdda://"), 0, 7) == 0) { nn_packet_write_u8(packet, CAMU_RESOURCE_CDIO); #endif } else { diff --git a/src/fruits/common.h b/src/fruits/common.h index c7b432a..fb9a127 100644 --- a/src/fruits/common.h +++ b/src/fruits/common.h @@ -3,13 +3,13 @@ AL_UNUSED_VARIABLE_PUSH -static str *CAMU_DB_PATH = al_str_c("/home/andrew/c/camu/data/camu_db_test"); +static str CAMU_DB_PATH = al_str_c("/home/andrew/c/camu/data/camu_db_test"); -static str *CAMU_TEST_IP = al_str_c("108.52.160.112"); -static str *CAMU_LOCALHOST = al_str_c("127.0.0.1"); +static str CAMU_TEST_IP = al_str_c("108.52.160.112"); +static str CAMU_LOCALHOST = al_str_c("127.0.0.1"); -static str *CAMU_TEST_PATH = al_str_c("/tmp/camu_sock"); -static str *CAMU_TEST_CONTROL_PATH = al_str_c("/tmp/camu_control_sock"); +static str CAMU_TEST_PATH = al_str_c("/tmp/camu_sock"); +static str CAMU_TEST_CONTROL_PATH = al_str_c("/tmp/camu_control_sock"); AL_UNUSED_VARIABLE_POP diff --git a/src/fruits/ctv/ctv.c b/src/fruits/ctv/ctv.c index b350c8a..ded4182 100644 --- a/src/fruits/ctv/ctv.c +++ b/src/fruits/ctv/ctv.c @@ -1,5 +1,6 @@ #include <stl/window.h> #include <stl/platform.h> +#include <al/log.h> #include "../../screen/screen.h" #include "../../render/renderer_libplacebo.h" @@ -106,10 +107,8 @@ static s32 log_callback(void *userdata, u8 level, char *message) { (void)userdata; (void)level; - __android_log_print(ANDROID_LOG_DEBUG, "CTV", "%s", message); - s32 ret = al_strlen(message); - al_free(message); - return ret; + __android_log_print(ANDROID_LOG_DEBUG, "CTV", "%.*s", AL_LOG_MESSAGE_SIZE, message); + return al_strnlen(message, AL_LOG_MESSAGE_SIZE); } void glfmMain(GLFMDisplay *display) diff --git a/src/fruits/ctv/meson.build b/src/fruits/ctv/meson.build index dff208d..5a4dca8 100644 --- a/src/fruits/ctv/meson.build +++ b/src/fruits/ctv/meson.build @@ -1,4 +1,4 @@ -ctv_src = ['ctv.c'] +ctv_src = ['ctv.c', '../../sink/common.c'] ctv_deps = [common_deps, libsink] ctv_args = ['-DCAMU_MIXER_THREADED', '-DCAMU_SCREEN_THREADED'] diff --git a/src/fruits/droid/ctv/gradle/libs.versions.toml b/src/fruits/droid/ctv/gradle/libs.versions.toml index ea02696..e1ef643 100644 --- a/src/fruits/droid/ctv/gradle/libs.versions.toml +++ b/src/fruits/droid/ctv/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -agp = "8.7.3" +agp = "8.8.0" [libraries] diff --git a/src/fruits/droid/ctv/gradle/wrapper/gradle-wrapper.properties b/src/fruits/droid/ctv/gradle/wrapper/gradle-wrapper.properties index 354c93e..698ab10 100644 --- a/src/fruits/droid/ctv/gradle/wrapper/gradle-wrapper.properties +++ b/src/fruits/droid/ctv/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Wed Oct 30 14:10:25 EDT 2024 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/liana/handlers.c b/src/liana/handlers.c index 1a28024..e52d8bb 100644 --- a/src/liana/handlers.c +++ b/src/liana/handlers.c @@ -1,7 +1,9 @@ #include "handlers.h" #include "handlers/codec.h" +#ifdef CACHE_HAVE_CDIO #include "handlers/cdio.h" +#endif struct lia_handler_entry liana_handlers[] = { { @@ -29,7 +31,7 @@ struct lia_handler_entry liana_handlers[] = { struct lia_handler_entry *lia_handler_by_name(str *name) { for (u32 i = 0; i < ARRAY_SIZE(liana_handlers); i++) { - if (al_str_eq(liana_handlers[i].name, name)) { + if (al_str_eq(&liana_handlers[i].name, name)) { return &liana_handlers[i]; } } diff --git a/src/liana/handlers.h b/src/liana/handlers.h index 0193f18..223ead5 100644 --- a/src/liana/handlers.h +++ b/src/liana/handlers.h @@ -3,7 +3,7 @@ #include "handler.h" struct lia_handler_entry { - str *name; + str name; struct lia_server_handler *(*create_server_handler)(void); struct lia_client_handler *(*create_client_handler)(void); }; diff --git a/src/liana/handlers/codec_server.c b/src/liana/handlers/codec_server.c index 24552bb..ff62d47 100644 --- a/src/liana/handlers/codec_server.c +++ b/src/liana/handlers/codec_server.c @@ -43,7 +43,7 @@ static void codec_server_write_info(struct lia_server_handler *handler, struct n struct lia_codec_server *codec = (struct lia_codec_server *)handler; u64 duration = codec->demux->get_duration(codec->demux); nn_packet_write_u64(packet, duration); - nn_packet_write_u32(packet, codec->demux->streams.size); + nn_packet_write_u32(packet, codec->demux->streams.count); struct camu_codec_stream *stream; al_array_foreach_ptr(codec->demux->streams, i, stream) { nn_packet_write_u8(packet, stream->mode); diff --git a/src/liana/list.c b/src/liana/list.c index 3c8a9c0..fa21fe6 100644 --- a/src/liana/list.c +++ b/src/liana/list.c @@ -9,7 +9,7 @@ /* static void buffer_ahead(struct lia_list *list) { - s32 size = (s32)list->entries.size; + s32 size = (s32)list->entries.count; if (list->current >= 0 && list->current + 1 < size) { s32 ahead = list->current + 1; for (s32 i = ahead; i < MIN(ahead + LIANA_BUFFER_AHEAD, size); i++) { @@ -89,7 +89,7 @@ static bool entry_load_and_get_duration(struct lia_list *list, struct lia_list_e if (status == LIANA_ENTRY_ERRORED) { if (sequence >= 0) { al_array_remove_at(list->entries, (u32)sequence); - if (sequence == list->current && (u32)list->current == list->entries.size) { + if (sequence == list->current && (u32)list->current == list->entries.count) { // This maps to the behavior of only skipping ahead on errors. list->current--; list->idle = true; @@ -139,7 +139,7 @@ static void set_queued(struct lia_list *list) static void evaluate_queued(struct lia_list *list) { - s32 size = (s32)list->entries.size; + s32 size = (s32)list->entries.count; s32 next = list->current + 1; if (next >= size || next == list->queued) return; @@ -226,7 +226,7 @@ static bool handle_add(struct lia_list *list, struct lia_list_entry *entry) }; struct lia_list_sink *sink; al_array_foreach(list->sinks, i, sink) { - al_assert(sink->set == -1); + //al_assert(sink->set == -1); sink->set = list->current; sink->callback(sink->userdata, LIANA_SINK_SET, entry, list->current, &time); } @@ -276,7 +276,7 @@ static void unset_all(struct lia_list *list) static void handle_unset(struct lia_list *list) { unset_all(list); - list->current = list->entries.size - 1; + list->current = list->entries.count - 1; list->idle = true; struct lia_list_sink *sink; al_array_foreach(list->sinks, i, sink) { @@ -286,7 +286,7 @@ static void handle_unset(struct lia_list *list) static struct lia_list_entry *get_entry_from_sequence(struct lia_list *list, s32 sequence) { - s32 size = (s32)list->entries.size; + s32 size = (s32)list->entries.count; if (sequence < 0 || sequence >= size) return NULL; return al_array_at(list->entries, sequence); } @@ -555,7 +555,7 @@ static bool handle_end(struct lia_list *list, u32 id, u32 reset_id) return false; #endif - s32 size = (s32)list->entries.size; + s32 size = (s32)list->entries.count; if (sequence == list->current) { s32 next = sequence + 1; if (list->queued >= 0) { @@ -588,7 +588,7 @@ static void handle_reverse(struct lia_list *list) { if (list->current == -1) return; struct lia_list_entry *previous = al_array_at(list->entries, list->current); - u32 size = list->entries.size; + u32 size = list->entries.count; for (u32 i = 0; i < size; i++) { u32 tail = size - (i + 1); if (tail <= i) break; @@ -609,10 +609,15 @@ static void handle_shuffle(struct lia_list *list) { if (list->current == -1) return; struct lia_list_entry *previous = al_array_at(list->entries, list->current); - u32 size = list->entries.size; - if (size == 0) return; - for (u32 i = 0; i < size - 1; i++) { - u32 j = i + al_rand() / (AL_RAND_MAX / (size - i) + 1); + u32 size = list->entries.count; + if (size <= 1) return; + /* https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle + for i from 0 to n−2 do + j ← random integer such that i ≤ j ≤ n-1 + exchange a[i] and a[j] + */ + for (u32 i = 0; i < size - 2; i++) { + u32 j = i + (al_rand() % (size - i)); SWAP(al_array_at(list->entries, i), al_array_at(list->entries, j)); } adjust_current(list, previous); @@ -627,13 +632,13 @@ static void handle_clear(struct lia_list *list) al_wstr_free(&entry->name); al_free(entry); } - list->entries.size = 0; + list->entries.count = 0; } static void run_queue(struct lia_list *list) { if (!list->cmd) { - if (al_array_is_empty(list->queue)) return; + if (!list->queue.count) return; al_array_pop_at(list->queue, 0, list->cmd); } struct lia_list_cmd *cmd = list->cmd; diff --git a/src/liana/list_cmp.h b/src/liana/list_cmp.h index ef923fb..c9c0812 100644 --- a/src/liana/list_cmp.h +++ b/src/liana/list_cmp.h @@ -8,36 +8,37 @@ AL_UNUSED_FUNCTION_PUSH static void camu_db_num_from_path(wstr *path, s64 *id, s64 *index) { - s32 index0 = al_wstr_rfind(path, L'/'); - if (index0 < 0) return; + u32 last_slash = al_wstr_rfind(path, L'/'); + if (last_slash == al_wstr_npos) { + return; + } + wstr temp = al_wstr_substr(path, last_slash + 1, path->length); - wstr w = *al_wstr_substr(path, index0 + 1, path->len); - index0 = al_wstr_find(&w, L'_'); - if (index0 < 0) return; - w = *al_wstr_substr(&w, index0 + 1, w.len); - index0 = al_wstr_find(&w, L'_'); - if (index0 < 0) return; - w = *al_wstr_substr(&w, index0 + 1, w.len); - index0 = al_wstr_find(&w, L'_'); - if (index0 < 0) return; - w = *al_wstr_substr(&w, 0, index0); + // Skip 2 '_' characters. + if (!(al_wstr_tok(&temp, L'_') && al_wstr_tok(&temp, L'_'))) { + return; + } - str s; - al_wstr_to_str(&w, &s); - s64 num = al_str_to_long(&s, 10); - al_str_free(&s); - if (num == INT64_MIN || num == INT64_MAX) return; + u32 target = al_wstr_find(&temp, L'_'); + if (target == al_wstr_npos) { + return; + } + temp = al_wstr_substr(&temp, 0, target); + + bool error; + s64 num = al_wstr_to_long(&temp, 10, &error); + if (error) return; *id = num; - index0 = al_wstr_rfind(path, L'.'); - s32 index1 = al_wstr_rfind(path, 'a'); - if (index0 < 0 || index1 < 0) return; - w = *al_wstr_substr(path, index1 + 1, index0); + u32 ext_dot = al_wstr_rfind(path, L'.'); + u32 media_a = al_wstr_rfind(path, 'a'); + if (ext_dot == al_wstr_npos || media_a == al_wstr_npos) { + return; + } + temp = al_wstr_substr(path, media_a + 1, ext_dot); - al_wstr_to_str(&w, &s); - num = al_str_to_long(&s, 10); - al_str_free(&s); - if (num == INT64_MIN || num == INT64_MAX) return; + num = al_wstr_to_long(&temp, 10, &error); + if (error) return; *index = num; } diff --git a/src/liana/vcr.c b/src/liana/vcr.c index 06f0fe4..c5b704e 100644 --- a/src/liana/vcr.c +++ b/src/liana/vcr.c @@ -53,9 +53,9 @@ void lia_vcr_init(struct lia_vcr *vcr, struct nn_event_loop *loop, struct nn_pac static void return_entire_cache(struct lia_vcr_track *track) { struct lia_vcr *vcr = track->vcr; - u32 size = track->cache.cache.size; - nn_packet_stream_return_packets(vcr->data, al_array_offset(track->cache.cache, 0), size); - track->cache.cache.size = 0; + u32 count = track->cache.cache.count; + nn_packet_stream_return_packets(vcr->data, al_array_offset(track->cache.cache, 0), count); + track->cache.cache.count = 0; } static nn_thread_result NNWT_THREADCALL vcr_track_thread(void *userdata) @@ -88,7 +88,7 @@ static nn_thread_result NNWT_THREADCALL vcr_track_thread(void *userdata) u32 size = nn_packet_get_size(packet); u64 buffer = al_atomic_sub(u64)(&vcr->count, size, AL_ATOMIC_RELAXED); #ifndef CAMU_DIRECT_MODE - u8 buffered = al_atomic_load(u8)(&track->buffered, AL_ATOMIC_RELAXED); + bool buffered = al_atomic_load(bool)(&track->buffered, AL_ATOMIC_RELAXED); if (buffered && buffer <= vcr->mark.low) { nn_signal_send(&vcr->signal); } @@ -180,7 +180,7 @@ void lia_vcr_add_track(struct lia_vcr *vcr, struct lia_vcr_track *track) track->vcr = vcr; nn_cond_init(&track->cond); nn_mutex_init(&track->mutex); - al_atomic_store(u8)(&track->buffered, !VCR_TRACK_THREADED(track), AL_ATOMIC_RELAXED); + al_atomic_store(bool)(&track->buffered, !VCR_TRACK_THREADED(track), AL_ATOMIC_RELAXED); nn_packet_cache_init(&track->cache, 256); al_array_push(vcr->tracks, track); al_atomic_store(s32)(&track->state, VCR_TRACK_RUNNING, AL_ATOMIC_RELAXED); @@ -188,7 +188,7 @@ void lia_vcr_add_track(struct lia_vcr *vcr, struct lia_vcr_track *track) bool lia_vcr_is_empty(struct lia_vcr *vcr) { - return al_array_is_empty(vcr->tracks); + return !vcr->tracks.count; } static struct lia_vcr_track *get_track_from_index(struct lia_vcr *vcr, s32 index) @@ -203,10 +203,10 @@ static struct lia_vcr_track *get_track_from_index(struct lia_vcr *vcr, s32 index #ifndef CAMU_DIRECT_MODE static void cork_if_buffered(struct lia_vcr *vcr, u64 buffer) { - u8 buffered = 1; + bool buffered = true; struct lia_vcr_track *track; al_array_foreach(vcr->tracks, i, track) { - buffered &= al_atomic_load(u8)(&track->buffered, AL_ATOMIC_RELAXED); + buffered &= al_atomic_load(bool)(&track->buffered, AL_ATOMIC_RELAXED); } if (buffered) { if (vcr->expand == VCR_EXPAND_UNTOUCHED) { @@ -263,15 +263,15 @@ void lia_vcr_push_packet(struct lia_vcr *vcr, struct nn_packet *packet) break; } if (VCR_TRACK_THREADED(track)) { - if (!nn_packet_cache_send_packet(&track->cache, packet)) { - break; - } u64 buffer; if ((buffer = al_atomic_add(u64)(&vcr->count, size, AL_ATOMIC_RELAXED)) >= vcr->mark.buffered) { #ifndef CAMU_DIRECT_MODE cork_if_buffered(vcr, buffer); #endif } + if (!nn_packet_cache_send_packet(&track->cache, packet)) { + break; + } // Keep packet. return; } else { @@ -301,13 +301,12 @@ void lia_vcr_push_packet(struct lia_vcr *vcr, struct nn_packet *packet) void lia_vcr_set_buffered(struct lia_vcr_track *track) { - al_atomic_store(u8)(&track->buffered, 1, AL_ATOMIC_RELAXED); + al_atomic_store(bool)(&track->buffered, true, AL_ATOMIC_RELAXED); } void lia_vcr_cork(struct lia_vcr_track *track) { al_atomic_store(s32)(&track->state, VCR_TRACK_STOPPED, AL_ATOMIC_RELAXED); - al_atomic_store(u8)(&track->buffered, 1, AL_ATOMIC_RELAXED); } void lia_vcr_uncork(struct lia_vcr_track *track) @@ -350,7 +349,7 @@ void lia_vcr_flush(struct lia_vcr *vcr) if (VCR_TRACK_THREADED(track)) { vcr_track_close_internal(track); return_entire_cache(track); - al_atomic_store(u8)(&track->buffered, 0, AL_ATOMIC_RELAXED); + al_atomic_store(bool)(&track->buffered, false, AL_ATOMIC_RELAXED); track->client->flush(track->client); nn_packet_cache_enable(&track->cache); al_atomic_store(s32)(&track->state, VCR_TRACK_RUNNING, AL_ATOMIC_RELAXED); diff --git a/src/liana/vcr.h b/src/liana/vcr.h index 8aefaa2..bd4f0f9 100644 --- a/src/liana/vcr.h +++ b/src/liana/vcr.h @@ -15,7 +15,7 @@ struct lia_vcr_track { struct camu_codec_stream stream; struct lia_client_handler *client; atomic(s32) state; - atomic(u8) buffered; + atomic(bool) buffered; struct nn_packet_cache cache; struct nn_cond cond; struct nn_mutex mutex; diff --git a/src/libsink/sink.c b/src/libsink/sink.c index 03f76b7..0f56c5b 100644 --- a/src/libsink/sink.c +++ b/src/libsink/sink.c @@ -11,6 +11,8 @@ #include "sink.h" #include "common.h" +//#define CAMU_SINK_ONESHOT + #ifndef CAMU_SINK_NO_VIDEO #include "../render/renderer_libplacebo.h" #endif @@ -58,8 +60,6 @@ enum { // If a buffer is still INIT or QUEUED after the entry is configured, it's "empty". #define BUFFER_EMPTY(buf) ((buf)->state == BUFFER_INIT || (buf)->state == BUFFER_QUEUED) -#define BUFFER_NOT_EMPTY(buf) (!BUFFER_EMPTY(buf)) - #define AUDIO_EMPTY(entry) BUFFER_EMPTY(&(entry)->audio) #ifndef CAMU_SINK_NO_VIDEO #define VIDEO_EMPTY(entry) BUFFER_EMPTY(&(entry)->video) @@ -487,7 +487,7 @@ static void maybe_remove_previous(struct camu_sink *sink) al_array_foreach(sink->previous, i, previous) { remove_entry_buffers(sink, previous); } - sink->previous.size = 0; + sink->previous.count = 0; } // Due to the looseness of the previous queue, we may have to explicitly remove an entry @@ -558,7 +558,7 @@ static void maybe_cleanup_old_entries(struct camu_sink *sink) al_array_remove_at(sink->entries, i); lia_client_disconnect(&entry->client); } - if (sink->entries.size <= ENTRY_MAX_AGE) return; + if (sink->entries.count <= ENTRY_MAX_AGE) return; } // Checking sink->lru >= ENTRY_MAX_AGE should guarantee @@ -570,7 +570,7 @@ static void maybe_cleanup_old_entries(struct camu_sink *sink) al_array_remove_at(sink->entries, i); lia_client_disconnect(&entry->client); } - if (sink->entries.size <= ENTRY_MAX_AGE) return; + if (sink->entries.count <= ENTRY_MAX_AGE) return; } } } @@ -714,6 +714,10 @@ static void pause_and_swap_to(struct camu_sink *sink, struct camu_sink_entry *ta static bool end_entry_and_advance_queue(struct camu_sink *sink, struct camu_sink_entry *entry) { al_log_info("sink", "Entry ended."); +#ifdef CAMU_SINK_ONESHOT + sink->callback(sink->userdata, CAMU_SINK_MOCK_CLOSE, 0, NULL); + return false; +#endif entry->ended = true; queue_cmd(sink, (struct camu_sink_cmd){ .op = END, @@ -743,6 +747,7 @@ static void audio_buffer_callback(void *userdata, u8 op) struct camu_sink *sink = entry->sink; switch (op) { case CAMU_BUFFER_BUFFERED: + lia_vcr_set_buffered(entry->audio.track); nn_mutex_lock(&sink->mutex); add_audio_if_set_and_buffered(entry); nn_mutex_unlock(&sink->mutex); @@ -765,7 +770,6 @@ static void audio_buffer_callback(void *userdata, u8 op) nn_mutex_unlock(&sink->mutex); break; case CAMU_BUFFER_EOF: { - lia_vcr_set_buffered(entry->audio.track); nn_mutex_lock(&sink->mutex); al_log_info("sink", "Audio EOF."); if (entry->audio.state == BUFFER_ADDED) { @@ -797,6 +801,7 @@ static void video_buffer_callback(void *userdata, u8 op) struct camu_sink *sink = entry->sink; switch (op) { case CAMU_BUFFER_BUFFERED: { + lia_vcr_set_buffered(entry->video.track); nn_mutex_lock(&sink->mutex); add_video_if_set_and_buffered(entry); nn_mutex_unlock(&sink->mutex); @@ -809,7 +814,6 @@ static void video_buffer_callback(void *userdata, u8 op) lia_vcr_uncork(entry->video.track); break; case CAMU_BUFFER_EOF: { - lia_vcr_set_buffered(entry->video.track); bool swapped = false; nn_mutex_lock(&sink->mutex); al_log_info("sink", "Video EOF."); @@ -867,7 +871,7 @@ static void clock_callback(void *userdata, u8 op) } } -static void evaluate_latency(struct camu_sink *sink, struct camu_sink_entry *entry) +static void evaluate_and_set_latency(struct camu_sink *sink, struct camu_sink_entry *entry) { #ifdef CAMU_SINK_LOCAL #ifndef CAMU_SINK_NO_VIDEO @@ -933,7 +937,7 @@ static void client_callback(void *userdata, u8 op, struct camu_codec_stream *str al_assert(false); } if (VIDEO_ADDED_OR_EMPTY(entry)) { - evaluate_latency(sink, entry); + evaluate_and_set_latency(sink, entry); } nn_mutex_unlock(&sink->mutex); break; @@ -954,7 +958,7 @@ static void client_callback(void *userdata, u8 op, struct camu_codec_stream *str al_assert(false); } if (AUDIO_ADDED_OR_EMPTY(entry)) { - evaluate_latency(sink, entry); + evaluate_and_set_latency(sink, entry); } nn_mutex_unlock(&sink->mutex); break; @@ -1292,6 +1296,7 @@ static bool set_command_callback(void *userdata, struct nn_rpc_connection *conn, struct camu_sink_entry *current = sink->current; #ifdef CAMU_SINK_LOCAL + (void)at; if (current && !current->ended && !camu_clock_is_paused(¤t->clock)) { camu_clock_pause(¤t->clock, 0); } diff --git a/src/libsink/sink.h b/src/libsink/sink.h index 10fc182..68fac15 100644 --- a/src/libsink/sink.h +++ b/src/libsink/sink.h @@ -29,6 +29,7 @@ enum { CAMU_SINK_START, CAMU_SINK_STOP, CAMU_SINK_CLEAR, + CAMU_SINK_MOCK_CLOSE, CAMU_SINK_EXIT }; diff --git a/src/mixer/audio_miniaudio.c b/src/mixer/audio_miniaudio.c index f0afeee..ba093f4 100644 --- a/src/mixer/audio_miniaudio.c +++ b/src/mixer/audio_miniaudio.c @@ -155,7 +155,7 @@ static void data_callback(ma_device *device, void *output, const void *input, u3 } #define DEFAULT_PERIODS 3 -#define DEFAULT_PERIOD_SIZE_IN_MILLISECONDS 64 +#define DEFAULT_PERIOD_SIZE_IN_MILLISECONDS 48 static bool audio_miniaudio_configure_stream(struct camu_audio *audio, void *opaque) { diff --git a/src/mixer/mixer.c b/src/mixer/mixer.c index 1360934..36ac95d 100644 --- a/src/mixer/mixer.c +++ b/src/mixer/mixer.c @@ -12,7 +12,7 @@ static s32 data_callback(void *userdata, u8 *data, s32 frame_count, bool *silence) { struct camu_mixer *mixer = (struct camu_mixer *)userdata; - size_t req = camu_audio_format_samples_to_bytes(&mixer->fmt.req, (size_t)frame_count); + ptrdiff_t req = (ptrdiff_t)camu_audio_format_samples_to_bytes(&mixer->fmt.req, (size_t)frame_count); #ifdef CAMU_MIXER_THREADED_START_STOP if (UNLIKELY(mixer->paused)) { al_memset(data, 0, req); @@ -36,17 +36,17 @@ static s32 data_callback(void *userdata, u8 *data, s32 frame_count, bool *silenc // Read from all current buffers on each callback to // emulate the behavior of an actual mixer. al_array_foreach(mixer->buffers, i, buf) { - if (i < mixer->buffers.size - 1) { + if (i < mixer->buffers.count - 1) { camu_audio_buffer_read(buf, data, req); } } for (;;) { - if (al_array_is_empty(mixer->buffers)) { + if (!mixer->buffers.count) { al_memset(data, 0, req); } else { - size_t signal; buf = al_array_last(mixer->buffers); *silence = false; + ptrdiff_t signal; if ((signal = camu_audio_buffer_read(buf, data, req)) < req) { #ifdef CAMU_MIXER_THREADED if (al_atomic_load(u8)(&mixer->queued, AL_ATOMIC_RELAXED)) { @@ -71,7 +71,7 @@ bool camu_mixer_init(struct camu_mixer *mixer, struct camu_audio *audio) mixer->audio = audio; mixer->audio->data_callback = data_callback; mixer->audio->userdata = mixer; - mixer->audio->init(mixer->audio, al_str_c("cmv")); + mixer->audio->init(mixer->audio, &al_str_c("cmv")); mixer->volume = 1.f; mixer->paused = true; mixer->empty_after = 0; @@ -156,21 +156,21 @@ static void remove_buffer_internal(struct camu_mixer *mixer, struct camu_audio_b static void run_queue_internal(struct camu_mixer *mixer) { struct camu_audio_buffer *buf; - if (mixer->rem_queue.size > 0) { + if (mixer->rem_queue.count > 0) { al_array_foreach(mixer->rem_queue, i, buf) { remove_buffer_internal(mixer, buf); } - mixer->rem_queue.size = 0; + mixer->rem_queue.count = 0; } - if (mixer->add_queue.size > 0) { - al_array_reserve(mixer->buffers, mixer->buffers.size + mixer->add_queue.size); + if (mixer->add_queue.count > 0) { + al_array_reserve(mixer->buffers, mixer->buffers.count + mixer->add_queue.count); al_array_foreach(mixer->add_queue, i, buf) { add_buffer_internal(mixer, buf); } - mixer->add_queue.size = 0; + mixer->add_queue.count = 0; } al_atomic_store(u8)(&mixer->queued, 0, AL_ATOMIC_RELAXED); - if (al_array_is_empty(mixer->buffers)) { + if (!mixer->buffers.count) { mixer->empty_after = MIXER_TRAILING_SILENCE; } else { mixer->empty_after = 0; @@ -192,7 +192,7 @@ void camu_mixer_add_buffer(struct camu_mixer *mixer, struct camu_audio_buffer *b al_array_foreach_rev(mixer->rem_queue, i, rbuf) { if (rbuf == buf) { al_array_remove_at(mixer->rem_queue, i); - bool queue_empty = mixer->add_queue.size + mixer->rem_queue.size == 0; + bool queue_empty = mixer->add_queue.count + mixer->rem_queue.count == 0; if (queue_empty) { al_atomic_store(u8)(&mixer->queued, 0, AL_ATOMIC_RELAXED); } @@ -223,7 +223,7 @@ void camu_mixer_remove_buffer(struct camu_mixer *mixer, struct camu_audio_buffer al_array_foreach_rev(mixer->add_queue, i, rbuf) { if (rbuf == buf) { al_array_remove_at(mixer->add_queue, i); - bool queue_empty = mixer->add_queue.size + mixer->rem_queue.size == 0; + bool queue_empty = mixer->add_queue.count + mixer->rem_queue.count == 0; if (queue_empty) { al_atomic_store(u8)(&mixer->queued, 0, AL_ATOMIC_RELAXED); } @@ -239,7 +239,7 @@ void camu_mixer_remove_buffer(struct camu_mixer *mixer, struct camu_audio_buffer nn_mutex_unlock(&mixer->mutex); #else remove_buffer_internal(mixer, buf); - if (al_array_is_empty(mixer->buffers)) { + if (!mixer->buffers.count) { mixer->empty_after = MIXER_TRAILING_SILENCE; } #endif diff --git a/src/portal/cpy/str.pxd b/src/portal/cpy/str.pxd index 3ef1e90..77cd093 100644 --- a/src/portal/cpy/str.pxd +++ b/src/portal/cpy/str.pxd @@ -2,7 +2,7 @@ include "types.pxd" cdef extern from "<al/str.h>": ctypedef struct str: - u32 len + u32 length u32 alloc char *data @@ -11,7 +11,7 @@ cdef extern from "<al/str.h>": cdef extern from "<al/wstr.h>": ctypedef struct wstr: - u32 len + u32 length u32 alloc wchar_t *data diff --git a/src/portal/cpy/types.pxd b/src/portal/cpy/types.pxd index 09cb224..d630afa 100644 --- a/src/portal/cpy/types.pxd +++ b/src/portal/cpy/types.pxd @@ -8,7 +8,9 @@ from libc.stdint cimport uint64_t from libc.stdint cimport int64_t from libc.stddef cimport wchar_t -ctypedef bint bool +from libcpp cimport bool +cdef extern from "<stdbool.h>": + pass ctypedef uint8_t u8 ctypedef int8_t s8 diff --git a/src/portal/py/modules/youtube.py b/src/portal/py/modules/youtube.py index 582a16c..9d5a135 100644 --- a/src/portal/py/modules/youtube.py +++ b/src/portal/py/modules/youtube.py @@ -27,7 +27,7 @@ ydl_opts = { 'logger': YDLLogger(), 'cachedir': False, 'socket_timeout': 10, - 'extractor_args': {'youtube': {'skip': ['hls'], 'player_client': ['android_vr']}} + 'extractor_args': {'youtube': {'skip': ['hls'], 'player_client': ['tv', 'ios']}} # 'android_vr', # 'cookiefile': '' } diff --git a/src/portal/src/packet_ext.c b/src/portal/src/packet_ext.c index 9b6d6be..8f30470 100644 --- a/src/portal/src/packet_ext.c +++ b/src/portal/src/packet_ext.c @@ -12,7 +12,7 @@ void nn_packet_write_post(struct nn_packet *packet, struct camu_post *post) NNWT_PACKET_WRITE_TYPE(packet, u8, post->type); nn_packet_write_str(packet, &post->unique_id); nn_packet_write_str(packet, &post->url); - NNWT_PACKET_WRITE_TYPE(packet, u32, post->dates.size); + NNWT_PACKET_WRITE_TYPE(packet, u32, post->dates.count); struct camu_post_date *date; al_array_foreach_ptr(post->dates, i, date) { NNWT_PACKET_WRITE_TYPE(packet, u8, date->type); @@ -32,7 +32,7 @@ void nn_packet_write_post(struct nn_packet *packet, struct camu_post *post) nn_packet_write_optional_int(packet, &post->quotes); nn_packet_write_optional_int(packet, &post->comments); nn_packet_write_optional_int(packet, &post->views); - NNWT_PACKET_WRITE_TYPE(packet, u32, post->media.size); + NNWT_PACKET_WRITE_TYPE(packet, u32, post->media.count); struct camu_post_media *media; al_array_foreach_ptr(post->media, i, media) { NNWT_PACKET_WRITE_TYPE(packet, u8, media->type); diff --git a/src/portal/src/search.c b/src/portal/src/search.c index 447e44c..e5d5dca 100644 --- a/src/portal/src/search.c +++ b/src/portal/src/search.c @@ -91,7 +91,7 @@ static nn_thread_result NNWT_THREADCALL queue_thread(void *userdata) al_str_clone(&search->query, &cmd->query); search->bridge = bridge; al_array_push(bridge->searches, search); - al_log_info("portal", "New search %x (%.*s).", id, AL_STR_PRINTF(&cmd->query)); + al_log_info("portal", "New search %x (%.*s).", id, al_str_fmt(&cmd->query)); result.id = search->id; } else { } @@ -107,7 +107,7 @@ static nn_thread_result NNWT_THREADCALL queue_thread(void *userdata) al_array_foreach_ptr(search->pages, j, page) { if (page->num == cmd->num) break; } - al_log_info("portal", "Loading page %i (%.*s).", cmd->num, AL_STR_PRINTF(&search->query)); + al_log_info("portal", "Loading page %i (%.*s).", cmd->num, al_str_fmt(&search->query)); if (portal_bridge_get_page(search, search->id, cmd->num) == -1) { break; } @@ -125,7 +125,7 @@ static nn_thread_result NNWT_THREADCALL queue_thread(void *userdata) } camu_queue_push(bridge->results, result); } - bridge->queue.size = 0; + bridge->queue.count = 0; nn_signal_send(&bridge->results_signal); } nn_mutex_unlock(&bridge->mutex); @@ -164,7 +164,7 @@ void camu_portal_init(struct camu_portal_bridge *bridge, struct camu_post_cache void camu_portal_create_search(struct camu_portal_bridge *bridge, str *module, str *query, void (*callback)(void *, void *, struct camu_portal_result *), void *userdata) { - struct camu_portal_cmd cmd; + struct camu_portal_cmd cmd = { 0 }; cmd.op = CAMU_CLIENT_CREATE_SEARCH; al_str_clone(&cmd.module, module); al_str_clone(&cmd.query, query); @@ -181,7 +181,7 @@ void camu_portal_create_search(struct camu_portal_bridge *bridge, str *module, s void camu_portal_get_page(struct camu_portal_bridge *bridge, s32 id, u32 num, void (*callback)(void *, void *, struct camu_portal_result *), void *userdata) { - struct camu_portal_cmd cmd; + struct camu_portal_cmd cmd = { 0 }; cmd.op = CAMU_CLIENT_GET_PAGE; cmd.id = id; cmd.num = num; diff --git a/src/render/queue_libplacebo.c b/src/render/queue_libplacebo.c index 861dd5e..22df3dc 100644 --- a/src/render/queue_libplacebo.c +++ b/src/render/queue_libplacebo.c @@ -219,7 +219,7 @@ static bool map_av_frame(pl_gpu gpu, pl_tex *tex, const struct pl_source_frame * ASS_Image *ass_frame = ass_render_frame(lq->ass_renderer, lq->ass_track, now, &change); if (ass_frame) { struct camu_overlay_lp *overlay = NULL; - if (lq->overlays.size > 0) { + if (lq->overlays.count > 0) { overlay = al_array_last(lq->overlays); } if (!overlay || change > 0) { diff --git a/src/render/renderer.h b/src/render/renderer.h index a9780e5..c78e1c1 100644 --- a/src/render/renderer.h +++ b/src/render/renderer.h @@ -39,7 +39,7 @@ struct camu_renderer { void *priv); struct camu_frame_queue *(*create_queue)(struct camu_renderer *); u32 (*get_latency)(struct camu_renderer *); - void (*resize)(struct camu_renderer *, s32 *, s32 *); + void (*resize)(struct camu_renderer *, s32 *, s32 *, bool); void (*render)(struct camu_renderer *, struct camu_screen *, bool); #ifdef CAMU_HAVE_FFMPEG s32 (*get_buffer2)(struct AVCodecContext *s, AVFrame *frame, s32 flags); diff --git a/src/render/renderer_libplacebo.c b/src/render/renderer_libplacebo.c index 3de0fdc..2539e1f 100644 --- a/src/render/renderer_libplacebo.c +++ b/src/render/renderer_libplacebo.c @@ -13,7 +13,7 @@ static f32 clear_color[4] = { 0.0f, 0.0f, 0.0f, 1.f }; -static void renderer_lp_resize(struct camu_renderer *renderer, s32 *width, s32 *height) +static void renderer_lp_resize(struct camu_renderer *renderer, s32 *width, s32 *height, bool double_swap) { struct camu_renderer_lp *lr = (struct camu_renderer_lp *)renderer; if (lr->swapchain) { @@ -22,14 +22,18 @@ static void renderer_lp_resize(struct camu_renderer *renderer, s32 *width, s32 * lr->have_frame = false; } pl_swapchain_resize(lr->swapchain, width, height); + lr->double_swap = double_swap; } } static void log_callback(void *userdata, enum pl_log_level level, const char *message) { (void)userdata; - (void)level; - al_log_info("render_libplacebo", message); + if (level < PL_LOG_INFO) { + al_log_info("render_libplacebo", message); + } else { + al_log_debug("render_libplacebo", message); + } } static bool renderer_lp_create_renderer(struct camu_renderer *renderer, s32 *width, s32 *height, @@ -140,9 +144,10 @@ static bool renderer_lp_create_renderer(struct camu_renderer *renderer, s32 *wid lr->renderer = pl_renderer_create(lr->logger, lr->gpu); - lr->have_frame = false; - pl_swapchain_resize(lr->swapchain, width, height); + lr->double_swap = false; + + lr->have_frame = false; al_memset(&lr->params, 0, sizeof(struct pl_render_params)); //lr->params = pl_render_fast_params; @@ -215,6 +220,11 @@ static void renderer_lp_render(struct camu_renderer *renderer, struct camu_scree } #endif + if (lr->double_swap) { + pl_swapchain_swap_buffers(lr->swapchain); + lr->double_swap = false; + } + if (!lr->have_frame) { struct pl_swapchain_frame frame; pl_swapchain_start_frame(lr->swapchain, &frame); @@ -229,7 +239,7 @@ static void renderer_lp_render(struct camu_renderer *renderer, struct camu_scree bool do_gpu_finish = false; struct camu_screen_video *video; - while (scr->videos.size > 0) { + while (scr->videos.count > 0) { bool any_eof = false; al_array_foreach_ptr(scr->videos, i, video) { bool weighted; @@ -269,7 +279,7 @@ static void renderer_lp_render(struct camu_renderer *renderer, struct camu_scree } } - if (al_array_is_empty(scr->videos) && !force) { + if (!scr->videos.count && !force) { return; } diff --git a/src/render/renderer_libplacebo.h b/src/render/renderer_libplacebo.h index 38407bb..a4bd40e 100644 --- a/src/render/renderer_libplacebo.h +++ b/src/render/renderer_libplacebo.h @@ -26,6 +26,7 @@ struct camu_renderer_lp { pl_gpu gpu; pl_log logger; pl_swapchain swapchain; + bool double_swap; struct pl_frame target; bool have_frame; pl_renderer renderer; diff --git a/src/screen/screen.c b/src/screen/screen.c index e76650f..e6f9970 100644 --- a/src/screen/screen.c +++ b/src/screen/screen.c @@ -30,11 +30,16 @@ static void should_close_callback(void *userdata) static void resize_callback(void *userdata, s32 width, s32 height) { struct camu_screen *scr = (struct camu_screen *)userdata; + bool fullscreen = scr->window->fullscreen; if (scr->renderer) { - scr->renderer->resize(scr->renderer, &width, &height); + // Checking if window->fullscreen changed here relies on the order of resize events. + // If it's possible for a different resize to be buffered before the resize + // of the fullscreen toggle, this may not work as expected. + scr->renderer->resize(scr->renderer, &width, &height, fullscreen != scr->last_fullscreen); } scr->width = width; scr->height = height; + scr->last_fullscreen = fullscreen; struct camu_screen_video *video; al_array_foreach_ptr(scr->videos, i, video) { camu_view_calculate(&video->view, scr->width, scr->height); @@ -316,6 +321,7 @@ bool camu_screen_create_window(struct camu_screen *scr, const char *name) } scr->width = scr->window->width; scr->height = scr->window->height; + scr->last_fullscreen = false; #ifdef STELA_EVENT_BUFFER nn_thread_create(&scr->thread, event_thread, scr); #endif @@ -357,7 +363,7 @@ static void add_buffer_internal(struct camu_screen *scr, struct camu_video_buffe if (buf->view.mode != CAMU_VIEW_NONE) { video.view = buf->view; #if 0 - } else if (!al_array_is_empty(scr->videos)) { + } else if (scr->videos.count > 0) { video.view = al_array_last(scr->videos).view; video.view.width = fmt->width; video.view.height = fmt->height; @@ -400,15 +406,15 @@ static void run_queue_internal(struct camu_screen *scr) al_array_foreach(scr->rem_queue, i, buf) { remove_buffer_internal(scr, buf); } - scr->rem_queue.size = 0; + scr->rem_queue.count = 0; // src->videos cannot be touched outside of the add/remove queue context. // For example, reserving space inside of screen_add_buffer() instead // of here would be very wrong. - al_array_reserve(scr->videos, scr->videos.size + scr->add_queue.size); + al_array_reserve(scr->videos, scr->videos.count + scr->add_queue.count); al_array_foreach(scr->add_queue, i, buf) { add_buffer_internal(scr, buf); } - scr->add_queue.size = 0; + scr->add_queue.count = 0; } #endif @@ -426,7 +432,7 @@ void camu_screen_add_buffer(struct camu_screen *scr, struct camu_video_buffer *b al_array_foreach_rev(scr->rem_queue, i, rbuf) { if (rbuf == buf) { al_array_remove_at(scr->rem_queue, i); - bool queue_empty = scr->add_queue.size + scr->rem_queue.size == 0; + bool queue_empty = scr->add_queue.count + scr->rem_queue.count == 0; if (queue_empty) { al_atomic_store(u8)(&scr->queued, 0, AL_ATOMIC_RELAXED); } @@ -457,7 +463,7 @@ void camu_screen_remove_buffer(struct camu_screen *scr, struct camu_video_buffer al_array_foreach_rev(scr->add_queue, i, rbuf) { if (rbuf == buf) { al_array_remove_at(scr->add_queue, i); - bool queue_empty = scr->add_queue.size + scr->rem_queue.size == 0; + bool queue_empty = scr->add_queue.count + scr->rem_queue.count == 0; if (queue_empty) { al_atomic_store(u8)(&scr->queued, 0, AL_ATOMIC_RELAXED); } diff --git a/src/screen/screen.h b/src/screen/screen.h index d567521..c84cfc0 100644 --- a/src/screen/screen.h +++ b/src/screen/screen.h @@ -59,6 +59,7 @@ struct camu_screen { bool force_render; s32 width; s32 height; + bool last_fullscreen; u64 last_click_ts; f64 last_mouse_y; f64 last_mouse_x; diff --git a/src/server/common.h b/src/server/common.h index 9948c02..80afb9b 100644 --- a/src/server/common.h +++ b/src/server/common.h @@ -56,8 +56,8 @@ AL_UNUSED_FUNCTION_PUSH static bool camu_is_url(str *s, u32 i) { - return al_str_cmp(s, al_str_c("https://"), i, 8) == 0 - || al_str_cmp(s, al_str_c("http://"), i, 7) == 0; + return al_str_cmp(s, &al_str_c("https://"), i, 8) == 0 + || al_str_cmp(s, &al_str_c("http://"), i, 7) == 0; } AL_UNUSED_FUNCTION_POP diff --git a/src/server/db.c b/src/server/db.c index ce4c99e..4cc449e 100644 --- a/src/server/db.c +++ b/src/server/db.c @@ -4,28 +4,34 @@ #include "server.h" -static bool open_user(struct camu_server *server, struct nn_dir_entry *dir) +// This is still nothing. + +static void open_user(struct camu_server *server, struct nn_dir *camu_db, struct nn_dir_entry *dir) { + str path; + nn_dir_entry_get_path(dir, camu_db, &path); struct nn_file file; - if (!nn_file_open(&file, &dir->path, 0)) { - return false; + if (!nn_file_open(&file, &path, 0)) { + goto out; } str s; nn_file_read_as_str(&file, &s); json_error_t error; - json_t *root = json_loadb(s.data, s.len, 0, &error); + json_t *root = json_loadb(s.data, s.length, 0, &error); if (!root) { al_log_error("server", "Failed to parse %.*s:%d:%d (%s).", - AL_STR_PRINTF(&dir->path), error.line, error.column, error.text); - return false; + al_str_fmt(&path), error.line, error.column, error.text); + al_str_free(&s); + goto out; } struct camu_user *user = al_alloc_object(struct camu_user); al_str_from(&user->name, json_string_value(json_object_get(root, "username"))); - al_log_info("server", "Loaded user \"%.*s\"", AL_STR_PRINTF(&user->name)); + al_log_info("server", "Loaded user \"%.*s\"", al_str_fmt(&user->name)); al_array_push(server->users, user); json_decref(root); al_str_free(&s); - return true; +out: + al_str_free(&path); } bool camu_db_open(struct camu_server *server, str *path) @@ -36,20 +42,22 @@ bool camu_db_open(struct camu_server *server, str *path) } struct nn_dir_entry entry; while (nn_dir_read(&camu_db, &entry)) { - if (al_str_eq(&entry.name, al_str_c("users"))) { + if (al_str_eq(&al_str_cr(nn_dir_entry_get_os_name(&entry)), &al_str_c("users"))) { struct nn_dir users; - if (nn_dir_open(&users, &entry.path)) { + str users_path; + nn_dir_entry_get_path(&entry, &camu_db, &users_path); + if (nn_dir_open(&users, &users_path)) { struct nn_dir_entry user; while (nn_dir_read(&users, &user)) { if (user.type == NNWT_ENTRY_FILE) { - open_user(server, &user); + open_user(server, &camu_db, &user); } - nn_dir_entry_free(&user); } nn_dir_close(&users); } + al_str_free(&users_path); + break; } - nn_dir_entry_free(&entry); } nn_dir_close(&camu_db); return true; diff --git a/src/server/server.c b/src/server/server.c index e949ee1..bdc1f96 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -58,7 +58,7 @@ static void write_user_state(struct camu_server *server, struct camu_user *user, { (void)user; #ifdef CAMU_HAVE_PORTAL - nn_packet_write_u32(packet, server->bridge.searches.size); + nn_packet_write_u32(packet, server->bridge.searches.count); struct camu_search *search; al_array_foreach(server->bridge.searches, i, search) { nn_packet_write_s32(packet, search->id); @@ -99,7 +99,7 @@ static bool identify_callback(void *userdata, struct nn_rpc_connection *conn, } client->user = user; al_array_push(server->clients, client); - al_log_info("server", "User \"%.*s\" logged in.", AL_STR_PRINTF(&user->name)); + al_log_info("server", "User \"%.*s\" logged in.", al_str_fmt(&user->name)); write_user_state(server, user, rpacket); break; } @@ -111,7 +111,7 @@ static bool identify_callback(void *userdata, struct nn_rpc_connection *conn, al_str_clone(&sink->name, &name); sink->server = server; al_array_push(server->sinks, sink); - handle_toggle_sink(server, al_str_c("default"), sink, true); + handle_toggle_sink(server, &al_str_c("default"), sink, true); al_log_info("server", "New sink."); break; } @@ -187,7 +187,7 @@ static void process_pending(struct camu_resource *resource) array(struct lia_list_entry *) pending; // resource->pending may be edited during a list_pump() call. al_array_clone(pending, resource->pending); - resource->pending.size = 0; + resource->pending.count = 0; struct lia_list_entry *entry; al_array_foreach(pending, i, entry) { lia_list_pump(entry->list); @@ -270,12 +270,12 @@ static void client_portal_callback(void *userdata0, void *userdata1, struct camu case CAMU_CLIENT_GET_PAGE: { struct camu_result_page *page = result->page; nn_packet_write_u32(packet, page->num); - nn_packet_write_u32(packet, page->posts.size); + nn_packet_write_u32(packet, page->posts.count); struct camu_post *post; al_array_foreach_ptr(page->posts, i, post) { nn_packet_write_post(packet, post); } - nn_packet_write_u32(packet, page->list.size); + nn_packet_write_u32(packet, page->list.count); str *unique_id; al_array_foreach_ptr(page->list, i, unique_id) { nn_packet_write_str(packet, unique_id); @@ -346,14 +346,14 @@ out: static struct cch_entry *entry_from_post(struct camu_server *server, struct camu_post *post, u32 index) { struct cch_entry *entry = NULL; - if (index <= post->media.size) { + if (index <= post->media.count) { struct camu_post_media *media = &al_array_at(post->media, index); if (!al_str_is_empty(&media->url)) { entry = cch_handler_http_create(&media->url, server->loop); } } if (!entry) { - al_log_warn("server", "Failed to load resource %.*s %u.", AL_STR_PRINTF(&post->unique_id), index); + al_log_warn("server", "Failed to load resource %.*s %u.", al_str_fmt(&post->unique_id), index); return NULL; } entry->handler->maybe_spawn_worker(entry->handler, 0); @@ -371,7 +371,7 @@ static void simple_search_portal_callback(void *userdata0, void *userdata1, stru return; } case CAMU_CLIENT_GET_PAGE: { - if (!result->page || al_array_is_empty(result->page->list)) break; + if (!result->page || !result->page->list.count) break; struct camu_post *post = camu_post_cache_get(&server->cache, &al_array_at(result->page->list, 0)); if (!post) break; struct cch_entry *entry = entry_from_post(server, post, 0); @@ -436,9 +436,10 @@ static void handle_add_command(struct camu_server *server, struct lia_list *list str url; nn_packet_read_str(packet, &url); u32 track = 0; - if (url.len > 7) { - s64 index = al_str_to_long(al_str_substr(&url, 7, url.len), 10); - if (index > 0 && index <= entry->chapters.size) + if (url.length > 7) { + bool error; + s64 index = al_str_to_long(&al_str_substr(&url, 7, url.length), 10, &error); + if (!error && index <= entry->chapters.count) track = (u32)index - 1; } entry->chapter = &al_array_at(entry->chapters, track); @@ -479,12 +480,12 @@ static void handle_add_command(struct camu_server *server, struct lia_list *list resource->load = LIANA_ENTRY_PREPARING; str query; if (al_str_at(&search, 0) == ';') { // search. - al_str_clone(&query, al_str_substr(&search, 1, search.len)); + al_str_clone(&query, &al_str_substr(&search, 1, search.length)); } else { al_str_from(&query, "link:"); al_str_cat(&query, &search); } - camu_portal_create_search(&server->bridge, al_str_c("youtube"), &query, simple_search_portal_callback, portal); + camu_portal_create_search(&server->bridge, &al_str_c("youtube"), &query, simple_search_portal_callback, portal); al_str_free(&query); break; } @@ -615,7 +616,7 @@ static void connection_closed_callback(void *userdata, struct nn_rpc_connection struct camu_server_client *client; al_array_foreach(server->clients, i, client) { if (client->conn == conn) { - al_log_info("server", "User \"%.*s\" logged out.", AL_STR_PRINTF(&client->user->name)); + al_log_info("server", "User \"%.*s\" logged out.", al_str_fmt(&client->user->name)); cleanup_client(client); al_array_remove_at(server->clients, i); break; @@ -656,7 +657,7 @@ static bool multiplex_callback(void *userdata, u8 id, struct nn_packet_stream *s void camu_server_init(struct camu_server *server, struct nn_event_loop *loop) { server->loop = loop; - server->addr = al_str_zero(); + server->addr = al_str_null(); al_array_init(server->nodes); al_array_init(server->clients); al_array_init(server->sinks); @@ -664,7 +665,7 @@ void camu_server_init(struct camu_server *server, struct nn_event_loop *loop) al_array_init(server->lists); struct lia_list *list = al_alloc_object(struct lia_list); - lia_list_init(list, al_str_c("default")); + lia_list_init(list, &al_str_c("default")); list->callback = list_callback; list->userdata = server; al_array_push(server->lists, list); diff --git a/src/sink/desktop.c b/src/sink/desktop.c index cb5e7c6..6fe6001 100644 --- a/src/sink/desktop.c +++ b/src/sink/desktop.c @@ -17,12 +17,20 @@ static u8 sink_callback(void *userdata, u8 op, u8 type, void *opaque) { struct camu_desktop *c = (struct camu_desktop *)userdata; + + if (op == CAMU_SINK_MOCK_CLOSE) { + c->should_quit = 1; + camu_screen_wake(&c->scr); + return CAMU_SINK_OK; + } + if (!camu_default_sink_callback(&c->scr, &c->mixer, op, type, opaque)) { camu_sink_close(&c->sink); if (c->exit_callback) { c->exit_callback(c->userdata, c); } } + return CAMU_SINK_OK; } @@ -108,7 +116,7 @@ bool camu_desktop_connect(struct camu_desktop *c, u8 type, struct nn_event_loop al_str_from(&c->sink.default_list, "default"); c->sink.callback = sink_callback; c->sink.userdata = c; - return camu_sink_connect(&c->sink, type, addr, port, al_str_c("desktop")); + return camu_sink_connect(&c->sink, type, addr, port, &al_str_c("desktop")); } bool camu_desktop_tick(struct camu_desktop *c) diff --git a/src/util/color_palette.c b/src/util/color_palette.c index bb4da03..886ba8e 100644 --- a/src/util/color_palette.c +++ b/src/util/color_palette.c @@ -40,24 +40,32 @@ bool camu_color_palette_init(str *path) nn_file_read_as_str(&file, &s); nn_file_close(&file); json_error_t error; - json_t *root = json_loadb(s.data, s.len, 0, &error); + json_t *root = json_loadb(s.data, s.length, 0, &error); if (!root) return false; json_t *special = json_object_get(root, "special"); json_t *colors = json_object_get(root, "colors"); if (!special || !colors) return false; json_t *object; + bool to_long_error; const char *color; + u32 value; for (u32 i = 0; i < ARRAY_SIZE(special_colors); i++) { object = json_object_get(special, special_colors[i]); if (!object) return false; color = json_string_value(object); - global_color_palette.colors[i] = (u32)al_str_to_long(al_str_w((char *)color, 1, 6), 16); + value = (u32)al_str_to_long(&al_str_w((char *)color, 1, 6), 16, &to_long_error); + if (!to_long_error) { + global_color_palette.colors[i] = value; + } } for (u32 i = 0; i < ARRAY_SIZE(normal_colors); i++) { object = json_object_get(colors, normal_colors[i]); if (!object) return false; color = json_string_value(object); - global_color_palette.colors[i + 2] = (u32)al_str_to_long(al_str_w((char *)color, 1, 6), 16); + value = (u32)al_str_to_long(&al_str_w((char *)color, 1, 6), 16, &to_long_error); + if (!to_long_error) { + global_color_palette.colors[i + 2] = value; + } } return true; } diff --git a/src/util/queue.h b/src/util/queue.h index bd91342..d103831 100644 --- a/src/util/queue.h +++ b/src/util/queue.h @@ -11,59 +11,60 @@ #define camu_queue_lock(q) \ AL_MACRO_WRAP \ -({ \ +{ \ nn_mutex_lock(&(q).mutex); \ -}) +} AL_MACRO_END #define camu_queue_unlock(q) \ AL_MACRO_WRAP \ -({ \ +{ \ nn_mutex_unlock(&(q).mutex); \ -}) +} AL_MACRO_END -#define camu_queue_size(q, r) \ +#define camu_queue_count(q, r) \ AL_MACRO_WRAP \ -({ \ +{ \ nn_mutex_lock(&(q).mutex); \ - r = (q).a.size; \ + r = (q).a.count; \ nn_mutex_unlock(&(q).mutex); \ -}) +} AL_MACRO_END #define camu_queue_init(q) \ AL_MACRO_WRAP \ -({ \ +{ \ al_array_init((q).a); \ nn_mutex_init(&(q).mutex); \ -}) +} AL_MACRO_END #define camu_queue_push(q, item) \ AL_MACRO_WRAP \ -({ \ +{ \ nn_mutex_lock(&(q).mutex); \ al_array_push((q).a, item); \ nn_mutex_unlock(&(q).mutex); \ -}) +} AL_MACRO_END #define camu_queue_pop(q, r) \ AL_MACRO_WRAP \ -({ \ +{ \ nn_mutex_lock(&(q).mutex); \ al_array_pop_at((q).a, 0, r); \ nn_mutex_unlock(&(q).mutex); \ -}) +} AL_MACRO_END #define camu_queue_try_pop(q, s, r) \ -AL_MACRO_WRAP \ -({ \ - nn_mutex_lock(&(q).mutex); \ - if ((s = (q).a.size) > 0) \ +AL_MACRO_WRAP \ +{ \ + nn_mutex_lock(&(q).mutex); \ + if ((s = (q).a.count) > 0) { \ al_array_pop_at((q).a, 0, r); \ - nn_mutex_unlock(&(q).mutex); \ -}) + } \ + nn_mutex_unlock(&(q).mutex); \ +} AL_MACRO_END #define camu_queue_free(q) \ AL_MACRO_WRAP \ -({ \ +{ \ nn_mutex_destroy(&(q).mutex); \ al_array_free((q).a); \ -}) +} AL_MACRO_END diff --git a/subprojects/libalabaster.wrap b/subprojects/libalabaster.wrap index 177c4e4..1fec842 100644 --- a/subprojects/libalabaster.wrap +++ b/subprojects/libalabaster.wrap @@ -1,4 +1,4 @@ [wrap-git] url = https://git.akon.city/libalabaster -revision = 27b5e13d75c58d5e32538a4b5aef65ab86f4bb38 +revision = 209310c561d89c9ed2040aa7053b320d32cc393c depth = 1 diff --git a/subprojects/libnaunet.wrap b/subprojects/libnaunet.wrap index e8fe3a6..0466a46 100644 --- a/subprojects/libnaunet.wrap +++ b/subprojects/libnaunet.wrap @@ -1,4 +1,4 @@ [wrap-git] url = https://git.akon.city/libnaunet -revision = 86dd8affaff59cf9d2657ad1c04fd62571b9a470 +revision = cef6cabce7ae97e9edfb6821ce4393d714579866 depth = 1 diff --git a/subprojects/miniaudio.wrap b/subprojects/miniaudio.wrap index c4cb007..9936650 100644 --- a/subprojects/miniaudio.wrap +++ b/subprojects/miniaudio.wrap @@ -1,6 +1,6 @@ [wrap-git] url = https://github.com/mackron/miniaudio.git -revision = 6a8a756b88feccfdf6c73345b44017b0d690d849 +revision = fc905ec97fdd4935f6066e648cccf1a098cd66cb depth = 1 patch_directory = miniaudio diff_files = miniaudio/miniaudio_pulse_flush.diff, miniaudio/miniaudio_alsa_compile.diff diff --git a/subprojects/packagefiles/ffmpeg/meson.build b/subprojects/packagefiles/ffmpeg/meson.build index 2a9cd33..435ee90 100644 --- a/subprojects/packagefiles/ffmpeg/meson.build +++ b/subprojects/packagefiles/ffmpeg/meson.build @@ -40,7 +40,7 @@ endif #'--extra-ldflags=-Lbuild/subprojects/libalabaster -l:libalabaster.a', #'--malloc-prefix=al_', -decoders = 'flac,mp3,mp3float,aac,opus,alac,mjpeg,jpeg2000,gif,h264,hevc,av1,vp9,vp8' +decoders = 'flac,mp3,mp3float,aac,opus,vorbis,alac,mjpeg,jpeg2000,gif,h264,hevc,av1,vp9,vp8' decoders += ',pcm_f32be,pcm_s32be,pcm_s32le,pcm_s32le_planar,pcm_f32le,pcm_s24be,pcm_s24le,pcm_s16be,pcm_s16be_planar,pcm_s16le,pcm_s16le_planar' #decoders += ',pcm_dvd,mpegvideo,mpeg2video' #decoders += ',ass,srt' @@ -49,7 +49,7 @@ demuxers = 'flac,mp3,aac,wav,image2,mjpeg,image2pipe,image_jpeg_pipe,gif,matrosk #demuxers += ',mpegts,mpegtsraw,mpegps,mpegvideo' #demuxers += ',ass,srt' -parsers = 'aac,opus,mjpeg,jpeg2000,h264,hevc,av1,vp9,vp8' +parsers = 'aac,opus,mjpeg,jpeg2000,gif,h264,hevc,av1,vp9,vp8' #parsers += ',mpegaudio,mpegvideo,dvd_nav' #extra_options += ['--enable-zlib', '--enable-libsoxr'] diff --git a/subprojects/stela.wrap b/subprojects/stela.wrap index 698b2fc..fb20893 100644 --- a/subprojects/stela.wrap +++ b/subprojects/stela.wrap @@ -1,4 +1,4 @@ [wrap-git] url = https://git.akon.city/stela -revision = 7b94b4baafa46357ebc6beba36d90ee5afe5091b +revision = 35a0c4feb6569895bf19c05c510a674666dcc4c6 depth = 1 |