From 29db390bdda45527ef74523890c125aa455d86ae Mon Sep 17 00:00:00 2001 From: Dario Pellegrino Date: Wed, 30 Jul 2025 15:27:44 +0200 Subject: [PATCH 01/12] Fix compile warnings Signed-off-by: Dario Pellegrino --- mod_openai_audio_stream.c | 3 +-- openai_audio_streamer_glue.cpp | 47 ++++++++++++++++++++-------------- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/mod_openai_audio_stream.c b/mod_openai_audio_stream.c index b427649..fd6a246 100644 --- a/mod_openai_audio_stream.c +++ b/mod_openai_audio_stream.c @@ -27,7 +27,6 @@ static switch_bool_t capture_callback(switch_media_bug_t *bug, void *user_data, switch (type) { case SWITCH_ABC_TYPE_INIT: - const char *uuid = switch_core_session_get_uuid(session); break; case SWITCH_ABC_TYPE_CLOSE: @@ -156,7 +155,7 @@ SWITCH_STANDARD_API(stream_function) assert(cmd); if (zstr(cmd) || argc < 2 || (0 == strcmp(argv[1], "start") && argc < 4)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error with command %s %s %s.\n", cmd, argv[0], argv[1]); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error with command %s.\n", cmd); stream->write_function(stream, "-USAGE: %s\n", STREAM_API_SYNTAX); goto done; } else { diff --git a/openai_audio_streamer_glue.cpp b/openai_audio_streamer_glue.cpp index a9340d1..98d7652 100644 --- a/openai_audio_streamer_glue.cpp +++ b/openai_audio_streamer_glue.cpp @@ -194,27 +194,39 @@ class AudioStreamer { } } + std::vector resampleRawAudio(const std::string& input_raw) { - size_t in_samples = input_raw.size() / 2; - size_t out_samples = static_cast(in_samples * out_sample_rate / static_cast(in_sample_rate)) + 1; + + double scaled = static_cast(in_samples) * out_sample_rate / in_sample_rate; + size_t out_samples = static_cast(scaled) + 1; std::vector in_buffer(in_samples); std::vector out_buffer(out_samples); std::memcpy(in_buffer.data(), input_raw.data(), input_raw.size()); - spx_uint32_t in_len = in_samples; - spx_uint32_t out_len = out_samples; + if (in_samples > UINT32_MAX || out_samples > UINT32_MAX) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, + "Too many samples to resample: in=%zu, out=%zu\n", + in_samples, out_samples); + return {}; + } + + spx_uint32_t in_len = static_cast(in_samples); + spx_uint32_t out_len = static_cast(out_samples); - int err = speex_resampler_process_int(m_resampler, 0, in_buffer.data(), &in_len, out_buffer.data(), &out_len); + int err = speex_resampler_process_int(m_resampler, 0, + in_buffer.data(), &in_len, + out_buffer.data(), &out_len); if (err != RESAMPLER_ERR_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Resampling failed with error code: %d\n", err); - return std::vector(); // return empty vector on error + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, + "Resampling failed with error code: %d\n", err); + return {}; // empty on error } - out_buffer.resize(out_len); // resize to actual size used + out_buffer.resize(out_len); // resize to actual resampled size return out_buffer; } @@ -223,7 +235,7 @@ class AudioStreamer { const int bitsPerSample = 16; // pcm16 int byteRate = in_sample_rate * numChannels * bitsPerSample / 8; int blockAlign = numChannels * bitsPerSample / 8; - uint32_t dataSize = rawAudio.size(); + uint32_t dataSize = static_cast(rawAudio.size()); uint32_t chunkSize = 36 + dataSize; std::ostringstream wavStream; // write in string like stream @@ -449,8 +461,10 @@ namespace { memset(tech_pvt, 0, sizeof(private_t)); - strncpy(tech_pvt->sessionId, switch_core_session_get_uuid(session), MAX_SESSION_ID); - strncpy(tech_pvt->ws_uri, wsUri, MAX_WS_URI); + strncpy(tech_pvt->sessionId, switch_core_session_get_uuid(session), MAX_SESSION_ID - 1); + tech_pvt->sessionId[MAX_SESSION_ID - 1] = '\0'; + strncpy(tech_pvt->ws_uri, wsUri, MAX_WS_URI - 1); + tech_pvt->ws_uri[MAX_WS_URI - 1] = '\0'; tech_pvt->sampling = desiredSampling; tech_pvt->responseHandler = responseHandler; tech_pvt->rtp_packets = rtp_packets; @@ -480,7 +494,7 @@ namespace { switch_mutex_init(&tech_pvt->mutex, SWITCH_MUTEX_NESTED, pool); - if (desiredSampling != sampling) { + if (static_cast(desiredSampling) != sampling) { if (switch_buffer_create(pool, &tech_pvt->sbuffer, buflen) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s: Error creating switch buffer.\n", tech_pvt->sessionId); @@ -510,7 +524,7 @@ namespace { ringBufferInit(tech_pvt->buffer, tech_pvt->data, adjSize); } - if (desiredSampling != sampling) { + if (static_cast(desiredSampling) != sampling) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "(%s) resampling from %u to %u\n", tech_pvt->sessionId, sampling, desiredSampling); tech_pvt->resampler = speex_resampler_init(channels, sampling, desiredSampling, SWITCH_RESAMPLE_QUALITY, &err); if (0 != err) { @@ -559,17 +573,14 @@ namespace { extern "C" { int validate_ws_uri(const char* url, char* wsUri) { - const char* scheme = nullptr; const char* hostStart = nullptr; const char* hostEnd = nullptr; const char* portStart = nullptr; // Check scheme if (strncmp(url, "ws://", 5) == 0) { - scheme = "ws"; hostStart = url + 5; } else if (strncmp(url, "wss://", 6) == 0) { - scheme = "wss"; hostStart = url + 6; } else { return 0; @@ -728,7 +739,7 @@ extern "C" { int channels, void **ppUserData) { - int deflate, heart_beat; + int deflate = 0, heart_beat = 0; bool suppressLog = false; const char* buffer_size; const char* extra_headers; @@ -957,8 +968,6 @@ extern "C" { return SWITCH_TRUE; } - uint32_t available = switch_buffer_inuse(tech_pvt->playback_buffer); - uint32_t bytes_needed = frame->datalen; uint32_t bytes_per_sample = frame->datalen / frame->samples; From 7af2c7bab2d8b9ac84ddbed197be301817280347 Mon Sep 17 00:00:00 2001 From: Dario Pellegrino Date: Wed, 30 Jul 2025 15:42:33 +0200 Subject: [PATCH 02/12] Update README Signed-off-by: Dario Pellegrino --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 183191f..9d033f4 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,8 @@ The following channel variables can be used to fine tune websocket connection an - `Buffer Size` actually represents a duration of audio chunk sent to websocket. If you want to send e.g. 100ms audio packets to your ws endpoint you would set this variable to 100. If ommited, default packet size of 20ms will be sent as grabbed from the audio channel (which is default FreeSWITCH frame size) - Set `STREAM_OPENAI_API_KEY` to have a valid OpenAI API key to authenticate with OpenAI's Realtime API. This is required for the module to function properly. If not set the module will use the `STREAM_EXTRA_HEADERS` to pass the OpenAI API key as a header assuming you prepared the headers in the channel variable. **NOTE**: An OpenAI API key is required for the module to function properly. If not set, the module will not be able to connect to the API. +- You can specify the OpenAI Realtime model in the URI, e.g. `uuid_openai_audio_stream ${uuid} start wss://api.openai.com/v1/realtime?model=gpt-4o-mini-realtime-preview-2024-12-17 mono 24k` + - Extra headers should be a JSON object with key-value pairs representing additional HTTP headers. Each key should be a header name, and its corresponding value should be a string. ```json { @@ -107,6 +109,7 @@ Attaches a media bug and starts streaming audio (in L16 format) to the websocket - "8k" = 8000 Hz sample rate will be generated - "16k" = 16000 Hz sample rate will be generated - "24k" = 24000 Hz sample rate will be generated +- **IMPORTANT NOTE**: The OpenAI Realtime API, when using PCM audio format, expects the audio to be in 24 kHz sample rate. Use the sampling-rate parameter as `24k` (or `24000`) and mono to ensure that the audio is sent in the correct format. From the OpenAI Realtime API documentation: *input audio must be 16-bit PCM at a 24kHz sample rate, single channel (mono), and little-endian byte order.* Support for exchanging audio with OpenAI in other formats may be developed in the future, which would make the `` and ` send_json From aaa21a4b328d53fea1c9e121004ae6c622595862 Mon Sep 17 00:00:00 2001 From: Dario Pellegrino Date: Wed, 20 Aug 2025 15:47:24 +0200 Subject: [PATCH 03/12] Add first ci with some static analysis tools Signed-off-by: Dario Pellegrino --- .github/workflows/static-analysis.yml | 56 ++++++++++++++++++ Dockerfile.ci | 81 +++++++++++++++++++++++++++ README.md | 2 + 3 files changed, 139 insertions(+) create mode 100644 .github/workflows/static-analysis.yml create mode 100644 Dockerfile.ci diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml new file mode 100644 index 0000000..5e7d31e --- /dev/null +++ b/.github/workflows/static-analysis.yml @@ -0,0 +1,56 @@ +name: Static Analysis + +on: + push: + branches: [ main, develop ] + pull_request: + branches: [ main, develop ] + workflow_dispatch: + +jobs: + analyze: + runs-on: ubuntu-22.04 + + steps: + - uses: actions/checkout@v4 + with: + submodules: 'recursive' + + - name: Set up Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build SDK image (cached) + uses: docker/build-push-action@v6 + with: + context: . + file: Dockerfile.ci + tags: freeswitch-sdk:ci + load: true + cache-from: type=gha + cache-to: type=gha,mode=max + + - name: Run analysis inside container + uses: addnab/docker-run-action@v3 + with: + image: freeswitch-sdk:ci + options: -v ${{ github.workspace }}:/work + run: | + set -eux + cd /work + cmake -S . -B build \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ + -DCMAKE_C_COMPILER=clang \ + -DCMAKE_CXX_COMPILER=clang++ \ + -DCMAKE_C_COMPILER_LAUNCHER=ccache \ + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + + scan-build --status-bugs cmake --build build -j"$(nproc)" + + clang-tidy -p build $(git ls-files '*.c' '*.cc' '*.cpp' '*.cxx') \ + --warnings-as-errors='' || true + + cppcheck --enable=all --inconclusive --std=c++17 --force \ + --project=build/compile_commands.json \ + --suppress=missingIncludeSystem \ + -i build . 2> cppcheck.log || true diff --git a/Dockerfile.ci b/Dockerfile.ci new file mode 100644 index 0000000..58c18f4 --- /dev/null +++ b/Dockerfile.ci @@ -0,0 +1,81 @@ +# syntax=docker/dockerfile:1.7 + +############################ +# Stage 1: Build dependencies + FreeSWITCH +############################ +FROM debian:12 AS builder + +ENV DEBIAN_FRONTEND=noninteractive + + +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates git curl wget \ + build-essential cmake automake autoconf libtool libtool-bin libltdl-dev pkg-config \ + libssl-dev zlib1g-dev libdb-dev unixodbc-dev libncurses5-dev libexpat1-dev \ + libgdbm-dev bison erlang-dev libtpl-dev libtiff5-dev uuid-dev \ + libpcre3-dev libpcre2-dev libedit-dev libsqlite3-dev libcurl4-openssl-dev nasm \ + libogg-dev libspeex-dev libspeexdsp-dev libldns-dev python3-dev \ + libavformat-dev libswscale-dev libswresample-dev \ + liblua5.2-dev libopus-dev libpq-dev \ + libsndfile1-dev libflac-dev libvorbis-dev \ + && rm -rf /var/lib/apt/lists/* + + +WORKDIR /src + +RUN git clone https://github.com/signalwire/libks && \ + git clone https://github.com/freeswitch/sofia-sip && \ + git clone https://github.com/freeswitch/spandsp && \ + git clone https://github.com/signalwire/signalwire-c && \ + git clone https://github.com/signalwire/freeswitch + +# libks +WORKDIR /src/libks +RUN cmake . -DCMAKE_INSTALL_PREFIX=/usr -DWITH_LIBBACKTRACE=1 && \ + make -j"$(nproc)" && make install + +# sofia-sip +WORKDIR /src/sofia-sip +RUN ./bootstrap.sh && \ + ./configure --with-pic --with-glib=no --without-doxygen --disable-stun --prefix=/usr && \ + make -j"$(nproc)" && make install + +# spandsp +WORKDIR /src/spandsp +RUN ./bootstrap.sh && \ + ./configure --with-pic --prefix=/usr && \ + make -j"$(nproc)" && make install + +# signalwire-c +WORKDIR /src/signalwire-c +RUN PKG_CONFIG_PATH=/usr/lib/pkgconfig cmake . -DCMAKE_INSTALL_PREFIX=/usr && \ + make -j"$(nproc)" && make install + +# FreeSWITCH SDK +WORKDIR /src/freeswitch +RUN ./bootstrap.sh -j && \ + ./configure --prefix=/usr && \ + make -j"$(nproc)" && make install + +############################ +# Stage 2: Slim SDK image (no FreeSWITCH runtime) +############################ +FROM debian:12 + +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && apt-get install -y --no-install-recommends \ + build-essential \ + clang clang-tidy clang-tools \ + cppcheck cmake pkg-config ccache \ + libssl-dev zlib1g-dev \ + libspeexdsp-dev libspandsp-dev \ + git curl wget \ + && rm -rf /var/lib/apt/lists/* + +# Copy only SDK bits +COPY --from=builder /usr/include/freeswitch/ /usr/include/freeswitch/ +COPY --from=builder /usr/lib/pkgconfig/freeswitch.pc /usr/lib/pkgconfig/ +COPY --from=builder /usr/lib/libfreeswitch.so* /usr/lib/ + +WORKDIR /work diff --git a/README.md b/README.md index 9d033f4..a27726c 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # mod_openai_audio_stream +![Static Analysis](https://github.com/dariopellegrino00/mod_openai_audio_stream/actions/workflows/static-analysis.yml/badge.svg) + A fork of [mod_audio_stream](https://github.com/amigniter/mod_audio_stream) specifically designed for streaming audio to OpenAI's realtime API and playing the responses back to the user via FreeSWITCH and WebSocket. **mod_openai_audio_stream** is a FreeSWITCH module that streams L16 audio from a channel to an OpenAI realtime websocket endpoint. The stream is adherent to OpenAI's Realtime API specification and allows for real-time audio playback directly in the channel. From 5d3fa25868aeb7c3344d74ca09aa010509908798 Mon Sep 17 00:00:00 2001 From: Dario Pellegrino Date: Wed, 20 Aug 2025 17:09:39 +0200 Subject: [PATCH 04/12] Fix build and static checks Signed-off-by: Dario Pellegrino --- .github/workflows/{static-analysis.yml => checks.yml} | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename .github/workflows/{static-analysis.yml => checks.yml} (98%) diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/checks.yml similarity index 98% rename from .github/workflows/static-analysis.yml rename to .github/workflows/checks.yml index 5e7d31e..f87617e 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/checks.yml @@ -1,4 +1,4 @@ -name: Static Analysis +name: Build & Static Checks on: push: diff --git a/README.md b/README.md index a27726c..35f1792 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # mod_openai_audio_stream -![Static Analysis](https://github.com/dariopellegrino00/mod_openai_audio_stream/actions/workflows/static-analysis.yml/badge.svg) +![Build & Static Code Checks](https://github.com/dariopellegrino00/mod_openai_audio_stream/actions/workflows/checks.yml/badge.svg) A fork of [mod_audio_stream](https://github.com/amigniter/mod_audio_stream) specifically designed for streaming audio to OpenAI's realtime API and playing the responses back to the user via FreeSWITCH and WebSocket. **mod_openai_audio_stream** is a FreeSWITCH module that streams L16 audio from a channel to an OpenAI realtime websocket endpoint. The stream is adherent to OpenAI's Realtime API specification and allows for real-time audio playback directly in the channel. From f489ad6ea85492dc07e871587cfda21c807b3ae3 Mon Sep 17 00:00:00 2001 From: Dario Pellegrino Date: Wed, 20 Aug 2025 17:35:07 +0200 Subject: [PATCH 05/12] Update README Signed-off-by: Dario Pellegrino --- README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 35f1792..294ad99 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,12 @@ # mod_openai_audio_stream -![Build & Static Code Checks](https://github.com/dariopellegrino00/mod_openai_audio_stream/actions/workflows/checks.yml/badge.svg) +![Build & Static Code Checks](https://github.com/VoiSmart/mod_openai_audio_stream/actions/workflows/checks.yml/badge.svg) -A fork of [mod_audio_stream](https://github.com/amigniter/mod_audio_stream) specifically designed for streaming audio to OpenAI's realtime API and playing the responses back to the user via FreeSWITCH and WebSocket. -**mod_openai_audio_stream** is a FreeSWITCH module that streams L16 audio from a channel to an OpenAI realtime websocket endpoint. The stream is adherent to OpenAI's Realtime API specification and allows for real-time audio playback directly in the channel. +**mod_openai_audio_stream** is a FreeSWITCH module that streams L16 audio from a channel to an OpenAI Realtime WebSocket endpoint. The stream follows OpenAI's Realtime API specification and enables real-time audio playback directly in the channel. + +It is a fork of [mod_audio_stream](https://github.com/amigniter/mod_audio_stream), specifically adapted for streaming audio to OpenAI's Realtime API and playing the responses back to the user via FreeSWITCH and WebSocket. + +The goal of **mod_openai_audio_stream** is to provide a simple, lightweight, yet effective module for streaming audio and receiving responses directly from OpenAI’s Realtime WebSocket into the call through FreeSWITCH. It uses [ixwebsocket](https://machinezone.github.io/IXWebSocket/), a C++ WebSocket library compiled as a static library. The purpose of **mod_openai_audio_stream** was to make a simple, less dependent but yet effective module to stream audio and receive responses directly from OpenAI realtime websocket into the call via switch. It uses [ixwebsocket](https://machinezone.github.io/IXWebSocket/), c++ library for websocket protocol which is compiled as a static library. From 614959f2266e2e26bc929dbc3b0a4ac02b793c30 Mon Sep 17 00:00:00 2001 From: Dario Pellegrino <72254164+dariopellegrino00@users.noreply.github.com> Date: Wed, 20 Aug 2025 17:45:53 +0200 Subject: [PATCH 06/12] Update README.md reduntant Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 294ad99..9ee293c 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,6 @@ It is a fork of [mod_audio_stream](https://github.com/amigniter/mod_audio_stream The goal of **mod_openai_audio_stream** is to provide a simple, lightweight, yet effective module for streaming audio and receiving responses directly from OpenAI’s Realtime WebSocket into the call through FreeSWITCH. It uses [ixwebsocket](https://machinezone.github.io/IXWebSocket/), a C++ WebSocket library compiled as a static library. -The purpose of **mod_openai_audio_stream** was to make a simple, less dependent but yet effective module to stream audio and receive responses directly from OpenAI realtime websocket into the call via switch. It uses [ixwebsocket](https://machinezone.github.io/IXWebSocket/), c++ library for websocket protocol which is compiled as a static library. ## Notes From 8a1f38d253e4d8cabe73e94fa5bb6371edd0791d Mon Sep 17 00:00:00 2001 From: Dario Pellegrino <72254164+dariopellegrino00@users.noreply.github.com> Date: Wed, 20 Aug 2025 17:47:47 +0200 Subject: [PATCH 07/12] Update .github/workflows/checks.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/checks.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index f87617e..b84b511 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -54,3 +54,4 @@ jobs: --project=build/compile_commands.json \ --suppress=missingIncludeSystem \ -i build . 2> cppcheck.log || true + cat cppcheck.log From df6fe9147ce043c73935d215e1adc696184968c3 Mon Sep 17 00:00:00 2001 From: Dario Pellegrino Date: Wed, 20 Aug 2025 17:58:52 +0200 Subject: [PATCH 08/12] Add clang-tidy critic warning as errors Signed-off-by: Dario Pellegrino --- .github/workflows/checks.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index b84b511..a194d5f 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -48,7 +48,8 @@ jobs: scan-build --status-bugs cmake --build build -j"$(nproc)" clang-tidy -p build $(git ls-files '*.c' '*.cc' '*.cpp' '*.cxx') \ - --warnings-as-errors='' || true + --warnings-as-errors='clang-analyzer-*,bugprone-*,performance-*' + cppcheck --enable=all --inconclusive --std=c++17 --force \ --project=build/compile_commands.json \ From 8005d738fe07eff69e80d4db50e616d2e87bed39 Mon Sep 17 00:00:00 2001 From: Dario Pellegrino <72254164+dariopellegrino00@users.noreply.github.com> Date: Wed, 20 Aug 2025 18:06:32 +0200 Subject: [PATCH 09/12] Update .github/workflows/checks.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/checks.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index a194d5f..8bfd444 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -48,7 +48,13 @@ jobs: scan-build --status-bugs cmake --build build -j"$(nproc)" clang-tidy -p build $(git ls-files '*.c' '*.cc' '*.cpp' '*.cxx') \ - --warnings-as-errors='clang-analyzer-*,bugprone-*,performance-*' + FILES="$(git ls-files '*.c' '*.cc' '*.cpp' '*.cxx')" + if [ -n "$FILES" ]; then + clang-tidy -p build $FILES \ + --warnings-as-errors='clang-analyzer-*,bugprone-*,performance-*' + else + echo "No source files found for clang-tidy analysis." + fi cppcheck --enable=all --inconclusive --std=c++17 --force \ From 0a9e493c5643c943e3812494ca1c6670b2d96c49 Mon Sep 17 00:00:00 2001 From: Dario Pellegrino <72254164+dariopellegrino00@users.noreply.github.com> Date: Wed, 20 Aug 2025 18:06:39 +0200 Subject: [PATCH 10/12] Update .github/workflows/checks.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/checks.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 8bfd444..b98e106 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -57,7 +57,7 @@ jobs: fi - cppcheck --enable=all --inconclusive --std=c++17 --force \ + cppcheck --enable=warning,style,performance,portability --std=c++17 --force \ --project=build/compile_commands.json \ --suppress=missingIncludeSystem \ -i build . 2> cppcheck.log || true From f89cc230c4a9d75638b0ec70bcb86218867116f8 Mon Sep 17 00:00:00 2001 From: Dario Pellegrino Date: Wed, 20 Aug 2025 18:26:14 +0200 Subject: [PATCH 11/12] Fix work not a git safe directory Signed-off-by: Dario Pellegrino --- .github/workflows/checks.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index b98e106..964eef7 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -37,6 +37,7 @@ jobs: run: | set -eux cd /work + git config --global --add safe.directory /work cmake -S . -B build \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ From 8b93611a95b14b325ad36aadbc91c0c854bb3ee0 Mon Sep 17 00:00:00 2001 From: Dario Pellegrino <72254164+dariopellegrino00@users.noreply.github.com> Date: Thu, 21 Aug 2025 12:00:03 +0200 Subject: [PATCH 12/12] Fix and Refactor CI code and build checks (#7) CI: Fix and Refactor code and build checks: * Fix old missed clang-tidy check causing failure * Fix strcpy urgent warning * Fix cppcheck checking all dependencies * Fix cppcheck not failing on urgent warnings * Add cppcheck print style issues after analysis success Signed-off-by: Dario Pellegrino --- .github/workflows/checks.yml | 20 +++++++++++++++----- openai_audio_streamer_glue.cpp | 9 +++++++-- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 964eef7..15416bc 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -48,8 +48,7 @@ jobs: scan-build --status-bugs cmake --build build -j"$(nproc)" - clang-tidy -p build $(git ls-files '*.c' '*.cc' '*.cpp' '*.cxx') \ - FILES="$(git ls-files '*.c' '*.cc' '*.cpp' '*.cxx')" + FILES="$(git ls-files '*.c' '*.cc' '*.cpp' '*.cxx' | grep -v '^buffer/' | grep -v '^libs/')" if [ -n "$FILES" ]; then clang-tidy -p build $FILES \ --warnings-as-errors='clang-analyzer-*,bugprone-*,performance-*' @@ -58,8 +57,19 @@ jobs: fi - cppcheck --enable=warning,style,performance,portability --std=c++17 --force \ + cppcheck --enable=warning,performance,portability --std=c++17 --force \ --project=build/compile_commands.json \ --suppress=missingIncludeSystem \ - -i build . 2> cppcheck.log || true - cat cppcheck.log + -i build -i buffer -i libs 2> cppcheck-warn.log + + cppcheck --enable=style --std=c++17 --force \ + --project=build/compile_commands.json \ + --suppress=missingIncludeSystem \ + -i build -i buffer -i libs 2> cppcheck-style.log || true + + if [ -s cppcheck-style.log ]; then + echo "Style issues found by cppcheck:" + cat cppcheck-style.log + else + echo "No style issues found by cppcheck." + fi diff --git a/openai_audio_streamer_glue.cpp b/openai_audio_streamer_glue.cpp index 98d7652..a8babf4 100644 --- a/openai_audio_streamer_glue.cpp +++ b/openai_audio_streamer_glue.cpp @@ -230,7 +230,10 @@ class AudioStreamer { return out_buffer; } - std::string createWavFromRaw(std::string rawAudio) { + // create wav file from raw audio + // rawAudio passed as constant reference because it is never edited + std::string createWavFromRaw(const std::string& rawAudio) { + const int numChannels = 1; // mono const int bitsPerSample = 16; // pcm16 int byteRate = in_sample_rate * numChannels * bitsPerSample / 8; @@ -1012,7 +1015,9 @@ extern "C" { { auto* tech_pvt = (private_t*) switch_core_media_bug_get_user_data(bug); char sessionId[MAX_SESSION_ID]; - strcpy(sessionId, tech_pvt->sessionId); + + strncpy(sessionId, tech_pvt->sessionId, MAX_SESSION_ID - 1); + sessionId[MAX_SESSION_ID - 1] = '\0'; switch_mutex_lock(tech_pvt->mutex); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "(%s) stream_session_cleanup\n", sessionId);