mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-16 00:17:03 +03:00
Compare commits
105 Commits
SqueezeAmp
...
SqueezeAmp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fdd34779e6 | ||
|
|
76dd27116f | ||
|
|
77f486e56f | ||
|
|
403623d4d6 | ||
|
|
60b163676a | ||
|
|
f49c3f7206 | ||
|
|
3fade26793 | ||
|
|
856303d8f1 | ||
|
|
b20c8306fa | ||
|
|
877f16181b | ||
|
|
2cba6972ff | ||
|
|
fbd9516667 | ||
|
|
646a220fd0 | ||
|
|
962dbf89c8 | ||
|
|
3a658f3ba2 | ||
|
|
4f5a7ade9d | ||
|
|
f15f846030 | ||
|
|
14f4caf584 | ||
|
|
46eb732d82 | ||
|
|
d092ae093c | ||
|
|
4a51efd556 | ||
|
|
c1375444b4 | ||
|
|
e5eabcaf86 | ||
|
|
93465db1b8 | ||
|
|
dc66d9e9dc | ||
|
|
8462de1c16 | ||
|
|
37f48d4bc8 | ||
|
|
ec019f98f3 | ||
|
|
5e5c7e0c80 | ||
|
|
3144cf5f91 | ||
|
|
18cc0adfb4 | ||
|
|
78ece491a9 | ||
|
|
9e66a822de | ||
|
|
0e12f7f887 | ||
|
|
5df561890c | ||
|
|
f6630fae4e | ||
|
|
e2df4b1cc3 | ||
|
|
3172576fc1 | ||
|
|
e0dd7a596b | ||
|
|
6e4dd65fd7 | ||
|
|
7e5f27af12 | ||
|
|
f805db3d27 | ||
|
|
a81d0e0513 | ||
|
|
6c524cd094 | ||
|
|
e34cec1ad1 | ||
|
|
a2c16decee | ||
|
|
d06893c43d | ||
|
|
aecaed4a5f | ||
|
|
113a75a61d | ||
|
|
f721d140e7 | ||
|
|
46848b3afe | ||
|
|
3d63670499 | ||
|
|
83114861c5 | ||
|
|
5e7ab93e4a | ||
|
|
2c56f2d7ae | ||
|
|
c62e719c11 | ||
|
|
0226355ab7 | ||
|
|
42bee2a7b0 | ||
|
|
130f54526f | ||
|
|
f14f2debc3 | ||
|
|
25772c9ccb | ||
|
|
1ae1b03fc3 | ||
|
|
08ff02dc3c | ||
|
|
3f4df9a348 | ||
|
|
bb70ea1eaa | ||
|
|
c0e8e36221 | ||
|
|
4c94042c1d | ||
|
|
66be31a76c | ||
|
|
5a53011383 | ||
|
|
9ca1b87919 | ||
|
|
2698577592 | ||
|
|
f70f973ca9 | ||
|
|
83592b7079 | ||
|
|
2967723fdf | ||
|
|
d6e75dc71e | ||
|
|
fc50d55a27 | ||
|
|
4fff2f0dc1 | ||
|
|
027d81af21 | ||
|
|
96a2581534 | ||
|
|
461486ce21 | ||
|
|
7f0bc6c2ba | ||
|
|
551db4a7d1 | ||
|
|
eee3123eba | ||
|
|
d1a5e0aaa6 | ||
|
|
e6d9c5f5a3 | ||
|
|
8164ccacaa | ||
|
|
b2ceb8c0e3 | ||
|
|
2e66a6a6cb | ||
|
|
ac1817f4d3 | ||
|
|
1d4bd8274b | ||
|
|
58af548252 | ||
|
|
c400f4467e | ||
|
|
24c69a70d2 | ||
|
|
0ce4e9e240 | ||
|
|
b50caddb39 | ||
|
|
639ed446f5 | ||
|
|
06b65f6f6c | ||
|
|
f70cd0eeb1 | ||
|
|
95018f39e8 | ||
|
|
c8e999590d | ||
|
|
b640ff1c88 | ||
|
|
bfe1be3c99 | ||
|
|
9416c6916a | ||
|
|
f23116d2c6 | ||
|
|
ff1d276148 |
232
.github/workflows/Platform_build.yml
vendored
Normal file
232
.github/workflows/Platform_build.yml
vendored
Normal file
@@ -0,0 +1,232 @@
|
||||
name: Platform Build
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '**4.3'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ui_build:
|
||||
description: 'Force Rebuilding the UI. When not forced, the system will check for [ui-build] in the last commit message to trigger a ui rebuild'
|
||||
required: true
|
||||
type: boolean
|
||||
release_build:
|
||||
description: 'Force a Release build. When not forced, the system will check for release word in the last commit message to trigger a release'
|
||||
required: true
|
||||
type: boolean
|
||||
|
||||
jobs:
|
||||
bootstrap:
|
||||
name: Global setup
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: sle118/squeezelite-esp32-idfv43
|
||||
outputs:
|
||||
build_number: ${{ steps.buildnumber.outputs.build_number }}
|
||||
ui_build: ${{ steps.build_flags.outputs.ui_build }}
|
||||
release_flag: ${{ steps.build_flags.outputs.release_flag }}
|
||||
mock: ${{ steps.build_flags.outputs.mock }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
- name: Generate common build number
|
||||
id: buildnumber
|
||||
uses: einaregilsson/build-number@v3
|
||||
with:
|
||||
token: ${{secrets.github_token}}
|
||||
- name: Set build flags
|
||||
id: build_flags
|
||||
run: |
|
||||
git config --global --add safe.directory /__w/squeezelite-esp32/squeezelite-esp32
|
||||
[ ${{github.event.inputs.ui_build}} ] && ui_build_option="--ui_build" || ui_build_option=""
|
||||
[ ${{github.event.inputs.release_build}} ] && release_build_option="--force" || release_build_option=""
|
||||
echo "ui_build_option=$ui_build_option" >> $GITHUB_ENV
|
||||
echo "release_build_option=$release_build_option" >> $GITHUB_ENV
|
||||
echo "Dumping environment"
|
||||
env
|
||||
. /opt/esp/python_env/idf4.3_py3.8_env/bin/activate
|
||||
# build_flags support the following options
|
||||
# --mock - to mock the compilation part - this is to be used for testing only
|
||||
# --force - to force a release build even if the last commit message doesn't contain the word "release"
|
||||
# --ui_build - to force a ui_build even if the last commit message doesn't contain "[ui-build]"
|
||||
build_tools.py build_flags $ui_build_option $release_build_option
|
||||
- name: Show Build Flags
|
||||
run: |
|
||||
echo "Running with the following options"
|
||||
echo "Web Build Flag=${{steps.build_flags.outputs.ui_build}}"
|
||||
echo "Mock flag=${{steps.build_flags.outputs.mock}}"
|
||||
echo "Release Flag=${{steps.build_flags.outputs.release_flag}}"
|
||||
- name: Refresh certificates
|
||||
if: ${{ steps.build_flags.outputs.release_flag }}
|
||||
run: |
|
||||
git update-index --chmod=+x ./server_certs/getcert.sh
|
||||
cd server_certs;./getcert.sh;cat github.pem;cd ..
|
||||
- name: Setup Node.js dependencies
|
||||
if: ${{ !env.ACT }}
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
cache: 'npm'
|
||||
cache-dependency-path: components/wifi-manager/webapp/package.json
|
||||
- name: Build Web Application
|
||||
if: ${{ steps.build_flags.outputs.ui_build == 1 }}
|
||||
run: |
|
||||
cd components/wifi-manager/webapp/
|
||||
npm install
|
||||
npm run-script build
|
||||
- name: Update repository with prebuilt items
|
||||
if: ${{ steps.build_flags.outputs.ui_build == 1 || steps.build_flags.outputs.release_flag == 1 }}
|
||||
run: |
|
||||
git config user.name github-actions
|
||||
git config user.email github-actions@github.com
|
||||
git add server_certs
|
||||
git add components/wifi-manager/webapp/*.h
|
||||
git add components/wifi-manager/webapp/*.c
|
||||
git add components/wifi-manager/webapp/*.cmake
|
||||
git add components/wifi-manager/webapp/dist/*
|
||||
git commit -m "Update prebuilt objects [skip actions]"
|
||||
git push https://${{secrets.github_token}}@github.com/sle118/squeezelite-esp32.git
|
||||
- name: Locally store commonly built objects
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: prebuilt_objects
|
||||
path: |
|
||||
server_certs
|
||||
components/wifi-manager/webapp/*.h
|
||||
components/wifi-manager/webapp/*.c
|
||||
components/wifi-manager/webapp/dist/*
|
||||
components/wifi-manager/webapp/*.cmake
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: sle118/squeezelite-esp32-idfv43
|
||||
needs: [bootstrap]
|
||||
strategy:
|
||||
matrix:
|
||||
node: [I2S-4MFlash, SqueezeAmp, Muse]
|
||||
depth: [16, 32]
|
||||
exclude:
|
||||
- node: Muse
|
||||
depth: 32
|
||||
- node: bootstrap
|
||||
depth: 32
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
- name: Show Build Flags
|
||||
run: |
|
||||
echo "Running with the following options"
|
||||
echo "Web Build Flag=${{needs.bootstrap.outputs.ui_build}}"
|
||||
echo "Mock flag=${{needs.bootstrap.outputs.mock}}"
|
||||
echo "Release Flag=${{needs.bootstrap.outputs.release_flag}}"
|
||||
echo Environment File name: $GITHUB_ENV
|
||||
- name: Set build parameters
|
||||
run: |
|
||||
. /opt/esp/python_env/idf4.3_py3.8_env/bin/activate
|
||||
git config --global --add safe.directory /__w/squeezelite-esp32/squeezelite-esp32
|
||||
git status
|
||||
build_tools.py environment --build ${{ needs.bootstrap.outputs.build_number }} --env_file "$GITHUB_ENV" --node "${{matrix.node}}" --depth ${{matrix.depth}} --major 2 --docker sle118/squeezelite-esp32-idfv43
|
||||
|
||||
- uses: actions/download-artifact@master
|
||||
name: Restore common objects
|
||||
with:
|
||||
name: prebuilt_objects
|
||||
- name: Build the firmware
|
||||
if: ${{ needs.bootstrap.outputs.mock == 0 }}
|
||||
run: |
|
||||
. ${IDF_PYTHON_ENV_PATH}/bin/activate
|
||||
chmod +x ./components/spotify/cspot/bell/nanopb/generator/protoc
|
||||
chmod +x ./components/spotify/cspot/bell/nanopb/generator/protoc-gen-nanopb
|
||||
chmod +x ./components/spotify/cspot/bell/nanopb/generator/*.py
|
||||
chmod +x ./components/spotify/cspot/bell/nanopb/generator/*.py2
|
||||
chmod +x ./components/spotify/cspot/bell/nanopb/generator/proto/*.py
|
||||
echo "Copying target sdkconfig"
|
||||
cp build-scripts/${TARGET_BUILD_NAME}-sdkconfig.defaults sdkconfig
|
||||
echo "Building project"
|
||||
idf.py build -DDEPTH=${DEPTH} -DBUILD_NUMBER=${BUILD_NUMBER}-${DEPTH}
|
||||
- name: Build Mock firmware
|
||||
if: ${{ needs.bootstrap.outputs.mock == 1 }}
|
||||
run: |
|
||||
mkdir -p build
|
||||
cd build
|
||||
mkdir -p partition_table
|
||||
mkdir -p bootloader
|
||||
echo \\"mock content\\"> ./squeezelite.bin
|
||||
echo \"mock content\"> ./recovery.bin
|
||||
echo \"mock content\"> ./bootloader/bootloader.bin
|
||||
echo \"mock content\"> ./partition_table/partition-table.bin
|
||||
echo \"mock content\"> ./ota_data_initial.bin
|
||||
echo \"mock content\"> ./flash_project_args
|
||||
echo \"mock content\"> ./size_comp1.txt
|
||||
echo \"mock content\"> ./size_comp2.txt
|
||||
echo \"mock content\"> ./partitions.csv
|
||||
echo { \"write_flash_args\" : [ \"--flash_mode\", \"dio\", \"--flash_size\", \"detect\", \"--flash_freq\", \"80m\" ], \"flash_settings\" : { \"flash_mode\": \"dio\", \"flash_size\": \"detect\", \"flash_freq\": \"80m\" }, \"flash_files\" : { \"0x8000\" : \"partition_table/partition-table.bin\", \"0xd000\" : \"ota_data_initial.bin\", \"0x1000\" : \"bootloader/bootloader.bin\", \"0x10000\" : \"recovery.bin\", \"0x150000\" : \"squeezelite.bin\" }, \"partition_table\" : { \"offset\" : \"0x8000\", \"file\" : \"partition_table/partition-table.bin\" }, \"otadata\" : { \"offset\" : \"0xd000\", \"file\" : \"ota_data_initial.bin\" }, \"bootloader\" : { \"offset\" : \"0x1000\", \"file\" : \"bootloader/bootloader.bin\" }, \"app\" : { \"offset\" : \"0x10000\", \"file\" : \"recovery.bin\" }, \"squeezelite\" : { \"offset\" : \"0x150000\", \"file\" : \"squeezelite.bin\" }, \"extra_esptool_args\" : { \"after\" : \"hard_reset\", \"before\" : \"default_reset\" } } > ./flasher_args.json
|
||||
- name: Create Release Artifact Zip
|
||||
if: ${{ needs.bootstrap.outputs.release_flag == 1 && needs.bootstrap.outputs.mock == 0 }}
|
||||
run: |
|
||||
if [ -z "${artifact_file_name}" ]
|
||||
then
|
||||
echo "No artifact file name set. Will not generate zip file."
|
||||
else
|
||||
echo "Generating build artifact zip file"
|
||||
zip -r build_output.zip build
|
||||
zip build/${artifact_file_name} partitions*.csv components/ build/*.bin build/bootloader/bootloader.bin build/partition_table/partition-table.bin build/flash_project_args build/size_*.txt
|
||||
fi
|
||||
- name: Upload Build Artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
if: ${{ needs.bootstrap.outputs.mock == 0 }}
|
||||
with:
|
||||
name: ${{ env.artifact_prefix }}
|
||||
path: |
|
||||
build/flash_project_args
|
||||
build/size_comp1.txt
|
||||
build/size_comp2.txt
|
||||
partitions.csv
|
||||
sdkconfig
|
||||
server_certs/github.pem
|
||||
build/*.bin
|
||||
build/bootloader/bootloader.bin
|
||||
build/partition_table/partition-table.bin
|
||||
build_output.zip
|
||||
- name: Create Release
|
||||
if: ${{ needs.bootstrap.outputs.release_flag == 1 && needs.bootstrap.outputs.mock == 0 }}
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
|
||||
with:
|
||||
tag_name: ${{ env.tag }}
|
||||
release_name: ${{ env.name }}
|
||||
body: ${{ env.description }}
|
||||
draft: false
|
||||
prerelease: true
|
||||
- name: Upload Release Asset - Squeezelite binary file
|
||||
if: ${{ needs.bootstrap.outputs.release_flag == 1 && needs.bootstrap.outputs.mock == 0 }}
|
||||
id: upload-release-asset
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
|
||||
asset_path: build/squeezelite.bin
|
||||
asset_name: ${{ env.artifact_bin_file_name }}
|
||||
asset_content_type: application/octet-stream
|
||||
- name: Upload Release Asset - Zip file
|
||||
if: ${{ needs.bootstrap.outputs.release_flag == 1 && needs.bootstrap.outputs.mock == 0 }}
|
||||
id: upload-release-asset-zip
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
|
||||
asset_path: build/${{ env.artifact_file_name }}
|
||||
asset_name: ${{ env.artifact_file_name }}
|
||||
asset_content_type: application/octet-stream
|
||||
update_web_installer:
|
||||
name: Update Web Installer After Release
|
||||
needs: [ bootstrap, build ]
|
||||
if: ${{( always() && !cancelled() ) && needs.bootstrap.outputs.release_flag == 1 && needs.bootstrap.outputs.mock == 0 }}
|
||||
uses: ./.github/workflows/web_deploy.yml
|
||||
2
.github/workflows/esp-idf-v4.3-build.yml
vendored
2
.github/workflows/esp-idf-v4.3-build.yml
vendored
@@ -65,7 +65,7 @@ jobs:
|
||||
BUILD_NUMBER=${{ needs.job1.outputs.build_number }}
|
||||
echo "BUILD_NUMBER=${BUILD_NUMBER}" >> $GITHUB_ENV
|
||||
echo "DOCKER_IMAGE_NAME=sle118/squeezelite-esp32-idfv4-master" >> $GITHUB_ENV
|
||||
tag="${TARGET_BUILD_NAME}.${{matrix.depth}}.${BUILD_NUMBER}.${branch_name}"
|
||||
tag="${TARGET_BUILD_NAME}.${{matrix.depth}}.${build_version_prefix}${BUILD_NUMBER}.${branch_name}"
|
||||
echo "tag=${tag}" >> $GITHUB_ENV
|
||||
last_commit="$(git log --pretty=format:'%s' --max-count=1)"
|
||||
if [[ "$last_commit" =~ .*"Release".* ]]; then echo "release_flag=1" >> $GITHUB_ENV; else echo "release_flag=0" >> $GITHUB_ENV; fi
|
||||
|
||||
23
.github/workflows/web_deploy.yml
vendored
Normal file
23
.github/workflows/web_deploy.yml
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
name: Update Web Installer
|
||||
on:
|
||||
workflow_call:
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
update_web_installer:
|
||||
name: Update Web Installer After Release
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: sle118/squeezelite-esp32-idfv43
|
||||
env:
|
||||
WEB_INSTALLER: ${{ secrets.WEB_INSTALLER }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
- name: Update Web Installer Project
|
||||
run: |
|
||||
. /opt/esp/python_env/idf4.3_py3.8_env/bin/activate
|
||||
git config --global --add safe.directory /__w/squeezelite-esp32/squeezelite-esp32
|
||||
build_tools.py manifest --flash_file "/build/flash_project_args" --outdir "./bin_files" --manif_name "manifest" --max_count 3
|
||||
build_tools.py pushinstaller --source "./bin_files" --manif_name "manifest" --target "web-installer" --url "https://github.com/sle118/squeezelite-esp32-installer.git" --artifacts "docs/artifacts" --web_installer_branch "main" --token "${{env.WEB_INSTALLER}}"
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -14,3 +14,7 @@ test/.vscode/tasks.json
|
||||
test/sdkconfig
|
||||
components/wifi-manager/UML-State-Machine-in-C
|
||||
*.bak
|
||||
|
||||
envfile.txt
|
||||
artifacts
|
||||
web-installer
|
||||
|
||||
@@ -13,7 +13,7 @@ add_definitions(-DHIERARCHICAL_STATES=1)
|
||||
#add_definitions(-DNETWORK_ETHERNET_LOG_LEVEL=ESP_LOG_DEBUG)
|
||||
#uncomment line below to get network status debug logs
|
||||
#add_definitions(-DNETWORK_STATUS_LOG_LEVEL=ESP_LOG_DEBUG)
|
||||
#add_definitions(-DNETWORK_HANDLERS_LOG_LEVEL=ESP_LOG_DEBUG)
|
||||
#add_definitions(-DNETWORK_HANDLERS_LOG_LEVEL=ESP_LOG_DEBUG)
|
||||
#add_definitions(-DNETWORK_WIFI_LOG_LEVEL=ESP_LOG_DEBUG)
|
||||
#add_definitions(-DNETWORK_MANAGER_LOG_LEVEL=ESP_LOG_DEBUG)
|
||||
#add_definitions(-DNETWORK_HTTP_SERVER_LOG_LEVEL=ESP_LOG_DEBUG)
|
||||
|
||||
125
Dockerfile
125
Dockerfile
@@ -3,6 +3,32 @@ FROM ubuntu:20.04
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
ENV GCC_TOOLS_BASE=/opt/esp/tools/xtensa-esp32-elf/esp-2021r2-8.4.0/xtensa-esp32-elf/bin/xtensa-esp32-elf-
|
||||
# To build the image for a branch or a tag of IDF, pass --build-arg IDF_CLONE_BRANCH_OR_TAG=name.
|
||||
# To build the image with a specific commit ID of IDF, pass --build-arg IDF_CHECKOUT_REF=commit-id.
|
||||
# It is possibe to combine both, e.g.:
|
||||
# IDF_CLONE_BRANCH_OR_TAG=release/vX.Y
|
||||
# IDF_CHECKOUT_REF=<some commit on release/vX.Y branch>.
|
||||
# The following commit contains the ldgen fix: eab738c79e063b3d6f4c345ea5e1d4f8caef725b
|
||||
# to build an image using that commit: docker build . --build-arg IDF_CHECKOUT_REF=eab738c79e063b3d6f4c345ea5e1d4f8caef725b -t sle118/squeezelite-esp32-idfv43
|
||||
# Docker build for release 4.3.2 as of 2022/02/28
|
||||
# docker build . --build-arg IDF_CHECKOUT_REF=8bf14a9238329954c7c5062eeeda569529aedf75 -t sle118/squeezelite-esp32-idfv43
|
||||
# To run the image interactive (windows):
|
||||
# docker run --rm -v %cd%:/project -w /project -it sle118/squeezelite-esp32-idfv43
|
||||
# To run the image interactive (linux):
|
||||
# docker run --rm -v `pwd`:/project -w /project -it sle118/squeezelite-esp32-idfv43
|
||||
# to build the web app inside of the interactive session
|
||||
# pushd components/wifi-manager/webapp/ && npm install && npm run-script build && popd
|
||||
#
|
||||
# to run the docker with netwotrk port published on the host:
|
||||
# docker run --rm -p 5000:5000/tcp -v %cd%:/project -w /project -it sle118/squeezelite-esp32-idfv43
|
||||
|
||||
ARG IDF_CLONE_URL=https://github.com/espressif/esp-idf.git
|
||||
ARG IDF_CLONE_BRANCH_OR_TAG=master
|
||||
ARG IDF_CHECKOUT_REF=8bf14a9238329954c7c5062eeeda569529aedf75
|
||||
|
||||
ENV IDF_PATH=/opt/esp/idf
|
||||
ENV IDF_TOOLS_PATH=/opt/esp
|
||||
|
||||
# We need libpython2.7 due to GDB tools
|
||||
# we also need npm 8 for the webapp to work
|
||||
RUN : \
|
||||
@@ -42,59 +68,49 @@ RUN : \
|
||||
&& git clone https://github.com/HBehrens/puncover.git \
|
||||
&& cd puncover \
|
||||
&& python setup.py -q install \
|
||||
&& :
|
||||
|
||||
# To build the image for a branch or a tag of IDF, pass --build-arg IDF_CLONE_BRANCH_OR_TAG=name.
|
||||
# To build the image with a specific commit ID of IDF, pass --build-arg IDF_CHECKOUT_REF=commit-id.
|
||||
# It is possibe to combine both, e.g.:
|
||||
# IDF_CLONE_BRANCH_OR_TAG=release/vX.Y
|
||||
# IDF_CHECKOUT_REF=<some commit on release/vX.Y branch>.
|
||||
# The following commit contains the ldgen fix: eab738c79e063b3d6f4c345ea5e1d4f8caef725b
|
||||
# to build an image using that commit: docker build . --build-arg IDF_CHECKOUT_REF=eab738c79e063b3d6f4c345ea5e1d4f8caef725b -t sle118/squeezelite-esp32-idfv4-master
|
||||
# Docker build for release 4.3.2 as of 2022/02/28
|
||||
# docker build . --build-arg IDF_CHECKOUT_REF=8bf14a9238329954c7c5062eeeda569529aedf75 -t sle118/squeezelite-esp32-idfv4-master
|
||||
# To run the image interactive (windows): docker run --rm -v %cd%:/project -w /project -it sle118/squeezelite-esp32-idfv4-master
|
||||
# to build the web app inside of the interactive session
|
||||
# pushd components/wifi-manager/webapp/ && npm install && npm run-script build && popd
|
||||
#
|
||||
# to run the docker with netwotrk port published on the host:
|
||||
# docker run --rm -p 5000:5000/tcp -v %cd%:/project -w /project -it sle118/squeezelite-esp32-idfv4-master
|
||||
|
||||
ARG IDF_CLONE_URL=https://github.com/espressif/esp-idf.git
|
||||
ARG IDF_CLONE_BRANCH_OR_TAG=master
|
||||
ARG IDF_CHECKOUT_REF=8bf14a9238329954c7c5062eeeda569529aedf75
|
||||
|
||||
ENV IDF_PATH=/opt/esp/idf
|
||||
ENV IDF_TOOLS_PATH=/opt/esp
|
||||
|
||||
|
||||
RUN echo IDF_CHECKOUT_REF=$IDF_CHECKOUT_REF IDF_CLONE_BRANCH_OR_TAG=$IDF_CLONE_BRANCH_OR_TAG && \
|
||||
git clone --recursive \
|
||||
&& echo IDF_CHECKOUT_REF=$IDF_CHECKOUT_REF IDF_CLONE_BRANCH_OR_TAG=$IDF_CLONE_BRANCH_OR_TAG \
|
||||
&& git clone --recursive \
|
||||
${IDF_CLONE_BRANCH_OR_TAG:+-b $IDF_CLONE_BRANCH_OR_TAG} \
|
||||
$IDF_CLONE_URL $IDF_PATH && \
|
||||
if [ -n "$IDF_CHECKOUT_REF" ]; then \
|
||||
cd $IDF_PATH && \
|
||||
git checkout $IDF_CHECKOUT_REF && \
|
||||
git submodule update --init --recursive; \
|
||||
fi
|
||||
COPY docker/patches $IDF_PATH
|
||||
|
||||
|
||||
|
||||
# Install all the required tools
|
||||
RUN : \
|
||||
$IDF_CLONE_URL $IDF_PATH \
|
||||
&& if [ -n "$IDF_CHECKOUT_REF" ]; then \
|
||||
cd $IDF_PATH \
|
||||
&& git checkout $IDF_CHECKOUT_REF \
|
||||
&& git submodule update --init --recursive; \
|
||||
fi \
|
||||
&& update-ca-certificates --fresh \
|
||||
&& $IDF_PATH/tools/idf_tools.py --non-interactive install required \
|
||||
&& $IDF_PATH/tools/idf_tools.py --non-interactive install cmake \
|
||||
&& $IDF_PATH/tools/idf_tools.py --non-interactive install-python-env \
|
||||
&& :
|
||||
RUN : \
|
||||
echo Installing pygit2 ******************************************************** \
|
||||
&& . /opt/esp/python_env/idf4.3_py3.8_env/bin/activate \
|
||||
&& ln -sf /opt/esp/python_env/idf4.3_py3.8_env/bin/python /usr/local/bin/python \
|
||||
&& pip install pygit2 requests \
|
||||
&& pip show pygit2 \
|
||||
&& python --version \
|
||||
&& pip --version \
|
||||
&& pip install protobuf grpcio-tools \
|
||||
&& rm -rf $IDF_TOOLS_PATH/dist \
|
||||
&& :
|
||||
|
||||
COPY docker/patches $IDF_PATH
|
||||
|
||||
#set idf environment variabies
|
||||
ENV PATH /opt/esp/idf/components/esptool_py/esptool:/opt/esp/idf/components/espcoredump:/opt/esp/idf/components/partition_table:/opt/esp/idf/components/app_update:/opt/esp/tools/xtensa-esp32-elf/esp-2021r2-8.4.0/xtensa-esp32-elf/bin:/opt/esp/tools/xtensa-esp32s2-elf/esp-2021r2-8.4.0/xtensa-esp32s2-elf/bin:/opt/esp/tools/xtensa-esp32s3-elf/esp-2021r2-8.4.0/xtensa-esp32s3-elf/bin:/opt/esp/tools/riscv32-esp-elf/esp-2021r2-8.4.0/riscv32-esp-elf/bin:/opt/esp/tools/esp32ulp-elf/2.28.51-esp-20191205/esp32ulp-elf-binutils/bin:/opt/esp/tools/esp32s2ulp-elf/2.28.51-esp-20191205/esp32s2ulp-elf-binutils/bin:/opt/esp/tools/cmake/3.16.4/bin:/opt/esp/tools/openocd-esp32/v0.10.0-esp32-20211111/openocd-esp32/bin:/opt/esp/python_env/idf4.3_py3.8_env/bin:/opt/esp/idf/tools:$PATH
|
||||
ENV GCC_TOOLS_BASE="/opt/esp/tools/xtensa-esp32-elf/esp-2021r2-8.4.0/xtensa-esp32-elf/bin/xtensa-esp32-elf-"
|
||||
ENV IDF_PATH="/opt/esp/idf"
|
||||
ENV IDF_PYTHON_ENV_PATH="/opt/esp/python_env/idf4.3_py3.8_env"
|
||||
ENV IDF_TOOLS_EXPORT_CMD="/opt/esp/idf/export.sh"
|
||||
ENV IDF_TOOLS_INSTALL_CMD="/opt/esp/idf/install.sh"
|
||||
ENV IDF_TOOLS_PATH="/opt/esp"
|
||||
ENV NODE_PATH="/v8/lib/node_modules"
|
||||
ENV NODE_VERSION="8"
|
||||
ENV OPENOCD_SCRIPTS="/opt/esp/tools/openocd-esp32/v0.10.0-esp32-20211111/openocd-esp32/share/openocd/scripts"
|
||||
# Ccache is installed, enable it by default
|
||||
|
||||
ENV IDF_CCACHE_ENABLE=1
|
||||
COPY docker/entrypoint.sh /opt/esp/entrypoint.sh
|
||||
|
||||
# Now install nodejs, npm and the packages we need
|
||||
COPY components/wifi-manager/webapp/package.json /opt
|
||||
|
||||
ENV NODE_VERSION 8
|
||||
@@ -117,17 +133,24 @@ SHELL ["/bin/bash", "--login", "-c"]
|
||||
|
||||
RUN : \
|
||||
&& curl -fsSL https://deb.nodesource.com/setup_16.x | bash - \
|
||||
&& apt-get install -y nodejs \
|
||||
&& echo installing node modules \
|
||||
&& cd /opt \
|
||||
&& npm i -g npm \
|
||||
&& node --version \
|
||||
&& npm install -g \
|
||||
&& :
|
||||
&& apt-get install -y nodejs jq \
|
||||
&& echo installing dev node modules globally \
|
||||
&& cd /opt \
|
||||
&& cat ./package.json | jq '.devDependencies | keys[] as $k | "\($k)@\(.[$k])"' | xargs -t npm install --global \
|
||||
&& echo installing npm global packages \
|
||||
&& npm i -g npm \
|
||||
&& node --version \
|
||||
&& npm install -g \
|
||||
&& :
|
||||
|
||||
ENV NODE_PATH $NVM_DIR/v$NODE_VERSION/lib/node_modules
|
||||
ENV PATH $NVM_DIR/v$NODE_VERSION/bin:$PATH
|
||||
|
||||
ENV PATH $IDF_PYTHON_ENV_PATH:$NVM_DIR/v$NODE_VERSION/bin:$PATH
|
||||
COPY ./docker/build_tools.py /usr/sbin/build_tools.py
|
||||
RUN : \
|
||||
&& echo Changing permissions ******************************************************** \
|
||||
&& chmod +x /opt/esp/entrypoint.sh \
|
||||
&& chmod +x /usr/sbin/build_tools.py \
|
||||
&& :
|
||||
|
||||
ENTRYPOINT [ "/opt/esp/entrypoint.sh" ]
|
||||
CMD [ "/bin/bash" ]
|
||||
|
||||
@@ -188,13 +188,14 @@ Ground -------------------------- coax signal ground
|
||||
The NVS parameter "display_config" sets the parameters for an optional display. Syntax is
|
||||
```
|
||||
I2C,width=<pixels>,height=<pixels>[address=<i2c_address>][,reset=<gpio>][,HFlip][,VFlip][driver=SSD1306|SSD1326[:1|4]|SSD1327|SH1106]
|
||||
SPI,width=<pixels>,height=<pixels>,cs=<gpio>[,back=<gpio>][,reset=<gpio>][,speed=<speed>][,HFlip][,VFlip][driver=SSD1306|SSD1322|SSD1326[:1|4]|SSD1327|SH1106|SSD1675|ST7735|ST7789|ILI9341[:16|18][,rotate]]
|
||||
SPI,width=<pixels>,height=<pixels>,cs=<gpio>[,back=<gpio>][,reset=<gpio>][,speed=<speed>][,HFlip][,VFlip][driver=SSD1306|SSD1322|SSD1326[:1|4]|SSD1327|SH1106|SSD1675|ST7735|ST7789|ILI9341[:16|18][,rotate]][,mode=<mode>]
|
||||
```
|
||||
- back: a LED backlight used by some older devices (ST7735). It is PWM controlled for brightness
|
||||
- reset: some display have a reset pin that is should normally be pulled up if unused
|
||||
- VFlip and HFlip are optional can be used to change display orientation
|
||||
- rotate: for non-square *drivers*, move to portrait mode. Note that *width* and *height* must be inverted then
|
||||
- Default speed is 8000000 (8MHz) but SPI can work up to 26MHz or even 40MHz
|
||||
- mode: Default mode = 0. Some display modules use different transaction line timings. Check the module documentation if a non-standard mode is required.
|
||||
- SH1106 is 128x64 monochrome I2C/SPI [here]((https://www.waveshare.com/wiki/1.3inch_OLED_HAT))
|
||||
- SSD1306 is 128x32 monochrome I2C/SPI [here](https://www.buydisplay.com/i2c-blue-0-91-inch-oled-display-module-128x32-arduino-raspberry-pi)
|
||||
- SSD1322 is 256x64 grayscale 16-levels SPI in multiple sizes [here](https://www.buydisplay.com/oled-display/oled-display-module?resolution=159) - it is very nice
|
||||
|
||||
@@ -259,7 +259,7 @@ CONFIG_CSPOT_SINK=y
|
||||
# Various I/O
|
||||
#
|
||||
CONFIG_I2C_CONFIG=""
|
||||
CONFIG_SET_GPIO=""
|
||||
CONFIG_SET_GPIO="0=ir"
|
||||
CONFIG_ROTARY_ENCODER=""
|
||||
# end of Various I/O
|
||||
|
||||
|
||||
@@ -3,12 +3,6 @@
|
||||
|
||||
|
||||
echo "Build process started"
|
||||
pushd components/wifi-manager/webapp/
|
||||
echo "Installing node.js dependencies"
|
||||
npm install
|
||||
echo "Building webapp"
|
||||
npm run-script build
|
||||
popd
|
||||
echo "Setting up build name and build number"
|
||||
if [ -z "${TARGET_BUILD_NAME}" ]
|
||||
then
|
||||
|
||||
@@ -11,7 +11,7 @@ bool GDS_I2CInit( int PortNumber, int SDA, int SCL, int speed );
|
||||
bool GDS_I2CAttachDevice( struct GDS_Device* Device, int Width, int Height, int I2CAddress, int RSTPin, int BacklightPin );
|
||||
|
||||
bool GDS_SPIInit( int SPI, int DC );
|
||||
bool GDS_SPIAttachDevice( struct GDS_Device* Device, int Width, int Height, int CSPin, int RSTPin, int Speed, int BacklightPin );
|
||||
bool GDS_SPIAttachDevice( struct GDS_Device* Device, int Width, int Height, int CSPin, int RSTPin, int Speed, int BacklightPin, int Mode );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ bool GDS_SPIInit( int SPI, int DC ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GDS_SPIAttachDevice( struct GDS_Device* Device, int Width, int Height, int CSPin, int RSTPin, int BackLightPin, int Speed ) {
|
||||
bool GDS_SPIAttachDevice( struct GDS_Device* Device, int Width, int Height, int CSPin, int RSTPin, int BackLightPin, int Speed, int Mode ) {
|
||||
spi_device_interface_config_t SPIDeviceConfig = { };
|
||||
spi_device_handle_t SPIDevice;
|
||||
|
||||
@@ -48,6 +48,7 @@ bool GDS_SPIAttachDevice( struct GDS_Device* Device, int Width, int Height, int
|
||||
SPIDeviceConfig.clock_speed_hz = Speed > 0 ? Speed : SPI_MASTER_FREQ_8M;
|
||||
SPIDeviceConfig.spics_io_num = CSPin;
|
||||
SPIDeviceConfig.queue_size = 1;
|
||||
SPIDeviceConfig.mode = Mode;
|
||||
SPIDeviceConfig.flags = SPI_DEVICE_NO_DUMMY;
|
||||
if (Device->SPIParams) Device->SPIParams(SPIDeviceConfig.clock_speed_hz, &SPIDeviceConfig.mode,
|
||||
&SPIDeviceConfig.cs_ena_pretrans, &SPIDeviceConfig.cs_ena_posttrans);
|
||||
|
||||
@@ -119,14 +119,15 @@ void display_init(char *welcome) {
|
||||
|
||||
ESP_LOGI(TAG, "Display is I2C on port %u", address);
|
||||
} else if (strcasestr(config, "SPI") && spi_system_host != -1) {
|
||||
int CS_pin = -1, speed = 0;
|
||||
int CS_pin = -1, speed = 0, mode = 0;
|
||||
|
||||
PARSE_PARAM(config, "cs", '=', CS_pin);
|
||||
PARSE_PARAM(config, "speed", '=', speed);
|
||||
PARSE_PARAM(config, "mode", '=', mode);
|
||||
|
||||
init = true;
|
||||
GDS_SPIInit( spi_system_host, spi_system_dc_gpio );
|
||||
GDS_SPIAttachDevice( display, width, height, CS_pin, RST_pin, backlight_pin, speed );
|
||||
GDS_SPIAttachDevice( display, width, height, CS_pin, RST_pin, backlight_pin, speed, mode );
|
||||
|
||||
ESP_LOGI(TAG, "Display is SPI host %u with cs:%d", spi_system_host, CS_pin);
|
||||
} else {
|
||||
|
||||
@@ -83,25 +83,26 @@ static void bt_app_task_handler(void *arg)
|
||||
|
||||
esp_bt_controller_mem_release(ESP_BT_MODE_BLE);
|
||||
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
|
||||
|
||||
if ((err = esp_bt_controller_init(&bt_cfg)) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s initialize controller failed: %s\n", __func__, esp_err_to_name(err));
|
||||
goto exit;
|
||||
}
|
||||
if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE ) {
|
||||
if ((err = esp_bt_controller_init(&bt_cfg)) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s initialize controller failed: %s\n", __func__, esp_err_to_name(err));
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if ((err = esp_bt_controller_enable(ESP_BT_MODE_CLASSIC_BT)) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s enable controller failed: %s\n", __func__, esp_err_to_name(err));
|
||||
goto exit;
|
||||
}
|
||||
if ((err = esp_bt_controller_enable(ESP_BT_MODE_CLASSIC_BT)) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s enable controller failed: %s\n", __func__, esp_err_to_name(err));
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if ((err = esp_bluedroid_init()) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s initialize bluedroid failed: %s\n", __func__, esp_err_to_name(err));
|
||||
goto exit;
|
||||
}
|
||||
if ((err = esp_bluedroid_init()) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s initialize bluedroid failed: %s\n", __func__, esp_err_to_name(err));
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if ((err = esp_bluedroid_enable()) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s enable bluedroid failed: %s\n", __func__, esp_err_to_name(err));
|
||||
goto exit;
|
||||
if ((err = esp_bluedroid_enable()) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s enable bluedroid failed: %s\n", __func__, esp_err_to_name(err));
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
/* Bluetooth device name, connection mode and profile set up */
|
||||
@@ -114,6 +115,14 @@ static void bt_app_task_handler(void *arg)
|
||||
esp_bt_gap_set_security_param(param_type, &iocap, sizeof(uint8_t));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set default parameters for Legacy Pairing
|
||||
* Use variable pin, input pin code when pairing
|
||||
*/
|
||||
esp_bt_pin_type_t pin_type = ESP_BT_PIN_TYPE_VARIABLE;
|
||||
esp_bt_pin_code_t pin_code;
|
||||
esp_bt_gap_set_pin(pin_type, 0, pin_code);
|
||||
|
||||
running = true;
|
||||
|
||||
while (running) {
|
||||
|
||||
@@ -672,9 +672,9 @@ static void filter_inquiry_scan_result(esp_bt_gap_cb_param_t *param)
|
||||
ESP_LOGV(TAG,"--Invalid class of device. Skipping.\n");
|
||||
return;
|
||||
}
|
||||
else if (!(esp_bt_gap_get_cod_srvc(cod) & ESP_BT_COD_SRVC_RENDERING))
|
||||
else if (!(esp_bt_gap_get_cod_srvc(cod) & (ESP_BT_COD_SRVC_RENDERING | ESP_BT_COD_SRVC_AUDIO)))
|
||||
{
|
||||
ESP_LOGV(TAG,"--Not a rendering device. Skipping.\n");
|
||||
ESP_LOGV(TAG,"--Not a rendering or audio device. Skipping.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -634,7 +634,7 @@ cJSON * config_alloc_get_cjson(const char *key){
|
||||
}
|
||||
return conf_json;
|
||||
}
|
||||
esp_err_t config_set_cjson_str(const char *key, cJSON *value){
|
||||
esp_err_t config_set_cjson_str_and_free(const char *key, cJSON *value){
|
||||
char * value_str = cJSON_PrintUnformatted(value);
|
||||
if(value_str==NULL){
|
||||
ESP_LOGE(TAG, "Unable to print cJSON for key [%s]", key);
|
||||
|
||||
@@ -53,7 +53,7 @@ void config_init();
|
||||
void * config_alloc_get_default(nvs_type_t type, const char *key, void * default_value, size_t blob_size);
|
||||
void * config_alloc_get_str(const char *key, char *lead, char *fallback);
|
||||
cJSON * config_alloc_get_cjson(const char *key);
|
||||
esp_err_t config_set_cjson_str(const char *key, cJSON *value);
|
||||
esp_err_t config_set_cjson_str_and_free(const char *key, cJSON *value);
|
||||
void config_get_uint16t_from_str(const char *key, uint16_t *value, uint16_t default_value);
|
||||
void config_delete_key(const char *key);
|
||||
void config_set_default(nvs_type_t type, const char *key, void * default_value, size_t blob_size);
|
||||
|
||||
@@ -592,8 +592,9 @@ static int is_valid_gpio_number(int gpio, const char * name, FILE *f, bool manda
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CSPOT_SINK
|
||||
static int do_cspot_config(int argc, char **argv){
|
||||
char * name = NULL;
|
||||
int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&cspot_args);
|
||||
if (nerrors != 0) {
|
||||
return 1;
|
||||
@@ -610,31 +611,37 @@ static int do_cspot_config(int argc, char **argv){
|
||||
cJSON * cspot_config = config_alloc_get_cjson("cspot_config");
|
||||
if(!cspot_config){
|
||||
nerrors++;
|
||||
fprintf(f,"error: Unable to get cspot config.\n");
|
||||
fprintf(f,"error: Unable to get default cspot config.\n");
|
||||
}
|
||||
else {
|
||||
cjson_update_string(&cspot_config,cspot_args.deviceName->hdr.longopts,cspot_args.deviceName->count>0?cspot_args.deviceName->sval[0]:NULL);
|
||||
// cjson_update_number(&cspot_config,cspot_args.volume->hdr.longopts,cspot_args.volume->count>0?cspot_args.volume->ival[0]:0);
|
||||
cjson_update_number(&cspot_config,cspot_args.bitrate->hdr.longopts,cspot_args.bitrate->count>0?cspot_args.bitrate->ival[0]:0);
|
||||
if(cspot_args.deviceName->count>0){
|
||||
cjson_update_string(&cspot_config,cspot_args.deviceName->hdr.longopts,cspot_args.deviceName->sval[0]);
|
||||
}
|
||||
if(cspot_args.bitrate->count>0){
|
||||
cjson_update_number(&cspot_config,cspot_args.bitrate->hdr.longopts,cspot_args.bitrate->ival[0]);
|
||||
}
|
||||
|
||||
if(!nerrors ){
|
||||
fprintf(f,"Storing cspot parameters.\n");
|
||||
nerrors+=(config_set_cjson_str("cspot_config",cspot_config) !=ESP_OK);
|
||||
nerrors+=(config_set_cjson_str_and_free("cspot_config",cspot_config) !=ESP_OK);
|
||||
}
|
||||
if(nerrors==0){
|
||||
fprintf(f,"Device name changed to %s\n",name);
|
||||
if(nerrors==0 ){
|
||||
if(cspot_args.deviceName->count>0){
|
||||
fprintf(f,"Device name changed to %s\n",cspot_args.deviceName->sval[0]);
|
||||
}
|
||||
if(cspot_args.bitrate->count>0){
|
||||
fprintf(f,"Bitrate changed to %u\n",cspot_args.bitrate->ival[0]);
|
||||
}
|
||||
}
|
||||
if(!nerrors ){
|
||||
fprintf(f,"Done.\n");
|
||||
}
|
||||
FREE_AND_NULL(name);
|
||||
fflush (f);
|
||||
cmd_send_messaging(argv[0],nerrors>0?MESSAGING_ERROR:MESSAGING_INFO,"%s", buf);
|
||||
fclose(f);
|
||||
FREE_AND_NULL(buf);
|
||||
return nerrors;
|
||||
}
|
||||
#endif
|
||||
static int do_i2s_cmd(int argc, char **argv)
|
||||
{
|
||||
i2s_platform_config_t i2s_dac_pin = {
|
||||
@@ -742,6 +749,7 @@ cJSON * known_model_cb(){
|
||||
}
|
||||
return values;
|
||||
}
|
||||
#ifdef CONFIG_CSPOT_SINK
|
||||
cJSON * cspot_cb(){
|
||||
cJSON * values = cJSON_CreateObject();
|
||||
if(!values){
|
||||
@@ -761,13 +769,11 @@ cJSON * cspot_cb(){
|
||||
if(cspot_values){
|
||||
cJSON_AddNumberToObject(values,cspot_args.bitrate->hdr.longopts,cJSON_GetNumberValue(cspot_values));
|
||||
}
|
||||
// cspot_values = cJSON_GetObjectItem(cspot_config,cspot_args.volume->hdr.longopts);
|
||||
// if(cspot_values){
|
||||
// cJSON_AddNumberToObject(values,cspot_args.volume->hdr.longopts,cJSON_GetNumberValue(cspot_values));
|
||||
// }
|
||||
|
||||
cJSON_Delete(cspot_config);
|
||||
return values;
|
||||
}
|
||||
#endif
|
||||
cJSON * i2s_cb(){
|
||||
cJSON * values = cJSON_CreateObject();
|
||||
|
||||
@@ -1171,7 +1177,7 @@ static void register_known_templates_config(){
|
||||
cmd_to_json_with_cb(&cmd,&known_model_cb);
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CSPOT_SINK
|
||||
static void register_cspot_config(){
|
||||
cspot_args.deviceName = arg_str1(NULL,"deviceName","","Device Name");
|
||||
cspot_args.bitrate = arg_int1(NULL,"bitrate","96|160|320","Streaming Bitrate (kbps)");
|
||||
@@ -1187,6 +1193,7 @@ static void register_cspot_config(){
|
||||
cmd_to_json_with_cb(&cmd,&cspot_cb);
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
|
||||
}
|
||||
#endif
|
||||
static void register_i2s_config(void){
|
||||
i2s_args.model_name = arg_str1(NULL,"model_name",STR_OR_BLANK(get_dac_list()),"DAC Model Name");
|
||||
i2s_args.clear = arg_lit0(NULL, "clear", "Clear configuration");
|
||||
@@ -1328,8 +1335,11 @@ static void register_squeezelite_config(void){
|
||||
void register_config_cmd(void){
|
||||
if(!is_dac_config_locked()){
|
||||
register_known_templates_config();
|
||||
|
||||
}
|
||||
#ifdef CONFIG_CSPOT_SINK
|
||||
register_cspot_config();
|
||||
#endif
|
||||
register_audio_config();
|
||||
// register_squeezelite_config();
|
||||
register_bt_source_config();
|
||||
|
||||
@@ -101,6 +101,7 @@ static struct {
|
||||
struct arg_int *reset;
|
||||
struct arg_lit *clear;
|
||||
struct arg_lit *invert;
|
||||
struct arg_int *mode;
|
||||
struct arg_end *end;
|
||||
} i2cdisp_args;
|
||||
|
||||
@@ -377,6 +378,13 @@ static int do_i2c_set_display(int argc, char **argv)
|
||||
}
|
||||
/* Check "--cs" option */
|
||||
nerrors +=is_output_gpio(i2cdisp_args.cs,f,&config.CS_pin, false);
|
||||
/* Check "--mode" option */
|
||||
if (i2cdisp_args.mode->count) {
|
||||
config.mode=i2cdisp_args.mode->ival[0];
|
||||
}
|
||||
else {
|
||||
config.mode = 0;
|
||||
}
|
||||
}
|
||||
|
||||
nerrors +=is_output_gpio(i2cdisp_args.reset,f,&config.RST_pin, false);
|
||||
@@ -964,6 +972,9 @@ cJSON * i2c_set_display_cb(){
|
||||
cJSON_AddBoolToObject(values,"hf",conf->hflip);
|
||||
cJSON_AddBoolToObject(values,"vf",conf->vflip);
|
||||
cJSON_AddBoolToObject(values,"invert",conf->invert);
|
||||
if(conf->mode>=0){
|
||||
cJSON_AddNumberToObject(values,"mode",conf->mode);
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
@@ -986,6 +997,7 @@ static void register_i2c_set_display(){
|
||||
i2cdisp_args.rotate = arg_lit0("r", "rotate", "Rotate 180 degrees");
|
||||
i2cdisp_args.invert = arg_lit0("i", "invert", "Invert colors");
|
||||
i2cdisp_args.clear = arg_lit0(NULL, "clear", "clear configuration and return");
|
||||
i2cdisp_args.mode = arg_int0("m", "mode", "<n>","SPI Only. Transaction Line Mode (Default 0)");
|
||||
i2cdisp_args.end = arg_end(8);
|
||||
const esp_console_cmd_t i2c_set_display= {
|
||||
.command = CFG_TYPE_HW("display"),
|
||||
|
||||
@@ -352,6 +352,10 @@ esp_err_t config_display_set(const display_config_t * config){
|
||||
snprintf(config_buffer2,buffer_size,"%s,speed=%i",config_buffer,config->speed);
|
||||
strcpy(config_buffer,config_buffer2);
|
||||
}
|
||||
if(config->mode >=0 && strcasecmp("SPI",config->type)==0){
|
||||
snprintf(config_buffer2,buffer_size,"%s,mode=%i",config_buffer,config->mode);
|
||||
strcpy(config_buffer,config_buffer2);
|
||||
}
|
||||
snprintf(config_buffer2,buffer_size,"%s,driver=%s%s%s%s",config_buffer,config->drivername,config->hflip?",HFlip":"",config->vflip?",VFlip":"",config->rotate?",rotate":"");
|
||||
strcpy(config_buffer,config_buffer2);
|
||||
log_send_messaging(MESSAGING_INFO,"Updating display configuration to %s",config_buffer);
|
||||
@@ -465,6 +469,7 @@ const display_config_t * config_display_get(){
|
||||
.rotate = false,
|
||||
.invert = false,
|
||||
.colorswap = 0,
|
||||
.mode = 0,
|
||||
};
|
||||
char *config = config_alloc_get(NVS_TYPE_STR, "display_config");
|
||||
if (!config) {
|
||||
@@ -484,6 +489,8 @@ const display_config_t * config_display_get(){
|
||||
PARSE_PARAM(config, "address", '=', dstruct.address);
|
||||
PARSE_PARAM(config, "cs", '=', dstruct.CS_pin);
|
||||
PARSE_PARAM(config, "speed", '=', dstruct.speed);
|
||||
PARSE_PARAM(config, "back", '=', dstruct.back);
|
||||
PARSE_PARAM(config, "mode", '=', dstruct.mode);
|
||||
|
||||
if (strstr(config, "I2C") ) dstruct.type=i2c_name_type;
|
||||
if (strstr(config, "SPI") ) dstruct.type=spi_name_type;
|
||||
|
||||
@@ -33,6 +33,7 @@ typedef struct {
|
||||
bool rotate;
|
||||
bool invert;
|
||||
int colorswap;
|
||||
int mode;
|
||||
} display_config_t;
|
||||
|
||||
typedef struct eth_config_struct {
|
||||
|
||||
@@ -415,7 +415,7 @@ bool create_rotary(void *id, int A, int B, int SW, int long_press, rotary_handle
|
||||
// create companion button if rotary has a switch
|
||||
if (SW != -1) button_create(id, SW, BUTTON_LOW, true, 0, rotary_button_handler, long_press, -1);
|
||||
|
||||
ESP_LOGI(TAG, "Creating rotary encoder A:%d B:%d, SW:%d", A, B, SW);
|
||||
ESP_LOGI(TAG, "Created rotary encoder A:%d B:%d, SW:%d", A, B, SW);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -432,5 +432,7 @@ bool create_infrared(int gpio, infrared_handler handler) {
|
||||
common_task_init();
|
||||
xRingbufferAddToQueueSetRead(infrared.rb, common_queue_set);
|
||||
|
||||
ESP_LOGI(TAG, "Created infrared receiver using GPIO %u", gpio);
|
||||
|
||||
return (infrared.rb != NULL);
|
||||
}
|
||||
|
||||
@@ -60,6 +60,10 @@ static const char TAG[] = "gpio expander";
|
||||
static void IRAM_ATTR intr_isr_handler(void* arg);
|
||||
static gpio_exp_t* find_expander(gpio_exp_t *expander, int *gpio);
|
||||
|
||||
static esp_err_t mpr121_init(gpio_exp_t* self);
|
||||
static uint32_t mpr121_read(gpio_exp_t* self);
|
||||
static void mpr121_write(gpio_exp_t* self);
|
||||
|
||||
static void pca9535_set_direction(gpio_exp_t* self);
|
||||
static uint32_t pca9535_read(gpio_exp_t* self);
|
||||
static void pca9535_write(gpio_exp_t* self);
|
||||
@@ -98,6 +102,11 @@ static const struct gpio_exp_model_s {
|
||||
void (*set_direction)(gpio_exp_t* self);
|
||||
void (*set_pull_mode)(gpio_exp_t* self);
|
||||
} registered[] = {
|
||||
{ .model = "mpr121",
|
||||
.trigger = GPIO_INTR_LOW_LEVEL,
|
||||
.init = mpr121_init,
|
||||
.read = mpr121_read,
|
||||
.write = mpr121_write, },
|
||||
{ .model = "pca9535",
|
||||
.trigger = GPIO_INTR_LOW_LEVEL,
|
||||
.set_direction = pca9535_set_direction,
|
||||
@@ -498,6 +507,56 @@ static gpio_exp_t* find_expander(gpio_exp_t *expander, int *gpio) {
|
||||
DRIVERS
|
||||
****************************************************************************************/
|
||||
|
||||
/****************************************************************************************
|
||||
* MPR121 family : init, direction, read and write
|
||||
*/
|
||||
static esp_err_t mpr121_init(gpio_exp_t* self) {
|
||||
static const struct {
|
||||
uint8_t addr;
|
||||
uint8_t data;
|
||||
} mpr121_init_table[] = {
|
||||
{ 0x80, 0x63 }, /* Soft reset */
|
||||
|
||||
{ 0x2b, 0x01 }, { 0x2c, 0x01 }, { 0x2d, 0x10 }, { 0x2e, 0x20 }, /* MHDR, NHDR, NCLR, FDLR */
|
||||
{ 0x2f, 0x01 }, { 0x30, 0x01 }, { 0x31, 0x10 }, { 0x32, 0x20 }, /* MHDF, NHDF, NCLF, FDLF */
|
||||
{ 0x33, 0x01 }, { 0x34, 0x10 }, { 0x35, 0xff }, /* NHDT, NCLT, FDLT */
|
||||
{ 0x5b, 0x11 }, { 0x5c, 0xff }, { 0x5d, 0x30 }, /* DTR, AFE1, AFE2 */
|
||||
{ 0x7b, 0x00 }, { 0x7c, 0x00 }, { 0x7d, 0x00 }, { 0x7e, 0x00 }, { 0x7f, 0x00 },/* ACCR0, ACCR1, USL, LSL, TL */
|
||||
|
||||
{ 0x41, 0x28 }, { 0x42, 0x14 }, /* ELE0: Touch Threshold, Release Threshold */
|
||||
{ 0x43, 0x28 }, { 0x44, 0x14 }, /* ELE1: Touch Threshold, Release Threshold */
|
||||
{ 0x45, 0x28 }, { 0x46, 0x14 }, /* ELE2: Touch Threshold, Release Threshold */
|
||||
{ 0x47, 0x28 }, { 0x48, 0x14 }, /* ELE3: Touch Threshold, Release Threshold */
|
||||
{ 0x49, 0x28 }, { 0x4a, 0x14 }, /* ELE4: Touch Threshold, Release Threshold */
|
||||
{ 0x4b, 0x28 }, { 0x4c, 0x14 }, /* ELE5: Touch Threshold, Release Threshold */
|
||||
{ 0x4d, 0x28 }, { 0x4e, 0x14 }, /* ELE6: Touch Threshold, Release Threshold */
|
||||
{ 0x4f, 0x28 }, { 0x50, 0x14 }, /* ELE7: Touch Threshold, Release Threshold */
|
||||
{ 0x51, 0x28 }, { 0x52, 0x14 }, /* ELE8: Touch Threshold, Release Threshold */
|
||||
{ 0x53, 0x28 }, { 0x54, 0x14 }, /* ELE9: Touch Threshold, Release Threshold */
|
||||
{ 0x55, 0x28 }, { 0x56, 0x14 }, /* ELE10: Touch Threshold, Release Threshold */
|
||||
{ 0x57, 0x28 }, { 0x58, 0x14 }, /* ELE11: Touch Threshold, Release Threshold */
|
||||
|
||||
{ 0x5e, 0xcc }, /* ECR - must be set last */
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
esp_err_t err = 0;
|
||||
for (int i = 0; mpr121_init_table[i].addr; i++) {
|
||||
err |= i2c_write(self->phy.port, self->phy.addr, mpr121_init_table[i].addr, mpr121_init_table[i].data, 1);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static uint32_t mpr121_read(gpio_exp_t* self) {
|
||||
// only return the lower 12 bits of the pin status registers
|
||||
return i2c_read(self->phy.port, self->phy.addr, 0x00, 2) & 0x0fff;
|
||||
}
|
||||
|
||||
static void mpr121_write(gpio_exp_t* self) {
|
||||
ESP_LOGE(TAG, "MPR121 GPIO write not implemented");
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
* PCA9535 family : direction, read and write
|
||||
*/
|
||||
|
||||
@@ -111,6 +111,7 @@ void services_init(void) {
|
||||
if (spi_config->mosi_io_num != -1 && spi_config->sclk_io_num != -1) {
|
||||
spi_bus_initialize( spi_system_host, spi_config, 1 );
|
||||
if (spi_system_dc_gpio != -1) {
|
||||
gpio_reset_pin(spi_system_dc_gpio);
|
||||
gpio_set_direction( spi_system_dc_gpio, GPIO_MODE_OUTPUT );
|
||||
gpio_set_level( spi_system_dc_gpio, 0 );
|
||||
} else {
|
||||
|
||||
@@ -8,7 +8,6 @@ idf_component_register(
|
||||
LDFRAGMENTS "linker.lf"
|
||||
)
|
||||
|
||||
add_definitions(-DBELL_USE_MBEDTLS)
|
||||
add_definitions(-Wno-unused-variable -Wno-unused-const-variable -Wchar-subscripts -Wunused-label -Wmaybe-uninitialized -Wmisleading-indentation)
|
||||
|
||||
set(BELL_DISABLE_CODECS ON)
|
||||
|
||||
@@ -116,6 +116,7 @@ static void cspotTask(void *pvParameters) {
|
||||
spircController = std::make_shared<SpircController>(mercuryManager, cspot.blob->username, audioSink);
|
||||
|
||||
spircController->setEventHandler([](CSpotEvent &event) {
|
||||
ESP_LOGI(TAG, "Getting Spotify event %d ", (int) event.eventType);
|
||||
switch (event.eventType) {
|
||||
case CSpotEventType::TRACK_INFO: {
|
||||
TrackInfo track = std::get<TrackInfo>(event.data);
|
||||
@@ -161,6 +162,8 @@ static void cspotTask(void *pvParameters) {
|
||||
}
|
||||
});
|
||||
|
||||
// need to make sure mercuryManager is running otherwise we'll loop and destroy instances
|
||||
while (!mercuryManager->isRunning) vTaskDelay(pdMS_TO_TICKS(25));
|
||||
mercuryManager->reconnectedCallback = []() {
|
||||
return spircController->subscribe();
|
||||
};
|
||||
@@ -293,18 +296,18 @@ bool NVSFile::flush() {
|
||||
* Shim HTTP server for spirc
|
||||
*/
|
||||
static esp_err_t handlerWrapper(httpd_req_t *req) {
|
||||
bell::HTTPRequest request = { };
|
||||
std::unique_ptr<bell::HTTPRequest> request = std::make_unique<bell::HTTPRequest>();
|
||||
char *query = NULL, *body = NULL;
|
||||
bell::httpHandler *handler = (bell::httpHandler*) req->user_ctx;
|
||||
size_t query_len = httpd_req_get_url_query_len(req);
|
||||
|
||||
request.connection = httpd_req_to_sockfd(req);
|
||||
request->connection = httpd_req_to_sockfd(req);
|
||||
|
||||
// get body if any (add '\0' at the end if used as string)
|
||||
if (req->content_len) {
|
||||
body = (char*) calloc(1, req->content_len + 1);
|
||||
int size = httpd_req_recv(req, body, req->content_len);
|
||||
request.body = body;
|
||||
request->body = body;
|
||||
ESP_LOGD(TAG,"wrapper received body %d/%d", size, req->content_len);
|
||||
}
|
||||
|
||||
@@ -324,7 +327,7 @@ static esp_err_t handlerWrapper(httpd_req_t *req) {
|
||||
while (key) {
|
||||
char *value = strchr(key, '=');
|
||||
*value++ = '\0';
|
||||
request.queryParams[key] = value;
|
||||
request->queryParams[key] = value;
|
||||
ESP_LOGD(TAG,"wrapper received key:%s value:%s", key, value);
|
||||
key = strtok(NULL, "&");
|
||||
};
|
||||
@@ -337,12 +340,12 @@ static esp_err_t handlerWrapper(httpd_req_t *req) {
|
||||
and then we'll return. So we can't obtain the response to be sent, as esp_http_server
|
||||
normally expects, instead respond() will use raw socket and close connection
|
||||
*/
|
||||
(*handler)(request);
|
||||
(*handler)(std::move(request));
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void ShimHTTPServer::registerHandler(bell::RequestType requestType, const std::string &routeUrl, bell::httpHandler handler) {
|
||||
void ShimHTTPServer::registerHandler(bell::RequestType requestType, const std::string &routeUrl, bell::httpHandler handler, bool readDataToStr) {
|
||||
httpd_uri_t request = {
|
||||
.uri = routeUrl.c_str(),
|
||||
.method = (requestType == bell::RequestType::GET ? HTTP_GET : HTTP_POST),
|
||||
|
||||
@@ -44,7 +44,6 @@ private:
|
||||
|
||||
public:
|
||||
ShimHTTPServer(httpd_handle_t server, int port) { serverHandle = server; serverPort = port; }
|
||||
|
||||
void registerHandler(bell::RequestType requestType, const std::string &, bell::httpHandler);
|
||||
void registerHandler(bell::RequestType requestType, const std::string &, bell::httpHandler, bool readDataToStr = false);
|
||||
void respond(const bell::HTTPResponse &);
|
||||
};
|
||||
|
||||
@@ -6,11 +6,21 @@ project(cspot)
|
||||
set(CSPOT_EXTERNAL_BELL "" CACHE STRING "External bell library target name, optional")
|
||||
|
||||
# CMake options
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
||||
if(MSVC)
|
||||
add_compile_definitions(NOMINMAX _WINSOCK_DEPRECATED_NO_WARNINGS _CRT_SECURE_NO_WARNINGS)
|
||||
add_definitions(/wd4068 /wd4244 /wd4018 /wd4101 /wd4102 /wd4142 /wd4996)
|
||||
endif()
|
||||
|
||||
# Main library sources
|
||||
file(GLOB SOURCES "src/*.cpp" "src/*.c")
|
||||
|
||||
if(WIN32)
|
||||
list(APPEND SOURCES "mdnssvc/mdns.c" "mdnssvc/mdnsd.c")
|
||||
list(APPEND EXTRA_INCLUDES "mdnssvc")
|
||||
endif()
|
||||
|
||||
# Use externally specified bell library or the submodule
|
||||
if(CSPOT_EXTERNAL_BELL)
|
||||
list(APPEND EXTRA_LIBS ${CSPOT_EXTERNAL_BELL})
|
||||
@@ -26,21 +36,21 @@ if(UNIX AND NOT APPLE)
|
||||
endif()
|
||||
|
||||
# Build protobuf code
|
||||
#set(NANOPB_OPTIONS "-I${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
#file(GLOB PROTOS protobuf/*.proto)
|
||||
#nanopb_generate_cpp(PROTO_SRCS PROTO_HDRS RELPATH ${CMAKE_CURRENT_SOURCE_DIR} ${PROTOS})
|
||||
#add_custom_target(generate_proto_sources DEPENDS ${PROTO_SRCS} ${PROTO_HDRS})
|
||||
#set_source_files_properties(${PROTO_SRCS} ${PROTO_HDRS}
|
||||
# PROPERTIES GENERATED TRUE)
|
||||
|
||||
file(GLOB SOURCES "src/*.cpp" "src/*.c" "protobuf/*.c")
|
||||
message("BEWARE => NOT GENERATING PROTOBUF")
|
||||
set(GENERATED_INCLUDES ".")
|
||||
if(1)
|
||||
set(NANOPB_OPTIONS "-I${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
file(GLOB PROTOS protobuf/*.proto)
|
||||
nanopb_generate_cpp(PROTO_SRCS PROTO_HDRS RELPATH ${CMAKE_CURRENT_SOURCE_DIR} ${PROTOS})
|
||||
add_custom_target(generate_proto_sources DEPENDS ${PROTO_SRCS} ${PROTO_HDRS})
|
||||
set_source_files_properties(${PROTO_SRCS} ${PROTO_HDRS} PROPERTIES GENERATED TRUE)
|
||||
else()
|
||||
list(APPEND SOURCES "protobuf/authentication.pb.c" "protobuf/keyexchange.pb.c" "protobuf/mercury.pb.c" "protobuf/metadata.pb.c" "protobuf/spirc.pb.c")
|
||||
list(APPEND EXTRA_INCLUDES ".")
|
||||
message(WARNING "NOT GENERATING PROTOBUF")
|
||||
endif()
|
||||
|
||||
add_library(cspot STATIC ${SOURCES} ${PROTO_SRCS})
|
||||
# PUBLIC to propagate includes from bell to cspot dependents
|
||||
target_compile_definitions(bell PUBLIC PB_ENABLE_MALLOC)
|
||||
target_compile_definitions(bell PUBLIC PB_FIELD_32BIT)
|
||||
target_link_libraries(cspot PUBLIC ${EXTRA_LIBS})
|
||||
#target_include_directories(cspot PUBLIC "include" ${CMAKE_CURRENT_BINARY_DIR} ${NANOPB_INCLUDE_DIRS})
|
||||
target_include_directories(cspot PUBLIC "include" ${GENERATED_INCLUDES} ${NANOPB_INCLUDE_DIRS})
|
||||
target_include_directories(cspot PUBLIC "include" ${CMAKE_CURRENT_BINARY_DIR} ${NANOPB_INCLUDE_DIRS} ${EXTRA_INCLUDES})
|
||||
|
||||
BIN
components/spotify/cspot/bell/.DS_Store
vendored
BIN
components/spotify/cspot/bell/.DS_Store
vendored
Binary file not shown.
126
components/spotify/cspot/bell/.gitignore
vendored
Normal file
126
components/spotify/cspot/bell/.gitignore
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/c,c++,cmake,macos
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=c,c++,cmake,macos
|
||||
|
||||
### C ###
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Object files
|
||||
*.o
|
||||
*.ko
|
||||
*.obj
|
||||
*.elf
|
||||
|
||||
# Linker output
|
||||
*.ilk
|
||||
*.map
|
||||
*.exp
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Libraries
|
||||
*.lib
|
||||
*.a
|
||||
*.la
|
||||
*.lo
|
||||
|
||||
# Shared objects (inc. Windows DLLs)
|
||||
*.dll
|
||||
*.so
|
||||
*.so.*
|
||||
*.dylib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
*.i*86
|
||||
*.x86_64
|
||||
*.hex
|
||||
|
||||
# Debug files
|
||||
*.dSYM/
|
||||
*.su
|
||||
*.idb
|
||||
*.pdb
|
||||
|
||||
# Kernel Module Compile Results
|
||||
*.mod*
|
||||
*.cmd
|
||||
.tmp_versions/
|
||||
modules.order
|
||||
Module.symvers
|
||||
Mkfile.old
|
||||
dkms.conf
|
||||
|
||||
### C++ ###
|
||||
# Prerequisites
|
||||
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
|
||||
# Precompiled Headers
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
*.smod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
|
||||
# Executables
|
||||
|
||||
### CMake ###
|
||||
CMakeLists.txt.user
|
||||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
CMakeScripts
|
||||
Testing
|
||||
Makefile
|
||||
cmake_install.cmake
|
||||
install_manifest.txt
|
||||
compile_commands.json
|
||||
CTestTestfile.cmake
|
||||
_deps
|
||||
|
||||
### CMake Patch ###
|
||||
# External projects
|
||||
*-prefix/
|
||||
|
||||
### macOS ###
|
||||
# General
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.com.apple.timemachine.donotpresent
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/c,c++,cmake,macos
|
||||
|
||||
build/
|
||||
3
components/spotify/cspot/bell/.gitmodules
vendored
3
components/spotify/cspot/bell/.gitmodules
vendored
@@ -5,3 +5,6 @@
|
||||
[submodule "cJSON"]
|
||||
path = cJSON
|
||||
url = https://github.com/DaveGamble/cJSON
|
||||
[submodule "nanopb"]
|
||||
path = nanopb
|
||||
url = https://github.com/nanopb/nanopb
|
||||
|
||||
@@ -4,79 +4,201 @@ cmake_policy(SET CMP0077 NEW)
|
||||
project(bell)
|
||||
|
||||
# Configurable options
|
||||
option(BELL_DISABLE_CODECS "Disable libhelix AAC and MP3 codecs" OFF)
|
||||
option(BELL_DISABLE_SINKS "Disable built-in audio sink implementations" OFF)
|
||||
option(BELL_USE_ALSA "Enable ALSA sink" OFF)
|
||||
option(BELL_USE_PORTAUDIO "Enable PortAudio sink" OFF)
|
||||
option(BELL_DISABLE_CODECS "Disable the entire audio codec wrapper" OFF)
|
||||
option(BELL_CODEC_AAC "Support libhelix-aac codec" ON)
|
||||
option(BELL_CODEC_MP3 "Support libhelix-mp3 codec" ON)
|
||||
option(BELL_CODEC_VORBIS "Support tremor Vorbis codec" ON)
|
||||
option(BELL_CODEC_ALAC "Support Apple ALAC codec" ON)
|
||||
option(BELL_CODEC_OPUS "Support Opus codec" ON)
|
||||
option(BELL_DISABLE_SINKS "Disable all built-in audio sink implementations" OFF)
|
||||
# These are default OFF, as they're OS-dependent (ESP32 sinks are always enabled - no external deps)
|
||||
option(BELL_SINK_ALSA "Enable ALSA audio sink" OFF)
|
||||
option(BELL_SINK_PORTAUDIO "Enable PortAudio sink" OFF)
|
||||
# cJSON wrapper
|
||||
option(BELL_DISABLE_CJSON "Disable cJSON and JSONObject completely" OFF)
|
||||
set(BELL_EXTERNAL_CJSON "" CACHE STRING "External cJSON library target name, optional")
|
||||
set(BELL_EXTERNAL_TREMOR "" CACHE STRING "External tremor library target name, optional")
|
||||
|
||||
if(BELL_EXTERNAL_MBEDTLS)
|
||||
set(MbedTLS_DIR ${BELL_EXTERNAL_MBEDTLS})
|
||||
message(STATUS "Setting local mbedtls ${MbedTLS_DIR}")
|
||||
endif()
|
||||
|
||||
# Backwards compatibility with deprecated options
|
||||
if(BELL_USE_ALSA)
|
||||
message(WARNING "Deprecated Bell options used, replace BELL_USE_ALSA with BELL_SINK_ALSA")
|
||||
set(BELL_SINK_ALSA ${BELL_USE_ALSA})
|
||||
endif()
|
||||
if(BELL_USE_PORTAUDIO)
|
||||
message(WARNING "Deprecated Bell options used, replace BELL_USE_PORTAUDIO with BELL_SINK_PORTAUDIO")
|
||||
set(BELL_SINK_PORTAUDIO ${BELL_USE_PORTAUDIO})
|
||||
endif()
|
||||
|
||||
message(STATUS "Bell options:")
|
||||
message(STATUS " Disable all codecs: ${BELL_DISABLE_CODECS}")
|
||||
if(NOT BELL_DISABLE_CODECS)
|
||||
message(STATUS " - AAC audio codec: ${BELL_CODEC_AAC}")
|
||||
message(STATUS " - MP3 audio codec: ${BELL_CODEC_MP3}")
|
||||
message(STATUS " - Vorbis audio codec: ${BELL_CODEC_VORBIS}")
|
||||
message(STATUS " - Opus audio codec: ${BELL_CODEC_OPUS}")
|
||||
message(STATUS " - ALAC audio codec: ${BELL_CODEC_ALAC}")
|
||||
endif()
|
||||
message(STATUS " Disable built-in audio sinks: ${BELL_DISABLE_SINKS}")
|
||||
if(NOT BELL_DISABLE_SINKS)
|
||||
message(STATUS " - ALSA sink: ${BELL_SINK_ALSA}")
|
||||
message(STATUS " - PortAudio sink: ${BELL_SINK_PORTAUDIO}")
|
||||
endif()
|
||||
message(STATUS " Disable cJSON and JSONObject: ${BELL_DISABLE_CJSON}")
|
||||
|
||||
# Include nanoPB library
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/nanopb/extra)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/nanopb/extra")
|
||||
find_package(Nanopb REQUIRED)
|
||||
list(APPEND EXTRA_INCLUDES ${NANOPB_INCLUDE_DIRS})
|
||||
|
||||
# CMake options
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||
add_definitions(-DUSE_DEFAULT_STDLIB=1)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
set(AUDIO_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/audio")
|
||||
add_definitions("-DUSE_DEFAULT_STDLIB=1")
|
||||
|
||||
# Main library sources
|
||||
file(GLOB SOURCES "src/*.cpp" "src/*.c" "nanopb/*.c")
|
||||
list(APPEND EXTRA_INCLUDES "include/platform")
|
||||
list(APPEND EXTRA_INCLUDES "include/audio/container")
|
||||
|
||||
# Add platform specific sources
|
||||
if(ESP_PLATFORM)
|
||||
file(GLOB ESP_PLATFORM_SOURCES "src/platform/esp/*.cpp" "src/platform/esp/*.c" "src/asm/biquad_f32_ae32.S")
|
||||
list(APPEND SOURCES ${ESP_PLATFORM_SOURCES})
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
file(GLOB UNIX_PLATFORM_SOURCES "src/platform/unix/*.cpp" "src/platform/linux/TLSSocket.cpp" "src/platform/unix/*.c")
|
||||
file(GLOB UNIX_PLATFORM_SOURCES "src/platform/unix/*.cpp" "src/platform/unix/*.c")
|
||||
list(APPEND SOURCES ${UNIX_PLATFORM_SOURCES})
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
file(GLOB APPLE_PLATFORM_SOURCES "src/platform/apple/*.cpp" "src/platform/linux/TLSSocket.cpp" "src/platform/apple/*.c")
|
||||
file(GLOB APPLE_PLATFORM_SOURCES "src/platform/apple/*.cpp" "src/platform/apple/*.c")
|
||||
list(APPEND SOURCES ${APPLE_PLATFORM_SOURCES})
|
||||
list(APPEND EXTRA_INCLUDES "/usr/local/opt/mbedtls@3/include")
|
||||
endif()
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
file(GLOB LINUX_PLATFORM_SOURCES "src/platform/linux/*.cpp" "src/platform/linux/*.c")
|
||||
list(APPEND SOURCES ${LINUX_PLATFORM_SOURCES})
|
||||
endif()
|
||||
if(WIN32)
|
||||
file(GLOB WIN32_PLATFORM_SOURCES "src/platform/win32/*.cpp" "src/platform/win32/*.c")
|
||||
list(APPEND SOURCES ${WIN32_PLATFORM_SOURCES})
|
||||
list(APPEND EXTRA_INCLUDES "include/platform/win32")
|
||||
endif()
|
||||
|
||||
# A hack to make Opus keep quiet
|
||||
function(message)
|
||||
if(NOT MESSAGE_QUIET)
|
||||
_message(${ARGN})
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
if(ESP_PLATFORM)
|
||||
# Use MBedTLS on ESP32
|
||||
list(REMOVE_ITEM SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/CryptoOpenSSL.cpp)
|
||||
idf_build_set_property(COMPILE_DEFINITIONS "-DBELL_USE_MBEDTLS" APPEND)
|
||||
list(APPEND EXTRA_LIBS idf::mbedtls idf::pthread idf::mdns)
|
||||
add_definitions(-Wunused-const-variable -Wchar-subscripts -Wunused-label -Wmaybe-uninitialized -Wmisleading-indentation)
|
||||
else()
|
||||
# Use OpenSSL elsewhere
|
||||
list(REMOVE_ITEM SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/CryptoMbedTLS.cpp)
|
||||
find_package(OpenSSL REQUIRED)
|
||||
find_package(Threads REQUIRED)
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
if(OPENSSL_FOUND)
|
||||
set(OPENSSL_USE_STATIC_LIBS TRUE)
|
||||
endif()
|
||||
list(APPEND EXTRA_LIBS OpenSSL::Crypto OpenSSL::SSL Threads::Threads)
|
||||
list(APPEND EXTRA_LIBS Threads::Threads)
|
||||
|
||||
find_package(MbedTLS REQUIRED)
|
||||
get_target_property(MBEDTLS_INFO MbedTLS::mbedtls INTERFACE_INCLUDE_DIRECTORIES)
|
||||
list(APPEND EXTRA_INCLUDES ${MBEDTLS_INFO})
|
||||
|
||||
# try to handle mbedtls when not system-wide installed
|
||||
if(BELL_EXTERNAL_MBEDTLS)
|
||||
if(MSVC)
|
||||
set(MBEDTLS_RELEASE "RELEASE" CACHE STRING "local mbedtls version")
|
||||
else()
|
||||
set(MBEDTLS_RELEASE "NOCONFIG" CACHE STRING "local mbedtls version")
|
||||
endif()
|
||||
message(STATUS "using local mbedtls version ${MBEDTLS_RELEASE}")
|
||||
get_target_property(MBEDTLS_INFO MbedTLS::mbedtls IMPORTED_LOCATION_${MBEDTLS_RELEASE})
|
||||
list(APPEND EXTRA_LIBS ${MBEDTLS_INFO})
|
||||
get_target_property(MBEDTLS_INFO MbedTLS::mbedx509 IMPORTED_LOCATION_${MBEDTLS_RELEASE})
|
||||
list(APPEND EXTRA_LIBS ${MBEDTLS_INFO})
|
||||
get_target_property(MBEDTLS_INFO MbedTLS::mbedcrypto IMPORTED_LOCATION_${MBEDTLS_RELEASE})
|
||||
list(APPEND EXTRA_LIBS ${MBEDTLS_INFO})
|
||||
else()
|
||||
list(APPEND EXTRA_LIBS mbedtls mbedcrypto mbedx509)
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
add_compile_definitions(NOMINMAX _CRT_SECURE_NO_WARNINGS)
|
||||
add_definitions(/wd4068 /wd4244 /wd4018 /wd4101 /wd4102 /wd4142)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(BELL_DISABLE_CODECS)
|
||||
list(REMOVE_ITEM SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/DecoderGlobals.cpp)
|
||||
else()
|
||||
file(GLOB LIBHELIX_AAC_SOURCES "libhelix-aac/*.c")
|
||||
file(GLOB LIBHELIX_MP3_SOURCES "libhelix-mp3/*.c")
|
||||
list(APPEND EXTRA_INCLUDES "libhelix-aac" "libhelix-mp3")
|
||||
list(APPEND SOURCES ${LIBHELIX_MP3_SOURCES} ${LIBHELIX_AAC_SOURCES})
|
||||
if(NOT BELL_DISABLE_CODECS)
|
||||
file(GLOB EXTRA_SOURCES "src/audio/container/*.cpp")
|
||||
list(APPEND SOURCES "${EXTRA_SOURCES}")
|
||||
list(APPEND SOURCES "${AUDIO_DIR}/codec/DecoderGlobals.cpp")
|
||||
list(APPEND SOURCES "${AUDIO_DIR}/codec/BaseCodec.cpp")
|
||||
list(APPEND SOURCES "${AUDIO_DIR}/codec/AudioCodecs.cpp")
|
||||
list(APPEND EXTRA_INCLUDES "include/audio/codec")
|
||||
# AAC-LC codec
|
||||
if(BELL_CODEC_AAC)
|
||||
file(GLOB LIBHELIX_AAC_SOURCES "libhelix-aac/*.c")
|
||||
list(APPEND LIBHELIX_SOURCES ${LIBHELIX_AAC_SOURCES})
|
||||
list(APPEND EXTRA_INCLUDES "libhelix-aac")
|
||||
list(APPEND SOURCES "${AUDIO_DIR}/codec/AACDecoder.cpp")
|
||||
list(APPEND CODEC_FLAGS "-DBELL_CODEC_AAC")
|
||||
endif()
|
||||
# MP3 codec
|
||||
if(BELL_CODEC_MP3)
|
||||
file(GLOB LIBHELIX_MP3_SOURCES "libhelix-mp3/*.c")
|
||||
list(APPEND LIBHELIX_SOURCES ${LIBHELIX_MP3_SOURCES})
|
||||
list(APPEND EXTRA_INCLUDES "libhelix-mp3")
|
||||
list(APPEND SOURCES "${AUDIO_DIR}/codec/MP3Decoder.cpp")
|
||||
list(APPEND CODEC_FLAGS "-DBELL_CODEC_MP3")
|
||||
endif()
|
||||
|
||||
# MP3 codec
|
||||
if(BELL_CODEC_ALAC)
|
||||
file(GLOB ALAC_SOURCES "alac/*.c" "alac/*.cpp")
|
||||
list(APPEND ALAC_SOURCES ${ALAC_SOURCES})
|
||||
list(APPEND EXTRA_INCLUDES "alac")
|
||||
# list(APPEND SOURCES "${AUDIO_DIR}/codec/ALACDecoder.cpp")
|
||||
list(APPEND CODEC_FLAGS "-DBELL_CODEC_ALAC")
|
||||
endif()
|
||||
# libhelix Cygwin workaround
|
||||
if(CYGWIN)
|
||||
# Both Cygwin and ESP are Unix-like so this seems to work (or, at least, compile)
|
||||
set_source_files_properties(src/DecoderGlobals.cpp PROPERTIES COMPILE_FLAGS -DESP_PLATFORM)
|
||||
set_source_files_properties(${LIBHELIX_AAC_SOURCES} PROPERTIES COMPILE_FLAGS -DESP_PLATFORM)
|
||||
set_source_files_properties(${LIBHELIX_MP3_SOURCES} PROPERTIES COMPILE_FLAGS -DESP_PLATFORM)
|
||||
set_source_files_properties("${AUDIO_DIR}/codec/DecoderGlobals.cpp" ${LIBHELIX_SOURCES} PROPERTIES COMPILE_FLAGS "-DESP_PLATFORM")
|
||||
endif()
|
||||
list(APPEND SOURCES ${LIBHELIX_SOURCES})
|
||||
list(APPEND SOURCES ${ALAC_SOURCES})
|
||||
# Vorbis codec
|
||||
if(BELL_CODEC_VORBIS)
|
||||
file(GLOB TREMOR_SOURCES "tremor/*.c")
|
||||
list(REMOVE_ITEM TREMOR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/tremor/ivorbisfile_example.c")
|
||||
list(APPEND SOURCES ${TREMOR_SOURCES})
|
||||
list(APPEND EXTRA_INCLUDES "tremor")
|
||||
list(APPEND SOURCES "${AUDIO_DIR}/codec/VorbisDecoder.cpp")
|
||||
list(APPEND CODEC_FLAGS "-DBELL_CODEC_VORBIS")
|
||||
endif()
|
||||
# Opus codec
|
||||
if(BELL_CODEC_OPUS)
|
||||
set(OPUS_INSTALL_CMAKE_CONFIG_MODULE OFF CACHE BOOL "")
|
||||
set(OPUS_INSTALL_CMAKE_CONFIG_MODULE OFF)
|
||||
set(OPUS_INSTALL_PKG_CONFIG_MODULE OFF CACHE BOOL "")
|
||||
set(OPUS_INSTALL_PKG_CONFIG_MODULE OFF)
|
||||
set(MESSAGE_QUIET ON)
|
||||
add_subdirectory("opus")
|
||||
unset(MESSAGE_QUIET)
|
||||
target_compile_options(opus PRIVATE "-O3")
|
||||
list(APPEND EXTRA_LIBS Opus::opus)
|
||||
list(APPEND SOURCES "${AUDIO_DIR}/codec/OPUSDecoder.cpp")
|
||||
list(APPEND CODEC_FLAGS -DBELL_CODEC_OPUS)
|
||||
endif()
|
||||
# Enable global codecs
|
||||
string(REPLACE ";" " " CODEC_FLAGS "${CODEC_FLAGS}")
|
||||
set_source_files_properties("${AUDIO_DIR}/codec/AudioCodecs.cpp" PROPERTIES COMPILE_FLAGS "${CODEC_FLAGS}")
|
||||
elseif(BELL_EXTERNAL_TREMOR)
|
||||
list(APPEND EXTRA_LIBS ${BELL_EXTERNAL_TREMOR})
|
||||
endif()
|
||||
|
||||
if(NOT BELL_DISABLE_SINKS)
|
||||
@@ -85,45 +207,52 @@ if(NOT BELL_DISABLE_SINKS)
|
||||
set(PLATFORM "esp")
|
||||
endif()
|
||||
# Add all built-in audio sinks
|
||||
file(GLOB SINK_SOURCES "src/sinks/${PLATFORM}/*.cpp" "src/sinks/${PLATFORM}/*.c")
|
||||
file(GLOB SINK_SOURCES "${AUDIO_DIR}/sinks/${PLATFORM}/*.cpp" "${AUDIO_DIR}/sinks/${PLATFORM}/*.c")
|
||||
list(APPEND EXTRA_INCLUDES "include/audio/sinks/${PLATFORM}")
|
||||
# Find ALSA if required, else remove the sink
|
||||
if(BELL_USE_ALSA)
|
||||
if(BELL_SINK_ALSA)
|
||||
find_package(ALSA REQUIRED)
|
||||
list(APPEND EXTRA_INCLUDES ${ALSA_INCLUDE_DIRS})
|
||||
list(APPEND EXTRA_LIBS ${ALSA_LIBRARIES})
|
||||
else()
|
||||
list(REMOVE_ITEM SINK_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/sinks/unix/ALSAAudioSink.cpp)
|
||||
list(REMOVE_ITEM SINK_SOURCES "${AUDIO_DIR}/sinks/unix/ALSAAudioSink.cpp")
|
||||
endif()
|
||||
# Find PortAudio if required, else remove the sink
|
||||
if(BELL_USE_PORTAUDIO)
|
||||
find_package(portaudio REQUIRED)
|
||||
list(APPEND EXTRA_INCLUDES ${PORTAUDIO_INCLUDE_DIRS})
|
||||
list(APPEND EXTRA_LIBS ${PORTAUDIO_LIBRARIES})
|
||||
if(BELL_SINK_PORTAUDIO)
|
||||
if(WIN32)
|
||||
list(APPEND EXTRA_INCLUDES "portaudio/include")
|
||||
if(NOT "${CMAKE_GENERATOR}" MATCHES "(Win64|IA64)")
|
||||
list(APPEND EXTRA_LIBS "${CMAKE_CURRENT_SOURCE_DIR}/portaudio/portaudio_win32.lib")
|
||||
else()
|
||||
list(APPEND EXTRA_LIBS "${CMAKE_CURRENT_SOURCE_DIR}/portaudio/portaudio_x64.lib")
|
||||
endif()
|
||||
else()
|
||||
find_package(portaudio REQUIRED)
|
||||
list(APPEND EXTRA_INCLUDES ${PORTAUDIO_INCLUDE_DIRS})
|
||||
list(APPEND EXTRA_LIBS ${PORTAUDIO_LIBRARIES})
|
||||
endif()
|
||||
else()
|
||||
list(REMOVE_ITEM SINK_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/sinks/unix/PortAudioSink.cpp)
|
||||
list(REMOVE_ITEM SINK_SOURCES "${AUDIO_DIR}/sinks/unix/PortAudioSink.cpp")
|
||||
endif()
|
||||
list(APPEND SOURCES ${SINK_SOURCES})
|
||||
list(APPEND EXTRA_INCLUDES "include/sinks/${PLATFORM}")
|
||||
endif()
|
||||
|
||||
if(BELL_EXTERNAL_CJSON)
|
||||
list(APPEND EXTRA_LIBS ${BELL_EXTERNAL_CJSON})
|
||||
if(BELL_DISABLE_CJSON)
|
||||
list(REMOVE_ITEM SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/JSONObject.cpp")
|
||||
else()
|
||||
list(APPEND EXTRA_INCLUDES "cJSON")
|
||||
list(APPEND SOURCES "cJSON/cJSON.c")
|
||||
endif()
|
||||
|
||||
if(BELL_EXTERNAL_TREMOR)
|
||||
list(APPEND EXTRA_LIBS ${BELL_EXTERNAL_TREMOR})
|
||||
else()
|
||||
file(GLOB TREMOR_SOURCES "tremor/*.c")
|
||||
list(REMOVE_ITEM TREMOR_SOURCES "tremor/ivorbisfile_example.c")
|
||||
list(APPEND EXTRA_INCLUDES "tremor")
|
||||
list(APPEND SOURCES ${TREMOR_SOURCES})
|
||||
if(BELL_EXTERNAL_CJSON)
|
||||
list(APPEND EXTRA_LIBS ${BELL_EXTERNAL_CJSON})
|
||||
else()
|
||||
list(APPEND SOURCES "cJSON/cJSON.c")
|
||||
list(APPEND EXTRA_INCLUDES "cJSON")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_library(bell STATIC ${SOURCES})
|
||||
# PUBLIC to propagate esp-idf includes to bell dependents
|
||||
target_link_libraries(bell PUBLIC ${EXTRA_LIBS})
|
||||
target_include_directories(bell PUBLIC "include" "include/platform" ${EXTRA_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
target_include_directories(bell PUBLIC "include" ${EXTRA_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
target_compile_definitions(bell PUBLIC PB_ENABLE_MALLOC)
|
||||
if(WIN32)
|
||||
target_compile_definitions(bell PUBLIC PB_NO_STATIC_ASSERT)
|
||||
endif()
|
||||
|
||||
@@ -121,6 +121,7 @@ set(SOURCES cJSON.c)
|
||||
option(BUILD_SHARED_AND_STATIC_LIBS "Build both shared and static libraries" Off)
|
||||
option(CJSON_OVERRIDE_BUILD_SHARED_LIBS "Override BUILD_SHARED_LIBS with CJSON_BUILD_SHARED_LIBS" OFF)
|
||||
option(CJSON_BUILD_SHARED_LIBS "Overrides BUILD_SHARED_LIBS if CJSON_OVERRIDE_BUILD_SHARED_LIBS is enabled" ON)
|
||||
option(ENABLE_CJSON_VERSION_SO "Enables cJSON so version" ON)
|
||||
|
||||
if ((CJSON_OVERRIDE_BUILD_SHARED_LIBS AND CJSON_BUILD_SHARED_LIBS) OR ((NOT CJSON_OVERRIDE_BUILD_SHARED_LIBS) AND BUILD_SHARED_LIBS))
|
||||
set(CJSON_LIBRARY_TYPE SHARED)
|
||||
@@ -155,17 +156,23 @@ install(TARGETS "${CJSON_LIB}"
|
||||
INCLUDES DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}"
|
||||
)
|
||||
if (BUILD_SHARED_AND_STATIC_LIBS)
|
||||
install(TARGETS "${CJSON_LIB}-static" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}")
|
||||
install(TARGETS "${CJSON_LIB}-static"
|
||||
EXPORT "${CJSON_LIB}"
|
||||
ARCHIVE DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}"
|
||||
INCLUDES DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}"
|
||||
)
|
||||
endif()
|
||||
if(ENABLE_TARGET_EXPORT)
|
||||
# export library information for CMake projects
|
||||
install(EXPORT "${CJSON_LIB}" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cJSON")
|
||||
endif()
|
||||
|
||||
set_target_properties("${CJSON_LIB}"
|
||||
PROPERTIES
|
||||
SOVERSION "${CJSON_VERSION_SO}"
|
||||
VERSION "${PROJECT_VERSION}")
|
||||
if(ENABLE_CJSON_VERSION_SO)
|
||||
set_target_properties("${CJSON_LIB}"
|
||||
PROPERTIES
|
||||
SOVERSION "${CJSON_VERSION_SO}"
|
||||
VERSION "${PROJECT_VERSION}")
|
||||
endif()
|
||||
|
||||
#cJSON_Utils
|
||||
option(ENABLE_CJSON_UTILS "Enable building the cJSON_Utils library." OFF)
|
||||
@@ -198,7 +205,11 @@ if(ENABLE_CJSON_UTILS)
|
||||
INCLUDES DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}"
|
||||
)
|
||||
if (BUILD_SHARED_AND_STATIC_LIBS)
|
||||
install(TARGETS "${CJSON_UTILS_LIB}-static" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}")
|
||||
install(TARGETS "${CJSON_UTILS_LIB}-static"
|
||||
EXPORT "${CJSON_UTILS_LIB}"
|
||||
ARCHIVE DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}"
|
||||
INCLUDES DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}"
|
||||
)
|
||||
endif()
|
||||
install(FILES cJSON_Utils.h DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/cjson")
|
||||
install (FILES "${CMAKE_CURRENT_BINARY_DIR}/libcjson_utils.pc" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig")
|
||||
@@ -207,10 +218,12 @@ if(ENABLE_CJSON_UTILS)
|
||||
install(EXPORT "${CJSON_UTILS_LIB}" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cJSON")
|
||||
endif()
|
||||
|
||||
set_target_properties("${CJSON_UTILS_LIB}"
|
||||
PROPERTIES
|
||||
SOVERSION "${CJSON_UTILS_VERSION_SO}"
|
||||
VERSION "${PROJECT_VERSION}")
|
||||
if(ENABLE_CJSON_VERSION_SO)
|
||||
set_target_properties("${CJSON_UTILS_LIB}"
|
||||
PROPERTIES
|
||||
SOVERSION "${CJSON_UTILS_VERSION_SO}"
|
||||
VERSION "${PROJECT_VERSION}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# create the other package config files
|
||||
|
||||
@@ -96,9 +96,9 @@ CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
|
||||
return (const char*) (global_error.json + global_error.position);
|
||||
}
|
||||
|
||||
CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item)
|
||||
CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item)
|
||||
{
|
||||
if (!cJSON_IsString(item))
|
||||
if (!cJSON_IsString(item))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
@@ -106,9 +106,9 @@ CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item)
|
||||
return item->valuestring;
|
||||
}
|
||||
|
||||
CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item)
|
||||
CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item)
|
||||
{
|
||||
if (!cJSON_IsNumber(item))
|
||||
if (!cJSON_IsNumber(item))
|
||||
{
|
||||
return (double) NAN;
|
||||
}
|
||||
@@ -511,7 +511,7 @@ static unsigned char* ensure(printbuffer * const p, size_t needed)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
memcpy(newbuffer, p->buffer, p->offset + 1);
|
||||
p->hooks.deallocate(p->buffer);
|
||||
}
|
||||
@@ -562,6 +562,10 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out
|
||||
{
|
||||
length = sprintf((char*)number_buffer, "null");
|
||||
}
|
||||
else if(d == (double)item->valueint)
|
||||
{
|
||||
length = sprintf((char*)number_buffer, "%d", item->valueint);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
|
||||
@@ -1103,7 +1107,7 @@ CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer
|
||||
}
|
||||
|
||||
buffer.content = (const unsigned char*)value;
|
||||
buffer.length = buffer_length;
|
||||
buffer.length = buffer_length;
|
||||
buffer.offset = 0;
|
||||
buffer.hooks = global_hooks;
|
||||
|
||||
@@ -2357,6 +2361,11 @@ static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSO
|
||||
cJSON_free(replacement->string);
|
||||
}
|
||||
replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
|
||||
if (replacement->string == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
replacement->type &= ~cJSON_StringIsConst;
|
||||
|
||||
return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
|
||||
@@ -2689,7 +2698,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int co
|
||||
if (a && a->child) {
|
||||
a->child->prev = n;
|
||||
}
|
||||
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
@@ -279,6 +279,13 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
|
||||
/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */
|
||||
CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring);
|
||||
|
||||
/* If the object is not a boolean type this does nothing and returns cJSON_Invalid else it returns the new type*/
|
||||
#define cJSON_SetBoolValue(object, boolValue) ( \
|
||||
(object != NULL && ((object)->type & (cJSON_False|cJSON_True))) ? \
|
||||
(object)->type=((object)->type &(~(cJSON_False|cJSON_True)))|((boolValue)?cJSON_True:cJSON_False) : \
|
||||
cJSON_Invalid\
|
||||
)
|
||||
|
||||
/* Macro for iterating over an array or object */
|
||||
#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include "unity/src/unity.h"
|
||||
#include "common.h"
|
||||
|
||||
|
||||
static void cjson_array_foreach_should_loop_over_arrays(void)
|
||||
{
|
||||
cJSON array[1];
|
||||
@@ -77,7 +76,6 @@ static void cjson_get_object_item_should_get_object_items(void)
|
||||
found = cJSON_GetObjectItem(item, NULL);
|
||||
TEST_ASSERT_NULL_MESSAGE(found, "Failed to fail on NULL string.");
|
||||
|
||||
|
||||
found = cJSON_GetObjectItem(item, "one");
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find first item.");
|
||||
TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 1);
|
||||
@@ -127,7 +125,8 @@ static void cjson_get_object_item_case_sensitive_should_get_object_items(void)
|
||||
cJSON_Delete(item);
|
||||
}
|
||||
|
||||
static void cjson_get_object_item_should_not_crash_with_array(void) {
|
||||
static void cjson_get_object_item_should_not_crash_with_array(void)
|
||||
{
|
||||
cJSON *array = NULL;
|
||||
cJSON *found = NULL;
|
||||
array = cJSON_Parse("[1]");
|
||||
@@ -138,7 +137,8 @@ static void cjson_get_object_item_should_not_crash_with_array(void) {
|
||||
cJSON_Delete(array);
|
||||
}
|
||||
|
||||
static void cjson_get_object_item_case_sensitive_should_not_crash_with_array(void) {
|
||||
static void cjson_get_object_item_case_sensitive_should_not_crash_with_array(void)
|
||||
{
|
||||
cJSON *array = NULL;
|
||||
cJSON *found = NULL;
|
||||
array = cJSON_Parse("[1]");
|
||||
@@ -302,7 +302,6 @@ static void cjson_replace_item_via_pointer_should_replace_items(void)
|
||||
cJSON_AddItemToArray(array, middle);
|
||||
cJSON_AddItemToArray(array, end);
|
||||
|
||||
|
||||
memset(replacements, '\0', sizeof(replacements));
|
||||
|
||||
/* replace beginning */
|
||||
@@ -329,7 +328,7 @@ static void cjson_replace_item_via_pointer_should_replace_items(void)
|
||||
|
||||
static void cjson_replace_item_in_object_should_preserve_name(void)
|
||||
{
|
||||
cJSON root[1] = {{ NULL, NULL, NULL, 0, NULL, 0, 0, NULL }};
|
||||
cJSON root[1] = {{NULL, NULL, NULL, 0, NULL, 0, 0, NULL}};
|
||||
cJSON *child = NULL;
|
||||
cJSON *replacement = NULL;
|
||||
cJSON_bool flag = false;
|
||||
@@ -339,7 +338,7 @@ static void cjson_replace_item_in_object_should_preserve_name(void)
|
||||
replacement = cJSON_CreateNumber(2);
|
||||
TEST_ASSERT_NOT_NULL(replacement);
|
||||
|
||||
flag = cJSON_AddItemToObject(root, "child", child);
|
||||
flag = cJSON_AddItemToObject(root, "child", child);
|
||||
TEST_ASSERT_TRUE_MESSAGE(flag, "add item to object failed");
|
||||
cJSON_ReplaceItemInObject(root, "child", replacement);
|
||||
|
||||
@@ -435,7 +434,7 @@ static void cjson_functions_should_not_crash_with_null_pointers(void)
|
||||
cJSON_Delete(item);
|
||||
}
|
||||
|
||||
static void * CJSON_CDECL failing_realloc(void *pointer, size_t size)
|
||||
static void *CJSON_CDECL failing_realloc(void *pointer, size_t size)
|
||||
{
|
||||
(void)size;
|
||||
(void)pointer;
|
||||
@@ -445,7 +444,7 @@ static void * CJSON_CDECL failing_realloc(void *pointer, size_t size)
|
||||
static void ensure_should_fail_on_failed_realloc(void)
|
||||
{
|
||||
printbuffer buffer = {NULL, 10, 0, 0, false, false, {&malloc, &free, &failing_realloc}};
|
||||
buffer.buffer = (unsigned char*)malloc(100);
|
||||
buffer.buffer = (unsigned char *)malloc(100);
|
||||
TEST_ASSERT_NOT_NULL(buffer.buffer);
|
||||
|
||||
TEST_ASSERT_NULL_MESSAGE(ensure(&buffer, 200), "Ensure didn't fail with failing realloc.");
|
||||
@@ -454,7 +453,7 @@ static void ensure_should_fail_on_failed_realloc(void)
|
||||
static void skip_utf8_bom_should_skip_bom(void)
|
||||
{
|
||||
const unsigned char string[] = "\xEF\xBB\xBF{}";
|
||||
parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
|
||||
parse_buffer buffer = {0, 0, 0, 0, {0, 0, 0}};
|
||||
buffer.content = string;
|
||||
buffer.length = sizeof(string);
|
||||
buffer.hooks = global_hooks;
|
||||
@@ -466,7 +465,7 @@ static void skip_utf8_bom_should_skip_bom(void)
|
||||
static void skip_utf8_bom_should_not_skip_bom_if_not_at_beginning(void)
|
||||
{
|
||||
const unsigned char string[] = " \xEF\xBB\xBF{}";
|
||||
parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
|
||||
parse_buffer buffer = {0, 0, 0, 0, {0, 0, 0}};
|
||||
buffer.content = string;
|
||||
buffer.length = sizeof(string);
|
||||
buffer.hooks = global_hooks;
|
||||
@@ -496,12 +495,13 @@ static void cjson_get_number_value_should_get_a_number(void)
|
||||
TEST_ASSERT_EQUAL_DOUBLE(cJSON_GetNumberValue(number), number->valuedouble);
|
||||
TEST_ASSERT_DOUBLE_IS_NAN(cJSON_GetNumberValue(string));
|
||||
TEST_ASSERT_DOUBLE_IS_NAN(cJSON_GetNumberValue(NULL));
|
||||
|
||||
|
||||
cJSON_Delete(number);
|
||||
cJSON_Delete(string);
|
||||
}
|
||||
|
||||
static void cjson_create_string_reference_should_create_a_string_reference(void) {
|
||||
static void cjson_create_string_reference_should_create_a_string_reference(void)
|
||||
{
|
||||
const char *string = "I am a string!";
|
||||
|
||||
cJSON *string_reference = cJSON_CreateStringReference(string);
|
||||
@@ -511,7 +511,8 @@ static void cjson_create_string_reference_should_create_a_string_reference(void)
|
||||
cJSON_Delete(string_reference);
|
||||
}
|
||||
|
||||
static void cjson_create_object_reference_should_create_an_object_reference(void) {
|
||||
static void cjson_create_object_reference_should_create_an_object_reference(void)
|
||||
{
|
||||
cJSON *number_reference = NULL;
|
||||
cJSON *number_object = cJSON_CreateObject();
|
||||
cJSON *number = cJSON_CreateNumber(42);
|
||||
@@ -529,7 +530,8 @@ static void cjson_create_object_reference_should_create_an_object_reference(void
|
||||
cJSON_Delete(number_reference);
|
||||
}
|
||||
|
||||
static void cjson_create_array_reference_should_create_an_array_reference(void) {
|
||||
static void cjson_create_array_reference_should_create_an_array_reference(void)
|
||||
{
|
||||
cJSON *number_reference = NULL;
|
||||
cJSON *number_array = cJSON_CreateArray();
|
||||
cJSON *number = cJSON_CreateNumber(42);
|
||||
@@ -566,7 +568,7 @@ static void cjson_add_item_to_object_should_not_use_after_free_when_string_is_al
|
||||
{
|
||||
cJSON *object = cJSON_CreateObject();
|
||||
cJSON *number = cJSON_CreateNumber(42);
|
||||
char *name = (char*)cJSON_strdup((const unsigned char*)"number", &global_hooks);
|
||||
char *name = (char *)cJSON_strdup((const unsigned char *)"number", &global_hooks);
|
||||
|
||||
TEST_ASSERT_NOT_NULL(object);
|
||||
TEST_ASSERT_NOT_NULL(number);
|
||||
@@ -626,7 +628,7 @@ static void cjson_set_valuestring_to_object_should_not_leak_memory(void)
|
||||
cJSON *item2 = cJSON_CreateStringReference(reference_valuestring);
|
||||
char *ptr1 = NULL;
|
||||
char *return_value = NULL;
|
||||
|
||||
|
||||
cJSON_AddItemToObject(root, "one", item1);
|
||||
cJSON_AddItemToObject(root, "two", item2);
|
||||
|
||||
@@ -650,6 +652,64 @@ static void cjson_set_valuestring_to_object_should_not_leak_memory(void)
|
||||
cJSON_Delete(root);
|
||||
}
|
||||
|
||||
static void cjson_set_bool_value_must_not_break_objects(void)
|
||||
{
|
||||
cJSON *bobj, *sobj, *oobj, *refobj = NULL;
|
||||
|
||||
TEST_ASSERT_TRUE((cJSON_SetBoolValue(refobj, 1) == cJSON_Invalid));
|
||||
|
||||
bobj = cJSON_CreateFalse();
|
||||
TEST_ASSERT_TRUE(cJSON_IsFalse(bobj));
|
||||
TEST_ASSERT_TRUE((cJSON_SetBoolValue(bobj, 1) == cJSON_True));
|
||||
TEST_ASSERT_TRUE(cJSON_IsTrue(bobj));
|
||||
cJSON_SetBoolValue(bobj, 1);
|
||||
TEST_ASSERT_TRUE(cJSON_IsTrue(bobj));
|
||||
TEST_ASSERT_TRUE((cJSON_SetBoolValue(bobj, 0) == cJSON_False));
|
||||
TEST_ASSERT_TRUE(cJSON_IsFalse(bobj));
|
||||
cJSON_SetBoolValue(bobj, 0);
|
||||
TEST_ASSERT_TRUE(cJSON_IsFalse(bobj));
|
||||
|
||||
sobj = cJSON_CreateString("test");
|
||||
TEST_ASSERT_TRUE(cJSON_IsString(sobj));
|
||||
cJSON_SetBoolValue(sobj, 1);
|
||||
TEST_ASSERT_TRUE(cJSON_IsString(sobj));
|
||||
cJSON_SetBoolValue(sobj, 0);
|
||||
TEST_ASSERT_TRUE(cJSON_IsString(sobj));
|
||||
|
||||
oobj = cJSON_CreateObject();
|
||||
TEST_ASSERT_TRUE(cJSON_IsObject(oobj));
|
||||
cJSON_SetBoolValue(oobj, 1);
|
||||
TEST_ASSERT_TRUE(cJSON_IsObject(oobj));
|
||||
cJSON_SetBoolValue(oobj, 0);
|
||||
TEST_ASSERT_TRUE(cJSON_IsObject(oobj));
|
||||
|
||||
refobj = cJSON_CreateStringReference("conststring");
|
||||
TEST_ASSERT_TRUE(cJSON_IsString(refobj));
|
||||
TEST_ASSERT_TRUE(refobj->type & cJSON_IsReference);
|
||||
cJSON_SetBoolValue(refobj, 1);
|
||||
TEST_ASSERT_TRUE(cJSON_IsString(refobj));
|
||||
TEST_ASSERT_TRUE(refobj->type & cJSON_IsReference);
|
||||
cJSON_SetBoolValue(refobj, 0);
|
||||
TEST_ASSERT_TRUE(cJSON_IsString(refobj));
|
||||
TEST_ASSERT_TRUE(refobj->type & cJSON_IsReference);
|
||||
cJSON_Delete(refobj);
|
||||
|
||||
refobj = cJSON_CreateObjectReference(oobj);
|
||||
TEST_ASSERT_TRUE(cJSON_IsObject(refobj));
|
||||
TEST_ASSERT_TRUE(refobj->type & cJSON_IsReference);
|
||||
cJSON_SetBoolValue(refobj, 1);
|
||||
TEST_ASSERT_TRUE(cJSON_IsObject(refobj));
|
||||
TEST_ASSERT_TRUE(refobj->type & cJSON_IsReference);
|
||||
cJSON_SetBoolValue(refobj, 0);
|
||||
TEST_ASSERT_TRUE(cJSON_IsObject(refobj));
|
||||
TEST_ASSERT_TRUE(refobj->type & cJSON_IsReference);
|
||||
cJSON_Delete(refobj);
|
||||
|
||||
cJSON_Delete(oobj);
|
||||
cJSON_Delete(bobj);
|
||||
cJSON_Delete(sobj);
|
||||
}
|
||||
|
||||
int CJSON_CDECL main(void)
|
||||
{
|
||||
UNITY_BEGIN();
|
||||
@@ -679,6 +739,7 @@ int CJSON_CDECL main(void)
|
||||
RUN_TEST(cjson_add_item_to_object_should_not_use_after_free_when_string_is_aliased);
|
||||
RUN_TEST(cjson_delete_item_from_array_should_not_broken_list_structure);
|
||||
RUN_TEST(cjson_set_valuestring_to_object_should_not_leak_memory);
|
||||
RUN_TEST(cjson_set_bool_value_must_not_break_objects);
|
||||
|
||||
return UNITY_END();
|
||||
}
|
||||
|
||||
@@ -6,7 +6,14 @@
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
namespace bell {
|
||||
|
||||
@@ -20,6 +27,40 @@ class ResponseReader {
|
||||
virtual void close() = 0;
|
||||
};
|
||||
|
||||
class RequestBodyReader : public ResponseReader {
|
||||
public:
|
||||
std::vector<uint8_t> partialBuffer;
|
||||
int fd = 0;
|
||||
size_t contentLength = 0;
|
||||
size_t sizeRead = 0;
|
||||
|
||||
RequestBodyReader(size_t contentLength, int fd, std::vector<uint8_t> &partialBuffer) {
|
||||
this->contentLength = contentLength;
|
||||
this->partialBuffer = partialBuffer;
|
||||
this->fd = fd;
|
||||
};
|
||||
|
||||
|
||||
size_t read(char *buffer, size_t size) {
|
||||
if (sizeRead < partialBuffer.size()) {
|
||||
size_t toRead = std::min(size, partialBuffer.size() - sizeRead);
|
||||
memcpy(buffer, &partialBuffer[sizeRead], toRead);
|
||||
sizeRead += toRead;
|
||||
return toRead;
|
||||
} else {
|
||||
size_t toRead = std::min(size, contentLength - sizeRead);
|
||||
size_t read = recv(fd, buffer, toRead, 0);
|
||||
sizeRead += read;
|
||||
return read;
|
||||
}
|
||||
}
|
||||
|
||||
void close() {
|
||||
}
|
||||
|
||||
size_t getTotalSize() { return contentLength; }
|
||||
};
|
||||
|
||||
class FileResponseReader : public ResponseReader {
|
||||
public:
|
||||
FILE *file;
|
||||
@@ -30,7 +71,7 @@ class FileResponseReader : public ResponseReader {
|
||||
fileSize = ftell(file); // get current file pointer
|
||||
fseek(file, 0, SEEK_SET); // seek back to beginning of file
|
||||
};
|
||||
~FileResponseReader() { fclose(file); };
|
||||
|
||||
|
||||
size_t read(char *buffer, size_t size) {
|
||||
return fread(buffer, 1, size, file);
|
||||
@@ -48,10 +89,13 @@ enum class RequestType { GET, POST };
|
||||
struct HTTPRequest {
|
||||
std::map<std::string, std::string> urlParams;
|
||||
std::map<std::string, std::string> queryParams;
|
||||
std::unique_ptr<ResponseReader> responseReader = std::unique_ptr<RequestBodyReader>(nullptr);
|
||||
|
||||
std::string body;
|
||||
std::string url;
|
||||
int handlerId;
|
||||
int connection;
|
||||
int contentLength;
|
||||
};
|
||||
|
||||
struct HTTPResponse {
|
||||
@@ -64,19 +108,22 @@ struct HTTPResponse {
|
||||
std::unique_ptr<ResponseReader> responseReader;
|
||||
};
|
||||
|
||||
typedef std::function<void(HTTPRequest &)> httpHandler;
|
||||
typedef std::function<void(std::unique_ptr<bell::HTTPRequest>)> httpHandler;
|
||||
|
||||
struct HTTPRoute {
|
||||
RequestType requestType;
|
||||
httpHandler handler;
|
||||
bool readBodyToStr;
|
||||
};
|
||||
|
||||
struct HTTPConnection {
|
||||
int fd = 0;
|
||||
std::vector<uint8_t> buffer;
|
||||
std::string currentLine = "";
|
||||
std::vector<uint8_t> partialBuffer = std::vector<uint8_t>();
|
||||
int contentLength = 0;
|
||||
bool isReadingBody = false;
|
||||
std::string httpMethod;
|
||||
bool toBeClosed = false;
|
||||
bool headersRead = false;
|
||||
bool isEventConnection = false;
|
||||
bool isCaptivePortal = false;
|
||||
};
|
||||
@@ -96,10 +143,11 @@ public:
|
||||
*
|
||||
* @param requestType GET or POST
|
||||
* @param endpoint registering under
|
||||
* @param readResponseToStr if true, response will be read to string, otherwise it will return a reader object
|
||||
* httpHandler lambda to be called when given endpoint gets executed
|
||||
*/
|
||||
virtual void registerHandler(RequestType requestType, const std::string & endpoint,
|
||||
httpHandler) = 0;
|
||||
httpHandler, bool readResponseToStr = true) = 0;
|
||||
|
||||
/**
|
||||
* Writes given response to a fd
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
@@ -18,7 +19,7 @@ namespace bell
|
||||
virtual void info(std::string filename, int line, std::string submodule, const char *format, ...) = 0;
|
||||
};
|
||||
|
||||
extern std::shared_ptr<bell::AbstractLogger> bellGlobalLogger;
|
||||
extern bell::AbstractLogger* bellGlobalLogger;
|
||||
class BellLogger : public bell::AbstractLogger
|
||||
{
|
||||
public:
|
||||
@@ -81,23 +82,27 @@ namespace bell
|
||||
|
||||
void printFilename(std::string filename)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
std::string basenameStr(filename.substr(filename.rfind("\\") + 1));
|
||||
#else
|
||||
std::string basenameStr(filename.substr(filename.rfind("/") + 1));
|
||||
#endif
|
||||
unsigned long hash = 5381;
|
||||
for (char const &c : basenameStr)
|
||||
{
|
||||
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
|
||||
}
|
||||
|
||||
printf("\e[0;%dm", allColors[hash % NColors]);
|
||||
printf("\033[0;%dm", allColors[hash % NColors]);
|
||||
|
||||
printf("%s", basenameStr.c_str());
|
||||
printf(colorReset);
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr const char *colorReset = "\e[0m";
|
||||
static constexpr const char *colorRed = "\e[0;31m";
|
||||
static constexpr const char *colorBlue = "\e[0;34m";
|
||||
static constexpr const char *colorReset = "\033[0m";
|
||||
static constexpr const char *colorRed = "\033[0;31m";
|
||||
static constexpr const char *colorBlue = "\033[0;34m";
|
||||
static constexpr const int NColors = 15;
|
||||
static constexpr int allColors[NColors] = {31, 32, 33, 34, 35, 36, 37, 90, 91, 92, 93, 94, 95, 96, 97};
|
||||
};
|
||||
|
||||
@@ -7,9 +7,12 @@
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/timers.h>
|
||||
#include <freertos/task.h>
|
||||
#elif _WIN32
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include <pthread.h>
|
||||
#include <string>
|
||||
|
||||
namespace bell
|
||||
@@ -62,14 +65,23 @@ namespace bell
|
||||
esp_pthread_set_cfg(&cfg);
|
||||
}
|
||||
#endif
|
||||
#if _WIN32
|
||||
thread = CreateThread(NULL, stackSize, (LPTHREAD_START_ROUTINE) taskEntryFunc, this, 0, NULL);
|
||||
return thread != NULL;
|
||||
#else
|
||||
return (pthread_create(&thread, NULL, taskEntryFunc, this) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void runTask() = 0;
|
||||
|
||||
private:
|
||||
#if _WIN32
|
||||
HANDLE thread;
|
||||
#else
|
||||
pthread_t thread;
|
||||
#endif
|
||||
#ifdef ESP_PLATFORM
|
||||
int priority;
|
||||
StaticTask_t *xTaskBuffer;
|
||||
@@ -96,7 +108,11 @@ namespace bell
|
||||
{
|
||||
Task* self = (Task*) This;
|
||||
self->runTask();
|
||||
#if _WIN32
|
||||
WaitForSingleObject(self->thread, INFINITE);
|
||||
#else
|
||||
pthread_join(self->thread, NULL);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
@@ -18,6 +18,9 @@ void freeAndNull(void *&ptr);
|
||||
#define BELL_SLEEP_MS(ms) vTaskDelay(ms / portTICK_PERIOD_MS)
|
||||
#define BELL_YIELD() taskYIELD()
|
||||
|
||||
#elif defined(_WIN32)
|
||||
#define BELL_SLEEP_MS(ms) Sleep(ms)
|
||||
#define BELL_YIELD() ;
|
||||
#else
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
127
components/spotify/cspot/bell/include/BufferedStream.h
Normal file
127
components/spotify/cspot/bell/include/BufferedStream.h
Normal file
@@ -0,0 +1,127 @@
|
||||
// Copyright (c) Kuba Szczodrzyński 2022-1-7.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ByteStream.h"
|
||||
#include "BellTask.h"
|
||||
#include "WrappedSemaphore.h"
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
/**
|
||||
* This class implements a wrapper around an arbitrary bell::ByteStream,
|
||||
* providing a circular reading buffer with configurable thresholds.
|
||||
*
|
||||
* The BufferedStream runs a bell::Task when it's started, so the caller can
|
||||
* access the buffer's data asynchronously, whenever needed. The buffer is refilled
|
||||
* automatically from source stream.
|
||||
*
|
||||
* The class implements bell::ByteStream's methods, although for proper functioning,
|
||||
* the caller code should be modified to check isReady() and isNotReady() flags.
|
||||
*
|
||||
* If the actual reading code can't be modified, waitForReady allows to wait for buffer readiness
|
||||
* during reading. Keep in mind that using the semaphore is probably more resource effective.
|
||||
*
|
||||
* The source stream (passed to open() or returned by the reader) should implement the read()
|
||||
* method correctly, such as that 0 is returned if, and only if the stream ends.
|
||||
*/
|
||||
class BufferedStream : public bell::ByteStream, bell::Task {
|
||||
public:
|
||||
typedef std::shared_ptr<bell::ByteStream> StreamPtr;
|
||||
typedef std::function<StreamPtr(uint32_t rangeStart)> StreamReader;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @param taskName name to use for the reading task
|
||||
* @param bufferSize total size of the reading buffer
|
||||
* @param readThreshold how much can be read before refilling the buffer
|
||||
* @param readSize amount of bytes to read from the source each time
|
||||
* @param readyThreshold minimum amount of available bytes to report isReady()
|
||||
* @param notReadyThreshold maximum amount of available bytes to report isNotReady()
|
||||
* @param waitForReady whether to wait for the buffer to be ready during reading
|
||||
* @param endWithSource whether to end the streaming as soon as source returns 0 from read()
|
||||
*/
|
||||
BufferedStream(
|
||||
const std::string &taskName,
|
||||
uint32_t bufferSize,
|
||||
uint32_t readThreshold,
|
||||
uint32_t readSize,
|
||||
uint32_t readyThreshold,
|
||||
uint32_t notReadyThreshold,
|
||||
bool waitForReady = false);
|
||||
~BufferedStream() override;
|
||||
bool open(const StreamPtr &stream);
|
||||
bool open(const StreamReader &newReader, uint32_t initialOffset = 0);
|
||||
void close() override;
|
||||
|
||||
// inherited methods
|
||||
public:
|
||||
/**
|
||||
* Read len bytes from the buffer to dst. If waitForReady is enabled
|
||||
* and readAvailable is lower than notReadyThreshold, the function
|
||||
* will block until readyThreshold bytes is available.
|
||||
*
|
||||
* @returns number of bytes copied to dst (might be lower than len,
|
||||
* if the buffer does not contain len bytes available), or 0 if the source
|
||||
* stream is already closed and there is no reader attached.
|
||||
*/
|
||||
size_t read(uint8_t *dst, size_t len) override;
|
||||
size_t skip(size_t len) override;
|
||||
size_t position() override;
|
||||
size_t size() override;
|
||||
|
||||
// stream status
|
||||
public:
|
||||
/**
|
||||
* Total amount of bytes served to read().
|
||||
*/
|
||||
uint32_t readTotal;
|
||||
/**
|
||||
* Total amount of bytes read from source.
|
||||
*/
|
||||
uint32_t bufferTotal;
|
||||
/**
|
||||
* Amount of bytes available to read from the buffer.
|
||||
*/
|
||||
std::atomic<uint32_t> readAvailable;
|
||||
/**
|
||||
* Whether the caller should start reading the data. This indicates that a safe
|
||||
* amount (determined by readyThreshold) of data is available in the buffer.
|
||||
*/
|
||||
bool isReady() const;
|
||||
/**
|
||||
* Whether the caller should stop reading the data. This indicates that the amount of data
|
||||
* available for reading is decreasing to a non-safe value, as data is being read
|
||||
* faster than it can be buffered.
|
||||
*/
|
||||
bool isNotReady() const;
|
||||
/**
|
||||
* Semaphore that is given when the buffer becomes ready (isReady() == true). Caller can
|
||||
* wait for the semaphore instead of continuously querying isReady().
|
||||
*/
|
||||
WrappedSemaphore readySem;
|
||||
|
||||
private:
|
||||
std::mutex runningMutex;
|
||||
bool running = false;
|
||||
bool terminate = false;
|
||||
WrappedSemaphore readSem; // signal to start writing to buffer after reading from it
|
||||
std::mutex readMutex; // mutex for locking read operations during writing, and vice versa
|
||||
uint32_t bufferSize;
|
||||
uint32_t readAt;
|
||||
uint32_t readSize;
|
||||
uint32_t readyThreshold;
|
||||
uint32_t notReadyThreshold;
|
||||
bool waitForReady;
|
||||
uint8_t *buf;
|
||||
uint8_t *bufEnd;
|
||||
uint8_t *bufReadPtr;
|
||||
uint8_t *bufWritePtr;
|
||||
StreamPtr source;
|
||||
StreamReader reader;
|
||||
void runTask() override;
|
||||
void reset();
|
||||
uint32_t lengthBetween(uint8_t *me, uint8_t *other);
|
||||
};
|
||||
@@ -1,14 +1,78 @@
|
||||
#ifndef BELL_CRYPTO_H
|
||||
#define BELL_CRYPTO_H
|
||||
|
||||
#define Crypto CryptoMbedTLS
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#include <mbedtls/base64.h>
|
||||
#include <mbedtls/bignum.h>
|
||||
#include <mbedtls/md.h>
|
||||
#include <mbedtls/aes.h>
|
||||
#include <mbedtls/pkcs5.h>
|
||||
#include <mbedtls/entropy.h>
|
||||
#include <mbedtls/ctr_drbg.h>
|
||||
|
||||
|
||||
#define DH_KEY_SIZE 96
|
||||
|
||||
static unsigned char DHPrime[] = {
|
||||
/* Well-known Group 1, 768-bit prime */
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc9,
|
||||
0x0f, 0xda, 0xa2, 0x21, 0x68, 0xc2, 0x34, 0xc4, 0xc6,
|
||||
0x62, 0x8b, 0x80, 0xdc, 0x1c, 0xd1, 0x29, 0x02, 0x4e,
|
||||
0x08, 0x8a, 0x67, 0xcc, 0x74, 0x02, 0x0b, 0xbe, 0xa6,
|
||||
0x3b, 0x13, 0x9b, 0x22, 0x51, 0x4a, 0x08, 0x79, 0x8e,
|
||||
0x34, 0x04, 0xdd, 0xef, 0x95, 0x19, 0xb3, 0xcd, 0x3a,
|
||||
0x43, 0x1b, 0x30, 0x2b, 0x0a, 0x6d, 0xf2, 0x5f, 0x14,
|
||||
0x37, 0x4f, 0xe1, 0x35, 0x6d, 0x6d, 0x51, 0xc2, 0x45,
|
||||
0xe4, 0x85, 0xb5, 0x76, 0x62, 0x5e, 0x7e, 0xc6, 0xf4,
|
||||
0x4c, 0x42, 0xe9, 0xa6, 0x3a, 0x36, 0x20, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
};
|
||||
|
||||
static unsigned char DHGenerator[1] = {2};
|
||||
|
||||
class CryptoMbedTLS {
|
||||
private:
|
||||
mbedtls_md_context_t sha1Context;
|
||||
mbedtls_aes_context aesCtx;
|
||||
public:
|
||||
CryptoMbedTLS();
|
||||
~CryptoMbedTLS();
|
||||
// Base64
|
||||
std::vector<uint8_t> base64Decode(const std::string& data);
|
||||
std::string base64Encode(const std::vector<uint8_t>& data);
|
||||
|
||||
// Sha1
|
||||
void sha1Init();
|
||||
void sha1Update(const std::string& s);
|
||||
void sha1Update(const std::vector<uint8_t>& vec);
|
||||
std::string sha1Final();
|
||||
std::vector<uint8_t> sha1FinalBytes();
|
||||
|
||||
// HMAC SHA1
|
||||
std::vector<uint8_t> sha1HMAC(const std::vector<uint8_t>& inputKey, const std::vector<uint8_t>& message);
|
||||
|
||||
// AES CTR
|
||||
void aesCTRXcrypt(const std::vector<uint8_t>& key, std::vector<uint8_t>& iv, uint8_t* data, size_t nbytes);
|
||||
|
||||
// AES ECB
|
||||
void aesECBdecrypt(const std::vector<uint8_t>& key, std::vector<uint8_t>& data);
|
||||
|
||||
// Diffie Hellman
|
||||
std::vector<uint8_t> publicKey;
|
||||
std::vector<uint8_t> privateKey;
|
||||
void dhInit();
|
||||
std::vector<uint8_t> dhCalculateShared(const std::vector<uint8_t>& remoteKey);
|
||||
|
||||
// PBKDF2
|
||||
std::vector<uint8_t> pbkdf2HmacSha1(const std::vector<uint8_t>& password, const std::vector<uint8_t>& salt, int iterations, int digestSize);
|
||||
|
||||
// Random stuff
|
||||
std::vector<uint8_t> generateVectorWithRandomData(size_t length);
|
||||
};
|
||||
|
||||
#ifdef BELL_USE_MBEDTLS
|
||||
#include "CryptoMbedTLS.h"
|
||||
#define Crypto CryptoMbedTLS
|
||||
#else
|
||||
#include "CryptoOpenSSL.h"
|
||||
#define Crypto CryptoOpenSSL
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,78 +0,0 @@
|
||||
#ifndef BELL_CRYPTOMBEDTLS_H
|
||||
#define BELL_CRYPTOMBEDTLS_H
|
||||
|
||||
#ifdef BELL_USE_MBEDTLS
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#include <mbedtls/base64.h>
|
||||
#include <mbedtls/bignum.h>
|
||||
#include <mbedtls/md.h>
|
||||
#include <mbedtls/aes.h>
|
||||
#include <mbedtls/pkcs5.h>
|
||||
#include <mbedtls/entropy.h>
|
||||
#include <mbedtls/ctr_drbg.h>
|
||||
|
||||
|
||||
#define DH_KEY_SIZE 96
|
||||
|
||||
static unsigned char DHPrime[] = {
|
||||
/* Well-known Group 1, 768-bit prime */
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc9,
|
||||
0x0f, 0xda, 0xa2, 0x21, 0x68, 0xc2, 0x34, 0xc4, 0xc6,
|
||||
0x62, 0x8b, 0x80, 0xdc, 0x1c, 0xd1, 0x29, 0x02, 0x4e,
|
||||
0x08, 0x8a, 0x67, 0xcc, 0x74, 0x02, 0x0b, 0xbe, 0xa6,
|
||||
0x3b, 0x13, 0x9b, 0x22, 0x51, 0x4a, 0x08, 0x79, 0x8e,
|
||||
0x34, 0x04, 0xdd, 0xef, 0x95, 0x19, 0xb3, 0xcd, 0x3a,
|
||||
0x43, 0x1b, 0x30, 0x2b, 0x0a, 0x6d, 0xf2, 0x5f, 0x14,
|
||||
0x37, 0x4f, 0xe1, 0x35, 0x6d, 0x6d, 0x51, 0xc2, 0x45,
|
||||
0xe4, 0x85, 0xb5, 0x76, 0x62, 0x5e, 0x7e, 0xc6, 0xf4,
|
||||
0x4c, 0x42, 0xe9, 0xa6, 0x3a, 0x36, 0x20, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
};
|
||||
|
||||
static unsigned char DHGenerator[1] = {2};
|
||||
|
||||
class CryptoMbedTLS {
|
||||
private:
|
||||
mbedtls_md_context_t sha1Context;
|
||||
mbedtls_aes_context aesCtx;
|
||||
public:
|
||||
CryptoMbedTLS();
|
||||
~CryptoMbedTLS();
|
||||
// Base64
|
||||
std::vector<uint8_t> base64Decode(const std::string& data);
|
||||
std::string base64Encode(const std::vector<uint8_t>& data);
|
||||
|
||||
// Sha1
|
||||
void sha1Init();
|
||||
void sha1Update(const std::string& s);
|
||||
void sha1Update(const std::vector<uint8_t>& vec);
|
||||
std::string sha1Final();
|
||||
std::vector<uint8_t> sha1FinalBytes();
|
||||
|
||||
// HMAC SHA1
|
||||
std::vector<uint8_t> sha1HMAC(const std::vector<uint8_t>& inputKey, const std::vector<uint8_t>& message);
|
||||
|
||||
// AES CTR
|
||||
void aesCTRXcrypt(const std::vector<uint8_t>& key, std::vector<uint8_t>& iv, uint8_t* data, size_t nbytes);
|
||||
|
||||
// AES ECB
|
||||
void aesECBdecrypt(const std::vector<uint8_t>& key, std::vector<uint8_t>& data);
|
||||
|
||||
// Diffie Hellman
|
||||
std::vector<uint8_t> publicKey;
|
||||
std::vector<uint8_t> privateKey;
|
||||
void dhInit();
|
||||
std::vector<uint8_t> dhCalculateShared(const std::vector<uint8_t>& remoteKey);
|
||||
|
||||
// PBKDF2
|
||||
std::vector<uint8_t> pbkdf2HmacSha1(const std::vector<uint8_t>& password, const std::vector<uint8_t>& salt, int iterations, int digestSize);
|
||||
|
||||
// Random stuff
|
||||
std::vector<uint8_t> generateVectorWithRandomData(size_t length);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,84 +0,0 @@
|
||||
#ifndef BELL_CRYPTOOPENSSL_H
|
||||
#define BELL_CRYPTOOPENSSL_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <openssl/engine.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/modes.h>
|
||||
|
||||
#define DH_KEY_SIZE 96
|
||||
|
||||
static unsigned char DHPrime[] = {
|
||||
/* Well-known Group 1, 768-bit prime */
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc9,
|
||||
0x0f, 0xda, 0xa2, 0x21, 0x68, 0xc2, 0x34, 0xc4, 0xc6,
|
||||
0x62, 0x8b, 0x80, 0xdc, 0x1c, 0xd1, 0x29, 0x02, 0x4e,
|
||||
0x08, 0x8a, 0x67, 0xcc, 0x74, 0x02, 0x0b, 0xbe, 0xa6,
|
||||
0x3b, 0x13, 0x9b, 0x22, 0x51, 0x4a, 0x08, 0x79, 0x8e,
|
||||
0x34, 0x04, 0xdd, 0xef, 0x95, 0x19, 0xb3, 0xcd, 0x3a,
|
||||
0x43, 0x1b, 0x30, 0x2b, 0x0a, 0x6d, 0xf2, 0x5f, 0x14,
|
||||
0x37, 0x4f, 0xe1, 0x35, 0x6d, 0x6d, 0x51, 0xc2, 0x45,
|
||||
0xe4, 0x85, 0xb5, 0x76, 0x62, 0x5e, 0x7e, 0xc6, 0xf4,
|
||||
0x4c, 0x42, 0xe9, 0xa6, 0x3a, 0x36, 0x20, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
};
|
||||
|
||||
static unsigned char DHGenerator[1] = {2};
|
||||
|
||||
class CryptoOpenSSL {
|
||||
private:
|
||||
DH* dhContext = nullptr;
|
||||
SHA_CTX sha1Context;
|
||||
public:
|
||||
CryptoOpenSSL();
|
||||
~CryptoOpenSSL();
|
||||
// Base64
|
||||
std::vector<uint8_t> base64Decode(const std::string& data);
|
||||
std::string base64Encode(const std::vector<uint8_t>& data);
|
||||
|
||||
// Sha1
|
||||
void sha1Init();
|
||||
void sha1Update(const std::string& s);
|
||||
void sha1Update(const std::vector<uint8_t>& vec);
|
||||
|
||||
void connectSSL(std::string url);
|
||||
int readSSL(uint8_t* buf, int len);
|
||||
int writeSSL(uint8_t* buf, int len);
|
||||
void closeSSL();
|
||||
|
||||
std::string sha1Final();
|
||||
std::vector<uint8_t> sha1FinalBytes();
|
||||
|
||||
// HMAC SHA1
|
||||
std::vector<uint8_t> sha1HMAC(const std::vector<uint8_t>& inputKey, const std::vector<uint8_t>& message);
|
||||
|
||||
// AES CTR
|
||||
void aesCTRXcrypt(const std::vector<uint8_t>& key, std::vector<uint8_t>& iv, uint8_t* buffer, size_t nbytes);
|
||||
|
||||
// AES ECB
|
||||
void aesECBdecrypt(const std::vector<uint8_t>& key, std::vector<uint8_t>& data);
|
||||
|
||||
// Diffie Hellman
|
||||
std::vector<uint8_t> publicKey;
|
||||
std::vector<uint8_t> privateKey;
|
||||
void dhInit();
|
||||
std::vector<uint8_t> dhCalculateShared(const std::vector<uint8_t>& remoteKey);
|
||||
|
||||
// PBKDF2
|
||||
std::vector<uint8_t> pbkdf2HmacSha1(const std::vector<uint8_t>& password, const std::vector<uint8_t>& salt, int iterations, int digestSize);
|
||||
|
||||
// Random stuff
|
||||
std::vector<uint8_t> generateVectorWithRandomData(size_t length);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "BellSocket.h"
|
||||
#include "ByteStream.h"
|
||||
#include "TCPSocket.h"
|
||||
#include "platform/TLSSocket.h"
|
||||
#include "TLSSocket.h"
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
@@ -11,16 +11,21 @@
|
||||
#include <iostream>
|
||||
#include <queue>
|
||||
#include <stdio.h>
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include "win32shim.h"
|
||||
#else
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <sstream>
|
||||
#include <BellLogger.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <fstream>
|
||||
#include <sys/socket.h>
|
||||
#include <string>
|
||||
#include <netdb.h>
|
||||
#include <mutex>
|
||||
#include <fcntl.h>
|
||||
#include "BaseHTTPServer.h"
|
||||
@@ -46,7 +51,7 @@ namespace bell
|
||||
std::map<int, HTTPConnection> connections;
|
||||
void writeResponse(const HTTPResponse &);
|
||||
void writeResponseEvents(int connFd);
|
||||
void findAndHandleRoute(std::string &, std::string &, int connectionFd);
|
||||
void findAndHandleRoute(HTTPConnection& connection);
|
||||
|
||||
std::vector<std::string> splitUrl(const std::string &url, char delimiter);
|
||||
std::mutex responseMutex;
|
||||
@@ -60,7 +65,7 @@ namespace bell
|
||||
public:
|
||||
HTTPServer(int serverPort);
|
||||
|
||||
void registerHandler(RequestType requestType, const std::string &, httpHandler);
|
||||
void registerHandler(RequestType requestType, const std::string &, httpHandler, bool readDataToStr = false);
|
||||
void respond(const HTTPResponse &);
|
||||
void redirectTo(const std::string&, int connectionFd);
|
||||
void publishEvent(std::string eventName, std::string eventData);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <ByteStream.h>
|
||||
#include <BellSocket.h>
|
||||
#include <TCPSocket.h>
|
||||
#include <platform/TLSSocket.h>
|
||||
#include <TLSSocket.h>
|
||||
|
||||
/*
|
||||
* HTTPStream
|
||||
|
||||
@@ -9,15 +9,21 @@
|
||||
#include <cstring>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include "win32shim.h"
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <netinet/tcp.h>
|
||||
#include <BellLogger.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
namespace bell
|
||||
{
|
||||
@@ -77,18 +83,23 @@ namespace bell
|
||||
}
|
||||
|
||||
size_t read(uint8_t *buf, size_t len) {
|
||||
return recv(sockFd, buf, len, 0);
|
||||
return recv(sockFd, (char*) buf, len, 0);
|
||||
}
|
||||
|
||||
size_t write(uint8_t *buf, size_t len) {
|
||||
return send(sockFd, buf, len, 0);
|
||||
return send(sockFd, (char*) buf, len, 0);
|
||||
}
|
||||
|
||||
size_t poll() {
|
||||
int value;
|
||||
ioctl(sockFd, FIONREAD, &value);
|
||||
return value;
|
||||
}
|
||||
size_t poll() {
|
||||
#ifdef _WIN32
|
||||
unsigned long value;
|
||||
ioctlsocket(sockFd, FIONREAD, &value);
|
||||
#else
|
||||
int value;
|
||||
ioctl(sockFd, FIONREAD, &value);
|
||||
#endif
|
||||
return value;
|
||||
}
|
||||
|
||||
void close() {
|
||||
if (!isClosed) {
|
||||
|
||||
@@ -8,50 +8,36 @@
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#else
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <sstream>
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
|
||||
#ifdef BELL_USE_MBEDTLS
|
||||
|
||||
#include "mbedtls/net_sockets.h"
|
||||
#include "mbedtls/ssl.h"
|
||||
#include "mbedtls/entropy.h"
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
#include "mbedtls/debug.h"
|
||||
#else
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/ssl.h>
|
||||
#endif
|
||||
|
||||
namespace bell {
|
||||
class TLSSocket : public bell::Socket {
|
||||
private:
|
||||
#ifdef BELL_USE_MBEDTLS
|
||||
mbedtls_net_context server_fd;
|
||||
mbedtls_entropy_context entropy;
|
||||
mbedtls_ctr_drbg_context ctr_drbg;
|
||||
mbedtls_ssl_context ssl;
|
||||
mbedtls_ssl_config conf;
|
||||
#else
|
||||
|
||||
BIO *sbio, *out;
|
||||
int len;
|
||||
char tmpbuf[1024];
|
||||
SSL_CTX *ctx;
|
||||
SSL *ssl;
|
||||
|
||||
int sockFd;
|
||||
int sslFd;
|
||||
#endif
|
||||
|
||||
bool isClosed = false;
|
||||
public:
|
||||
8
components/spotify/cspot/bell/include/TimeDefs.h
Normal file
8
components/spotify/cspot/bell/include/TimeDefs.h
Normal file
@@ -0,0 +1,8 @@
|
||||
//
|
||||
// Created by Filip Grzywok on 28/02/2022.
|
||||
//
|
||||
|
||||
#ifndef EUPHONIUMCLI_TIMEDEFS_H
|
||||
#define EUPHONIUMCLI_TIMEDEFS_H
|
||||
|
||||
#endif // EUPHONIUMCLI_TIMEDEFS_H
|
||||
@@ -0,0 +1,19 @@
|
||||
// Copyright (c) Kuba Szczodrzyński 2022-1-12.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BaseCodec.h"
|
||||
#include "aacdec.h"
|
||||
|
||||
class AACDecoder : public BaseCodec {
|
||||
private:
|
||||
HAACDecoder aac;
|
||||
int16_t *pcmData;
|
||||
AACFrameInfo frame = {};
|
||||
|
||||
public:
|
||||
AACDecoder();
|
||||
~AACDecoder();
|
||||
bool setup(uint32_t sampleRate, uint8_t channelCount, uint8_t bitDepth) override;
|
||||
uint8_t *decode(uint8_t *inData, uint32_t inLen, uint32_t &outLen) override;
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright (c) Kuba Szczodrzyński 2022-1-12.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BaseCodec.h"
|
||||
#include "alac_wrapper.h"
|
||||
|
||||
class ALACDecoder : public BaseCodec {
|
||||
private:
|
||||
alac_codec_s* alacCodec;
|
||||
int16_t *pcmData;
|
||||
|
||||
public:
|
||||
ALACDecoder();
|
||||
~ALACDecoder();
|
||||
bool setup(uint32_t sampleRate, uint8_t channelCount, uint8_t bitDepth) override;
|
||||
uint8_t *decode(uint8_t *inData, uint32_t inLen, uint32_t &outLen) override;
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) Kuba Szczodrzyński 2022-1-12.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BaseCodec.h"
|
||||
#include "BaseContainer.h"
|
||||
#include <memory>
|
||||
|
||||
enum class AudioCodec {
|
||||
UNKNOWN = 0,
|
||||
AAC = 1,
|
||||
MP3 = 2,
|
||||
VORBIS = 3,
|
||||
OPUS = 4,
|
||||
FLAC = 5,
|
||||
};
|
||||
|
||||
class AudioCodecs {
|
||||
public:
|
||||
static std::shared_ptr<BaseCodec> getCodec(AudioCodec type);
|
||||
static std::shared_ptr<BaseCodec> getCodec(BaseContainer *container);
|
||||
static void addCodec(AudioCodec type, const std::shared_ptr<BaseCodec> &codec);
|
||||
};
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright (c) Kuba Szczodrzyński 2022-1-12.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BaseContainer.h"
|
||||
|
||||
class BaseCodec {
|
||||
public:
|
||||
/**
|
||||
* Setup the codec (sample rate, channel count, etc) using the specified container.
|
||||
*/
|
||||
virtual bool setup(BaseContainer *container);
|
||||
/**
|
||||
* Setup the codec manually, using the provided values.
|
||||
*/
|
||||
virtual bool setup(uint32_t sampleRate, uint8_t channelCount, uint8_t bitDepth) = 0;
|
||||
/**
|
||||
* Decode the given sample.
|
||||
*
|
||||
* @param [in] inData encoded data. Should allow nullptr, in which case nullptr should be returned.
|
||||
* @param [in] inLen size of inData, in bytes
|
||||
* @param [out] outLen size of output PCM data, in bytes
|
||||
* @return pointer to decoded raw PCM audio data, allocated inside the codec object; nullptr on failure
|
||||
*/
|
||||
virtual uint8_t *decode(uint8_t *inData, uint32_t inLen, uint32_t &outLen) = 0;
|
||||
/**
|
||||
* Read a single sample from the container, decode it, and return the result.
|
||||
*
|
||||
* @param [in] container media container to read the sample from (the container's codec must match this instance)
|
||||
* @param [out] outLen size of output PCM data, in bytes
|
||||
* @return pointer to decoded raw PCM audio data, allocated inside the codec object; nullptr on failure
|
||||
*/
|
||||
uint8_t *decode(BaseContainer *container, uint32_t &outLen);
|
||||
/**
|
||||
* Last error that occurred, this is a codec-specific value.
|
||||
* This may be set by a codec upon decoding failure.
|
||||
*/
|
||||
int lastErrno = -1;
|
||||
};
|
||||
@@ -43,7 +43,7 @@ namespace bell
|
||||
}
|
||||
};
|
||||
|
||||
extern std::shared_ptr<bell::DecodersInstance> decodersInstance;
|
||||
extern bell::DecodersInstance* decodersInstance;
|
||||
|
||||
void createDecoders();
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// Copyright (c) Kuba Szczodrzyński 2022-1-14.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BaseCodec.h"
|
||||
#include "mp3dec.h"
|
||||
|
||||
class MP3Decoder : public BaseCodec {
|
||||
private:
|
||||
HMP3Decoder mp3;
|
||||
int16_t *pcmData;
|
||||
MP3FrameInfo frame = {};
|
||||
|
||||
public:
|
||||
MP3Decoder();
|
||||
~MP3Decoder();
|
||||
bool setup(uint32_t sampleRate, uint8_t channelCount, uint8_t bitDepth) override;
|
||||
uint8_t *decode(uint8_t *inData, uint32_t inLen, uint32_t &outLen) override;
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
// Copyright (c) Kuba Szczodrzyński 2022-1-14.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BaseCodec.h"
|
||||
|
||||
struct OpusDecoder;
|
||||
|
||||
class OPUSDecoder : public BaseCodec {
|
||||
private:
|
||||
OpusDecoder *opus;
|
||||
int16_t *pcmData;
|
||||
|
||||
public:
|
||||
OPUSDecoder();
|
||||
~OPUSDecoder();
|
||||
bool setup(uint32_t sampleRate, uint8_t channelCount, uint8_t bitDepth) override;
|
||||
uint8_t *decode(uint8_t *inData, uint32_t inLen, uint32_t &outLen) override;
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
// Copyright (c) Kuba Szczodrzyński 2022-1-14.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BaseCodec.h"
|
||||
#include "ivorbiscodec.h"
|
||||
|
||||
class VorbisDecoder : public BaseCodec {
|
||||
private:
|
||||
vorbis_info *vi = nullptr;
|
||||
vorbis_comment *vc = nullptr;
|
||||
vorbis_dsp_state *vd = nullptr;
|
||||
ogg_packet op = {};
|
||||
int16_t *pcmData;
|
||||
|
||||
public:
|
||||
VorbisDecoder();
|
||||
~VorbisDecoder();
|
||||
bool setup(uint32_t sampleRate, uint8_t channelCount, uint8_t bitDepth) override;
|
||||
uint8_t *decode(uint8_t *inData, uint32_t inLen, uint32_t &outLen) override;
|
||||
bool setup(BaseContainer *container) override;
|
||||
|
||||
private:
|
||||
void setPacket(uint8_t *inData, uint32_t inLen) const;
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
// Copyright (c) Kuba Szczodrzyński 2022-1-15.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BaseContainer.h"
|
||||
|
||||
class AudioContainers {
|
||||
public:
|
||||
static std::unique_ptr<BaseContainer> create(const char *mimeType);
|
||||
};
|
||||
@@ -0,0 +1,104 @@
|
||||
// Copyright (c) Kuba Szczodrzyński 2022-1-7.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BinaryReader.h"
|
||||
#include "ByteStream.h"
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
/**
|
||||
* Either the media file or the requested position/offset is not loaded yet.
|
||||
*/
|
||||
#define SAMPLE_NOT_LOADED -1
|
||||
/**
|
||||
* The media file does not contain the requested position/offset.
|
||||
*/
|
||||
#define SAMPLE_NOT_FOUND -2
|
||||
/**
|
||||
* The file is not seekable (i.e. doesn't contain an index table).
|
||||
*/
|
||||
#define SAMPLE_NOT_SEEKABLE -3
|
||||
|
||||
enum class AudioCodec;
|
||||
|
||||
class BaseContainer {
|
||||
public:
|
||||
BaseContainer() = default;
|
||||
/**
|
||||
* Feed a new data source to the container.
|
||||
* @param stream ByteStream reading source data
|
||||
* @param position absolute position of the current ByteStream within the source media
|
||||
*/
|
||||
virtual void feed(const std::shared_ptr<bell::ByteStream> &stream, uint32_t position);
|
||||
/**
|
||||
* Try to parse the media provided by the source stream.
|
||||
* @return whether parsing was successful
|
||||
*/
|
||||
virtual bool parse() = 0;
|
||||
/**
|
||||
* Get absolute offset within the source media for the given timestamp.
|
||||
* When seeking to a specified time, the caller should run feed() with a stream
|
||||
* reader starting at the returned offset. Depending on the container type,
|
||||
* the returned offset may not point to the exact time position (i.e. chunks with
|
||||
* headers), so seekTo() should be used afterwards.
|
||||
*
|
||||
* @param timeMs requested timestamp, in milliseconds
|
||||
* @return byte offset within the source media that should be loaded
|
||||
* in order to seek to the requested position; negative value on error
|
||||
*/
|
||||
virtual int32_t getLoadingOffset(uint32_t timeMs) = 0;
|
||||
/**
|
||||
* Try to seek to the specified position (in milliseconds), using the currently
|
||||
* loaded source stream. This method will fail if the source stream does not yield
|
||||
* data for the requested position, or block until the stream loads data for this position.
|
||||
*
|
||||
* @param timeMs requested timestamp, in milliseconds
|
||||
*/
|
||||
virtual bool seekTo(uint32_t timeMs) = 0;
|
||||
/**
|
||||
* Get the current playback position, in milliseconds. May return -1 if the track
|
||||
* is not playing (has ended or not started yet).
|
||||
*/
|
||||
virtual int32_t getCurrentTimeMs() = 0;
|
||||
/**
|
||||
* Read an encoded audio sample from the container, starting at the current position.
|
||||
*
|
||||
* @param [out] len length of the data stored in the returned pointer, in bytes
|
||||
* @return pointer to data allocated inside the container object; should not be freed or changed.
|
||||
* On failure, nullptr is returned, and len is left unchanged.
|
||||
*/
|
||||
virtual uint8_t *readSample(uint32_t &len) = 0;
|
||||
/**
|
||||
* Get optional initialization data for the specified codec. This may be used by a codec,
|
||||
* for containers that contain the setup data.
|
||||
*
|
||||
* @param [out] len length of the setup data
|
||||
* @return ptr to [len] setup data bytes, or nullptr if not available/not supported
|
||||
*/
|
||||
virtual uint8_t *getSetupData(uint32_t &len, AudioCodec matchCodec) = 0;
|
||||
|
||||
public:
|
||||
bool closed = false;
|
||||
bool isSeekable = false;
|
||||
// audio parameters
|
||||
AudioCodec codec = (AudioCodec)0;
|
||||
uint32_t sampleRate = 0;
|
||||
uint8_t channelCount = 0;
|
||||
uint8_t bitDepth = 0;
|
||||
uint32_t durationMs = 0;
|
||||
|
||||
protected:
|
||||
std::unique_ptr<bell::BinaryReader> reader;
|
||||
std::shared_ptr<bell::ByteStream> source;
|
||||
uint32_t pos = 0;
|
||||
uint8_t readUint8();
|
||||
uint16_t readUint16();
|
||||
uint32_t readUint24();
|
||||
uint32_t readUint32();
|
||||
uint64_t readUint64();
|
||||
uint32_t readVarint32();
|
||||
uint32_t readBytes(uint8_t *dst, uint32_t num);
|
||||
uint32_t skipBytes(uint32_t num);
|
||||
uint32_t skipTo(uint32_t offset);
|
||||
};
|
||||
@@ -0,0 +1,108 @@
|
||||
// Copyright (c) Kuba Szczodrzyński 2022-1-8.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
enum class AudioSampleFormat;
|
||||
enum class MP4AObjectType;
|
||||
enum class MP4AProfile;
|
||||
|
||||
typedef struct {
|
||||
/** Absolute offset of mdat header (or moof for fMP4) */
|
||||
uint32_t start;
|
||||
/** Absolute offset of the last mdat byte */
|
||||
uint32_t end;
|
||||
/** Total duration of this fragment */
|
||||
uint32_t duration;
|
||||
} Mpeg4Fragment;
|
||||
|
||||
typedef struct {
|
||||
/** Number of chunks this descriptor applies to */
|
||||
uint16_t count;
|
||||
/** Number of samples in the described chunks */
|
||||
uint32_t samples;
|
||||
uint16_t sampleDescriptionId;
|
||||
} Mpeg4ChunkRange;
|
||||
|
||||
/** Absolute offset of the chunk data */
|
||||
typedef uint32_t Mpeg4ChunkOffset;
|
||||
|
||||
typedef struct {
|
||||
/** Abs. offset of data start in the current chunk */
|
||||
uint32_t start;
|
||||
/** Abs. offset of data end in the current chunk */
|
||||
uint32_t end;
|
||||
/** Abs. offset of the next chunk data, or 0 for last chunk in a fragment */
|
||||
uint32_t nextStart;
|
||||
} Mpeg4Chunk;
|
||||
|
||||
typedef struct {
|
||||
/** Number of samples this descriptor applies to */
|
||||
uint32_t count;
|
||||
/** Duration of the described samples */
|
||||
uint32_t duration;
|
||||
} Mpeg4SampleRange;
|
||||
|
||||
/** Size of a single sample */
|
||||
typedef uint32_t Mpeg4SampleSize;
|
||||
|
||||
/** Flags for a sample */
|
||||
typedef uint32_t SampleFlags;
|
||||
|
||||
/** Default values for samples in the movie/fragment */
|
||||
typedef struct {
|
||||
/** Absolute offset of first mdat byte */
|
||||
uint32_t offset;
|
||||
uint32_t sampleDescriptionId;
|
||||
uint32_t duration;
|
||||
uint32_t size;
|
||||
SampleFlags flags;
|
||||
} SampleDefaults;
|
||||
|
||||
/** Sample Description Table */
|
||||
typedef struct {
|
||||
uint16_t dataReferenceIndex;
|
||||
AudioSampleFormat format;
|
||||
// params for MPEG-4 Elementary Stream Descriptors
|
||||
MP4AObjectType mp4aObjectType;
|
||||
MP4AProfile mp4aProfile;
|
||||
// atom header for unknown descriptors
|
||||
uint32_t dataType;
|
||||
// codec-specific data (either DecoderSpecificInfo or the entire descriptor)
|
||||
uint32_t dataLength;
|
||||
uint8_t *data;
|
||||
} SampleDescription;
|
||||
|
||||
typedef struct {
|
||||
// byte 1 - bits 0:7
|
||||
bool durationIsEmpty : 1;
|
||||
bool defaultBaseIsMoof : 1;
|
||||
bool dummy1 : 6;
|
||||
// byte 2 - bits 0:7
|
||||
uint8_t dummy2 : 8;
|
||||
// byte 3 - bits 0:7
|
||||
bool baseDataOffsetPresent : 1;
|
||||
bool sampleDescriptionIndexPresent : 1;
|
||||
bool dummy3 : 1;
|
||||
bool defaultSampleDurationPresent : 1;
|
||||
bool defaultSampleSizePresent : 1;
|
||||
bool defaultSampleFlagsPresent : 1;
|
||||
bool dummy4 : 2;
|
||||
} TfFlags;
|
||||
|
||||
typedef struct {
|
||||
// byte 1 - bits 0:7
|
||||
uint8_t dummy1 : 8;
|
||||
// byte 2 - bits 0:7
|
||||
bool sampleDurationPresent : 1;
|
||||
bool sampleSizePresent : 1;
|
||||
bool sampleFlagsPresent : 1;
|
||||
bool sampleCompositionTimeOffsetsPresent : 1;
|
||||
bool dummy2 : 4;
|
||||
// byte 3 - bits 0:7
|
||||
bool dataOffsetPresent : 1;
|
||||
bool dummy3 : 1;
|
||||
bool firstSampleFlagsPresent : 1;
|
||||
bool dummy4 : 5;
|
||||
} TrFlags;
|
||||
@@ -0,0 +1,114 @@
|
||||
// Copyright (c) Kuba Szczodrzyński 2022-1-8.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BaseContainer.h"
|
||||
#include "Mpeg4Atoms.h"
|
||||
#include <memory>
|
||||
|
||||
class Mpeg4Container : public BaseContainer {
|
||||
public:
|
||||
~Mpeg4Container();
|
||||
/**
|
||||
* Start parsing the MP4 file. This method expects the source to read from 0th byte.
|
||||
* This method leaves pos at first mdat data byte, or mdat header for fMP4 files.
|
||||
*/
|
||||
bool parse() override;
|
||||
int32_t getLoadingOffset(uint32_t timeMs) override;
|
||||
bool seekTo(uint32_t timeMs) override;
|
||||
int32_t getCurrentTimeMs() override;
|
||||
uint8_t *readSample(uint32_t &len) override;
|
||||
uint8_t *getSetupData(uint32_t &len, AudioCodec matchCodec) override;
|
||||
void feed(const std::shared_ptr<bell::ByteStream> &stream, uint32_t position) override;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Parse a single movie fragment. This method expects the source to read moof data, without the header.
|
||||
* After running, [pos] is left at next mdat header. A new fragment will be created if [pos] does not exist
|
||||
* in [fragments] table.
|
||||
*/
|
||||
bool parseMoof(uint32_t moofSize);
|
||||
bool goToData();
|
||||
// char mediaBrand[5];
|
||||
uint32_t totalDuration;
|
||||
bool totalDurationPresent = false;
|
||||
int8_t audioTrackId = -1;
|
||||
uint32_t timescale = 0;
|
||||
uint32_t sampleSizeMax = 0;
|
||||
uint8_t *sampleData = nullptr;
|
||||
uint32_t sampleDataLen = 0;
|
||||
bool isParsed = false;
|
||||
bool isFragmented = false;
|
||||
/** True if source reads **audio** mdat data bytes, false if source reads atom headers */
|
||||
bool isInData = false;
|
||||
|
||||
private: // data for the entire movie:
|
||||
/** All fragments in the MPEG file */
|
||||
Mpeg4Fragment *fragments;
|
||||
uint16_t fragmentsLen;
|
||||
/** Default sample descriptions for each track */
|
||||
SampleDefaults *sampleDefs;
|
||||
uint32_t sampleDefsLen;
|
||||
/** Track IDs of [sampleDef] items */
|
||||
uint32_t *sampleDefTracks;
|
||||
/** Sample Description Table */
|
||||
SampleDescription *sampleDesc;
|
||||
uint32_t sampleDescLen;
|
||||
|
||||
private: // data changing every fragment:
|
||||
/** Chunks in the current fragment */
|
||||
Mpeg4ChunkRange *chunks;
|
||||
uint32_t chunksLen;
|
||||
/** Absolute chunk offsets in the current fragment */
|
||||
Mpeg4ChunkOffset *chunkOffsets;
|
||||
uint32_t chunkOffsetsLen;
|
||||
/** All sample descriptors in the current fragment */
|
||||
Mpeg4SampleRange *samples;
|
||||
uint32_t samplesLen;
|
||||
/** All sample sizes in the current fragment */
|
||||
Mpeg4SampleSize *sampleSizes;
|
||||
uint32_t sampleSizesLen;
|
||||
|
||||
private: // current status and position within the file
|
||||
/** Currently loaded fragment (ptr) */
|
||||
Mpeg4Fragment *curFragment;
|
||||
/** The chunk currently being processed */
|
||||
Mpeg4Chunk curChunk;
|
||||
/** Size of the current sample (ptr) */
|
||||
Mpeg4SampleSize *curSampleSize;
|
||||
|
||||
private: // Mpeg4Utils.cpp
|
||||
void readAtomHeader(uint32_t &size, uint32_t &type);
|
||||
void freeAll();
|
||||
void freeFragment();
|
||||
SampleDefaults *getSampleDef(uint32_t trackId);
|
||||
void setCurrentFragment();
|
||||
void setCurrentSample();
|
||||
static bool isInFragment(Mpeg4Fragment *f, uint32_t offset);
|
||||
static AudioCodec getCodec(SampleDescription *desc);
|
||||
Mpeg4Fragment *createFragment();
|
||||
int64_t findSample(int64_t byTime, int32_t byPos, uint64_t startTime);
|
||||
|
||||
private: // Mpeg4Parser.cpp
|
||||
/** Populate [chunks] using the Sample-to-chunk Table */
|
||||
void readStsc();
|
||||
/** Populate [chunkOffsets] using the Chunk Offset Table */
|
||||
void readStco();
|
||||
/** Populate [samples] using the Time-to-sample Table */
|
||||
void readStts();
|
||||
/** Populate [sampleSizes] using the Sample Size Table */
|
||||
void readStsz();
|
||||
/** Populate [sampleDesc] using the Sample Description Table */
|
||||
void readStsd();
|
||||
|
||||
private: // Mpeg4ParserFrag.cpp
|
||||
/** Populate [fragments] using the Segment Index Table */
|
||||
void readSidx(uint32_t atomSize);
|
||||
/** Populate [sampleDefs] using Track Extends */
|
||||
void readTrex();
|
||||
/** Populate [sampleDefs] using Track Fragment Header */
|
||||
void readTfhd(uint32_t trafEnd, uint32_t moofOffset);
|
||||
/** Populate [chunks, chunkOffsets, samples, sampleSizes] using Track Fragment Run Table */
|
||||
void readTrun(uint32_t atomSize, uint32_t moofOffset);
|
||||
void allocSampleData();
|
||||
};
|
||||
@@ -0,0 +1,206 @@
|
||||
// Copyright (c) Kuba Szczodrzyński 2022-1-12.
|
||||
|
||||
#pragma once
|
||||
|
||||
enum class AtomType {
|
||||
/** File Type */
|
||||
ATOM_FTYP = 0x66747970,
|
||||
/** Movie */
|
||||
ATOM_MOOV = 0x6D6F6F76,
|
||||
/** Movie Header */
|
||||
ATOM_MVHD = 0x6D766864,
|
||||
/** Movie Extends */
|
||||
ATOM_MVEX = 0x6D766578,
|
||||
/** Movie Extends Header */
|
||||
ATOM_MEHD = 0x6D656864,
|
||||
/** Track Extends */
|
||||
ATOM_TREX = 0x74726578,
|
||||
/** Track */
|
||||
ATOM_TRAK = 0x7472616B,
|
||||
/** Track Header */
|
||||
ATOM_TKHD = 0x746B6864,
|
||||
/** Edit */
|
||||
ATOM_EDTS = 0x65647473,
|
||||
/** Edit List */
|
||||
ATOM_ELST = 0x656C7374,
|
||||
/** Media */
|
||||
ATOM_MDIA = 0x6D646961,
|
||||
/** Media Header */
|
||||
ATOM_MDHD = 0x6D646864,
|
||||
/** Handler Reference */
|
||||
ATOM_HDLR = 0x68646C72,
|
||||
/** Handler Type - Sound */
|
||||
ATOM_SOUN = 0x736F756E,
|
||||
/** Handler Type - Video */
|
||||
ATOM_VIDE = 0x76696465,
|
||||
/** Handler Type - Subtitle */
|
||||
ATOM_SUBT = 0x73756274,
|
||||
/** Media Information */
|
||||
ATOM_MINF = 0x6D696E66,
|
||||
/** Data Information */
|
||||
ATOM_DINF = 0x64696E66,
|
||||
/** Data Reference */
|
||||
ATOM_DREF = 0x64726566,
|
||||
/** Data Entry Url */
|
||||
ATOM_URL = 0x75726C20,
|
||||
/** Sample Table */
|
||||
ATOM_STBL = 0x7374626C,
|
||||
/** Sample Description */
|
||||
ATOM_STSD = 0x73747364,
|
||||
/** siDecompressionParam */
|
||||
ATOM_WAVE = 0x77617665,
|
||||
/** Format Atom */
|
||||
ATOM_FRMA = 0x66726D61,
|
||||
/** Audio Channel Layout Atom */
|
||||
ATOM_CHAN = 0x6368616E,
|
||||
/** Terminator Atom */
|
||||
ATOM_TERM = 0x00000000,
|
||||
/** MPEG-4 Elementary Stream Descriptor */
|
||||
ATOM_ESDS = 0x65736473,
|
||||
/** Time-to-sample Table */
|
||||
ATOM_STTS = 0x73747473,
|
||||
/** Sync Sample Table */
|
||||
ATOM_STSS = 0x73747373,
|
||||
/** Sample-to-chunk Table */
|
||||
ATOM_STSC = 0x73747363,
|
||||
/** Chunk Offset Table */
|
||||
ATOM_STCO = 0x7374636F,
|
||||
/** Sample Size Table */
|
||||
ATOM_STSZ = 0x7374737A,
|
||||
/** Sound Media Header */
|
||||
ATOM_SMHD = 0x736D6864,
|
||||
/** Segment Index Table */
|
||||
ATOM_SIDX = 0x73696478,
|
||||
/** Movie Fragment */
|
||||
ATOM_MOOF = 0x6D6F6F66,
|
||||
/** Movie Fragment Header */
|
||||
ATOM_MFHD = 0x6D666864,
|
||||
/** Track Fragment */
|
||||
ATOM_TRAF = 0x74726166,
|
||||
/** Track Fragment Header */
|
||||
ATOM_TFHD = 0x74666864,
|
||||
/** Track Fragment Run */
|
||||
ATOM_TRUN = 0x7472756E,
|
||||
/** Media Data */
|
||||
ATOM_MDAT = 0x6D646174,
|
||||
};
|
||||
|
||||
// These formats are the direct sub-children of the stsd atom.
|
||||
// https://mp4ra.org/#/codecs (+additions)
|
||||
enum class AudioSampleFormat {
|
||||
UNDEFINED = 0,
|
||||
A3DS = 0x61336473, // Auro-Cx 3D audio
|
||||
AC3 = 0x61632d33, // AC-3 audio
|
||||
AC4 = 0x61632d34, // AC-4 audio
|
||||
AGSM = 0x6167736d, // GSM
|
||||
ALAC = 0x616c6163, // Apple lossless audio codec
|
||||
ALAW = 0x616c6177, // a-Law
|
||||
CAVS = 0x63617673, // AVS2-P3 codec
|
||||
DRA1 = 0x64726131, // DRA Audio
|
||||
DTS_MINUS = 0x6474732d, // Dependent base layer for DTS layered audio
|
||||
DTS_PLUS = 0x6474732b, // Enhancement layer for DTS layered audio
|
||||
DTSC = 0x64747363, // Core Substream
|
||||
DTSE = 0x64747365, // Extension Substream containing only LBR
|
||||
DTSH = 0x64747368, // Core Substream + Extension Substream
|
||||
DTSL = 0x6474736c, // Extension Substream containing only XLL
|
||||
DTSX = 0x64747378, // DTS-UHD profile 2
|
||||
DTSY = 0x64747379, // DTS-UHD profile 3 or higher
|
||||
DVI = 0x64766920, // DVI (as used in RTP, 4:1 compression)
|
||||
EC3 = 0x65632d33, // Enhanced AC-3 audio
|
||||
ENCA = 0x656e6361, // Encrypted/Protected audio
|
||||
FL32 = 0x666c3332, // 32 bit float
|
||||
FL64 = 0x666c3634, // 64 bit float
|
||||
FLAC = 0x664c6143, // Free Lossless Audio Codec
|
||||
G719 = 0x67373139, // ITU-T Recommendation G.719 (2008)
|
||||
G726 = 0x67373236, // ITU-T Recommendation G.726 (1990)
|
||||
IMA4 = 0x696d6134, // IMA (International Multimedia Assocation, defunct, 4:1)
|
||||
IN24 = 0x696e3234, // 24 bit integer uncompressed
|
||||
IN32 = 0x696e3332, // 32 bit integer uncompressed
|
||||
LPCM = 0x6c70636d, // Uncompressed audio (various integer and float formats)
|
||||
M4AE = 0x6d346165, // MPEG-4 Audio Enhancement
|
||||
MHA1 = 0x6d686131, // MPEG-H Audio (single stream, unencapsulated)
|
||||
MHA2 = 0x6d686132, // MPEG-H Audio (multi-stream, unencapsulated)
|
||||
MHM1 = 0x6d686d31, // MPEG-H Audio (single stream, MHAS encapsulated)
|
||||
MHM2 = 0x6d686d32, // MPEG-H Audio (multi-stream, MHAS encapsulated)
|
||||
MLPA = 0x6d6c7061, // MLP Audio
|
||||
MP4A = 0x6d703461, // MPEG-4 Audio
|
||||
OPUS = 0x4f707573, // Opus audio coding
|
||||
QCLP = 0x51636c70, // Qualcomm PureVoice
|
||||
QDM2 = 0x51444d32, // Qdesign music 2
|
||||
QDMC = 0x51444d43, // Qdesign music 1
|
||||
RAW = 0x72617720, // Uncompressed audio
|
||||
SAMR = 0x73616d72, // Narrowband AMR voice
|
||||
SAWB = 0x73617762, // Wideband AMR voice
|
||||
SAWP = 0x73617770, // Extended AMR-WB (AMR-WB+)
|
||||
SEVC = 0x73657663, // EVRC Voice
|
||||
SEVS = 0x73657673, // Enhanced Voice Services (EVS)
|
||||
SQCP = 0x73716370, // 13K Voice
|
||||
SSMV = 0x73736d76, // SMV Voice
|
||||
TWOS = 0x74776f73, // Uncompressed 16-bit audio
|
||||
ULAW = 0x756c6177, // Samples have been compressed using uLaw 2:1.
|
||||
VDVA = 0x76647661, // DV audio (variable duration per video frame)
|
||||
};
|
||||
|
||||
// These are present in the DecoderConfigDescriptor tag in ESDS (for AudioSampleFormat::FORMAT_MP4A).
|
||||
// Source: https://mp4ra.org/#/codecs
|
||||
enum class MP4AObjectType {
|
||||
UNDEFINED = 0,
|
||||
_13K = 0xE1, // 13K Voice
|
||||
AAC_LC = 0x67, // ISO/IEC 13818-7 (AAC) Low Complexity Profile
|
||||
AAC_MAIN = 0x66, // ISO/IEC 13818-7 (AAC) Main Profile
|
||||
AAC_SSR = 0x68, // ISO/IEC 13818-7 (AAC) Scaleable Sampling Rate Profile
|
||||
AC3 = 0xA5, // AC-3
|
||||
AC3_ENH = 0xA6, // Enhanced AC-3
|
||||
AC4 = 0xAE, // AC-4
|
||||
AURO_CX_3D = 0xAF, // Auro-Cx 3D audio
|
||||
DRA = 0xA7, // DRA Audio
|
||||
DTS_CORE = 0xA9, // Core Substream
|
||||
DTS_CORE_EXT = 0xAA, // Core Substream + Extension Substream
|
||||
DTS_LBR = 0xAC, // Extension Substream containing only LBR
|
||||
DTS_UHD2 = 0xB2, // DTS-UHD profile 2
|
||||
DTS_UHD3 = 0xB3, // DTS-UHD profile 3 or higher
|
||||
DTS_XLL = 0xAB, // Extension Substream containing only XLL
|
||||
EVRC = 0xA0, // EVRC Voice
|
||||
G719 = 0xA8, // ITU G.719 Audio
|
||||
MP4A = 0x40, // ISO/IEC 14496-3 (MPEG-4 Audio)
|
||||
MPEG1 = 0x6B, // ISO/IEC 11172-3 (MPEG-1 Part 3)
|
||||
MPEG2 = 0x69, // ISO/IEC 13818-3 (MPEG-2 Part 3)
|
||||
OPUS = 0xAD, // Opus audio
|
||||
SMV = 0xA1, // SMV Voice
|
||||
VORBIS = 0xDD, // Vorbis
|
||||
};
|
||||
|
||||
// These are present in the DecoderSpecificInfo tag in ESDS (for MP4AObjectType::TYPE_MP4A).
|
||||
// Source: https://wiki.multimedia.cx/index.php/MPEG-4_Audio
|
||||
enum class MP4AProfile {
|
||||
UNDEFINED = 0,
|
||||
AAC_MAIN = 1, // AAC main
|
||||
AAC_LC = 2, // AAC LC
|
||||
AAC_SSR = 3, // AAC SSR
|
||||
AAC_LTP = 4, // AAC LTP
|
||||
SBR = 5, // SBR
|
||||
AAC_SCALABLE = 6, // AAC Scalable
|
||||
TWINVQ = 7, // TwinVQ
|
||||
CELP = 8, // CELP
|
||||
HVXC = 9, // HVXC
|
||||
TTSI = 12, // TTSI
|
||||
MAIN_SYNTHETIC = 13, // Main synthetic
|
||||
WAVETABLE_SYNTHESIS = 14, // Wavetable synthesis
|
||||
GENERAL_MIDI = 15, // General MIDI
|
||||
ALGORITHMIC_SYNTHESIS_AND_AUDIO_FX = 16, // Algorithmic Synthesis and Audio FX
|
||||
ER_AAC_LC = 17, // ER AAC LC
|
||||
ER_AAC_LTP = 19, // ER AAC LTP
|
||||
ER_AAC_SCALABLE = 20, // ER AAC Scalable
|
||||
ER_TWINVQ = 21, // ER TwinVQ
|
||||
ER_BSAC = 22, // ER BSAC
|
||||
ER_AAC_LD = 23, // ER AAC LD
|
||||
ER_CELP = 24, // ER CELP
|
||||
ER_HVXC = 25, // ER HVXC
|
||||
ER_HILN = 26, // ER HILN
|
||||
ER_PARAMETRIC = 27, // ER Parametric
|
||||
SSC = 28, // SSC
|
||||
LAYER_1 = 32, // Layer-1
|
||||
LAYER_2 = 33, // Layer-2
|
||||
LAYER_3 = 34, // Layer-3
|
||||
DST = 35, // DST
|
||||
};
|
||||
@@ -0,0 +1,81 @@
|
||||
// Copyright (c) Kuba Szczodrzyński 2022-1-16.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BaseContainer.h"
|
||||
|
||||
enum class ElementId;
|
||||
|
||||
class WebmContainer : public BaseContainer {
|
||||
public:
|
||||
~WebmContainer();
|
||||
bool parse() override;
|
||||
int32_t getLoadingOffset(uint32_t timeMs) override;
|
||||
bool seekTo(uint32_t timeMs) override;
|
||||
int32_t getCurrentTimeMs() override;
|
||||
uint8_t *readSample(uint32_t &len) override;
|
||||
uint8_t *getSetupData(uint32_t &len, AudioCodec matchCodec) override;
|
||||
void feed(const std::shared_ptr<bell::ByteStream> &stream, uint32_t position) override;
|
||||
|
||||
private:
|
||||
typedef struct {
|
||||
uint32_t time;
|
||||
uint32_t offset;
|
||||
} CuePoint;
|
||||
|
||||
private:
|
||||
// used while parsing
|
||||
uint32_t esize;
|
||||
ElementId eid;
|
||||
// container parameters
|
||||
char *docType = nullptr;
|
||||
uint8_t audioTrackId = 255;
|
||||
float timescale = 0.0f;
|
||||
char *codecId = nullptr;
|
||||
uint8_t *codecPrivate = nullptr;
|
||||
uint32_t codecPrivateLen = 0;
|
||||
// container state
|
||||
CuePoint *cues = nullptr;
|
||||
uint16_t cuesLen = 0;
|
||||
uint32_t clusterEnd = 0;
|
||||
uint32_t clusterTime = 0;
|
||||
uint32_t currentTime = 0;
|
||||
bool isParsed = false;
|
||||
// buffer
|
||||
uint8_t *sampleData = nullptr;
|
||||
uint32_t sampleLen = 0;
|
||||
// lacing parameters
|
||||
uint32_t *laceSizes = nullptr;
|
||||
uint32_t *laceCurrent = nullptr;
|
||||
uint8_t laceLeft = 0;
|
||||
// set to read the current buffer instead of loading new frames
|
||||
uint16_t readOutFrameSize = 0;
|
||||
|
||||
private:
|
||||
uint32_t readVarNum32(bool raw = false);
|
||||
uint64_t readVarNum64();
|
||||
uint32_t readUint(uint8_t len);
|
||||
uint64_t readUlong(uint8_t len);
|
||||
float readFloat(uint8_t len);
|
||||
void readElem();
|
||||
void parseSegment(uint32_t start);
|
||||
void parseTrack(uint32_t end);
|
||||
void parseCuePoint(uint16_t idx, uint32_t end, uint32_t segmentStart);
|
||||
/**
|
||||
* Continue reading elements until a block is encountered.
|
||||
*
|
||||
* If [untilTime] is set, the method will keep reading until [currentTime]
|
||||
* is less than [untilTime]. Because of how WebM works, [pos] will be one frame later
|
||||
* than the requested time, although the container will report the correct position.
|
||||
*
|
||||
* @return size of the frame pointed by [pos]
|
||||
*/
|
||||
uint32_t readCluster(uint32_t untilTime = 0);
|
||||
/**
|
||||
* Parse a single block within a cluster. This method will populate lacing parameters if needed.
|
||||
* @param end offset of the next byte after this block
|
||||
* @return size of the frame pointed by [pos]
|
||||
*/
|
||||
uint32_t readBlock(uint32_t end);
|
||||
uint8_t *readFrame(uint32_t size, uint32_t &outLen);
|
||||
};
|
||||
@@ -0,0 +1,713 @@
|
||||
// Copyright (c) Kuba Szczodrzyński 2022-1-16.
|
||||
|
||||
#pragma once
|
||||
|
||||
enum class ElementId {
|
||||
/** [sub-elements] Set the EBML characteristics of the data to follow. Each EBML document has to start with this. */
|
||||
EBML = 0x1A45DFA3,
|
||||
/** [u-integer] The version of EBML parser used to create the file. */
|
||||
EBMLVersion = 0x4286,
|
||||
/** [u-integer] The minimum EBML version a parser has to support to read this file. */
|
||||
EBMLReadVersion = 0x42F7,
|
||||
/** [u-integer] The maximum length of the IDs you'll find in this file (4 or less in Matroska). */
|
||||
EBMLMaxIDLength = 0x42F2,
|
||||
/** [u-integer] The maximum length of the sizes you'll find in this file (8 or less in Matroska). This does not
|
||||
override the element size indicated at the beginning of an element. Elements that have an indicated size which is
|
||||
larger than what is allowed by EBMLMaxSizeLength shall be considered invalid. */
|
||||
EBMLMaxSizeLength = 0x42F3,
|
||||
/** [string] A string that describes the type of document that follows this EBML header ('matroska' in our case). */
|
||||
DocType = 0x4282,
|
||||
/** [u-integer] The version of DocType interpreter used to create the file. */
|
||||
DocTypeVersion = 0x4287,
|
||||
/** [u-integer] The minimum DocType version an interpreter has to support to read this file. */
|
||||
DocTypeReadVersion = 0x4285,
|
||||
/** [binary] The CRC is computed on all the data from the last CRC element (or start of the upper level element), up
|
||||
to the CRC element, including other previous CRC elements. All level 1 elements should include a CRC-32. */
|
||||
CRC32 = 0xBF,
|
||||
/** [binary] Used to void damaged data, to avoid unexpected behaviors when using damaged data. The content is
|
||||
discarded. Also used to reserve space in a sub-element for later use. */
|
||||
Void = 0xEC,
|
||||
/** [sub-elements] Contain signature of some (coming) elements in the stream. */
|
||||
SignatureSlot = 0x1B538667,
|
||||
/** [u-integer] Signature algorithm used (1=RSA, 2=elliptic). */
|
||||
SignatureAlgo = 0x7E8A,
|
||||
/** [u-integer] Hash algorithm used (1=SHA1-160, 2=MD5). */
|
||||
SignatureHash = 0x7E9A,
|
||||
/** [binary] The public key to use with the algorithm (in the case of a PKI-based signature). */
|
||||
SignaturePublicKey = 0x7EA5,
|
||||
/** [binary] The signature of the data (until a new. */
|
||||
Signature = 0x7EB5,
|
||||
/** [sub-elements] Contains elements that will be used to compute the signature. */
|
||||
SignatureElements = 0x7E5B,
|
||||
/** [sub-elements] A list consists of a number of consecutive elements that represent one case where data is used in
|
||||
signature. Ex: Cluster|Block|BlockAdditional means that the BlockAdditional of all Blocks in all Clusters is used
|
||||
for encryption. */
|
||||
SignatureElementList = 0x7E7B,
|
||||
/** [binary] An element ID whose data will be used to compute the signature. */
|
||||
SignedElement = 0x6532,
|
||||
|
||||
/* ebml_matroska.xml */
|
||||
/** [master] The Root Element that contains all other Top-Level Elements (Elements defined only at Level 1). A
|
||||
Matroska file is composed of 1 Segment. */
|
||||
Segment = 0x18538067,
|
||||
/** [master] Contains the Segment Position of other Top-Level Elements. */
|
||||
SeekHead = 0x114D9B74,
|
||||
/** [master] Contains a single seek entry to an EBML Element. */
|
||||
Seek = 0x4DBB,
|
||||
/** [binary] The binary ID corresponding to the Element name. */
|
||||
SeekID = 0x53AB,
|
||||
/** [uinteger] The Segment Position of the Element. */
|
||||
SeekPosition = 0x53AC,
|
||||
/** [master] Contains general information about the Segment. */
|
||||
Info = 0x1549A966,
|
||||
/** [binary] A randomly generated unique ID to identify the Segment amongst many others (128 bits). */
|
||||
SegmentUID = 0x73A4,
|
||||
/** [utf-8] A filename corresponding to this Segment. */
|
||||
SegmentFilename = 0x7384,
|
||||
/** [binary] A unique ID to identify the previous Segment of a Linked Segment (128 bits). */
|
||||
PrevUID = 0x3CB923,
|
||||
/** [utf-8] A filename corresponding to the file of the previous Linked Segment. */
|
||||
PrevFilename = 0x3C83AB,
|
||||
/** [binary] A unique ID to identify the next Segment of a Linked Segment (128 bits). */
|
||||
NextUID = 0x3EB923,
|
||||
/** [utf-8] A filename corresponding to the file of the next Linked Segment. */
|
||||
NextFilename = 0x3E83BB,
|
||||
/** [binary] A randomly generated unique ID that all Segments of a Linked Segment **MUST** share (128 bits). */
|
||||
SegmentFamily = 0x4444,
|
||||
/** [master] The mapping between this `Segment` and a segment value in the given Chapter Codec. */
|
||||
ChapterTranslate = 0x6924,
|
||||
/** [binary] The binary value used to represent this Segment in the chapter codec data. The format depends on the
|
||||
ChapProcessCodecID used; see (#chapprocesscodecid-element). */
|
||||
ChapterTranslateID = 0x69A5,
|
||||
/** [uinteger] This `ChapterTranslate` applies to this chapter codec of the given chapter edition(s); see
|
||||
(#chapprocesscodecid-element). */
|
||||
ChapterTranslateCodec = 0x69BF,
|
||||
/** [uinteger] Specify a chapter edition UID on which this `ChapterTranslate` applies. */
|
||||
ChapterTranslateEditionUID = 0x69FC,
|
||||
/** [uinteger] Timestamp scale in nanoseconds (1.000.000 means all timestamps in the Segment are expressed in
|
||||
milliseconds). */
|
||||
TimestampScale = 0x2AD7B1,
|
||||
/** [float] Duration of the Segment in nanoseconds based on TimestampScale. */
|
||||
Duration = 0x4489,
|
||||
/** [date] The date and time that the Segment was created by the muxing application or library. */
|
||||
DateUTC = 0x4461,
|
||||
/** [utf-8] General name of the Segment. */
|
||||
Title = 0x7BA9,
|
||||
/** [utf-8] Muxing application or library (example: "libmatroska-0.4.3"). */
|
||||
MuxingApp = 0x4D80,
|
||||
/** [utf-8] Writing application (example: "mkvmerge-0.3.3"). */
|
||||
WritingApp = 0x5741,
|
||||
/** [master] The Top-Level Element containing the (monolithic) Block structure. */
|
||||
Cluster = 0x1F43B675,
|
||||
/** [uinteger] Absolute timestamp of the cluster (based on TimestampScale). */
|
||||
Timestamp = 0xE7,
|
||||
/** [master] The list of tracks that are not used in that part of the stream. It is useful when using overlay tracks
|
||||
on seeking or to decide what track to use. */
|
||||
SilentTracks = 0x5854,
|
||||
/** [uinteger] One of the track number that are not used from now on in the stream. It could change later if not
|
||||
specified as silent in a further Cluster. */
|
||||
SilentTrackNumber = 0x58D7,
|
||||
/** [uinteger] The Segment Position of the Cluster in the Segment (0 in live streams). It might help to
|
||||
resynchronise offset on damaged streams. */
|
||||
Position = 0xA7,
|
||||
/** [uinteger] Size of the previous Cluster, in octets. Can be useful for backward playing. */
|
||||
PrevSize = 0xAB,
|
||||
/** [binary] Similar to Block, see (#block-structure), but without all the extra information, mostly used to reduced
|
||||
overhead when no extra feature is needed; see (#simpleblock-structure) on SimpleBlock Structure. */
|
||||
SimpleBlock = 0xA3,
|
||||
/** [master] Basic container of information containing a single Block and information specific to that Block. */
|
||||
BlockGroup = 0xA0,
|
||||
/** [binary] Block containing the actual data to be rendered and a timestamp relative to the Cluster Timestamp; see
|
||||
(#block-structure) on Block Structure. */
|
||||
Block = 0xA1,
|
||||
/** [binary] A Block with no data. It **MUST** be stored in the stream at the place the real Block would be in
|
||||
display order. */
|
||||
BlockVirtual = 0xA2,
|
||||
/** [master] Contain additional blocks to complete the main one. An EBML parser that has no knowledge of the Block
|
||||
structure could still see and use/skip these data. */
|
||||
BlockAdditions = 0x75A1,
|
||||
/** [master] Contain the BlockAdditional and some parameters. */
|
||||
BlockMore = 0xA6,
|
||||
/** [uinteger] An ID to identify the BlockAdditional level. If BlockAddIDType of the corresponding block is 0, this
|
||||
value is also the value of BlockAddIDType for the meaning of the content of BlockAdditional. */
|
||||
BlockAddID = 0xEE,
|
||||
/** [binary] Interpreted by the codec as it wishes (using the BlockAddID). */
|
||||
BlockAdditional = 0xA5,
|
||||
/** [uinteger] The duration of the Block (based on TimestampScale). The BlockDuration Element can be useful at the
|
||||
end of a Track to define the duration of the last frame (as there is no subsequent Block available), or when
|
||||
there is a break in a track like for subtitle tracks. */
|
||||
BlockDuration = 0x9B,
|
||||
/** [uinteger] This frame is referenced and has the specified cache priority. In cache only a frame of the same or
|
||||
higher priority can replace this frame. A value of 0 means the frame is not referenced. */
|
||||
ReferencePriority = 0xFA,
|
||||
/** [integer] A timestamp value, relative to the timestamp of the Block in this BlockGroup. This is used to
|
||||
reference other frames necessary to decode this frame. The relative value **SHOULD** correspond to a valid
|
||||
`Block` this `Block` depends on. Historically Matroska Writer didn't write the actual `Block(s)` this `Block`
|
||||
depends on, but *some* `Block` in the past. The value "0" **MAY** also be used to signify this `Block` cannot be
|
||||
decoded on its own, but without knownledge of which `Block` is necessary. In this case, other `ReferenceBlock`
|
||||
**MUST NOT** be found in the same `BlockGroup`. If the `BlockGroup` doesn't have any `ReferenceBlock` element,
|
||||
then the `Block` it contains can be decoded without using any other `Block` data. */
|
||||
ReferenceBlock = 0xFB,
|
||||
/** [integer] The Segment Position of the data that would otherwise be in position of the virtual block. */
|
||||
ReferenceVirtual = 0xFD,
|
||||
/** [binary] The new codec state to use. Data interpretation is private to the codec. This information **SHOULD**
|
||||
always be referenced by a seek entry. */
|
||||
CodecState = 0xA4,
|
||||
/** [integer] Duration in nanoseconds of the silent data added to the Block (padding at the end of the Block for
|
||||
positive value, at the beginning of the Block for negative value). The duration of DiscardPadding is not
|
||||
calculated in the duration of the TrackEntry and **SHOULD** be discarded during playback. */
|
||||
DiscardPadding = 0x75A2,
|
||||
/** [master] Contains slices description. */
|
||||
Slices = 0x8E,
|
||||
/** [master] Contains extra time information about the data contained in the Block. Being able to interpret this
|
||||
Element is not **REQUIRED** for playback. */
|
||||
TimeSlice = 0xE8,
|
||||
/** [uinteger] The reverse number of the frame in the lace (0 is the last frame, 1 is the next to last, etc). Being
|
||||
able to interpret this Element is not **REQUIRED** for playback. */
|
||||
LaceNumber = 0xCC,
|
||||
/** [uinteger] The number of the frame to generate from this lace with this delay (allow you to generate many frames
|
||||
from the same Block/Frame). */
|
||||
FrameNumber = 0xCD,
|
||||
/** [uinteger] The ID of the BlockAdditional Element (0 is the main Block). */
|
||||
BlockAdditionID = 0xCB,
|
||||
/** [uinteger] The (scaled) delay to apply to the Element. */
|
||||
Delay = 0xCE,
|
||||
/** [uinteger] The (scaled) duration to apply to the Element. */
|
||||
SliceDuration = 0xCF,
|
||||
/** [master] Contains information about the last reference frame. See [@?DivXTrickTrack]. */
|
||||
ReferenceFrame = 0xC8,
|
||||
/** [uinteger] The relative offset, in bytes, from the previous BlockGroup element for this Smooth FF/RW video track
|
||||
to the containing BlockGroup element. See [@?DivXTrickTrack]. */
|
||||
ReferenceOffset = 0xC9,
|
||||
/** [uinteger] The timecode of the BlockGroup pointed to by ReferenceOffset. See [@?DivXTrickTrack]. */
|
||||
ReferenceTimestamp = 0xCA,
|
||||
/** [binary] Similar to SimpleBlock, see (#simpleblock-structure), but the data inside the Block are Transformed
|
||||
(encrypt and/or signed). */
|
||||
EncryptedBlock = 0xAF,
|
||||
/** [master] A Top-Level Element of information with many tracks described. */
|
||||
Tracks = 0x1654AE6B,
|
||||
/** [master] Describes a track with all Elements. */
|
||||
TrackEntry = 0xAE,
|
||||
/** [uinteger] The track number as used in the Block Header (using more than 127 tracks is not encouraged, though
|
||||
the design allows an unlimited number). */
|
||||
TrackNumber = 0xD7,
|
||||
/** [uinteger] A unique ID to identify the Track. */
|
||||
TrackUID = 0x73C5,
|
||||
/** [uinteger] The `TrackType` defines the type of each frame found in the Track. The value **SHOULD** be stored on
|
||||
1 octet. */
|
||||
TrackType = 0x83,
|
||||
/** [uinteger] Set to 1 if the track is usable. It is possible to turn a not usable track into a usable track using
|
||||
chapter codecs or control tracks. */
|
||||
FlagEnabled = 0xB9,
|
||||
/** [uinteger] Set if that track (audio, video or subs) **SHOULD** be eligible for automatic selection by the
|
||||
player; see (#default-track-selection) for more details. */
|
||||
FlagDefault = 0x88,
|
||||
/** [uinteger] Applies only to subtitles. Set if that track **SHOULD** be eligible for automatic selection by the
|
||||
player if it matches the user's language preference, even if the user's preferences would normally not enable
|
||||
subtitles with the selected audio track; this can be used for tracks containing only translations of
|
||||
foreign-language audio or onscreen text. See (#default-track-selection) for more details. */
|
||||
FlagForced = 0x55AA,
|
||||
/** [uinteger] Set to 1 if that track is suitable for users with hearing impairments, set to 0 if it is unsuitable
|
||||
for users with hearing impairments. */
|
||||
FlagHearingImpaired = 0x55AB,
|
||||
/** [uinteger] Set to 1 if that track is suitable for users with visual impairments, set to 0 if it is unsuitable
|
||||
for users with visual impairments. */
|
||||
FlagVisualImpaired = 0x55AC,
|
||||
/** [uinteger] Set to 1 if that track contains textual descriptions of video content, set to 0 if that track does
|
||||
not contain textual descriptions of video content. */
|
||||
FlagTextDescriptions = 0x55AD,
|
||||
/** [uinteger] Set to 1 if that track is in the content's original language, set to 0 if it is a translation. */
|
||||
FlagOriginal = 0x55AE,
|
||||
/** [uinteger] Set to 1 if that track contains commentary, set to 0 if it does not contain commentary. */
|
||||
FlagCommentary = 0x55AF,
|
||||
/** [uinteger] Set to 1 if the track **MAY** contain blocks using lacing. When set to 0 all blocks **MUST** have
|
||||
their lacing flags set to No lacing; see (#block-lacing) on Block Lacing. */
|
||||
FlagLacing = 0x9C,
|
||||
/** [uinteger] The minimum number of frames a player **SHOULD** be able to cache during playback. If set to 0, the
|
||||
reference pseudo-cache system is not used. */
|
||||
MinCache = 0x6DE7,
|
||||
/** [uinteger] The maximum cache size necessary to store referenced frames in and the current frame. 0 means no
|
||||
cache is needed. */
|
||||
MaxCache = 0x6DF8,
|
||||
/** [uinteger] Number of nanoseconds (not scaled via TimestampScale) per frame (frame in the Matroska sense -- one
|
||||
Element put into a (Simple)Block). */
|
||||
DefaultDuration = 0x23E383,
|
||||
/** [uinteger] The period in nanoseconds (not scaled by TimestampScale) between two successive fields at the output
|
||||
of the decoding process, see (#defaultdecodedfieldduration) for more information */
|
||||
DefaultDecodedFieldDuration = 0x234E7A,
|
||||
/** [float] DEPRECATED, DO NOT USE. The scale to apply on this track to work at normal speed in relation with other
|
||||
tracks (mostly used to adjust video speed when the audio length differs). */
|
||||
TrackTimestampScale = 0x23314F,
|
||||
/** [integer] A value to add to the Block's Timestamp. This can be used to adjust the playback offset of a track. */
|
||||
TrackOffset = 0x537F,
|
||||
/** [uinteger] The maximum value of BlockAddID ((#blockaddid-element)). A value 0 means there is no BlockAdditions
|
||||
((#blockadditions-element)) for this track. */
|
||||
MaxBlockAdditionID = 0x55EE,
|
||||
/** [master] Contains elements that extend the track format, by adding content either to each frame, with BlockAddID
|
||||
((#blockaddid-element)), or to the track as a whole with BlockAddIDExtraData. */
|
||||
BlockAdditionMapping = 0x41E4,
|
||||
/** [uinteger] If the track format extension needs content beside frames, the value refers to the BlockAddID
|
||||
((#blockaddid-element)), value being described. To keep MaxBlockAdditionID as low as possible, small values
|
||||
**SHOULD** be used. */
|
||||
BlockAddIDValue = 0x41F0,
|
||||
/** [string] A human-friendly name describing the type of BlockAdditional data, as defined by the associated Block
|
||||
Additional Mapping. */
|
||||
BlockAddIDName = 0x41A4,
|
||||
/** [uinteger] Stores the registered identifier of the Block Additional Mapping to define how the BlockAdditional
|
||||
data should be handled. */
|
||||
BlockAddIDType = 0x41E7,
|
||||
/** [binary] Extra binary data that the BlockAddIDType can use to interpret the BlockAdditional data. The
|
||||
interpretation of the binary data depends on the BlockAddIDType value and the corresponding Block Additional
|
||||
Mapping. */
|
||||
BlockAddIDExtraData = 0x41ED,
|
||||
/** [utf-8] A human-readable track name. */
|
||||
Name = 0x536E,
|
||||
/** [string] Specifies the language of the track in the Matroska languages form; see (#language-codes) on language
|
||||
codes. This Element **MUST** be ignored if the LanguageIETF Element is used in the same TrackEntry. */
|
||||
Language = 0x22B59C,
|
||||
/** [string] Specifies the language of the track according to [@!BCP47] and using the IANA Language Subtag Registry
|
||||
[@!IANALangRegistry]. If this Element is used, then any Language Elements used in the same TrackEntry **MUST** be
|
||||
ignored. */
|
||||
LanguageIETF = 0x22B59D,
|
||||
/** [string] An ID corresponding to the codec, see [@!MatroskaCodec] for more info. */
|
||||
CodecID = 0x86,
|
||||
/** [binary] Private data only known to the codec. */
|
||||
CodecPrivate = 0x63A2,
|
||||
/** [utf-8] A human-readable string specifying the codec. */
|
||||
CodecName = 0x258688,
|
||||
/** [uinteger] The UID of an attachment that is used by this codec. */
|
||||
AttachmentLink = 0x7446,
|
||||
/** [utf-8] A string describing the encoding setting used. */
|
||||
CodecSettings = 0x3A9697,
|
||||
/** [string] A URL to find information about the codec used. */
|
||||
CodecInfoURL = 0x3B4040,
|
||||
/** [string] A URL to download about the codec used. */
|
||||
CodecDownloadURL = 0x26B240,
|
||||
/** [uinteger] Set to 1 if the codec can decode potentially damaged data. */
|
||||
CodecDecodeAll = 0xAA,
|
||||
/** [uinteger] Specify that this track is an overlay track for the Track specified (in the u-integer). That means
|
||||
when this track has a gap, see (#silenttracks-element) on SilentTracks, the overlay track **SHOULD** be used
|
||||
instead. The order of multiple TrackOverlay matters, the first one is the one that **SHOULD** be used. If not
|
||||
found it **SHOULD** be the second, etc. */
|
||||
TrackOverlay = 0x6FAB,
|
||||
/** [uinteger] CodecDelay is The codec-built-in delay in nanoseconds. This value **MUST** be subtracted from each
|
||||
block timestamp in order to get the actual timestamp. The value **SHOULD** be small so the muxing of tracks with
|
||||
the same actual timestamp are in the same Cluster. */
|
||||
CodecDelay = 0x56AA,
|
||||
/** [uinteger] After a discontinuity, SeekPreRoll is the duration in nanoseconds of the data the decoder **MUST**
|
||||
decode before the decoded data is valid. */
|
||||
SeekPreRoll = 0x56BB,
|
||||
/** [master] The mapping between this `TrackEntry` and a track value in the given Chapter Codec. */
|
||||
TrackTranslate = 0x6624,
|
||||
/** [binary] The binary value used to represent this `TrackEntry` in the chapter codec data. The format depends on
|
||||
the `ChapProcessCodecID` used; see (#chapprocesscodecid-element). */
|
||||
TrackTranslateTrackID = 0x66A5,
|
||||
/** [uinteger] This `TrackTranslate` applies to this chapter codec of the given chapter edition(s); see
|
||||
(#chapprocesscodecid-element). */
|
||||
TrackTranslateCodec = 0x66BF,
|
||||
/** [uinteger] Specify a chapter edition UID on which this `TrackTranslate` applies. */
|
||||
TrackTranslateEditionUID = 0x66FC,
|
||||
/** [master] Video settings. */
|
||||
Video = 0xE0,
|
||||
/** [uinteger] Specify whether the video frames in this track are interlaced or not. */
|
||||
FlagInterlaced = 0x9A,
|
||||
/** [uinteger] Specify the field ordering of video frames in this track. */
|
||||
FieldOrder = 0x9D,
|
||||
/** [uinteger] Stereo-3D video mode. There are some more details in (#multi-planar-and-3d-videos). */
|
||||
StereoMode = 0x53B8,
|
||||
/** [uinteger] Alpha Video Mode. Presence of this Element indicates that the BlockAdditional Element could contain
|
||||
Alpha data. */
|
||||
AlphaMode = 0x53C0,
|
||||
/** [uinteger] DEPRECATED, DO NOT USE. Bogus StereoMode value used in old versions of libmatroska. */
|
||||
OldStereoMode = 0x53B9,
|
||||
/** [uinteger] Width of the encoded video frames in pixels. */
|
||||
PixelWidth = 0xB0,
|
||||
/** [uinteger] Height of the encoded video frames in pixels. */
|
||||
PixelHeight = 0xBA,
|
||||
/** [uinteger] The number of video pixels to remove at the bottom of the image. */
|
||||
PixelCropBottom = 0x54AA,
|
||||
/** [uinteger] The number of video pixels to remove at the top of the image. */
|
||||
PixelCropTop = 0x54BB,
|
||||
/** [uinteger] The number of video pixels to remove on the left of the image. */
|
||||
PixelCropLeft = 0x54CC,
|
||||
/** [uinteger] The number of video pixels to remove on the right of the image. */
|
||||
PixelCropRight = 0x54DD,
|
||||
/** [uinteger] Width of the video frames to display. Applies to the video frame after cropping (PixelCrop*
|
||||
Elements). */
|
||||
DisplayWidth = 0x54B0,
|
||||
/** [uinteger] Height of the video frames to display. Applies to the video frame after cropping (PixelCrop*
|
||||
Elements). */
|
||||
DisplayHeight = 0x54BA,
|
||||
/** [uinteger] How DisplayWidth & DisplayHeight are interpreted. */
|
||||
DisplayUnit = 0x54B2,
|
||||
/** [uinteger] Specify the possible modifications to the aspect ratio. */
|
||||
AspectRatioType = 0x54B3,
|
||||
/** [binary] Specify the uncompressed pixel format used for the Track's data as a FourCC. This value is similar in
|
||||
scope to the biCompression value of AVI's `BITMAPINFO` [@?AVIFormat]. See the YUV video formats [@?FourCC-YUV]
|
||||
and RGB video formats [@?FourCC-RGB] for common values. */
|
||||
UncompressedFourCC = 0x2EB524,
|
||||
/** [float] Gamma Value. */
|
||||
GammaValue = 0x2FB523,
|
||||
/** [float] Number of frames per second. This value is Informational only. It is intended for constant frame rate
|
||||
streams, and **SHOULD NOT** be used for a variable frame rate TrackEntry. */
|
||||
FrameRate = 0x2383E3,
|
||||
/** [master] Settings describing the colour format. */
|
||||
Colour = 0x55B0,
|
||||
/** [uinteger] The Matrix Coefficients of the video used to derive luma and chroma values from red, green, and blue
|
||||
color primaries. For clarity, the value and meanings for MatrixCoefficients are adopted from Table 4 of ISO/IEC
|
||||
23001-8:2016 or ITU-T H.273. */
|
||||
MatrixCoefficients = 0x55B1,
|
||||
/** [uinteger] Number of decoded bits per channel. A value of 0 indicates that the BitsPerChannel is unspecified. */
|
||||
BitsPerChannel = 0x55B2,
|
||||
/** [uinteger] The amount of pixels to remove in the Cr and Cb channels for every pixel not removed horizontally.
|
||||
Example: For video with 4:2:0 chroma subsampling, the ChromaSubsamplingHorz **SHOULD** be set to 1. */
|
||||
ChromaSubsamplingHorz = 0x55B3,
|
||||
/** [uinteger] The amount of pixels to remove in the Cr and Cb channels for every pixel not removed vertically.
|
||||
Example: For video with 4:2:0 chroma subsampling, the ChromaSubsamplingVert **SHOULD** be set to 1. */
|
||||
ChromaSubsamplingVert = 0x55B4,
|
||||
/** [uinteger] The amount of pixels to remove in the Cb channel for every pixel not removed horizontally. This is
|
||||
additive with ChromaSubsamplingHorz. Example: For video with 4:2:1 chroma subsampling, the ChromaSubsamplingHorz
|
||||
**SHOULD** be set to 1 and CbSubsamplingHorz **SHOULD** be set to 1. */
|
||||
CbSubsamplingHorz = 0x55B5,
|
||||
/** [uinteger] The amount of pixels to remove in the Cb channel for every pixel not removed vertically. This is
|
||||
additive with ChromaSubsamplingVert. */
|
||||
CbSubsamplingVert = 0x55B6,
|
||||
/** [uinteger] How chroma is subsampled horizontally. */
|
||||
ChromaSitingHorz = 0x55B7,
|
||||
/** [uinteger] How chroma is subsampled vertically. */
|
||||
ChromaSitingVert = 0x55B8,
|
||||
/** [uinteger] Clipping of the color ranges. */
|
||||
Range = 0x55B9,
|
||||
/** [uinteger] The transfer characteristics of the video. For clarity, the value and meanings for
|
||||
TransferCharacteristics are adopted from Table 3 of ISO/IEC 23091-4 or ITU-T H.273. */
|
||||
TransferCharacteristics = 0x55BA,
|
||||
/** [uinteger] The colour primaries of the video. For clarity, the value and meanings for Primaries are adopted from
|
||||
Table 2 of ISO/IEC 23091-4 or ITU-T H.273. */
|
||||
Primaries = 0x55BB,
|
||||
/** [uinteger] Maximum brightness of a single pixel (Maximum Content Light Level) in candelas per square meter
|
||||
(cd/m^2^). */
|
||||
MaxCLL = 0x55BC,
|
||||
/** [uinteger] Maximum brightness of a single full frame (Maximum Frame-Average Light Level) in candelas per square
|
||||
meter (cd/m^2^). */
|
||||
MaxFALL = 0x55BD,
|
||||
/** [master] SMPTE 2086 mastering data. */
|
||||
MasteringMetadata = 0x55D0,
|
||||
/** [float] Red X chromaticity coordinate, as defined by CIE 1931. */
|
||||
PrimaryRChromaticityX = 0x55D1,
|
||||
/** [float] Red Y chromaticity coordinate, as defined by CIE 1931. */
|
||||
PrimaryRChromaticityY = 0x55D2,
|
||||
/** [float] Green X chromaticity coordinate, as defined by CIE 1931. */
|
||||
PrimaryGChromaticityX = 0x55D3,
|
||||
/** [float] Green Y chromaticity coordinate, as defined by CIE 1931. */
|
||||
PrimaryGChromaticityY = 0x55D4,
|
||||
/** [float] Blue X chromaticity coordinate, as defined by CIE 1931. */
|
||||
PrimaryBChromaticityX = 0x55D5,
|
||||
/** [float] Blue Y chromaticity coordinate, as defined by CIE 1931. */
|
||||
PrimaryBChromaticityY = 0x55D6,
|
||||
/** [float] White X chromaticity coordinate, as defined by CIE 1931. */
|
||||
WhitePointChromaticityX = 0x55D7,
|
||||
/** [float] White Y chromaticity coordinate, as defined by CIE 1931. */
|
||||
WhitePointChromaticityY = 0x55D8,
|
||||
/** [float] Maximum luminance. Represented in candelas per square meter (cd/m^2^). */
|
||||
LuminanceMax = 0x55D9,
|
||||
/** [float] Minimum luminance. Represented in candelas per square meter (cd/m^2^). */
|
||||
LuminanceMin = 0x55DA,
|
||||
/** [master] Describes the video projection details. Used to render spherical, VR videos or flipping videos
|
||||
horizontally/vertically. */
|
||||
Projection = 0x7670,
|
||||
/** [uinteger] Describes the projection used for this video track. */
|
||||
ProjectionType = 0x7671,
|
||||
/** [binary] Private data that only applies to a specific projection. * If `ProjectionType` equals 0
|
||||
(Rectangular), then this element must not be present. * If `ProjectionType` equals 1 (Equirectangular),
|
||||
then this element must be present and contain the same binary data that would be stored inside an ISOBMFF
|
||||
Equirectangular Projection Box ('equi'). * If `ProjectionType` equals 2 (Cubemap), then this element must be
|
||||
present and contain the same binary data that would be stored inside an ISOBMFF Cubemap Projection Box
|
||||
('cbmp'). * If `ProjectionType` equals 3 (Mesh), then this element must be present and contain the same binary
|
||||
data that would be stored inside an ISOBMFF Mesh Projection Box ('mshp'). */
|
||||
ProjectionPrivate = 0x7672,
|
||||
/** [float] Specifies a yaw rotation to the projection. Value represents a clockwise rotation, in degrees, around
|
||||
the up vector. This rotation must be applied before any `ProjectionPosePitch` or `ProjectionPoseRoll` rotations.
|
||||
The value of this element **MUST** be in the -180 to 180 degree range, both included. Setting
|
||||
`ProjectionPoseYaw` to 180 or -180 degrees, with the `ProjectionPoseRoll` and `ProjectionPosePitch` set to 0
|
||||
degrees flips the image horizontally. */
|
||||
ProjectionPoseYaw = 0x7673,
|
||||
/** [float] Specifies a pitch rotation to the projection. Value represents a counter-clockwise rotation, in
|
||||
degrees, around the right vector. This rotation must be applied after the `ProjectionPoseYaw` rotation and before
|
||||
the `ProjectionPoseRoll` rotation. The value of this element **MUST** be in the -90 to 90 degree range, both
|
||||
included. */
|
||||
ProjectionPosePitch = 0x7674,
|
||||
/** [float] Specifies a roll rotation to the projection. Value represents a counter-clockwise rotation, in degrees,
|
||||
around the forward vector. This rotation must be applied after the `ProjectionPoseYaw` and `ProjectionPosePitch`
|
||||
rotations. The value of this element **MUST** be in the -180 to 180 degree range, both included. Setting
|
||||
`ProjectionPoseRoll` to 180 or -180 degrees, the `ProjectionPoseYaw` to 180 or -180 degrees with
|
||||
`ProjectionPosePitch` set to 0 degrees flips the image vertically. Setting `ProjectionPoseRoll` to 180 or -180
|
||||
degrees, with the `ProjectionPoseYaw` and `ProjectionPosePitch` set to 0 degrees flips the image horizontally and
|
||||
vertically. */
|
||||
ProjectionPoseRoll = 0x7675,
|
||||
/** [master] Audio settings. */
|
||||
Audio = 0xE1,
|
||||
/** [float] Sampling frequency in Hz. */
|
||||
SamplingFrequency = 0xB5,
|
||||
/** [float] Real output sampling frequency in Hz (used for SBR techniques). */
|
||||
OutputSamplingFrequency = 0x78B5,
|
||||
/** [uinteger] Numbers of channels in the track. */
|
||||
Channels = 0x9F,
|
||||
/** [binary] Table of horizontal angles for each successive channel. */
|
||||
ChannelPositions = 0x7D7B,
|
||||
/** [uinteger] Bits per sample, mostly used for PCM. */
|
||||
BitDepth = 0x6264,
|
||||
/** [master] Operation that needs to be applied on tracks to create this virtual track. For more details look at
|
||||
(#track-operation). */
|
||||
TrackOperation = 0xE2,
|
||||
/** [master] Contains the list of all video plane tracks that need to be combined to create this 3D track */
|
||||
TrackCombinePlanes = 0xE3,
|
||||
/** [master] Contains a video plane track that need to be combined to create this 3D track */
|
||||
TrackPlane = 0xE4,
|
||||
/** [uinteger] The trackUID number of the track representing the plane. */
|
||||
TrackPlaneUID = 0xE5,
|
||||
/** [uinteger] The kind of plane this track corresponds to. */
|
||||
TrackPlaneType = 0xE6,
|
||||
/** [master] Contains the list of all tracks whose Blocks need to be combined to create this virtual track */
|
||||
TrackJoinBlocks = 0xE9,
|
||||
/** [uinteger] The trackUID number of a track whose blocks are used to create this virtual track. */
|
||||
TrackJoinUID = 0xED,
|
||||
/** [uinteger] The TrackUID of the Smooth FF/RW video in the paired EBML structure corresponding to this video
|
||||
track. See [@?DivXTrickTrack]. */
|
||||
TrickTrackUID = 0xC0,
|
||||
/** [binary] The SegmentUID of the Segment containing the track identified by TrickTrackUID. See [@?DivXTrickTrack].
|
||||
*/
|
||||
TrickTrackSegmentUID = 0xC1,
|
||||
/** [uinteger] Set to 1 if this video track is a Smooth FF/RW track. If set to 1, MasterTrackUID and
|
||||
MasterTrackSegUID should must be present and BlockGroups for this track must contain ReferenceFrame structures.
|
||||
Otherwise, TrickTrackUID and TrickTrackSegUID must be present if this track has a corresponding Smooth FF/RW
|
||||
track. See [@?DivXTrickTrack]. */
|
||||
TrickTrackFlag = 0xC6,
|
||||
/** [uinteger] The TrackUID of the video track in the paired EBML structure that corresponds to this Smooth FF/RW
|
||||
track. See [@?DivXTrickTrack]. */
|
||||
TrickMasterTrackUID = 0xC7,
|
||||
/** [binary] The SegmentUID of the Segment containing the track identified by MasterTrackUID. See
|
||||
[@?DivXTrickTrack]. */
|
||||
TrickMasterTrackSegmentUID = 0xC4,
|
||||
/** [master] Settings for several content encoding mechanisms like compression or encryption. */
|
||||
ContentEncodings = 0x6D80,
|
||||
/** [master] Settings for one content encoding like compression or encryption. */
|
||||
ContentEncoding = 0x6240,
|
||||
/** [uinteger] Tells when this modification was used during encoding/muxing starting with 0 and counting upwards.
|
||||
The decoder/demuxer has to start with the highest order number it finds and work its way down. This value has to
|
||||
be unique over all ContentEncodingOrder Elements in the TrackEntry that contains this ContentEncodingOrder
|
||||
element. */
|
||||
ContentEncodingOrder = 0x5031,
|
||||
/** [uinteger] A bit field that describes which Elements have been modified in this way. Values (big-endian) can be
|
||||
OR'ed. */
|
||||
ContentEncodingScope = 0x5032,
|
||||
/** [uinteger] A value describing what kind of transformation is applied. */
|
||||
ContentEncodingType = 0x5033,
|
||||
/** [master] Settings describing the compression used. This Element **MUST** be present if the value of
|
||||
ContentEncodingType is 0 and absent otherwise. Each block **MUST** be decompressable even if no previous block is
|
||||
available in order not to prevent seeking. */
|
||||
ContentCompression = 0x5034,
|
||||
/** [uinteger] The compression algorithm used. */
|
||||
ContentCompAlgo = 0x4254,
|
||||
/** [binary] Settings that might be needed by the decompressor. For Header Stripping (`ContentCompAlgo`=3), the
|
||||
bytes that were removed from the beginning of each frames of the track. */
|
||||
ContentCompSettings = 0x4255,
|
||||
/** [master] Settings describing the encryption used. This Element **MUST** be present if the value of
|
||||
`ContentEncodingType` is 1 (encryption) and **MUST** be ignored otherwise. */
|
||||
ContentEncryption = 0x5035,
|
||||
/** [uinteger] The encryption algorithm used. The value "0" means that the contents have not been encrypted. */
|
||||
ContentEncAlgo = 0x47E1,
|
||||
/** [binary] For public key algorithms this is the ID of the public key the the data was encrypted with. */
|
||||
ContentEncKeyID = 0x47E2,
|
||||
/** [master] Settings describing the encryption algorithm used. If `ContentEncAlgo` != 5 this **MUST** be ignored.
|
||||
*/
|
||||
ContentEncAESSettings = 0x47E7,
|
||||
/** [uinteger] The AES cipher mode used in the encryption. */
|
||||
AESSettingsCipherMode = 0x47E8,
|
||||
/** [binary] A cryptographic signature of the contents. */
|
||||
ContentSignature = 0x47E3,
|
||||
/** [binary] This is the ID of the private key the data was signed with. */
|
||||
ContentSigKeyID = 0x47E4,
|
||||
/** [uinteger] The algorithm used for the signature. */
|
||||
ContentSigAlgo = 0x47E5,
|
||||
/** [uinteger] The hash algorithm used for the signature. */
|
||||
ContentSigHashAlgo = 0x47E6,
|
||||
/** [master] A Top-Level Element to speed seeking access. All entries are local to the Segment. */
|
||||
Cues = 0x1C53BB6B,
|
||||
/** [master] Contains all information relative to a seek point in the Segment. */
|
||||
CuePoint = 0xBB,
|
||||
/** [uinteger] Absolute timestamp according to the Segment time base. */
|
||||
CueTime = 0xB3,
|
||||
/** [master] Contain positions for different tracks corresponding to the timestamp. */
|
||||
CueTrackPositions = 0xB7,
|
||||
/** [uinteger] The track for which a position is given. */
|
||||
CueTrack = 0xF7,
|
||||
/** [uinteger] The Segment Position of the Cluster containing the associated Block. */
|
||||
CueClusterPosition = 0xF1,
|
||||
/** [uinteger] The relative position inside the Cluster of the referenced SimpleBlock or BlockGroup with 0 being the
|
||||
first possible position for an Element inside that Cluster. */
|
||||
CueRelativePosition = 0xF0,
|
||||
/** [uinteger] The duration of the block according to the Segment time base. If missing the track's DefaultDuration
|
||||
does not apply and no duration information is available in terms of the cues. */
|
||||
CueDuration = 0xB2,
|
||||
/** [uinteger] Number of the Block in the specified Cluster. */
|
||||
CueBlockNumber = 0x5378,
|
||||
/** [uinteger] The Segment Position of the Codec State corresponding to this Cue Element. 0 means that the data is
|
||||
taken from the initial Track Entry. */
|
||||
CueCodecState = 0xEA,
|
||||
/** [master] The Clusters containing the referenced Blocks. */
|
||||
CueReference = 0xDB,
|
||||
/** [uinteger] Timestamp of the referenced Block. */
|
||||
CueRefTime = 0x96,
|
||||
/** [uinteger] The Segment Position of the Cluster containing the referenced Block. */
|
||||
CueRefCluster = 0x97,
|
||||
/** [uinteger] Number of the referenced Block of Track X in the specified Cluster. */
|
||||
CueRefNumber = 0x535F,
|
||||
/** [uinteger] The Segment Position of the Codec State corresponding to this referenced Element. 0 means that the
|
||||
data is taken from the initial Track Entry. */
|
||||
CueRefCodecState = 0xEB,
|
||||
/** [master] Contain attached files. */
|
||||
Attachments = 0x1941A469,
|
||||
/** [master] An attached file. */
|
||||
AttachedFile = 0x61A7,
|
||||
/** [utf-8] A human-friendly name for the attached file. */
|
||||
FileDescription = 0x467E,
|
||||
/** [utf-8] Filename of the attached file. */
|
||||
FileName = 0x466E,
|
||||
/** [string] MIME type of the file. */
|
||||
FileMimeType = 0x4660,
|
||||
/** [binary] The data of the file. */
|
||||
FileData = 0x465C,
|
||||
/** [uinteger] Unique ID representing the file, as random as possible. */
|
||||
FileUID = 0x46AE,
|
||||
/** [binary] A binary value that a track/codec can refer to when the attachment is needed. */
|
||||
FileReferral = 0x4675,
|
||||
/** [uinteger] The timecode at which this optimized font attachment comes into context, based on the Segment
|
||||
TimecodeScale. This element is reserved for future use and if written must be the segment start time. See
|
||||
[@?DivXWorldFonts]. */
|
||||
FileUsedStartTime = 0x4661,
|
||||
/** [uinteger] The timecode at which this optimized font attachment goes out of context, based on the Segment
|
||||
TimecodeScale. This element is reserved for future use and if written must be the segment end time. See
|
||||
[@?DivXWorldFonts]. */
|
||||
FileUsedEndTime = 0x4662,
|
||||
/** [master] A system to define basic menus and partition data. For more detailed information, look at the Chapters
|
||||
explanation in (#chapters). */
|
||||
Chapters = 0x1043A770,
|
||||
/** [master] Contains all information about a Segment edition. */
|
||||
EditionEntry = 0x45B9,
|
||||
/** [uinteger] A unique ID to identify the edition. It's useful for tagging an edition. */
|
||||
EditionUID = 0x45BC,
|
||||
/** [uinteger] Set to 1 if an edition is hidden. Hidden editions **SHOULD NOT** be available to the user interface
|
||||
(but still to Control Tracks; see (#chapter-flags) on Chapter flags). */
|
||||
EditionFlagHidden = 0x45BD,
|
||||
/** [uinteger] Set to 1 if the edition **SHOULD** be used as the default one. */
|
||||
EditionFlagDefault = 0x45DB,
|
||||
/** [uinteger] Set to 1 if the chapters can be defined multiple times and the order to play them is enforced; see
|
||||
(#editionflagordered). */
|
||||
EditionFlagOrdered = 0x45DD,
|
||||
/** [master] Contains the atom information to use as the chapter atom (apply to all tracks). */
|
||||
ChapterAtom = 0xB6,
|
||||
/** [uinteger] A unique ID to identify the Chapter. */
|
||||
ChapterUID = 0x73C4,
|
||||
/** [utf-8] A unique string ID to identify the Chapter. Use for WebVTT cue identifier storage [@!WebVTT]. */
|
||||
ChapterStringUID = 0x5654,
|
||||
/** [uinteger] Timestamp of the start of Chapter (not scaled). */
|
||||
ChapterTimeStart = 0x91,
|
||||
/** [uinteger] Timestamp of the end of Chapter (timestamp excluded, not scaled). The value **MUST** be greater than
|
||||
or equal to the `ChapterTimeStart` of the same `ChapterAtom`. */
|
||||
ChapterTimeEnd = 0x92,
|
||||
/** [uinteger] Set to 1 if a chapter is hidden. Hidden chapters **SHOULD NOT** be available to the user interface
|
||||
(but still to Control Tracks; see (#chapterflaghidden) on Chapter flags). */
|
||||
ChapterFlagHidden = 0x98,
|
||||
/** [uinteger] Set to 1 if the chapter is enabled. It can be enabled/disabled by a Control Track. When disabled, the
|
||||
movie **SHOULD** skip all the content between the TimeStart and TimeEnd of this chapter; see (#chapter-flags) on
|
||||
Chapter flags. */
|
||||
ChapterFlagEnabled = 0x4598,
|
||||
/** [binary] The SegmentUID of another Segment to play during this chapter. */
|
||||
ChapterSegmentUID = 0x6E67,
|
||||
/** [uinteger] The EditionUID to play from the Segment linked in ChapterSegmentUID. If ChapterSegmentEditionUID is
|
||||
undeclared, then no Edition of the linked Segment is used; see (#medium-linking) on medium-linking Segments. */
|
||||
ChapterSegmentEditionUID = 0x6EBC,
|
||||
/** [uinteger] Specify the physical equivalent of this ChapterAtom like "DVD" (60) or "SIDE" (50); see
|
||||
(#physical-types) for a complete list of values. */
|
||||
ChapterPhysicalEquiv = 0x63C3,
|
||||
/** [master] List of tracks on which the chapter applies. If this Element is not present, all tracks apply */
|
||||
ChapterTrack = 0x8F,
|
||||
/** [uinteger] UID of the Track to apply this chapter to. In the absence of a control track, choosing this chapter
|
||||
will select the listed Tracks and deselect unlisted tracks. Absence of this Element indicates that the Chapter
|
||||
**SHOULD** be applied to any currently used Tracks. */
|
||||
ChapterTrackUID = 0x89,
|
||||
/** [master] Contains all possible strings to use for the chapter display. */
|
||||
ChapterDisplay = 0x80,
|
||||
/** [utf-8] Contains the string to use as the chapter atom. */
|
||||
ChapString = 0x85,
|
||||
/** [string] A language corresponding to the string, in the bibliographic ISO-639-2 form [@!ISO639-2]. This Element
|
||||
**MUST** be ignored if a ChapLanguageIETF Element is used within the same ChapterDisplay Element. */
|
||||
ChapLanguage = 0x437C,
|
||||
/** [string] Specifies a language corresponding to the ChapString in the format defined in [@!BCP47] and using the
|
||||
IANA Language Subtag Registry [@!IANALangRegistry]. If a ChapLanguageIETF Element is used, then any ChapLanguage
|
||||
and ChapCountry Elements used in the same ChapterDisplay **MUST** be ignored. */
|
||||
ChapLanguageIETF = 0x437D,
|
||||
/** [string] A country corresponding to the string, using the same 2 octets country-codes as in Internet domains
|
||||
[@!IANADomains] based on [@!ISO3166-1] alpha-2 codes. This Element **MUST** be ignored if a ChapLanguageIETF
|
||||
Element is used within the same ChapterDisplay Element. */
|
||||
ChapCountry = 0x437E,
|
||||
/** [master] Contains all the commands associated to the Atom. */
|
||||
ChapProcess = 0x6944,
|
||||
/** [uinteger] Contains the type of the codec used for the processing. A value of 0 means native Matroska processing
|
||||
(to be defined), a value of 1 means the DVD command set is used; see (#menu-features) on DVD menus. More codec
|
||||
IDs can be added later. */
|
||||
ChapProcessCodecID = 0x6955,
|
||||
/** [binary] Some optional data attached to the ChapProcessCodecID information. For ChapProcessCodecID = 1, it
|
||||
is the "DVD level" equivalent; see (#menu-features) on DVD menus. */
|
||||
ChapProcessPrivate = 0x450D,
|
||||
/** [master] Contains all the commands associated to the Atom. */
|
||||
ChapProcessCommand = 0x6911,
|
||||
/** [uinteger] Defines when the process command **SHOULD** be handled */
|
||||
ChapProcessTime = 0x6922,
|
||||
/** [binary] Contains the command information. The data **SHOULD** be interpreted depending on the
|
||||
ChapProcessCodecID value. For ChapProcessCodecID = 1, the data correspond to the binary DVD cell pre/post
|
||||
commands; see (#menu-features) on DVD menus. */
|
||||
ChapProcessData = 0x6933,
|
||||
/** [master] Element containing metadata describing Tracks, Editions, Chapters, Attachments, or the Segment as a
|
||||
whole. A list of valid tags can be found in [@!MatroskaTags]. */
|
||||
Tags = 0x1254C367,
|
||||
/** [master] A single metadata descriptor. */
|
||||
Tag = 0x7373,
|
||||
/** [master] Specifies which other elements the metadata represented by the Tag applies to. If empty or not present,
|
||||
then the Tag describes everything in the Segment. */
|
||||
Targets = 0x63C0,
|
||||
/** [uinteger] A number to indicate the logical level of the target. */
|
||||
TargetTypeValue = 0x68CA,
|
||||
/** [string] An informational string that can be used to display the logical level of the target like "ALBUM",
|
||||
"TRACK", "MOVIE", "CHAPTER", etc ; see Section 6.4 of [@!MatroskaTags]. */
|
||||
TargetType = 0x63CA,
|
||||
/** [uinteger] A unique ID to identify the Track(s) the tags belong to. */
|
||||
TagTrackUID = 0x63C5,
|
||||
/** [uinteger] A unique ID to identify the EditionEntry(s) the tags belong to. */
|
||||
TagEditionUID = 0x63C9,
|
||||
/** [uinteger] A unique ID to identify the Chapter(s) the tags belong to. */
|
||||
TagChapterUID = 0x63C4,
|
||||
/** [uinteger] A unique ID to identify the Attachment(s) the tags belong to. */
|
||||
TagAttachmentUID = 0x63C6,
|
||||
/** [master] Contains general information about the target. */
|
||||
SimpleTag = 0x67C8,
|
||||
/** [utf-8] The name of the Tag that is going to be stored. */
|
||||
TagName = 0x45A3,
|
||||
/** [string] Specifies the language of the tag specified, in the Matroska languages form; see (#language-codes) on
|
||||
language codes. This Element **MUST** be ignored if the TagLanguageIETF Element is used within the same SimpleTag
|
||||
Element. */
|
||||
TagLanguage = 0x447A,
|
||||
/** [string] Specifies the language used in the TagString according to [@!BCP47] and using the IANA Language Subtag
|
||||
Registry [@!IANALangRegistry]. If this Element is used, then any TagLanguage Elements used in the same SimpleTag
|
||||
**MUST** be ignored. */
|
||||
TagLanguageIETF = 0x447B,
|
||||
/** [uinteger] A boolean value to indicate if this is the default/original language to use for the given tag. */
|
||||
TagDefault = 0x4484,
|
||||
/** [uinteger] A variant of the TagDefault element with a bogus Element ID; see (#tagdefault-element). */
|
||||
TagDefaultBogus = 0x44B4,
|
||||
/** [utf-8] The value of the Tag. */
|
||||
TagString = 0x4487,
|
||||
/** [binary] The values of the Tag, if it is binary. Note that this cannot be used in the same SimpleTag as
|
||||
TagString. */
|
||||
TagBinary = 0x4485,
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef ES8311AUDIOSINK_H
|
||||
#define ES8311AUDIOSINK_H
|
||||
|
||||
#include "driver/i2s.h"
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include "BufferedAudioSink.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/i2c.h"
|
||||
#include <sys/unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
class ES8311AudioSink : public BufferedAudioSink
|
||||
{
|
||||
public:
|
||||
ES8311AudioSink();
|
||||
~ES8311AudioSink();
|
||||
void writeReg(uint8_t reg_add, uint8_t data);
|
||||
void volumeChanged(uint16_t volume);
|
||||
private:
|
||||
};
|
||||
|
||||
#endif
|
||||
121
components/spotify/cspot/bell/include/audio/sinks/esp/es8311.h
Normal file
121
components/spotify/cspot/bell/include/audio/sinks/esp/es8311.h
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* ES8311.h -- ES8311 ALSA SoC Audio Codec
|
||||
*
|
||||
* Authors:
|
||||
*
|
||||
* Based on ES8374.h by David Yang
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef _ES8311_H
|
||||
#define _ES8311_H
|
||||
#include "driver/i2c.h"
|
||||
#include "esxxx_common.h"
|
||||
|
||||
/*
|
||||
* ES8311_REGISTER NAME_REG_REGISTER ADDRESS
|
||||
*/
|
||||
#define ES8311_RESET_REG00 0x00 /*reset digital,csm,clock manager etc.*/
|
||||
|
||||
/*
|
||||
* Clock Scheme Register definition
|
||||
*/
|
||||
#define ES8311_CLK_MANAGER_REG01 0x01 /* select clk src for mclk, enable clock for codec */
|
||||
#define ES8311_CLK_MANAGER_REG02 0x02 /* clk divider and clk multiplier */
|
||||
#define ES8311_CLK_MANAGER_REG03 0x03 /* adc fsmode and osr */
|
||||
#define ES8311_CLK_MANAGER_REG04 0x04 /* dac osr */
|
||||
#define ES8311_CLK_MANAGER_REG05 0x05 /* clk divier for adc and dac */
|
||||
#define ES8311_CLK_MANAGER_REG06 0x06 /* bclk inverter and divider */
|
||||
#define ES8311_CLK_MANAGER_REG07 0x07 /* tri-state, lrck divider */
|
||||
#define ES8311_CLK_MANAGER_REG08 0x08 /* lrck divider */
|
||||
#define ES8311_SDPIN_REG09 0x09 /* dac serial digital port */
|
||||
#define ES8311_SDPOUT_REG0A 0x0A /* adc serial digital port */
|
||||
#define ES8311_SYSTEM_REG0B 0x0B /* system */
|
||||
#define ES8311_SYSTEM_REG0C 0x0C /* system */
|
||||
#define ES8311_SYSTEM_REG0D 0x0D /* system, power up/down */
|
||||
#define ES8311_SYSTEM_REG0E 0x0E /* system, power up/down */
|
||||
#define ES8311_SYSTEM_REG0F 0x0F /* system, low power */
|
||||
#define ES8311_SYSTEM_REG10 0x10 /* system */
|
||||
#define ES8311_SYSTEM_REG11 0x11 /* system */
|
||||
#define ES8311_SYSTEM_REG12 0x12 /* system, Enable DAC */
|
||||
#define ES8311_SYSTEM_REG13 0x13 /* system */
|
||||
#define ES8311_SYSTEM_REG14 0x14 /* system, select DMIC, select analog pga gain */
|
||||
#define ES8311_ADC_REG15 0x15 /* ADC, adc ramp rate, dmic sense */
|
||||
#define ES8311_ADC_REG16 0x16 /* ADC */
|
||||
#define ES8311_ADC_REG17 0x17 /* ADC, volume */
|
||||
#define ES8311_ADC_REG18 0x18 /* ADC, alc enable and winsize */
|
||||
#define ES8311_ADC_REG19 0x19 /* ADC, alc maxlevel */
|
||||
#define ES8311_ADC_REG1A 0x1A /* ADC, alc automute */
|
||||
#define ES8311_ADC_REG1B 0x1B /* ADC, alc automute, adc hpf s1 */
|
||||
#define ES8311_ADC_REG1C 0x1C /* ADC, equalizer, hpf s2 */
|
||||
#define ES8311_DAC_REG31 0x31 /* DAC, mute */
|
||||
#define ES8311_DAC_REG32 0x32 /* DAC, volume */
|
||||
#define ES8311_DAC_REG33 0x33 /* DAC, offset */
|
||||
#define ES8311_DAC_REG34 0x34 /* DAC, drc enable, drc winsize */
|
||||
#define ES8311_DAC_REG35 0x35 /* DAC, drc maxlevel, minilevel */
|
||||
#define ES8311_DAC_REG37 0x37 /* DAC, ramprate */
|
||||
#define ES8311_GPIO_REG44 0x44 /* GPIO, dac2adc for test */
|
||||
#define ES8311_GP_REG45 0x45 /* GP CONTROL */
|
||||
#define ES8311_CHD1_REGFD 0xFD /* CHIP ID1 */
|
||||
#define ES8311_CHD2_REGFE 0xFE /* CHIP ID2 */
|
||||
#define ES8311_CHVER_REGFF 0xFF /* VERSION */
|
||||
#define ES8311_CHD1_REGFD 0xFD /* CHIP ID1 */
|
||||
|
||||
#define ES8311_MAX_REGISTER 0xFF
|
||||
|
||||
|
||||
typedef struct {
|
||||
ESCodecMode esMode;
|
||||
i2c_port_t i2c_port_num;
|
||||
i2c_config_t i2c_cfg;
|
||||
DacOutput dacOutput;
|
||||
AdcInput adcInput;
|
||||
} Es8311Config;
|
||||
|
||||
|
||||
#define AUDIO_CODEC_ES8311_DEFAULT(){ \
|
||||
.esMode = ES_MODE_SLAVE, \
|
||||
.i2c_port_num = I2C_NUM_0, \
|
||||
.i2c_cfg = { \
|
||||
.mode = I2C_MODE_MASTER, \
|
||||
.sda_io_num = IIC_DATA, \
|
||||
.scl_io_num = IIC_CLK, \
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,\
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,\
|
||||
.master.clk_speed = 100000\
|
||||
}, \
|
||||
.adcInput = ADC_INPUT_LINPUT1_RINPUT1,\
|
||||
.dacOutput = DAC_OUTPUT_LOUT1 | DAC_OUTPUT_LOUT2 | DAC_OUTPUT_ROUT1 | DAC_OUTPUT_ROUT2,\
|
||||
};
|
||||
|
||||
int Es8311Init(Es8311Config *cfg);
|
||||
void Es8311Uninit();
|
||||
esp_err_t Es8311GetRef(bool flag);
|
||||
esp_err_t Es7243Init(void);
|
||||
|
||||
int Es7243ReadReg(uint8_t regAdd);
|
||||
|
||||
int Es8311ConfigFmt(ESCodecModule mode, ESCodecI2SFmt fmt);
|
||||
int Es8311I2sConfigClock(ESCodecI2sClock cfg);
|
||||
int Es8311SetBitsPerSample(ESCodecModule mode, BitsLength bitPerSample);
|
||||
|
||||
int Es8311Start(ESCodecModule mode);
|
||||
int Es8311Stop(ESCodecModule mode);
|
||||
|
||||
int Es8311SetVoiceVolume(int volume);
|
||||
int Es8311GetVoiceVolume(int *volume);
|
||||
int Es8311SetVoiceMute(int enable);
|
||||
int Es8311GetVoiceMute(int *mute);
|
||||
int Es8311SetMicGain(MicGain gain);
|
||||
|
||||
int Es8311ConfigAdcInput(AdcInput input);
|
||||
int Es8311ConfigDacOutput(DacOutput output);
|
||||
|
||||
int ES8311WriteReg(uint8_t regAdd, uint8_t data);
|
||||
|
||||
void Es8311ReadAll();
|
||||
int Es8311ReadReg(uint8_t regAdd);
|
||||
#endif
|
||||
@@ -0,0 +1,166 @@
|
||||
#ifndef __ESCODEC_COMMON_H__
|
||||
#define __ESCODEC_COMMON_H__
|
||||
|
||||
typedef enum BitsLength {
|
||||
BIT_LENGTH_MIN = -1,
|
||||
BIT_LENGTH_16BITS = 0x03,
|
||||
BIT_LENGTH_18BITS = 0x02,
|
||||
BIT_LENGTH_20BITS = 0x01,
|
||||
BIT_LENGTH_24BITS = 0x00,
|
||||
BIT_LENGTH_32BITS = 0x04,
|
||||
BIT_LENGTH_MAX,
|
||||
} BitsLength;
|
||||
|
||||
typedef enum {
|
||||
SAMPLE_RATE_MIN = -1,
|
||||
SAMPLE_RATE_16K,
|
||||
SAMPLE_RATE_32K,
|
||||
SAMPLE_RATE_44_1K,
|
||||
SAMPLE_RATE_MAX,
|
||||
} SampleRate;
|
||||
|
||||
typedef enum {
|
||||
MclkDiv_MIN = -1,
|
||||
MclkDiv_1 = 1,
|
||||
MclkDiv_2 = 2,
|
||||
MclkDiv_3 = 3,
|
||||
MclkDiv_4 = 4,
|
||||
MclkDiv_6 = 5,
|
||||
MclkDiv_8 = 6,
|
||||
MclkDiv_9 = 7,
|
||||
MclkDiv_11 = 8,
|
||||
MclkDiv_12 = 9,
|
||||
MclkDiv_16 = 10,
|
||||
MclkDiv_18 = 11,
|
||||
MclkDiv_22 = 12,
|
||||
MclkDiv_24 = 13,
|
||||
MclkDiv_33 = 14,
|
||||
MclkDiv_36 = 15,
|
||||
MclkDiv_44 = 16,
|
||||
MclkDiv_48 = 17,
|
||||
MclkDiv_66 = 18,
|
||||
MclkDiv_72 = 19,
|
||||
MclkDiv_5 = 20,
|
||||
MclkDiv_10 = 21,
|
||||
MclkDiv_15 = 22,
|
||||
MclkDiv_17 = 23,
|
||||
MclkDiv_20 = 24,
|
||||
MclkDiv_25 = 25,
|
||||
MclkDiv_30 = 26,
|
||||
MclkDiv_32 = 27,
|
||||
MclkDiv_34 = 28,
|
||||
MclkDiv_7 = 29,
|
||||
MclkDiv_13 = 30,
|
||||
MclkDiv_14 = 31,
|
||||
MclkDiv_MAX,
|
||||
} SclkDiv;
|
||||
|
||||
typedef enum {
|
||||
LclkDiv_MIN = -1,
|
||||
LclkDiv_128 = 0,
|
||||
LclkDiv_192 = 1,
|
||||
LclkDiv_256 = 2,
|
||||
LclkDiv_384 = 3,
|
||||
LclkDiv_512 = 4,
|
||||
LclkDiv_576 = 5,
|
||||
LclkDiv_768 = 6,
|
||||
LclkDiv_1024 = 7,
|
||||
LclkDiv_1152 = 8,
|
||||
LclkDiv_1408 = 9,
|
||||
LclkDiv_1536 = 10,
|
||||
LclkDiv_2112 = 11,
|
||||
LclkDiv_2304 = 12,
|
||||
|
||||
LclkDiv_125 = 16,
|
||||
LclkDiv_136 = 17,
|
||||
LclkDiv_250 = 18,
|
||||
LclkDiv_272 = 19,
|
||||
LclkDiv_375 = 20,
|
||||
LclkDiv_500 = 21,
|
||||
LclkDiv_544 = 22,
|
||||
LclkDiv_750 = 23,
|
||||
LclkDiv_1000 = 24,
|
||||
LclkDiv_1088 = 25,
|
||||
LclkDiv_1496 = 26,
|
||||
LclkDiv_1500 = 27,
|
||||
LclkDiv_MAX,
|
||||
} LclkDiv;
|
||||
|
||||
typedef enum {
|
||||
ADC_INPUT_MIN = -1,
|
||||
ADC_INPUT_LINPUT1_RINPUT1 = 0x00,
|
||||
ADC_INPUT_MIC1 = 0x05,
|
||||
ADC_INPUT_MIC2 = 0x06,
|
||||
ADC_INPUT_LINPUT2_RINPUT2 = 0x50,
|
||||
ADC_INPUT_DIFFERENCE = 0xf0,
|
||||
ADC_INPUT_MAX,
|
||||
} AdcInput;
|
||||
|
||||
typedef enum {
|
||||
DAC_OUTPUT_MIN = -1,
|
||||
DAC_OUTPUT_LOUT1 = 0x04,
|
||||
DAC_OUTPUT_LOUT2 = 0x08,
|
||||
DAC_OUTPUT_SPK = 0x09,
|
||||
DAC_OUTPUT_ROUT1 = 0x10,
|
||||
DAC_OUTPUT_ROUT2 = 0x20,
|
||||
DAC_OUTPUT_ALL = 0x3c,
|
||||
DAC_OUTPUT_MAX,
|
||||
} DacOutput;
|
||||
|
||||
typedef enum {
|
||||
D2SE_PGA_GAIN_MIN = -1,
|
||||
D2SE_PGA_GAIN_DIS = 0,
|
||||
D2SE_PGA_GAIN_EN = 1,
|
||||
D2SE_PGA_GAIN_MAX = 2,
|
||||
} D2SEPGA;
|
||||
|
||||
typedef enum {
|
||||
MIC_GAIN_MIN = -1,
|
||||
MIC_GAIN_0DB = 0,
|
||||
MIC_GAIN_3DB = 3,
|
||||
MIC_GAIN_6DB = 6,
|
||||
MIC_GAIN_9DB = 9,
|
||||
MIC_GAIN_12DB = 12,
|
||||
MIC_GAIN_15DB = 15,
|
||||
MIC_GAIN_18DB = 18,
|
||||
MIC_GAIN_21DB = 21,
|
||||
MIC_GAIN_24DB = 24,
|
||||
#if defined CONFIG_CODEC_CHIP_IS_ES8311
|
||||
MIC_GAIN_30DB = 30,
|
||||
MIC_GAIN_36DB = 36,
|
||||
MIC_GAIN_42DB = 42,
|
||||
#endif
|
||||
MIC_GAIN_MAX,
|
||||
} MicGain;
|
||||
|
||||
typedef enum {
|
||||
ES_MODULE_MIN = -1,
|
||||
ES_MODULE_ADC = 0x01,
|
||||
ES_MODULE_DAC = 0x02,
|
||||
ES_MODULE_ADC_DAC = 0x03,
|
||||
ES_MODULE_LINE = 0x04,
|
||||
ES_MODULE_MAX
|
||||
} ESCodecModule;
|
||||
|
||||
typedef enum {
|
||||
ES_MODE_MIN = -1,
|
||||
ES_MODE_SLAVE = 0x00,
|
||||
ES_MODE_MASTER = 0x01,
|
||||
ES_MODE_MAX,
|
||||
} ESCodecMode;
|
||||
|
||||
typedef enum {
|
||||
ES_ = -1,
|
||||
ES_I2S_NORMAL = 0,
|
||||
ES_I2S_LEFT = 1,
|
||||
ES_I2S_RIGHT = 2,
|
||||
ES_I2S_DSP = 3,
|
||||
ES_I2S_MAX
|
||||
} ESCodecI2SFmt;
|
||||
|
||||
typedef struct {
|
||||
SclkDiv sclkDiv;
|
||||
LclkDiv lclkDiv;
|
||||
} ESCodecI2sClock;
|
||||
|
||||
#endif //__ESCODEC_COMMON_H__
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "AudioSink.h"
|
||||
#include <alsa/asoundlib.h>
|
||||
#include <stdio.h>
|
||||
#include <Task.h>
|
||||
#include <BellTask.h>
|
||||
#include <unistd.h>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
18
components/spotify/cspot/bell/include/platform/MDNSService.h
Normal file
18
components/spotify/cspot/bell/include/platform/MDNSService.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef BELLL_MDNS_SERVICE_H
|
||||
#define BELLL_MDNS_SERVICE_H
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
class MDNSService {
|
||||
public:
|
||||
static void registerService(
|
||||
const std::string &serviceName,
|
||||
const std::string &serviceType,
|
||||
const std::string &serviceProto,
|
||||
const std::string &serviceHost,
|
||||
int servicePort,
|
||||
const std::map<std::string, std::string> txtData
|
||||
);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -6,6 +6,8 @@
|
||||
#include "freertos/semphr.h"
|
||||
#elif __APPLE__
|
||||
#include <dispatch/dispatch.h>
|
||||
#elif _WIN32
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
#include <time.h>
|
||||
#include <semaphore.h>
|
||||
@@ -18,6 +20,8 @@ private:
|
||||
xSemaphoreHandle semaphoreHandle;
|
||||
#elif __APPLE__
|
||||
dispatch_semaphore_t semaphoreHandle;
|
||||
#elif _WIN32
|
||||
HANDLE semaphoreHandle;
|
||||
#else
|
||||
sem_t semaphoreHandle;
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <winsock2.h>
|
||||
|
||||
#define SHUT_RDWR SD_BOTH
|
||||
#define ssize_t SSIZE_T
|
||||
|
||||
#define strcasecmp stricmp
|
||||
#define strncasecmp _strnicmp
|
||||
#define bzero(p,n) memset(p,0,n)
|
||||
#define usleep(x) Sleep((x)/1000)
|
||||
|
||||
inline void close(int sock) { closesocket(sock); }
|
||||
inline size_t read(int sock, char* buf, size_t n) { return recv(sock, buf, n, 0); }
|
||||
inline int write(int sock, const char* buf, size_t n) { return send(sock, buf, n, 0); }
|
||||
39
components/spotify/cspot/bell/nanopb/.github/workflows/cifuzz.yml
vendored
Normal file
39
components/spotify/cspot/bell/nanopb/.github/workflows/cifuzz.yml
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
name: CIFuzz
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- '**.c'
|
||||
- '**.h'
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- '**.c'
|
||||
- '**.h'
|
||||
|
||||
jobs:
|
||||
Fuzzing:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Build Fuzzers
|
||||
id: build
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
|
||||
with:
|
||||
oss-fuzz-project-name: 'nanopb'
|
||||
dry-run: false
|
||||
sanitizer: undefined
|
||||
- name: Run Fuzzers
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
|
||||
with:
|
||||
oss-fuzz-project-name: 'nanopb'
|
||||
fuzz-seconds: 600
|
||||
dry-run: false
|
||||
sanitizer: undefined
|
||||
- name: Upload Crash
|
||||
uses: actions/upload-artifact@v1
|
||||
if: failure() && steps.build.outcome == 'success'
|
||||
with:
|
||||
name: artifacts
|
||||
path: ./out/artifacts
|
||||
63
components/spotify/cspot/bell/nanopb/.github/workflows/platformio.yaml
vendored
Normal file
63
components/spotify/cspot/bell/nanopb/.github/workflows/platformio.yaml
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
name: platformio
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
platformio:
|
||||
name: Build and run PlatformIO example
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: ⤵️ Check out code from GitHub
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: nanopb
|
||||
|
||||
- name: Installing dependencies for local act
|
||||
if: ${{ env.ACT }}
|
||||
run: |
|
||||
sudo apt update
|
||||
|
||||
- name: Installing common dependencies
|
||||
run: |
|
||||
sudo apt install -y python3-pip
|
||||
|
||||
- name: Install and setup PlatformIO
|
||||
run: |
|
||||
pip3 install -U platformio
|
||||
export PATH=~/.local/bin:$PATH
|
||||
|
||||
- name: Build PlatformIO package
|
||||
run: |
|
||||
cd nanopb
|
||||
pio package pack
|
||||
|
||||
- name: Example - Extract PlatformIO package to example dir
|
||||
run: |
|
||||
cp -R nanopb/examples/platformio example
|
||||
mkdir -p example/lib/nanopb
|
||||
tar -xzf nanopb/Nanopb-*.tar.gz -C example/lib/nanopb
|
||||
|
||||
- name: Example - Build
|
||||
run: |
|
||||
cd example
|
||||
pio run
|
||||
|
||||
- name: Example - Run test without options
|
||||
run: example/.pio/build/pio_without_options/program
|
||||
|
||||
- name: Example - Run test with options
|
||||
run: example/.pio/build/pio_with_options/program
|
||||
|
||||
- name: Build with default platformio.ini
|
||||
run: |
|
||||
mkdir -p test_default_pio_conf
|
||||
cd test_default_pio_conf
|
||||
pio project init
|
||||
ln -s ../nanopb lib/nanopb
|
||||
echo "[env:native]" >> platformio.ini
|
||||
echo "platform = native" >> platformio.ini
|
||||
echo "lib_deps = Nanopb" >> platformio.ini
|
||||
echo "int main(int argc, char *argv[]){}" > src/main.cpp
|
||||
pio run
|
||||
15
components/spotify/cspot/bell/nanopb/.github/workflows/spm.yml
vendored
Normal file
15
components/spotify/cspot/bell/nanopb/.github/workflows/spm.yml
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
name: spm
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
swift-build-run:
|
||||
runs-on: macOS-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Build
|
||||
run: swift build
|
||||
- name: Run
|
||||
run: swift test
|
||||
@@ -98,3 +98,19 @@ leabut <leabut@users.noreply.github.com>
|
||||
Angel ILIEV <a.v.iliev13@gmail.com>
|
||||
Jakub Tymejczyk <jakub@tymejczyk.pl>
|
||||
Matthew Simmons <simmonmt@acm.org>
|
||||
Anthony Pesch <inolen@gmail.com>
|
||||
Avik De <avikde@gmail.com>
|
||||
ConradWood <github@conradwood.net>
|
||||
David Sabatie <david.sabatie@notrenet.com>
|
||||
Sebastian Stockhammer <sebastian.stockhammer@rosenberger.de>
|
||||
Gil Shapira <gil.shapira@intusurg.com>
|
||||
Ian Frosst <ianjfrosst@gmail.com>
|
||||
Ingo Kresse <ingo.kresse@kuka.com>
|
||||
Ivan Zrno <ivan.zrno2@gmail.com>
|
||||
Jonathan Seilkopf <j.seilkopf@isatech.de>
|
||||
Karl Ljungkvist <k.ljungkvist@gmail.com>
|
||||
Mathis Logemann <mathisloge@gmail.com>
|
||||
Oleg Dolgy <60554929+odolgy@users.noreply.github.com>
|
||||
Pavel Sokolov <pavel@sokolov.me>
|
||||
Slavey Karadzhov <slav@attachix.com>
|
||||
Tobias Nießen <tniessen@tnie.de>
|
||||
|
||||
@@ -1,3 +1,43 @@
|
||||
nanopb-0.4.6 (2022-05-30)
|
||||
Fix passing of error message from substream callback (#703)
|
||||
Fix comments going to wrong member variables (#701)
|
||||
Fix regression in 0.4.3 where generator did not find all dependencies (#720)
|
||||
Fix FindNanopb.cmake not finding options file (#659)
|
||||
Fix double-definition errors with size_union (#692)
|
||||
Fix generator error with same inner message name (#746)
|
||||
Fix infinite recursion in generator/protoc script (#762)
|
||||
Fix unicode comment handling for Python 2 (#740)
|
||||
Fix compiler warnings with PB_BUFFER_ONLY (#717)
|
||||
Fix options dependency in nanopb.mk (#666)
|
||||
Fix handling of filenames with dot in them in FindNanopb.cmake (#756)
|
||||
Add fallback_type option (#772, #773)
|
||||
Use C11 static assert mechanism by default (#761, #766)
|
||||
Use 'static_assert' keyword for iar (#679)
|
||||
Explicitly check for pItem == NULL to satisfy Xcode analyzer (#667, #674)
|
||||
Support --proto-path as alias to -I (#749)
|
||||
Refactor name mangling to separate class, improve error messages (#735)
|
||||
Move PB_WT_PACKED definition to the header to fix compiler warnings (#671)
|
||||
FindNanopb.cmake: use --nanopb_opt for option passing by default (#752)
|
||||
FindNanopb.cmake: Add option NANOPB_GENERATE_CPP_STANDALONE (#741)
|
||||
FindNanopb.cmake: Add PROTOC_OPTIONS variable (#768, #771)
|
||||
CMakeLists: add build interface for using as a submodule (#669)
|
||||
CMakeLists: fix error with nanopb_BUILD_GENERATOR=OFF (#764)
|
||||
CMakeLists: make more uniform (#676)
|
||||
CMakeLists: Fix uninitialized PYTHON_INSTDIR (#652)
|
||||
Clean up CMake examples (#741)
|
||||
Rebuild nanopb_pb2.py and print version numbers on import failure (#733, #742)
|
||||
Use memcpy instead of iterating on buf_read/write (#751)
|
||||
Add generator support for PlatformIO (#718)
|
||||
Add clean target to generator/proto/Makefile (#681)
|
||||
Windows .bats: use standard python invocation instead of py.exe launcher (#657)
|
||||
Fix problems running tests with newer SCons version
|
||||
Improve handling of varint overflows
|
||||
Improve optimization for little-endian platforms
|
||||
|
||||
NOTE: During development, prereleases were published on PlatformIO registry
|
||||
as versions 0.4.6 - 0.4.6.3. The version 0.4.6.4 on PlatformIO corresponds
|
||||
to the real final 0.4.6 release.
|
||||
|
||||
nanopb-0.4.5 (2021-03-22)
|
||||
Fix invalid free() with oneof (#647, GHSA-7mv5-5mxh-qg88)
|
||||
Fix unordered field numbers inside oneof causing fields to be ignored (#617)
|
||||
@@ -149,6 +189,13 @@ nanopb-0.4.0 (2019-12-20)
|
||||
CMake: Split nanopb_out command (#454)
|
||||
CMake: install created shared library(dll) in windows to the binary folder (#447)
|
||||
|
||||
nanopb-0.3.9.9 (2022-04-23)
|
||||
Fix Xcode analyzer warnings (#667, #674)
|
||||
Fix clang sanitizer warnings
|
||||
|
||||
Note: there are no known functional differences between 0.3.9.8 and 0.3.9.9.
|
||||
The changes are merely to fix warnings introduced by new compiler versions.
|
||||
|
||||
nanopb-0.3.9.8 (2021-03-22)
|
||||
Fix invalid free() with oneof (#647, GHSA-7mv5-5mxh-qg88)
|
||||
Don't generate lines with trailing spaces (#622)
|
||||
|
||||
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 2.8.12)
|
||||
|
||||
project(nanopb C)
|
||||
|
||||
set(nanopb_VERSION_STRING nanopb-0.4.6-dev)
|
||||
set(nanopb_VERSION_STRING nanopb-0.4.7-dev)
|
||||
set(nanopb_SOVERSION 0)
|
||||
|
||||
string(REPLACE "nanopb-" "" nanopb_VERSION ${nanopb_VERSION_STRING})
|
||||
@@ -65,10 +65,10 @@ if(nanopb_BUILD_GENERATOR)
|
||||
DESTINATION ${PYTHON_INSTDIR}/proto/
|
||||
)
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
install(FILES generator/proto/_utils.py
|
||||
DESTINATION ${PYTHON_INSTDIR}/proto/)
|
||||
install( FILES generator/proto/_utils.py
|
||||
DESTINATION ${PYTHON_INSTDIR}/proto/ )
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
install(
|
||||
@@ -123,7 +123,7 @@ if(nanopb_BUILD_RUNTIME)
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
target_include_directories(protobuf-nanopb-static INTERFACE
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -9,9 +9,6 @@ nanopb_generate_cpp(PROTO_SRCS PROTO_HDRS RELPATH proto
|
||||
proto/simple.proto proto/sub/unlucky.proto)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
#add_custom_target(generate_proto_sources DEPENDS ${PROTO_SRCS} ${PROTO_HDRS})
|
||||
set_source_files_properties(${PROTO_SRCS} ${PROTO_HDRS}
|
||||
PROPERTIES GENERATED TRUE)
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -g -O0")
|
||||
|
||||
|
||||
@@ -7,9 +7,6 @@ include_directories(${NANOPB_INCLUDE_DIRS})
|
||||
|
||||
nanopb_generate_cpp(PROTO_SRCS PROTO_HDRS simple.proto)
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
#add_custom_target(generate_proto_sources DEPENDS ${PROTO_SRCS} ${PROTO_HDRS})
|
||||
set_source_files_properties(${PROTO_SRCS} ${PROTO_HDRS}
|
||||
PROPERTIES GENERATED TRUE)
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -g -O0")
|
||||
|
||||
|
||||
0
components/spotify/cspot/bell/nanopb/generator/protoc
Normal file → Executable file
0
components/spotify/cspot/bell/nanopb/generator/protoc
Normal file → Executable file
1
components/spotify/cspot/bell/nanopb/generator/protoc-gen-nanopb
Normal file → Executable file
1
components/spotify/cspot/bell/nanopb/generator/protoc-gen-nanopb
Normal file → Executable file
@@ -10,5 +10,4 @@
|
||||
# --plugin= on the command line.
|
||||
|
||||
MYPATH=$(dirname "$0")
|
||||
echo "Executing $MYPATH/nanopb_generator.py "
|
||||
exec "$MYPATH/nanopb_generator.py" --protoc-plugin
|
||||
|
||||
@@ -52,6 +52,11 @@
|
||||
* Normally it is automatically detected based on __BYTE_ORDER__ macro. */
|
||||
/* #define PB_LITTLE_ENDIAN_8BIT 1 */
|
||||
|
||||
/* Configure static assert mechanism. Instead of changing these, set your
|
||||
* compiler to C11 standard mode if possible. */
|
||||
/* #define PB_C99_STATIC_ASSERT 1 */
|
||||
/* #define PB_NO_STATIC_ASSERT 1 */
|
||||
|
||||
/******************************************************************
|
||||
* You usually don't need to change anything below this line. *
|
||||
* Feel free to look around and use the defined macros, though. *
|
||||
@@ -60,7 +65,7 @@
|
||||
|
||||
/* Version of the nanopb library. Just in case you want to check it in
|
||||
* your own program. */
|
||||
#define NANOPB_VERSION "nanopb-0.4.6-dev"
|
||||
#define NANOPB_VERSION "nanopb-0.4.7-dev"
|
||||
|
||||
/* Include all the system headers needed by nanopb. You will need the
|
||||
* definitions of the following:
|
||||
@@ -165,14 +170,17 @@ extern "C" {
|
||||
# if defined(__ICCARM__)
|
||||
/* IAR has static_assert keyword but no _Static_assert */
|
||||
# define PB_STATIC_ASSERT(COND,MSG) static_assert(COND,#MSG);
|
||||
# elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
|
||||
/* C11 standard _Static_assert mechanism */
|
||||
# define PB_STATIC_ASSERT(COND,MSG) _Static_assert(COND,#MSG);
|
||||
# else
|
||||
# elif defined(PB_C99_STATIC_ASSERT)
|
||||
/* Classic negative-size-array static assert mechanism */
|
||||
# define PB_STATIC_ASSERT(COND,MSG) typedef char PB_STATIC_ASSERT_MSG(MSG, __LINE__, __COUNTER__)[(COND)?1:-1];
|
||||
# define PB_STATIC_ASSERT_MSG(MSG, LINE, COUNTER) PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER)
|
||||
# define PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER) pb_static_assertion_##MSG##_##LINE##_##COUNTER
|
||||
# elif defined(__cplusplus)
|
||||
/* C++11 standard static_assert mechanism */
|
||||
# define PB_STATIC_ASSERT(COND,MSG) static_assert(COND,#MSG);
|
||||
# else
|
||||
/* C11 standard _Static_assert mechanism */
|
||||
# define PB_STATIC_ASSERT(COND,MSG) _Static_assert(COND,#MSG);
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
@@ -180,6 +188,14 @@ extern "C" {
|
||||
# define PB_STATIC_ASSERT(COND,MSG)
|
||||
#endif
|
||||
|
||||
/* Test that PB_STATIC_ASSERT works
|
||||
* If you get errors here, you may need to do one of these:
|
||||
* - Enable C11 standard support in your compiler
|
||||
* - Define PB_C99_STATIC_ASSERT to enable C99 standard support
|
||||
* - Define PB_NO_STATIC_ASSERT to disable static asserts altogether
|
||||
*/
|
||||
PB_STATIC_ASSERT(1, STATIC_ASSERT_IS_NOT_WORKING)
|
||||
|
||||
/* Number of required fields to keep track of. */
|
||||
#ifndef PB_MAX_REQUIRED_FIELDS
|
||||
#define PB_MAX_REQUIRED_FIELDS 64
|
||||
@@ -886,10 +902,13 @@ struct pb_extension_s {
|
||||
#define PB_INLINE_CONSTEXPR PB_CONSTEXPR
|
||||
#endif // __cplusplus >= 201703L
|
||||
|
||||
extern "C++"
|
||||
{
|
||||
namespace nanopb {
|
||||
// Each type will be partially specialized by the generator.
|
||||
template <typename GenMessageT> struct MessageDescriptor;
|
||||
} // namespace nanopb
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
|
||||
@@ -67,14 +67,12 @@ typedef struct {
|
||||
|
||||
static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count)
|
||||
{
|
||||
size_t i;
|
||||
const pb_byte_t *source = (const pb_byte_t*)stream->state;
|
||||
stream->state = (pb_byte_t*)stream->state + count;
|
||||
|
||||
if (buf != NULL)
|
||||
{
|
||||
for (i = 0; i < count; i++)
|
||||
buf[i] = source[i];
|
||||
memcpy(buf, source, count * sizeof(pb_byte_t));
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -211,18 +209,20 @@ static bool checkreturn pb_decode_varint32_eof(pb_istream_t *stream, uint32_t *d
|
||||
PB_RETURN_ERROR(stream, "varint overflow");
|
||||
}
|
||||
}
|
||||
else if (bitpos == 28)
|
||||
{
|
||||
if ((byte & 0x70) != 0 && (byte & 0x78) != 0x78)
|
||||
{
|
||||
PB_RETURN_ERROR(stream, "varint overflow");
|
||||
}
|
||||
result |= (uint32_t)(byte & 0x0F) << bitpos;
|
||||
}
|
||||
else
|
||||
{
|
||||
result |= (uint32_t)(byte & 0x7F) << bitpos;
|
||||
}
|
||||
bitpos = (uint_fast8_t)(bitpos + 7);
|
||||
} while (byte & 0x80);
|
||||
|
||||
if (bitpos == 35 && (byte & 0x70) != 0)
|
||||
{
|
||||
/* The last byte was at bitpos=28, so only bottom 4 bits fit. */
|
||||
PB_RETURN_ERROR(stream, "varint overflow");
|
||||
}
|
||||
}
|
||||
|
||||
*dest = result;
|
||||
@@ -243,12 +243,12 @@ bool checkreturn pb_decode_varint(pb_istream_t *stream, uint64_t *dest)
|
||||
|
||||
do
|
||||
{
|
||||
if (bitpos >= 64)
|
||||
PB_RETURN_ERROR(stream, "varint overflow");
|
||||
|
||||
if (!pb_readbyte(stream, &byte))
|
||||
return false;
|
||||
|
||||
if (bitpos >= 63 && (byte & 0xFE) != 0)
|
||||
PB_RETURN_ERROR(stream, "varint overflow");
|
||||
|
||||
result |= (uint64_t)(byte & 0x7F) << bitpos;
|
||||
bitpos = (uint_fast8_t)(bitpos + 7);
|
||||
} while (byte & 0x80);
|
||||
@@ -761,7 +761,10 @@ static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type
|
||||
{
|
||||
prev_bytes_left = substream.bytes_left;
|
||||
if (!field->descriptor->field_callback(&substream, NULL, field))
|
||||
PB_RETURN_ERROR(stream, "callback failed");
|
||||
{
|
||||
PB_SET_ERROR(stream, substream.errmsg ? substream.errmsg : "callback failed");
|
||||
return false;
|
||||
}
|
||||
} while (substream.bytes_left > 0 && substream.bytes_left < prev_bytes_left);
|
||||
|
||||
if (!pb_close_string_substream(stream, &substream))
|
||||
|
||||
@@ -51,12 +51,10 @@ static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb
|
||||
|
||||
static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count)
|
||||
{
|
||||
size_t i;
|
||||
pb_byte_t *dest = (pb_byte_t*)stream->state;
|
||||
stream->state = dest + count;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
dest[i] = buf[i];
|
||||
memcpy(dest, buf, count * sizeof(pb_byte_t));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -626,8 +624,9 @@ bool checkreturn pb_encode_varint(pb_ostream_t *stream, pb_uint64_t value)
|
||||
bool checkreturn pb_encode_svarint(pb_ostream_t *stream, pb_int64_t value)
|
||||
{
|
||||
pb_uint64_t zigzagged;
|
||||
pb_uint64_t mask = ((pb_uint64_t)-1) >> 1; /* Satisfy clang -fsanitize=integer */
|
||||
if (value < 0)
|
||||
zigzagged = ~((pb_uint64_t)value << 1);
|
||||
zigzagged = ~(((pb_uint64_t)value & mask) << 1);
|
||||
else
|
||||
zigzagged = (pb_uint64_t)value << 1;
|
||||
|
||||
|
||||
@@ -146,7 +146,7 @@ int main(int argc, char *argv[])
|
||||
filename = argv[2];
|
||||
}
|
||||
|
||||
elf_firmware_t firmware;
|
||||
elf_firmware_t firmware = {};
|
||||
elf_read_firmware(filename, &firmware);
|
||||
avr_init(g_avr);
|
||||
avr_load_firmware(g_avr, &firmware);
|
||||
|
||||
BIN
components/spotify/cspot/bell/src/.DS_Store
vendored
BIN
components/spotify/cspot/bell/src/.DS_Store
vendored
Binary file not shown.
@@ -1,88 +0,0 @@
|
||||
#include "BaseHTTPServer.h"
|
||||
#include <sstream>
|
||||
|
||||
unsigned char bell::BaseHTTPServer::h2int(char c)
|
||||
{
|
||||
if (c >= '0' && c <= '9')
|
||||
{
|
||||
return ((unsigned char)c - '0');
|
||||
}
|
||||
if (c >= 'a' && c <= 'f')
|
||||
{
|
||||
return ((unsigned char)c - 'a' + 10);
|
||||
}
|
||||
if (c >= 'A' && c <= 'F')
|
||||
{
|
||||
return ((unsigned char)c - 'A' + 10);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
std::string bell::BaseHTTPServer::urlDecode(std::string str)
|
||||
{
|
||||
std::string encodedString = "";
|
||||
char c;
|
||||
char code0;
|
||||
char code1;
|
||||
for (int i = 0; i < str.length(); i++)
|
||||
{
|
||||
c = str[i];
|
||||
if (c == '+')
|
||||
{
|
||||
encodedString += ' ';
|
||||
}
|
||||
else if (c == '%')
|
||||
{
|
||||
i++;
|
||||
code0 = str[i];
|
||||
i++;
|
||||
code1 = str[i];
|
||||
c = (h2int(code0) << 4) | h2int(code1);
|
||||
encodedString += c;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
encodedString += c;
|
||||
}
|
||||
}
|
||||
|
||||
return encodedString;
|
||||
}
|
||||
|
||||
std::vector<std::string> bell::BaseHTTPServer::splitUrl(const std::string &url, char delimiter)
|
||||
{
|
||||
std::stringstream ssb(url);
|
||||
std::string segment;
|
||||
std::vector<std::string> seglist;
|
||||
|
||||
while (std::getline(ssb, segment, delimiter))
|
||||
{
|
||||
seglist.push_back(segment);
|
||||
}
|
||||
return seglist;
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> bell::BaseHTTPServer::parseQueryString(const std::string &queryString)
|
||||
{
|
||||
std::map<std::string, std::string> query;
|
||||
auto prefixedString = "&" + queryString;
|
||||
while (prefixedString.find("&") != std::string::npos)
|
||||
{
|
||||
auto keyStart = prefixedString.find("&");
|
||||
auto keyEnd = prefixedString.find("=");
|
||||
// Find second occurence of "&" in prefixedString
|
||||
auto valueEnd = prefixedString.find("&", keyStart + 1);
|
||||
if (valueEnd == std::string::npos)
|
||||
{
|
||||
valueEnd = prefixedString.size();
|
||||
}
|
||||
|
||||
auto key = prefixedString.substr(keyStart + 1, keyEnd - 1);
|
||||
auto value = prefixedString.substr(keyEnd + 1, valueEnd - keyEnd - 1);
|
||||
query[key] = urlDecode(value);
|
||||
prefixedString = prefixedString.substr(valueEnd);
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
#include "BellLogger.h"
|
||||
|
||||
std::shared_ptr<bell::AbstractLogger> bell::bellGlobalLogger;
|
||||
bell::AbstractLogger* bell::bellGlobalLogger;
|
||||
|
||||
void bell::setDefaultLogger() {
|
||||
bell::bellGlobalLogger = std::make_shared<bell::BellLogger>();
|
||||
bell::bellGlobalLogger = new bell::BellLogger();
|
||||
}
|
||||
|
||||
void bell::enableSubmoduleLogging() {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user