Compare commits

..

5 Commits

Author SHA1 Message Date
github-actions
aa8b5ec2d4 Update prebuilt objects [skip actions] 2022-12-02 18:34:52 +00:00
Sebastien L
3c94f63876 Fix offline icons 2022-12-02 12:00:57 -05:00
Sebastien L
383a2fd7ce Fix include file name 2022-11-29 11:54:43 -05:00
Sebastien L
f74ecf5e60 improv-wifi initial commit 2022-11-29 11:53:20 -05:00
Sebastien L
1390e258db improv-wifi initial commit 2022-11-29 11:04:27 -05:00
3181 changed files with 21124 additions and 474091 deletions

View File

@@ -13,6 +13,7 @@ on:
description: 'Force a Release build. When not forced, the system will check for release word in the last commit message to trigger a release' 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 required: true
type: boolean type: boolean
jobs: jobs:
bootstrap: bootstrap:
name: Global setup name: Global setup
@@ -137,11 +138,11 @@ jobs:
if: ${{ needs.bootstrap.outputs.mock == 0 }} if: ${{ needs.bootstrap.outputs.mock == 0 }}
run: | run: |
. ${IDF_PYTHON_ENV_PATH}/bin/activate . ${IDF_PYTHON_ENV_PATH}/bin/activate
chmod +x ./components/spotify/cspot/bell/external/nanopb/generator/protoc chmod +x ./components/spotify/cspot/bell/nanopb/generator/protoc
chmod +x ./components/spotify/cspot/bell/external/nanopb/generator/protoc-gen-nanopb chmod +x ./components/spotify/cspot/bell/nanopb/generator/protoc-gen-nanopb
chmod +x ./components/spotify/cspot/bell/external/nanopb/generator/*.py chmod +x ./components/spotify/cspot/bell/nanopb/generator/*.py
chmod +x ./components/spotify/cspot/bell/external/nanopb/generator/*.py2 chmod +x ./components/spotify/cspot/bell/nanopb/generator/*.py2
chmod +x ./components/spotify/cspot/bell/external/nanopb/generator/proto/*.py chmod +x ./components/spotify/cspot/bell/nanopb/generator/proto/*.py
echo "Copying target sdkconfig" echo "Copying target sdkconfig"
cp build-scripts/${TARGET_BUILD_NAME}-sdkconfig.defaults sdkconfig cp build-scripts/${TARGET_BUILD_NAME}-sdkconfig.defaults sdkconfig
echo "Building project" echo "Building project"
@@ -227,7 +228,5 @@ jobs:
update_web_installer: update_web_installer:
name: Update Web Installer After Release name: Update Web Installer After Release
needs: [ bootstrap, build ] needs: [ bootstrap, build ]
if: ${{ always() && !cancelled() && needs.bootstrap.outputs.release_flag == 1 && needs.bootstrap.outputs.mock == 0 }} if: ${{( always() && !cancelled() ) && needs.bootstrap.outputs.release_flag == 1 && needs.bootstrap.outputs.mock == 0 }}
uses: ./.github/workflows/web_deploy.yml uses: ./.github/workflows/web_deploy.yml
secrets:
WEB_INSTALLER: ${{ secrets.WEB_INSTALLER }}

View File

@@ -19,7 +19,6 @@ on:
branches: [ master-cmake ] branches: [ master-cmake ]
schedule: schedule:
- cron: '19 12 * * 4' - cron: '19 12 * * 4'
workflow_dispatch:
jobs: jobs:
analyze: analyze:
@@ -40,7 +39,7 @@ jobs:
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@v2 uses: github/codeql-action/init@v1
with: with:
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file. # If you wish to specify custom queries, you can do so here or in a config file.
@@ -51,7 +50,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below) # If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@v2 uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell. # Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl # 📚 https://git.io/JvXDl
@@ -63,13 +62,6 @@ jobs:
#- run: | #- run: |
# make bootstrap # make bootstrap
# make release # make release
# Exclude specific artifacts from analysis
- name: Exclude Artifacts
run: |
# Exclude components/wifi-manager/webapp/dist/js/index* from analysis
echo 'components/wifi-manager/webapp/dist/js/index*' >> .codeql-exclude-paths
echo 'components/wifi-manager/webapp/dist/js/index*' >> .codeql-exclude-paths.txt
echo 'components/wifi-manager/webapp/dist/index*' >> .codeql-exclude-paths
echo 'components/wifi-manager/webapp/dist/index*' >> .codeql-exclude-paths.txt
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2 uses: github/codeql-action/analyze@v1

View File

@@ -51,11 +51,11 @@ jobs:
run: | run: |
git update-index --chmod=+x ./server_certs/getcert.sh git update-index --chmod=+x ./server_certs/getcert.sh
git update-index --chmod=+x ./buildFirmware.sh git update-index --chmod=+x ./buildFirmware.sh
git update-index --chmod=+x ./components/spotify/cspot/bell/external/nanopb/generator/protoc git update-index --chmod=+x ./components/spotify/cspot/bell/nanopb/generator/protoc
git update-index --chmod=+x ./components/spotify/cspot/bell/external/nanopb/generator/protoc-gen-nanopb git update-index --chmod=+x ./components/spotify/cspot/bell/nanopb/generator/protoc-gen-nanopb
git update-index --chmod=+x ./components/spotify/cspot/bell/external/nanopb/generator/*.py git update-index --chmod=+x ./components/spotify/cspot/bell/nanopb/generator/*.py
git update-index --chmod=+x ./components/spotify/cspot/bell/external/nanopb/generator/*.py2 git update-index --chmod=+x ./components/spotify/cspot/bell/nanopb/generator/*.py2
git update-index --chmod=+x ./components/spotify/cspot/bell/external/nanopb/generator/proto/*.py git update-index --chmod=+x ./components/spotify/cspot/bell/nanopb/generator/proto/*.py
cd server_certs;./getcert.sh;cat github.pem;cd .. cd server_certs;./getcert.sh;cat github.pem;cd ..

View File

@@ -1,9 +1,6 @@
name: Update Web Installer name: Update Web Installer
on: on:
workflow_call: workflow_call:
secrets:
WEB_INSTALLER:
required: true
workflow_dispatch: workflow_dispatch:
jobs: jobs:
update_web_installer: update_web_installer:

10
.gitignore vendored
View File

@@ -18,3 +18,13 @@ components/wifi-manager/UML-State-Machine-in-C
envfile.txt envfile.txt
artifacts artifacts
web-installer web-installer
squeezelite-esp32.code-workspace
esp-idf-vscode-generated.gdb
debug.log
components/wifi-manager/esp32_improv.cpp.txt
components/wifi-manager/esp32_improv.h.txt

View File

@@ -13,7 +13,7 @@ add_definitions(-DHIERARCHICAL_STATES=1)
#add_definitions(-DNETWORK_ETHERNET_LOG_LEVEL=ESP_LOG_DEBUG) #add_definitions(-DNETWORK_ETHERNET_LOG_LEVEL=ESP_LOG_DEBUG)
#uncomment line below to get network status debug logs #uncomment line below to get network status debug logs
#add_definitions(-DNETWORK_STATUS_LOG_LEVEL=ESP_LOG_DEBUG) #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_WIFI_LOG_LEVEL=ESP_LOG_DEBUG)
#add_definitions(-DNETWORK_MANAGER_LOG_LEVEL=ESP_LOG_DEBUG) #add_definitions(-DNETWORK_MANAGER_LOG_LEVEL=ESP_LOG_DEBUG)
#add_definitions(-DNETWORK_HTTP_SERVER_LOG_LEVEL=ESP_LOG_DEBUG) #add_definitions(-DNETWORK_HTTP_SERVER_LOG_LEVEL=ESP_LOG_DEBUG)

View File

@@ -15,7 +15,7 @@ ENV GCC_TOOLS_BASE=/opt/esp/tools/xtensa-esp32-elf/esp-2021r2-8.4.0/xtensa-esp32
# To run the image interactive (windows): # To run the image interactive (windows):
# docker run --rm -v %cd%:/project -w /project -it sle118/squeezelite-esp32-idfv43 # docker run --rm -v %cd%:/project -w /project -it sle118/squeezelite-esp32-idfv43
# To run the image interactive (linux): # To run the image interactive (linux):
# docker run --rm -v `pwd`:/project -w /project -it sle118/squeezelite-esp32-idfv43 # docker run --rm -v `pwd`:/project -w /project -it sle118/squeezelite-esp32-idfv4-master
# to build the web app inside of the interactive session # to build the web app inside of the interactive session
# pushd components/wifi-manager/webapp/ && npm install && npm run-script build && popd # pushd components/wifi-manager/webapp/ && npm install && npm run-script build && popd
# #
@@ -90,7 +90,7 @@ RUN : \
&& pip show pygit2 \ && pip show pygit2 \
&& python --version \ && python --version \
&& pip --version \ && pip --version \
&& pip install protobuf grpcio-tools \ && pip3 install protobuf grpcio-tools \
&& rm -rf $IDF_TOOLS_PATH/dist \ && rm -rf $IDF_TOOLS_PATH/dist \
&& : && :

216
README.md
View File

@@ -1,23 +1,21 @@
[![Platform Build](https://github.com/sle118/squeezelite-esp32/actions/workflows/Platform_build.yml/badge.svg)](https://github.com/sle118/squeezelite-esp32/actions/workflows/Platform_build.yml) ![Cross-Build](https://github.com/sle118/squeezelite-esp32/workflows/Cross-Build/badge.svg?branch=master-cmake)
![ESP-IDF v4.3.1](https://github.com/sle118/squeezelite-esp32/actions/workflows/esp-idf-v4.3-build.yml/badge.svg?branch=master-v4.3)
# Squeezelite-esp32 # Squeezelite-esp32
## What is this
## What is this?
Squeezelite-esp32 is an audio software suite made to run on espressif's ESP32 wifi (b/g/n) and bluetooth chipset. It offers the following capabilities Squeezelite-esp32 is an audio software suite made to run on espressif's ESP32 wifi (b/g/n) and bluetooth chipset. It offers the following capabilities
- Stream your local music and connect to all major on-line music providers (Spotify, Deezer, Tidal, Qobuz) using [Logitech Media Server - a.k.a LMS](https://forums.slimdevices.com/) and enjoy multi-room audio synchronization. LMS can be extended by numerous plugins and can be controlled using a Web browser or dedicated applications (iPhone, Android). It can also send audio to UPnP, Sonos, ChromeCast and AirPlay speakers/devices. - Stream your local music and connect to all major on-line music providers (Spotify, Deezer, Tidal, Qobuz) using [Logitech Media Server - a.k.a LMS](https://forums.slimdevices.com/) and enjoy multi-room audio synchronization. LMS can be extended by numerous plugins and can be controlled using a Web browser or dedicated applications (iPhone, Android). It can also send audio to UPnP, Sonos, ChromeCast and AirPlay speakers/devices.
- Stream from a **Bluetooth** device (iPhone, Android) - Stream from a Bluetooth device (iPhone, Android)
- Stream from an **AirPlay** controller (iPhone, iTunes ...) and enjoy synchronization multiroom as well (although it's AirPlay 1 only) - Stream from an AirPlay controller (iPhone, iTunes ...) and enjoy synchronization multiroom as well (although it's AirPlay 1 only)
- Stream direcly from **Spotify** using SpotifyConnect (thanks to [cspot](https://github.com/feelfreelinux/cspot)
Depending on the hardware connected to the ESP32, you can send audio to a local DAC, to SPDIF or to a Bluetooth speaker. The bare minimum required hardware is a WROVER module with 4MB of Flash and 4MB of PSRAM (https://www.espressif.com/en/products/modules/esp32). With that module standalone, just apply power and you can stream to a Bluetooth speaker. You can also send audio to most I2S DAC as well as to SPDIF receivers using just a cable or an optical transducer. Depending on the hardware connected to the ESP32, you can send audio to a local DAC, to SPDIF or to a Bluetooth speaker. The bare minimum required hardware is a WROVER module with 4MB of Flash and 4MB of PSRAM (https://www.espressif.com/en/products/modules/esp32). With that module standalone, just apply power and you can stream to a Bluetooth speaker. You can also send audio to most I2S DAC as well as to SPDIF receivers using just a cable or an optical transducer.
But squeezelite-esp32 is highly extensible and you can add But squeezelite-esp32 is highly extensible and you can add
- [Buttons](#buttons) and [Rotary Encoder](#rotary-encoder) and map/combine them to various functions (play, pause, volume, next ...) - Buttons and Rotary Encoder and map/combine them to various functions (play, pause, volume, next ...)
- [GPIO expander](#gpio-expanders) (buttons, led and rotary) - IR receiver (no pullup resistor or capacitor needed, just the 38kHz receiver)
- [IR receiver](#infrared) (no pullup resistor or capacitor needed, just the 38kHz receiver) - Monochrome, GrayScale or Color displays using SPI or I2C (supported drivers are SH1106, SSD1306, SSD1322, SSD1326/7, SSD1351, ST7735, ST7789 and ILI9341).
- [Monochrome, GrayScale or Color displays](#display) using SPI or I2C (supported drivers are SH1106, SSD1306, SSD1322, SSD1326/7, SSD1351, ST7735, ST7789 and ILI9341). - Ethernet using a Microchip LAN8720 with RMII interface or Davicom DM9051 over SPI.
- [Ethernet](#ethernet-required-unpublished-version-43) using a Microchip LAN8720 with RMII interface or Davicom DM9051/W5500 over SPI.
Other features include Other features include
@@ -52,44 +50,29 @@ The esp32 must run at 240 MHz, with Quad-SPI I/O at 80 MHz and a clock of 40 Mhz
In 16 bits mode, although 192 kHz is reported as max rate, it's highly recommended to limit reported sampling rate to 96k (-Z 96000). Note that some high-speed 24/96k on-line streams might stutter because of TCP/IP stack performances. It is usually due to the fact that the server sends small packets of data and the esp32 cannot receive encoded audio fast enough, regardless of task priority settings (I've tried to tweak that a fair bit). The best option in that case is to let LMS proxy the stream as it will provide larger chunks and a "smoother" stream that can then be handled. In 16 bits mode, although 192 kHz is reported as max rate, it's highly recommended to limit reported sampling rate to 96k (-Z 96000). Note that some high-speed 24/96k on-line streams might stutter because of TCP/IP stack performances. It is usually due to the fact that the server sends small packets of data and the esp32 cannot receive encoded audio fast enough, regardless of task priority settings (I've tried to tweak that a fair bit). The best option in that case is to let LMS proxy the stream as it will provide larger chunks and a "smoother" stream that can then be handled.
Note as well that some codecs consume more CPU than others or have not been optimized as much. I've done my best to tweak these, but that level of optimization includes writing some assembly which is painful. One very demanding codec is AAC when files are encoded with SBR. It allows reconstruction of upper part of spectrum and thus higher sampling rate, but the codec spec is such that this is optional, you can decode simply lower band and accept lower sampling rate - See the AAC_DISABLE_SBR option below. Note as well that some codecs consume more CPU than others or have not been optimized as much. I've done my best to tweak these, but that level of optimization includes writing some assembly which is painful. One very demanding codec is AAC when files are encoded with SBR. It allows reconstruction of upper part of spectrum and thus higher sampling rate, but the codec spec is such that this is optional, you can decode simply lower band and accept lower sampling rate - See the AAC_DISABLE_SBR option below.
## Supported Hardware ## Supported Hardware
Any esp32-based hardware with at least 4MB of flash and 4MB of PSRAM will be capable of running squeezelite-esp32 and there are various boards that include such chip. A few are mentionned below, but any should work. You can find various help & instructions [here](https://forums.slimdevices.com/showthread.php?112697-ANNOUNCE-Squeezelite-ESP32-(dedicated-thread)) Any esp32-based hardware with at least 4MB of flash and 4MB of PSRAM will be capable of running squeezelite-esp32 and there are various boards that include such chip. A few are mentionned below, but any should work. You can find various help & instructions [here](https://forums.slimdevices.com/showthread.php?112697-ANNOUNCE-Squeezelite-ESP32-(dedicated-thread))
**For the sake of clarity, WROOM modules DO NOT work as they don't include PSRAM. Some designs might add it externally, but it's (very) unlikely.** **For the sake of clarity, WROOM modules DO NOT work as they don't include PSRAM. Some designs might add it externally, but it's (very) unlikely.**
### Raw WROVER module ### Raw WROVER module
Per above description, a [WROVER module](https://www.espressif.com/en/products/modules/esp32) is enough to run Squeezelite-esp32, but that requires a bit of tinkering to extend it to have analogue audio or hardware buttons (e.g.) Per above description, a [WROVER module](https://www.espressif.com/en/products/modules/esp32) is enough to run Squeezelite-esp32, but that requires a bit of tinkering to extend it to have analogue audio or hardware buttons (e.g.)
Please note that when sending to a Bluetooth speaker (source), only 44.1 kHz can be used, so you either let LMS do the resampling, but you must make sure it only sends 44.1kHz tracks or enable internal resampling (using -R) option. If you connect a DAC, choice of sample rates will depends on its capabilities. See below for more details. Please note that when sending to a Bluetooth speaker (source), only 44.1 kHz can be used, so you either let LMS do the resampling, but you must make sure it only sends 44.1kHz tracks or enable internal resampling (using -R) option. If you connect a DAC, choice of sample rates will depends on its capabilities. See below for more details.
Most DAC will work out-of-the-box with simply an I2S connection, but some require specific commands to be sent using I2C. See DAC option below to understand how to send these dedicated commands. There is build-in support for TAS575x, TAS5780, TAS5713 and AC101 DAC. Most DAC will work out-of-the-box with simply an I2S connection, but some require specific commands to be sent using I2C. See DAC option below to understand how to send these dedicated commands. There is build-in support for TAS575x, TAS5780, TAS5713 and AC101 DAC.
### SqueezeAMP ### SqueezeAMP
This is the main hardware companion of Squeezelite-esp32 and has been developped together. Details on capabilities can be found [here](https://forums.slimdevices.com/showthread.php?110926-pre-ANNOUNCE-SqueezeAMP-and-SqueezeliteESP32) and [here](https://github.com/philippe44/SqueezeAMP). This is the main hardware companion of Squeezelite-esp32 and has been developped together. Details on capabilities can be found [here](https://forums.slimdevices.com/showthread.php?110926-pre-ANNOUNCE-SqueezeAMP-and-SqueezeliteESP32) and [here](https://github.com/philippe44/SqueezeAMP).
If you want to rebuild, use the `squeezelite-esp32-SqueezeAmp-sdkconfig.defaults` configuration file. if you want to rebuild, use the `squeezelite-esp32-SqueezeAmp-sdkconfig.defaults` configuration file.
NB: You can use the pre-build binaries SqueezeAMP4MBFlash which has all the hardware I/O set properly. You can also use the generic binary I2S4MBFlash in which case the NVS parameters shall be set to get the exact same behavior NB: You can use the pre-build binaries SqueezeAMP4MBFlash which has all the hardware I/O set properly. You can also use the generic binary I2S4MBFlash in which case the NVS parameters shall be set to get the exact same behavior
- set_GPIO: `12=green,13=red,34=jack,2=spkfault` - set_GPIO: 12=green,13=red,34=jack,2=spkfault
- bat_config: `channel=7,scale=20.24` - batt_config: channel=7,scale=20.24
- dac_config: `model=TAS57xx,bck=33,ws=25,do=32,sda=27,scl=26,mute=14:0` - dac_config: model=TAS57xx,bck=33,ws=25,do=32,sda=27,scl=26,mute=14:0
- spdif_config: `bck=33,ws=25,do=15` - spdif_config: bck=33,ws=25,do=15
### MuseLuxe
This portable battery-powered [speaker](https://raspiaudio.com/produit/esp-muse-luxe) is compatible with squeezelite-esp32 for which there is a dedicated build supplied with every update. If you want to rebuild, use the `squeezelite-esp32-Muse-sdkconfig.defaults` configuration file.
NB: You can use the pre-build binaries Muse4MBFlash which has all the hardware I/O set properly. You can also use the generic binary I2S4MBFlash in which case the NVS parameters shall be set to get the exact same behavior
- target: `muse`
- bat_config: `channel=5,scale=7.48,atten=3,cells=1`
- spi_config: `"mosi=15,miso=2,clk=14` *(this one is probably optional)*
- dac_config: `model=I2S,bck=5,ws=25,do=26,di=35,i2c=16,sda=18,scl=23,mck`
- dac_controlset: `{"init":[ {"reg":0,"val":128}, {"reg":0,"val":0}, {"reg":25,"val":4}, {"reg":1,"val":80}, {"reg":2,"val":0}, {"reg":8,"val":0}, {"reg":4,"val":192}, {"reg":0,"val":18}, {"reg":1,"val":0}, {"reg":23,"val":24}, {"reg":24,"val":2}, {"reg":38,"val":9}, {"reg":39,"val":144}, {"reg":42,"val":144}, {"reg":43,"val":128}, {"reg":45,"val":128}, {"reg":27,"val":0}, {"reg":26,"val":0}, {"reg":2,"val":240}, {"reg":2,"val":0}, {"reg":29,"val":28}, {"reg":4,"val":48}, {"reg":25,"val":0}, {"reg":46,"val":33}, {"reg":47,"val":33} ]}`
- actrls_config: buttons
- define a "buttons" variable with: `[{"gpio":32, "pull":true, "debounce":10, "normal":{"pressed":"ACTRLS_VOLDOWN"}}, {"gpio":19, "pull":true, "debounce":40, "normal":{"pressed":"ACTRLS_VOLUP"}}, {"gpio":12, "pull":true, "debounce":40, "long_press":1000, "normal":{"pressed":"ACTRLS_TOGGLE"},"longpress":{"pressed":"ACTRLS_POWER"}}]`
### ESP32-A1S ### ESP32-A1S
Works with [ESP32-A1S](https://docs.ai-thinker.com/esp32-a1s) module that includes audio codec and headset output. You still need to use a demo board like [this](https://www.aliexpress.com/item/4001060963585.html) or an external amplifier if you want direct speaker connection. Note that there is a version with AC101 codec and another one with ES8388 with probably two variants - these boards are a mess (see below) Works with [ESP32-A1S](https://docs.ai-thinker.com/esp32-a1s) module that includes audio codec and headset output. You still need to use a demo board like [this](https://www.aliexpress.com/item/4001060963585.html) or an external amplifier if you want direct speaker connection. Note that there is a version with AC101 codec and another one with ES8388 (see below)
The board shown above has the following IO set The board shown above has the following IO set
- amplifier: GPIO21 - amplifier: GPIO21
@@ -105,30 +88,23 @@ The board shown above has the following IO set
(note that some GPIO need pullups) (note that some GPIO need pullups)
So a possible config would be So a possible config would be
- set_GPIO: `21=amp,22=green:0,39=jack:0` - set_GPIO: 21=amp,22=green:0,39=jack:0
- a button mapping: - a button mapping:
```json ```
[{"gpio":5,"normal":{"pressed":"ACTRLS_TOGGLE"}},{"gpio":18,"pull":true,"shifter_gpio":5,"normal":{"pressed":"ACTRLS_VOLUP"}, "shifted":{"pressed":"ACTRLS_NEXT"}}, {"gpio":23,"pull":true,"shifter_gpio":5,"normal":{"pressed":"ACTRLS_VOLDOWN"},"shifted":{"pressed":"ACTRLS_PREV"}}] [{"gpio":5,"normal":{"pressed":"ACTRLS_TOGGLE"}},{"gpio":18,"pull":true,"shifter_gpio":5,"normal":{"pressed":"ACTRLS_VOLUP"}, "shifted":{"pressed":"ACTRLS_NEXT"}}, {"gpio":23,"pull":true,"shifter_gpio":5,"normal":{"pressed":"ACTRLS_VOLDOWN"},"shifted":{"pressed":"ACTRLS_PREV"}}]
``` ```
for **AC101** for AC101
- dac_config: `model=AC101,bck=27,ws=26,do=25,di=35,sda=33,scl=32` - dac_config: model=AC101,bck=27,ws=26,do=25,di=35,sda=33,scl=32
for **ES8388** (it seems that there are variants with same version number - a total mess) for ES8388
- dac_config: `model=ES8388,bck=5,ws=25,do=26,sda=18,scl=23,i2c=16` - dac_config: model=ES8388,bck=5,ws=25,do=26,sda=18,scl=23,i2c=16
or
- dac_config: `model=ES8388,bck=27,ws=25,do=26,sda=33,scl=32,i2c=16`
### T-WATCH2020 by LilyGo ### T-WATCH2020 by LilyGo
This is a fun [smartwatch](http://www.lilygo.cn/prod_view.aspx?TypeId=50036&Id=1290&FId=t3:50036:3) based on ESP32. It has a 240x240 ST7789 screen and onboard audio. Not very useful to listen to anything but it works. This is an example of a device that requires an I2C set of commands for its dac (see below). There is a build-option if you decide to rebuild everything by yourself, otherwise the I2S default option works with the following parameters This is a fun [smartwatch](http://www.lilygo.cn/prod_view.aspx?TypeId=50036&Id=1290&FId=t3:50036:3) based on ESP32. It has a 240x240 ST7789 screen and onboard audio. Not very useful to listen to anything but it works. This is an example of a device that requires an I2C set of commands for its dac (see below). There is a build-option if you decide to rebuild everything by yourself, otherwise the I2S default option works with the following parameters
- dac_config: `model=I2S,bck=26,ws=25,do=33,i2c=106,sda=21,scl=22` - dac_config: model=I2S,bck=26,ws=25,do=33,i2c=106,sda=21,scl=22
- dac_controlset: - dac_controlset: { "init": [ {"reg":41, "val":128}, {"reg":18, "val":255} ], "poweron": [ {"reg":18, "val":64, "mode":"or"} ], "poweroff": [ {"reg":18, "val":191, "mode":"and"} ] }
```json - spi_config: dc=27,data=19,clk=18
{ "init": [ {"reg":41, "val":128}, {"reg":18, "val":255} ], "poweron": [ {"reg":18, "val":64, "mode":"or"} ], "poweroff": [ {"reg":18, "val":191, "mode":"and"} ] } - display_config: SPI,driver=ST7789,width=240,height=240,cs=5,back=12,speed=16000000,HFlip,VFlip
```
- spi_config: `dc=27,data=19,clk=18`
- display_config: `SPI,driver=ST7789,width=240,height=240,cs=5,back=12,speed=16000000,HFlip,VFlip`
### ESP32-WROVER + I2S DAC ### ESP32-WROVER + I2S DAC
Squeezelite-esp32 requires esp32 chipset and 4MB PSRAM. ESP32-WROVER meets these requirements. To get an audio output an I2S DAC can be used. Cheap PCM5102 I2S DACs work others may also work. PCM5012 DACs can be hooked up via: Squeezelite-esp32 requires esp32 chipset and 4MB PSRAM. ESP32-WROVER meets these requirements. To get an audio output an I2S DAC can be used. Cheap PCM5102 I2S DACs work others may also work. PCM5012 DACs can be hooked up via:
@@ -154,23 +130,18 @@ And the super cool project https://github.com/rochuck/squeeze-amp-too
## Configuration ## Configuration
To access NVS, in the webUI, go to credits and select "shows nvs editor". Go into the NVS editor tab to change NFS parameters. In syntax description below \<\> means a value while \[\] describe optional parameters. To access NVS, in the webUI, go to credits and select "shows nvs editor". Go into the NVS editor tab to change NFS parameters. In syntax description below \<\> means a value while \[\] describe optional parameters.
As mentionned above, there are a few dedicated builds that are provided today: SqueezeAMP and Muse but if you build it yourself, you can also create a build for T-WATCH2020. The default build is a generic firmware named I2S which can be configured through NVS to produce *exactly* the same results than dedicated builds. The difference is that parameters must be entered and can accidently be erased. The GUI provides a great help to load "known config sets" as well.
By design choice, there is no code that is only embedded for a given version, all code is always there. The philosophy is to minimize as much as possible platform-specific code and use of specific `#ifdef` is prohibited, no matter what. So if you want to add your own platfrom, please look **very hard** at the `main\KConfig.projbuild` to see how you can, using parameters below, make your device purely a configuration-based solution. When there is really no other option, look at `targets\<target>` to add your own code. I will not accept PR for code that can avoid creating such dedicated code whenever possible. The NVS "target" will be used to call target-specific code then, but again this is purely runtime, not compile-time.
### I2C ### I2C
The NVS parameter "i2c_config" set the i2c's gpio used for generic purpose (e.g. display). Leave it blank to disable I2C usage. Note that on SqueezeAMP, port must be 1. Default speed is 400000 but some display can do up to 800000 or more. Syntax is The NVS parameter "i2c_config" set the i2c's gpio used for generic purpose (e.g. display). Leave it blank to disable I2C usage. Note that on SqueezeAMP, port must be 1. Default speed is 400000 but some display can do up to 800000 or more. Syntax is
``` ```
sda=<gpio>,scl=<gpio>[,port=0|1][,speed=<speed>] sda=<gpio>,scl=<gpio>[,port=0|1][,speed=<speed>]
``` ```
**Please note that you can not use the same GPIO or port as the DAC.** <strong>Please note that you can not use the same GPIO or port as the DAC</strong>
### SPI ### SPI
The esp32 has 4 SPI sub-systems, one is unaccessible so numbering is 0..2 and SPI0 is reserved for Flash/PSRAM. The NVS parameter "spi_config" set the spi's gpio used for generic purpose (e.g. display). Leave it blank to disable SPI usage. The DC parameter is needed for displays. Syntax is The esp32 has 4 SPI sub-systems, one is unaccessible so numbering is 0..2 and SPI0 is reserved for Flash/PSRAM. The NVS parameter "spi_config" set the spi's gpio used for generic purpose (e.g. display). Leave it blank to disable SPI usage. The DC parameter is needed for displays. Syntax is
``` ```
data|mosi=<gpio>,clk=<gpio>[,dc=<gpio>][,host=1|2][,miso=<gpio>] data|mosi=<gpio>,clk=<gpio>[,dc=<gpio>][,host=1|2][,miso=<gpio>]
``` ```
Default and only "host" is 1 as others are used already by flash and spiram. The optional "miso" (MasterInSlaveOut) parameter is only used when SPI bus is bi-directional and shared with other peripheral like ethernet, gpio expander. Note that "data" can also be named "mosi" (MasterOutSlaveIn). Default "host" is 1. The "miso" parameter is only used when SPI bus is to be shared with other peripheral (e.g. ethernet, see below), otherwise it can be omitted. Note that "data" can also be named "mosi".
### DAC/I2S ### DAC/I2S
The NVS parameter "dac_config" set the gpio used for i2s communication with your DAC. You can define the defaults at compile time but nvs parameter takes precedence except for SqueezeAMP and A1S where these are forced at runtime. Syntax is The NVS parameter "dac_config" set the gpio used for i2s communication with your DAC. You can define the defaults at compile time but nvs parameter takes precedence except for SqueezeAMP and A1S where these are forced at runtime. Syntax is
``` ```
@@ -178,20 +149,17 @@ bck=<gpio>,ws=<gpio>,do=<gpio>[,mck][,mute=<gpio>[:0|1][,model=TAS57xx|TAS5713|A
``` ```
if "model" is not set or is not recognized, then default "I2S" is used. The option "mck" is used for some codecs that require a master clock (although they should not). Only GPIO0 can be used as MCLK and be aware that this cannot coexit with RMII Ethernet (see ethernet section below). I2C parameters are optional and only needed if your DAC requires an I2C control (See 'dac_controlset' below). Note that "i2c" parameters are decimal, hex notation is not allowed. if "model" is not set or is not recognized, then default "I2S" is used. The option "mck" is used for some codecs that require a master clock (although they should not). Only GPIO0 can be used as MCLK and be aware that this cannot coexit with RMII Ethernet (see ethernet section below). I2C parameters are optional and only needed if your DAC requires an I2C control (See 'dac_controlset' below). Note that "i2c" parameters are decimal, hex notation is not allowed.
So far, TAS57xx, TAS5713, AC101, WM8978 and ES8388 are recognized models where the proper init sequence/volume/power controls are sent. For other codecs that might require an I2C commands, please use the parameter "dac_controlset" that allows definition of simple commands to be sent over i2c for init, power, speakder and headset on and off using a JSON syntax: So far, TAS57xx, TAS5713, AC101, WM8978 and ES8388 are recognized models where the proper init sequence/volume/power controls are sent. For other codecs that might require an I2C commands, please use the parameter "dac_controlset" that allows definition of simple commands to be sent over i2c for init, power on and off using a JSON syntax:
```json
{ <command>: [ {"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"}, ... {{"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"} ],
<command>: [ {"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"}, ... {{"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"} ],
... }
``` ```
Where `<command>` is one of init, poweron, poweroff, speakeron, speakeroff, headseton, headsetoff { init: [ {"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"}, ... {{"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"} ],
poweron: [ {"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"}, ... {{"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"} ],
This is standard JSON notation, so if you are not familiar with it, Google is your best friend. Be aware that the '...' means you can have as many entries as you want, it's not part of the syntax. Every section is optional, but it does not make sense to set i2c in the 'dac_config' parameter and not setting anything here. The parameter 'mode' allows to *or* the register with the value or to *and* it. Don't set 'mode' if you simply want to write. The 'val parameter can be an array [v1, v2,...] to write a serie of bytes in a single i2c burst (in that case 'mode' is ignored). **Note that all values must be decimal**. You can use a validator like [this](https://jsonlint.com) to verify your syntax poweroff: [ {"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"}, ... {{"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"} ] }
```
This is standard JSON notation, so if you are not familiar with it, Google is your best friend. Be aware that the '...' means you can have as many entries as you want, it's not part of the syntax. Every section is optional, but it does not make sense to set i2c in the 'dac_config' parameter and not setting anything here. The parameter 'mode' allows to *or* the register with the value or to *and* it. Don't set 'mode' if you simply want to write. **Note that all values must be decimal**. You can use a validator like [this](https://jsonlint.com) to verify your syntax
NB: For specific builds (all except I2S), all this is ignored. For know codecs, the built-in sequences can be overwritten using dac_controlset NB: For specific builds (all except I2S), all this is ignored. For know codecs, the built-in sequences can be overwritten using dac_controlset
**Please note that you can not use the same GPIO or port as the I2C.** <strong>Please note that you can not use the same GPIO or port as the I2C</strong>
### SPDIF ### SPDIF
The NVS parameter "spdif_config" sets the i2s's gpio needed for SPDIF. The NVS parameter "spdif_config" sets the i2s's gpio needed for SPDIF.
@@ -216,26 +184,26 @@ GPIO ----210ohm-----------||---- coax S/PDIF signal out
| |
Ground -------------------------- coax signal ground Ground -------------------------- coax signal ground
``` ```
### Display ### Display
The NVS parameter "display_config" sets the parameters for an optional display. It can be I2C (see [here](#i2c) for shared bus) or SPI (see [here](#spi) for shared bus) Syntax is 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] 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[:x=<offset>][:y=<offset>]|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 - 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. Most displays require reset and will not initialize well otherwise. - 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 - 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 - 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 - Default speed is 8000000 (8MHz) but SPI can work up to 26MHz or even 40MHz
- SH1106 is 128x64 monochrome I2C/SPI [here](https://www.waveshare.com/wiki/1.3inch_OLED_HAT) - 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) - 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 - 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
- SSD1326 is 256x32 monochrome or grayscale 16-levels SPI [here](https://www.aliexpress.com/item/32833603664.html?spm=a2g0o.productlist.0.0.2d19776cyQvsBi&algo_pvid=c7a3db92-e019-4095-8a28-dfdf0a087f98&algo_expid=c7a3db92-e019-4095-8a28-dfdf0a087f98-1&btsid=0ab6f81e15955375483301352e4208&ws_ab_test=searchweb0_0,searchweb201602_,searchweb201603_) - SSD1326 is 256x32 monochrome or grayscale 16-levels SPI [here](https://www.aliexpress.com/item/32833603664.html?spm=a2g0o.productlist.0.0.2d19776cyQvsBi&algo_pvid=c7a3db92-e019-4095-8a28-dfdf0a087f98&algo_expid=c7a3db92-e019-4095-8a28-dfdf0a087f98-1&btsid=0ab6f81e15955375483301352e4208&ws_ab_test=searchweb0_0,searchweb201602_,searchweb201603_)
- SSD1327 is 128x128 16-level grayscale SPI [here](https://www.amazon.com/gp/product/B079N1LLG8/ref=ox_sc_act_title_1?smid=A1N6DLY3NQK2VM&psc=1) - artwork can be up to 96x96 with vertical vu-meter/spectrum - SSD1327 is 128x128 16-level grayscale SPI [here](https://www.amazon.com/gp/product/B079N1LLG8/ref=ox_sc_act_title_1?smid=A1N6DLY3NQK2VM&psc=1) - artwork can be up to 96x96 with vertical vu-meter/spectrum
- SSD1351 is 128x128 65k/262k color SPI [here](https://www.waveshare.com/product/displays/lcd-oled/lcd-oled-3/1.5inch-rgb-oled-module.htm) - SSD1351 is 128x128 65k/262k color SPI [here](https://www.waveshare.com/product/displays/lcd-oled/lcd-oled-3/1.5inch-rgb-oled-module.htm)
- SSD1675 is an e-ink paper and is experimental as e-ink is really not suitable for LMS du to its very low refresh rate - SSD1675 is an e-ink paper and is experimental as e-ink is really not suitable for LMS du to its very low refresh rate
- ST7735 is a 128x160 65k color SPI [here](https://www.waveshare.com/product/displays/lcd-oled/lcd-oled-3/1.8inch-lcd-module.htm). This needs a backlight control. Some have X/Y offsets betwen the driver and the glass (green/black/red models) that can be added using "x" and "y" options (case sensitive!) - ST7735 is a 128x160 65k color SPI [here](https://www.waveshare.com/product/displays/lcd-oled/lcd-oled-3/1.8inch-lcd-module.htm). This needs a backlight control
- ST7789 is a 240x320 65k (262k not enabled) color SPI [here](https://www.waveshare.com/product/displays/lcd-oled/lcd-oled-3/2inch-lcd-module.htm). It also exist with 240x240 displays. See **rotate** for use in portrait mode - ST7789 is a 240x320 65k (262k not enabled) color SPI [here](https://www.waveshare.com/product/displays/lcd-oled/lcd-oled-3/2inch-lcd-module.htm). It also exist with 240x240 displays. See **rotate** for use in portrait mode
- ILI9341 is another 240x320 65k (262k capable) color SPI. I've not used it much, the driver it has been provided by one external contributor to the project - ILI9341 is another 240x320 65k (262k capable) color SPI. I've not used it much, the driver it has been provided by one external contributor to the project
@@ -243,12 +211,13 @@ You can tweak how the vu-meter and spectrum analyzer are displayed, as well as s
The NVS parameter "metadata_config" sets how metadata is displayed for AirPlay and Bluetooth. Syntax is The NVS parameter "metadata_config" sets how metadata is displayed for AirPlay and Bluetooth. Syntax is
``` ```
[format=<display_content>][,speed=<speed>][,pause=<pause>][,artwork[:0|1]] [format=<display_content>][,speed=<speed>][,pause=<pause>]
``` ```
- 'speed' is the scrolling speed in ms (default is 33ms) - 'speed' is the scrolling speed in ms (default is 33ms)
- 'pause' is the pause time between scrolls in ms (default is 3600ms) - 'pause' is the pause time between scrolls in ms (default is 3600ms)
- 'format' can contain free text and any of the 3 keywords `%artist%`, `%album%`, `%title%`. Using that format string, the keywords are replaced by their value to build the string to be displayed. Note that the plain text following a keyword that happens to be empty during playback of a track will be removed. For example, if you have set format=`%artist% - %title%` and there is no artist in the metadata then only `<title>` will be displayed not ` - <title>`.
- 'artwork' enables coverart display, if available (does not work for Bluetooth). The optional parameter indicates if the artwork should be resized (1) to fit the available space. Note that the built-in resizer can only do 2,4 and 8 downsizing, so fit is not optimal. The artwork will be placed at the right of the display for landscape displays and underneath the two information lines for others (there is no user option to tweak that). - 'format' can contain free text and any of the 3 keywords %artist%, %album%, %title%. Using that format string, the keywords are replaced by their value to build the string to be displayed. Note that the plain text following a keyword that happens to be empty during playback of a track will be removed. For example, if you have set format=%artist% - %title% and there is no artist in the metadata then only <title> will be displayed not " - <title>".
### Infrared ### Infrared
You can use any IR receiver compatible with NEC protocol (38KHz). Vcc, GND and output are the only pins that need to be connected, no pullup, no filtering capacitor, it's a straight connection. You can use any IR receiver compatible with NEC protocol (38KHz). Vcc, GND and output are the only pins that need to be connected, no pullup, no filtering capacitor, it's a straight connection.
@@ -264,13 +233,13 @@ The parameter "set_GPIO" is used to assign GPIO to various functions.
GPIO can be set to GND provide or Vcc at boot. This is convenient to power devices that consume less than 40mA from the side connector. Be careful because there is no conflict checks being made wrt which GPIO you're changing, so you might damage your board or create a conflict here. GPIO can be set to GND provide or Vcc at boot. This is convenient to power devices that consume less than 40mA from the side connector. Be careful because there is no conflict checks being made wrt which GPIO you're changing, so you might damage your board or create a conflict here.
The `<amp>` parameter can use used to assign a GPIO that will be set to active level (default 1) when playback starts. It will be reset when squeezelite becomes idle. The idle timeout is set on the squeezelite command line through `-C <timeout>` The \<amp\> parameter can use used to assign a GPIO that will be set to active level (default 1) when playback starts. It will be reset when squeezelite becomes idle. The idle timeout is set on the squeezelite command line through -C \<timeout\>
If you have an audio jack that supports insertion (use :0 or :1 to set the level when inserted), you can specify which GPIO it's connected to. Using the parameter jack_mutes_amp allows to mute the amp when headset (e.g.) is inserted. If you have an audio jack that supports insertion (use :0 or :1 to set the level when inserted), you can specify which GPIO it's connected to. Using the parameter jack_mutes_amp allows to mute the amp when headset (e.g.) is inserted.
You can set the Green and Red status led as well with their respective active state (:0 or :1) You can set the Green and Red status led as well with their respective active state (:0 or :1)
The `<ir>` parameter set the GPIO associated to an IR receiver. No need to add pullup or capacitor The \<ir\> parameter set the GPIO associated to an IR receiver. No need to add pullup or capacitor
Syntax is: Syntax is:
@@ -279,34 +248,12 @@ Syntax is:
``` ```
You can define the defaults for jack, spkfault leds at compile time but nvs parameter takes precedence except for well-known configurations where these are forced at runtime. You can define the defaults for jack, spkfault leds at compile time but nvs parameter takes precedence except for well-known configurations where these are forced at runtime.
**Note that gpio 36 and 39 are input only and cannot use interrupt. When set to jack or speaker fault, a 100ms polling checks their value but that's expensive** **Note that gpio 36 and 39 are input only and cannot use interrupt. When set to jack or speaker fault, a 100ms polling checks their value but that's expensive**
### GPIO expanders
It is possible to add GPIO expanders using I2C or SPI bus. They should mainly be used for buttons but they can support generic-purpose outputs as well. These additional GPIOs can be numbered starting from an arbitrary value (40 and above as esp32 has GPIO 0..39). Then these new "virtual" GPIOs from (e.g) 100 to 115 can be used in [button](#Buttons) configuration, [set_GPIO](#set-gpio) or other config settings.
Each expander can support up to 32 GPIO. To use an expander for buttons, an interrupt must be provided, polling mode is not acceptable. An expander w/o interruption can still be configured, but only output will be usable. Note that the same interrupt can be shared accross expanders, as long as they are using open drain or open collectors (which they probably all do)
The parameter "gpio_exp_config" is a semicolon (;) separated list with following syntax for each expander
```
model=<model>,addr=<addr>,[,port=system|dac][,base=<n>|100][,count=<n>|16][,intr=<gpio>][,cs=<gpio>][,speed=<Hz>]
```
- model: pca9535, pca85xx, mcp23017 and mcp23s17 (SPI version)
- addr: chip i2c/spi address (decimal)
- port (I2C): use either "system" port (shared with display for example) or "dac" port (system is default)
- cs (SPI): gpio used for Chip Select
- speed (SPI): speed of the SPI bus for that device (in Hz)
- base: GPIO numbering offset to use everywhere else (default 40)
- count: number of GPIO of expander (default 16 - might be obsolted if model if sufficient to decide)
- intr: real GPIO to use as interrupt.
Note that PWM ("led_brightness" below) is not supported for expanded GPIOs and they cannot be used for high speed or precise timing signals like CS, D/C, Reset and Ready. Buttons, rotary encoder, amplifier control and power are supported. Depending on the actual chipset, pullup or pulldown might be supported so you might have to add external resistors (only MCP23x17 does pullup). The pca8575 is not a great chip, it generate a fair bit of spurious interrupts when used for GPIO out. When using a SPI expander, the bus must be configured using shared [SPI](#SPI) bus
### LED ### LED
See [set_GPIO](#set-gpio) for how to set the green and red LEDs. In addition, their brightness can be controlled using the "led_brigthness" parameter. The syntax is See §**set_GPIO** for how to set the green and red LEDs. In addition, their brightness can be controlled using the "led_brigthness" parameter. The syntax is
``` ```
[green=0..100][,red=0..100] [green=0..100][,red=0..100]
``` ```
NB: For well-known configuration, this is ignored NB: For well-known configuration, this is ignored
### Rotary Encoder ### Rotary Encoder
One rotary encoder is supported, quadrature shift with press. Such encoders usually have 2 pins for encoders (A and B), and common C that must be set to ground and an optional SW pin for press. A, B and SW must be pulled up, so automatic pull-up is provided by ESP32, but you can add your own resistors. A bit of filtering on A and B (~470nF) helps for debouncing which is not made by software. One rotary encoder is supported, quadrature shift with press. Such encoders usually have 2 pins for encoders (A and B), and common C that must be set to ground and an optional SW pin for press. A, B and SW must be pulled up, so automatic pull-up is provided by ESP32, but you can add your own resistors. A bit of filtering on A and B (~470nF) helps for debouncing which is not made by software.
@@ -332,15 +279,14 @@ The SW gpio is optional, you can re-affect it to a pure button if you prefer but
See also the "IMPORTANT NOTE" on the "Buttons" section and remember that when 'lms_ctrls_raw' (see below) is activated, none of these knobonly,volume,longpress options apply, raw button codes (not actions) are simply sent to LMS See also the "IMPORTANT NOTE" on the "Buttons" section and remember that when 'lms_ctrls_raw' (see below) is activated, none of these knobonly,volume,longpress options apply, raw button codes (not actions) are simply sent to LMS
**Note that gpio 36 and 39 are input only and cannot use interrupt, so they cannot be set to A or B. When using them for SW, a 100ms polling is used which is expensive** **Note that gpio 36 and 39 are input only and cannot use interrupt, so they cannot be set to A or B. When using them for SW, a 100ms polling is used which is expensive**
### Buttons ### Buttons
Buttons are described using a JSON string with the following syntax Buttons are described using a JSON string with the following syntax
```json ```
[ [
{"gpio":<num>, {"gpio":<num>,
"type":"BUTTON_LOW | BUTTON_HIGH", "type":"BUTTON_LOW | BUTTON_HIGH",
"pull":[true|false], "pull":[true|false],
"long_press":<ms>, "long_press":<ms>,
"debounce":<ms>, "debounce":<ms>,
"shifter_gpio":<-1|num>, "shifter_gpio":<-1|num>,
"normal": {"pressed":"<action>","released":"<action>"}, "normal": {"pressed":"<action>","released":"<action>"},
@@ -364,7 +310,7 @@ Where (all parameters are optionals except gpio)
- "shifted": action to take when a button is pressed/released and shifted (see above/below) - "shifted": action to take when a button is pressed/released and shifted (see above/below)
- "longshifted": action to take when a button is long-pressed/released and shifted (see above/below) - "longshifted": action to take when a button is long-pressed/released and shifted (see above/below)
Where `<action>` is either the name of another configuration to load (remap) or one amongst Where \<action\> is either the name of another configuration to load (remap) or one amongst
``` ```
ACTRLS_NONE, ACTRLS_POWER, ACTRLS_VOLUP, ACTRLS_VOLDOWN, ACTRLS_TOGGLE, ACTRLS_PLAY, ACTRLS_NONE, ACTRLS_POWER, ACTRLS_VOLUP, ACTRLS_VOLDOWN, ACTRLS_TOGGLE, ACTRLS_PLAY,
@@ -377,7 +323,7 @@ KNOB_LEFT, KNOB_RIGHT, KNOB_PUSH,
One you've created such a string, use it to fill a new NVS parameter with any name below 16(?) characters. You can have as many of these configs as you can. Then set the config parameter "actrls_config" with the name of your default config One you've created such a string, use it to fill a new NVS parameter with any name below 16(?) characters. You can have as many of these configs as you can. Then set the config parameter "actrls_config" with the name of your default config
For example a config named "buttons" : For example a config named "buttons" :
```json ```
[{"gpio":4,"type":"BUTTON_LOW","pull":true,"long_press":1000,"normal":{"pressed":"ACTRLS_VOLDOWN"},"longpress":{"pressed":"buttons_remap"}}, [{"gpio":4,"type":"BUTTON_LOW","pull":true,"long_press":1000,"normal":{"pressed":"ACTRLS_VOLDOWN"},"longpress":{"pressed":"buttons_remap"}},
{"gpio":5,"type":"BUTTON_LOW","pull":true,"shifter_gpio":4,"normal":{"pressed":"ACTRLS_VOLUP"}, "shifted":{"pressed":"ACTRLS_TOGGLE"}}] {"gpio":5,"type":"BUTTON_LOW","pull":true,"shifter_gpio":4,"normal":{"pressed":"ACTRLS_VOLUP"}, "shifted":{"pressed":"ACTRLS_TOGGLE"}}]
``` ```
@@ -386,7 +332,7 @@ Defines two buttons
- second on GPIO 5, active low. When pressed it triggers a volume up command. If first button is pressed together with this button, then a play/pause toggle command is generated. - second on GPIO 5, active low. When pressed it triggers a volume up command. If first button is pressed together with this button, then a play/pause toggle command is generated.
While the config named "buttons_remap" While the config named "buttons_remap"
```json ```
[{"gpio":4,"type":"BUTTON_LOW","pull":true,"long_press":1000,"normal":{"pressed":"BCTRLS_DOWN"},"longpress":{"pressed":"buttons"}}, [{"gpio":4,"type":"BUTTON_LOW","pull":true,"long_press":1000,"normal":{"pressed":"BCTRLS_DOWN"},"longpress":{"pressed":"buttons"}},
{"gpio":5,"type":"BUTTON_LOW","pull":true,"shifter_gpio":4,"normal":{"pressed":"BCTRLS_UP"}}] {"gpio":5,"type":"BUTTON_LOW","pull":true,"shifter_gpio":4,"normal":{"pressed":"BCTRLS_UP"}}]
``` ```
@@ -394,14 +340,10 @@ Defines two buttons
- first on GPIO 4, active low. When pressed, it triggers a navigation down command. When pressed more than 1000ms, it changes the button configuration for the one described above - first on GPIO 4, active low. When pressed, it triggers a navigation down command. When pressed more than 1000ms, it changes the button configuration for the one described above
- second on GPIO 5, active low. When pressed it triggers a navigation up command. That button, in that configuration, has no shift option - second on GPIO 5, active low. When pressed it triggers a navigation up command. That button, in that configuration, has no shift option
Below is a difficult but functional 2-buttons interface for your decoding pleasure: Below is a difficult but functional 2-buttons interface for your decoding pleasure
`actrls_config`: *buttons*
``` ```
buttons
```
`buttons`:
```json
[{"gpio":4,"type":"BUTTON_LOW","pull":true,"long_press":1000, [{"gpio":4,"type":"BUTTON_LOW","pull":true,"long_press":1000,
"normal":{"pressed":"ACTRLS_VOLDOWN"}, "normal":{"pressed":"ACTRLS_VOLDOWN"},
"longpress":{"pressed":"buttons_remap"}}, "longpress":{"pressed":"buttons_remap"}},
@@ -411,8 +353,8 @@ buttons
"longpress":{"pressed":"ACTRLS_NEXT"}} "longpress":{"pressed":"ACTRLS_NEXT"}}
] ]
``` ```
`buttons_remap`: *buttons_remap*
```json ```
[{"gpio":4,"type":"BUTTON_LOW","pull":true,"long_press":1000, [{"gpio":4,"type":"BUTTON_LOW","pull":true,"long_press":1000,
"normal":{"pressed":"BCTRLS_DOWN"}, "normal":{"pressed":"BCTRLS_DOWN"},
"longpress":{"pressed":"buttons"}}, "longpress":{"pressed":"buttons"}},
@@ -423,20 +365,18 @@ buttons
"longshifted":{"pressed":"BCTRLS_LEFT"}} "longshifted":{"pressed":"BCTRLS_LEFT"}}
] ]
``` ```
**IMPORTANT NOTE**: LMS also supports the possibility to send 'raw' button codes. It's a bit complicated, so bear with me. Buttons can either be processed by SqueezeESP32 and mapped to a "function" like play/pause or they can be just sent to LMS as plain (raw) code and the full logic of press/release/longpress is handled by LMS, you don't have any control on that. <strong>IMPORTANT NOTE</strong>: LMS also supports the possibility to send 'raw' button codes. It's a bit complicated, so bear with me. Buttons can either be processed by SqueezeESP32 and mapped to a "function" like play/pause or they can be just sent to LMS as plain (raw) code and the full logic of press/release/longpress is handled by LMS, you don't have any control on that.
The benefit of the "raw" mode is that you can build a player which is as close as possible to a Boom (e.g.) but you can't use the remapping function nor longress or shift logics to do your own mapping when you have a limited set of buttons. In 'raw' mode, all you really need to define is the mapping between the gpio and the button. As far as LMS is concerned, any other option in these JSON payloads does not matter. Now, when you use BT or AirPlay, the full JSON construct described above fully applies, so the shift, longpress, remapping options still work. The benefit of the "raw" mode is that you can build a player which is as close as possible to a Boom (e.g.) but you can't use the remapping function nor longress or shift logics to do your own mapping when you have a limited set of buttons. In 'raw' mode, all you really need to define is the mapping between the gpio and the button. As far as LMS is concerned, any other option in these JSON payloads does not matter. Now, when you use BT or AirPlay, the full JSON construct described above fully applies, so the shift, longpress, remapping options still work.
**Be aware that when using non "raw" mode, the CLI (Command Line Interface) of LMS is used and *must* be available without password** **Be aware that when using non "raw" mode, the CLI (Command Line Interface) of LMS is used and *must* be available without password**
There is no good or bad option, it's your choice. Use the NVS parameter "lms_ctrls_raw" to change that option There is no good or bad option, it's your choice. Use the NVS parameter "lms_ctrls_raw" to change that option
**Note that gpio 36 and 39 are input only and cannot use interrupt. When using them for a button, a 100ms polling is started which is expensive. Long press is also likely to not work very well** **Note that gpio 36 and 39 are input only and cannot use interrupt. When using them for a button, a 100ms polling is started which is expensive. Long press is also likely to not work very well**
### Ethernet ### Ethernet (coming soon)
Wired ethernet is supported by esp32 with various options but squeezelite is only supporting a Microchip LAN8720 with a RMII interface like [this](https://www.aliexpress.com/item/32858432526.html) or SPI-ethernet bridges like Davicom DM9051 [that](https://www.amazon.com/dp/B08JLFWX9Z) or W5500 like [this](https://www.aliexpress.com/item/32312441357.html). Wired ethernet is supported by esp32 with various options but squeezelite is only supporting a Microchip LAN8720 with a RMII interface like [this](https://www.aliexpress.com/item/32858432526.html) or Davicom DM9051 over SPI like [that](https://www.amazon.com/dp/B08JLFWX9Z).
**Note:** Touch buttons that can be find on some board like the LyraT V4.3 are not supported currently.
#### RMII (LAN8720) #### RMII (LAN8720)
- RMII PHY wiring is fixed and can not be changed - RMII PHY wiring is fixed and can not be changed
@@ -448,7 +388,6 @@ Wired ethernet is supported by esp32 with various options but squeezelite is onl
| GPIO25 | RX0 | EMAC_RXD0 | | GPIO25 | RX0 | EMAC_RXD0 |
| GPIO26 | RX1 | EMAC_RXD1 | | GPIO26 | RX1 | EMAC_RXD1 |
| GPIO27 | CRS_DV | EMAC_RX_DRV | | GPIO27 | CRS_DV | EMAC_RX_DRV |
| GPIO0 | REF_CLK | 50MHz clock |
- SMI (Serial Management Interface) wiring is not fixed and you can change it either in the configuration or using "eth_config" parameter with the following syntax: - SMI (Serial Management Interface) wiring is not fixed and you can change it either in the configuration or using "eth_config" parameter with the following syntax:
``` ```
@@ -458,31 +397,30 @@ Connecting a reset pin for the LAN8720 is optional but recommended to avoid that
- Clock - Clock
The APLL of the esp32 is required for the audio codec, so we **need** a LAN8720 that provides a 50MHz clock. That clock **must** be connected to GPIO0, there is no alternative. This means that if your DAC requires an MCLK, then you are out of luck. It is not possible to have both to work together. There might be some workaround using CLK_OUT2 and GPIO3, but I don't have time for this. The APLL of the esp32 is required for the audio codec, so we **need** a LAN8720 that provides a 50MHz clock. That clock **must** be connected to GPIO0, there is no alternative. This means that if your DAC requires an MCLK, then you are out of luck. It is not possible to have both to work together. There might be some workaround using CLK_OUT2 and GPIO3, but I don't have time for this.
#### SPI (DM9051 or W5500) #### SPI (DM9051)
Ethernet over SPI is supported as well and requires less GPIOs but is obvsiously slower. SPI is the shared bus set with [spi_config](#spi). The "eth_config" parameter syntax becomes: Ethernet over SPI is supported as well and requires less GPIOs but is obvsiously slower. Another benefit is that the SPI bus can be shared with the display, but it's also possible to have a dedicated SPI interface. The esp32 has 4 SPI sub-systems, one is unaccessible so numbering is 0..2 and SPI0 is reserved for Flash/PSRAM. The "eth_config" parameter syntax becomes:
``` ```
model=dm9051|w5500,cs=<gpio>,speed=<clk_in_Hz>,intr=<gpio>[,rst=<gpio>] model=dm9051,cs=<gpio>,speed=<clk_in_Hz>,intr=<gpio>[,host=<-1|1|2>][,rst=<gpio>][,mosi=<gpio>,miso=<gpio>,clk=<gpio>]
``` ```
- To use the system SPI, shared with display (see spi_config) "host" must be set to -1. Any other value will reserve the SPI interface (careful of conflict with spi_config). The default "host" is 2 to avoid conflicting wiht default "spi_config" settings. - To use the system SPI, shared with display (see spi_config) "host" must be set to -1. Any other value will reserve the SPI interface (careful of conflict with spi_config). The default "host" is 2 to avoid conflicting wiht default "spi_config" settings.
- When not using system SPI, "mosi" for data out, "miso" for data in and "clk" **must** be set - When not using system SPI, "mosi" for data out, "miso" for data in and "clk" **must** be set
- The esp32 has a special I/O multiplexer for faster speed (up to 80 MHz) but that requires using specific GPIOs, which depends on SPI bus (See [here](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/spi_master.html) for more details) - The esp32 has a special I/O multiplexer for faster speed (up to 80 MHz) but that requires using specific GPIOs, which depends on SPI bus (See [here](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/spi_master.html) for more details)
| Pin Name | SPI1 | SPI2 | | Pin Name | SPI2 | SPI3 |
| -------- | ---- | ---- | | -------- | ---- | ---- |
| CS | 15 | 5 | | CS0* | 15 | 5 |
| SCLK | 14 | 18 | | SCLK | 14 | 18 |
| MISO | 12 | 19 | | MISO | 12 | 19 |
| MOSI | 13 | 23 | | MOSI | 13 | 23 |
** THIS IS NOT AVAILABLE YET, SO MORE TO COME ON HOW TO USE WIRED ETHERNET***
### Battery / ADC ### Battery / ADC
The NVS parameter "bat_config" sets the ADC1 channel used to measure battery/DC voltage. The "atten" value attenuates the input voltage to the ADC input (the read value maintains a 0-1V rage) where: 0=no attenuation(0..800mV), 1=2.5dB attenuation(0..1.1V), 2=6dB attenuation(0..1.35V), 3=11dB attenuation(0..2.6V). Scale is a float ratio applied to every sample of the 12 bits ADC. A measure is taken every 10s and an average is made every 5 minutes (not a sliding window). Syntax is The NVS parameter "bat_config" sets the ADC1 channel used to measure battery/DC voltage. The "atten" value attenuates the input voltage to the ADC input (the read value maintains a 0-1V rage) where: 0=no attenuation(0..800mV), 1=2.5dB attenuation(0..1.1V), 2=6dB attenuation(0..1.35V), 3=11dB attenuation(0..2.6V). Scale is a float ratio applied to every sample of the 12 bits ADC. A measure is taken every 10s and an average is made every 5 minutes (not a sliding window). Syntax is
``` ```
channel=0..7,scale=<scale>,cells=<2|3>[,atten=<0|1|2|3>] channel=0..7,scale=<scale>,cells=<2|3>[,atten=<0|1|2|3>]
``` ```
NB: Set parameter to empty to disable battery reading. For well-known configuration, this is ignored (except for SqueezeAMP where number of cells is required) NB: Set parameter to empty to disable battery reading. For well-known configuration, this is ignored (except for SqueezeAMP where number of cells is required)
# Configuration # Configuration
## Setup WiFi ## Setup WiFi
- Boot the esp, look for a new wifi access point showing up and connect to it. Default build ssid and passwords are "squeezelite"/"squeezelite". - Boot the esp, look for a new wifi access point showing up and connect to it. Default build ssid and passwords are "squeezelite"/"squeezelite".
- Once connected, navigate to 192.168.4.1 - Once connected, navigate to 192.168.4.1
@@ -491,6 +429,7 @@ NB: Set parameter to empty to disable battery reading. For well-known configurat
- Once connection is established, note down the address the device received; this is the address you will use to configure it going forward - Once connection is established, note down the address the device received; this is the address you will use to configure it going forward
## Setup squeezelite command line (optional) ## Setup squeezelite command line (optional)
At this point, the device should have disabled its built-in access point and should be connected to a known WiFi network. At this point, the device should have disabled its built-in access point and should be connected to a known WiFi network.
- navigate to the address that was noted in step #1 - navigate to the address that was noted in step #1
- Using the list of predefined options, choose the mode in which you want squeezelite to start - Using the list of predefined options, choose the mode in which you want squeezelite to start
@@ -503,6 +442,7 @@ At this point, the device should have disabled its built-in access point and sho
- You can enable accessto NVS parameters under 'credits' - You can enable accessto NVS parameters under 'credits'
## Monitor ## Monitor
In addition of the esp-idf serial link monitor option, you can also enable a telnet server (see NVS parameters) where you'll have access to a ton of logs of what's happening inside the WROVER. In addition of the esp-idf serial link monitor option, you can also enable a telnet server (see NVS parameters) where you'll have access to a ton of logs of what's happening inside the WROVER.
## Update Squeezelite ## Update Squeezelite
@@ -534,23 +474,20 @@ See squeezlite command line, but keys options are
- r "<minrate>-<maxrate>" - r "<minrate>-<maxrate>"
- C <sec> : set timeout to switch off amp gpio - C <sec> : set timeout to switch off amp gpio
- W : activate WAV and AIFF header parsing - W : activate WAV and AIFF header parsing
# Building everything yourself # Building everything yourself
## Setting up ESP-IDF ## Setting up ESP-IDF
### Docker ### Docker
A simple alternative to building the project's binaries is to leverage the same docker image that is being used on the GitHub Actions to build our releases. The instructions below assume that you have cloned the squeezelite-esp32 code that you want to build locally and that you have opened a command line/bash session in the folder that contains the code. A simple alternative to building the project's binaries is to leverage the same docker image that is being used on the GitHub Actions to build our releases. The instructions below assume that you have cloned the squeezelite-esp32 code that you want to build locally and that you have opened a command line/bash session in the folder that contains the code.
Pull the most recent docker image for the environment: Pull the most recent docker image for the environment:
``` ```
docker pull sle118/squeezelite-esp32-idfv43 docker pull sle118/squeezelite-esp32-idfv4-master
``` ```
Then run the container interactively : Then run the container interactively :
``` ```
for windows: for windows:
docker run -v %cd%:/project -w /project -it sle118/squeezelite-esp32-idfv43 docker run -v %cd%:/project -w /project -it sle118/squeezelite-esp32-idfv4-master
for linux: for linux:
docker run -it -v `pwd`:/workspace/squeezelite-esp32 sle118/squeezelite-esp32-idfv43 docker run -it -v `pwd`:/workspace/squeezelite-esp32 sle118/squeezelite-esp32-idfv4-master
``` ```
The above command will mount this repo into the docker container and start a bash terminal. From there, simply run idf.py build to build, etc. Note that at the time of writing these lines, flashing is not possible for docker running under windows https://github.com/docker/for-win/issues/1018. The above command will mount this repo into the docker container and start a bash terminal. From there, simply run idf.py build to build, etc. Note that at the time of writing these lines, flashing is not possible for docker running under windows https://github.com/docker/for-win/issues/1018.
@@ -573,7 +510,6 @@ Use `idf.py monitor` to monitor the application (see esp-idf documentation)
Note: You can use `idf.py build -DDEPTH=32` to build the 32 bits version and add the `-DVERSION=<your_version>` to add a custom version name (it will be 0.0-<your_version>). If you want to change the whole version string, see squeezelite.h. You can also disable the SBR extension of AAC codecs as it consumes a lot of CPU and might overload the esp32. Use `-DAAC_DISABLE_SBR=1` for that Note: You can use `idf.py build -DDEPTH=32` to build the 32 bits version and add the `-DVERSION=<your_version>` to add a custom version name (it will be 0.0-<your_version>). If you want to change the whole version string, see squeezelite.h. You can also disable the SBR extension of AAC codecs as it consumes a lot of CPU and might overload the esp32. Use `-DAAC_DISABLE_SBR=1` for that
If you have already cloned the repository and you are getting compile errors on one of the submodules (e.g. telnet), run the following git command in the root of the repository location: `git submodule update --init --recursive` If you have already cloned the repository and you are getting compile errors on one of the submodules (e.g. telnet), run the following git command in the root of the repository location: `git submodule update --init --recursive`
### Rebuild codecs (highly recommended to NOT try that) ### Rebuild codecs (highly recommended to NOT try that)
- for codecs libraries, add -mlongcalls if you want to rebuild them, but you should not (use the provided ones in codecs/lib). if you really want to rebuild them, open an issue - for codecs libraries, add -mlongcalls if you want to rebuild them, but you should not (use the provided ones in codecs/lib). if you really want to rebuild them, open an issue
- libmad, libflac (no esp's version), libvorbis (tremor - not esp's version), alac work - libmad, libflac (no esp's version), libvorbis (tremor - not esp's version), alac work

View File

@@ -942,10 +942,11 @@ CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y
# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set # CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set
CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y
CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1
# CONFIG_FREERTOS_ASSERT_FAIL_ABORT is not set CONFIG_FREERTOS_ASSERT_FAIL_ABORT=y
CONFIG_FREERTOS_ASSERT_DISABLE=y
CONFIG_FREERTOS_ISR_STACKSIZE=2096
# CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE is not set # CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE is not set
# CONFIG_FREERTOS_ASSERT_DISABLE is not set
CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536
CONFIG_FREERTOS_ISR_STACKSIZE=1536
# CONFIG_FREERTOS_LEGACY_HOOKS is not set # CONFIG_FREERTOS_LEGACY_HOOKS is not set
CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16
CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y
@@ -1118,7 +1119,7 @@ CONFIG_LWIP_DHCP_MAX_NTP_SERVERS=1
CONFIG_LWIP_SNTP_UPDATE_DELAY=3600000 CONFIG_LWIP_SNTP_UPDATE_DELAY=3600000
# end of SNTP # end of SNTP
CONFIG_LWIP_ESP_LWIP_ASSERT=y # CONFIG_LWIP_ESP_LWIP_ASSERT is not set
# #
# Hooks # Hooks

View File

@@ -901,10 +901,11 @@ CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y
# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set # CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set
CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y
CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1
# CONFIG_FREERTOS_ASSERT_FAIL_ABORT is not set CONFIG_FREERTOS_ASSERT_FAIL_ABORT=y
CONFIG_FREERTOS_ASSERT_DISABLE=y
CONFIG_FREERTOS_ISR_STACKSIZE=2096
# CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE is not set # CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE is not set
# CONFIG_FREERTOS_ASSERT_DISABLE is not set
CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536
CONFIG_FREERTOS_ISR_STACKSIZE=1536
# CONFIG_FREERTOS_LEGACY_HOOKS is not set # CONFIG_FREERTOS_LEGACY_HOOKS is not set
CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16
CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y
@@ -1077,7 +1078,7 @@ CONFIG_LWIP_DHCP_MAX_NTP_SERVERS=1
CONFIG_LWIP_SNTP_UPDATE_DELAY=3600000 CONFIG_LWIP_SNTP_UPDATE_DELAY=3600000
# end of SNTP # end of SNTP
CONFIG_LWIP_ESP_LWIP_ASSERT=y # CONFIG_LWIP_ESP_LWIP_ASSERT is not set
# #
# Hooks # Hooks

View File

@@ -259,7 +259,7 @@ CONFIG_CSPOT_SINK=y
# Various I/O # Various I/O
# #
CONFIG_I2C_CONFIG="" CONFIG_I2C_CONFIG=""
CONFIG_SET_GPIO="0=ir" CONFIG_SET_GPIO=""
CONFIG_ROTARY_ENCODER="" CONFIG_ROTARY_ENCODER=""
# end of Various I/O # end of Various I/O
@@ -912,10 +912,11 @@ CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y
# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set # CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set
CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y
CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1
# CONFIG_FREERTOS_ASSERT_FAIL_ABORT is not set CONFIG_FREERTOS_ASSERT_FAIL_ABORT=y
CONFIG_FREERTOS_ASSERT_DISABLE=y
CONFIG_FREERTOS_ISR_STACKSIZE=2096
# CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE is not set # CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE is not set
# CONFIG_FREERTOS_ASSERT_DISABLE is not set
CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536
CONFIG_FREERTOS_ISR_STACKSIZE=1536
# CONFIG_FREERTOS_LEGACY_HOOKS is not set # CONFIG_FREERTOS_LEGACY_HOOKS is not set
CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16
CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y
@@ -1088,7 +1089,7 @@ CONFIG_LWIP_DHCP_MAX_NTP_SERVERS=1
CONFIG_LWIP_SNTP_UPDATE_DELAY=3600000 CONFIG_LWIP_SNTP_UPDATE_DELAY=3600000
# end of SNTP # end of SNTP
CONFIG_LWIP_ESP_LWIP_ASSERT=y # CONFIG_LWIP_ESP_LWIP_ASSERT is not set
# #
# Hooks # Hooks

View File

@@ -1,5 +1,5 @@
idf_component_register( idf_component_register(
INCLUDE_DIRS . ./inc inc/alac inc/helix-aac inc/mad inc/resample16 inc/soxr inc/vorbis inc/opus INCLUDE_DIRS . ./inc inc/alac inc/FLAC inc/helix-aac inc/mad inc/ogg inc/opus inc/opusfile inc/resample16 inc/soxr inc/vorbis
) )
if (DEFINED AAC_DISABLE_SBR) if (DEFINED AAC_DISABLE_SBR)
@@ -14,6 +14,7 @@ add_prebuilt_library(libvorbisidec lib/libvorbisidec.a )
add_prebuilt_library(libogg lib/libogg.a ) add_prebuilt_library(libogg lib/libogg.a )
add_prebuilt_library(libalac lib/libalac.a ) add_prebuilt_library(libalac lib/libalac.a )
add_prebuilt_library(libresample16 lib/libresample16.a ) add_prebuilt_library(libresample16 lib/libresample16.a )
add_prebuilt_library(libopusfile lib/libopusfile.a )
add_prebuilt_library(libopus lib/libopus.a ) add_prebuilt_library(libopus lib/libopus.a )
target_link_libraries(${COMPONENT_LIB} INTERFACE libmad) target_link_libraries(${COMPONENT_LIB} INTERFACE libmad)
@@ -23,4 +24,5 @@ target_link_libraries(${COMPONENT_LIB} INTERFACE libvorbisidec)
target_link_libraries(${COMPONENT_LIB} INTERFACE libogg) target_link_libraries(${COMPONENT_LIB} INTERFACE libogg)
target_link_libraries(${COMPONENT_LIB} INTERFACE libalac) target_link_libraries(${COMPONENT_LIB} INTERFACE libalac)
target_link_libraries(${COMPONENT_LIB} INTERFACE libresample16) target_link_libraries(${COMPONENT_LIB} INTERFACE libresample16)
target_link_libraries(${COMPONENT_LIB} INTERFACE libopusfile)
target_link_libraries(${COMPONENT_LIB} INTERFACE libopus) target_link_libraries(${COMPONENT_LIB} INTERFACE libopus)

View File

@@ -1,6 +1,6 @@
/* libFLAC - Free Lossless Audio Codec library /* libFLAC - Free Lossless Audio Codec library
* Copyright (C) 2000-2009 Josh Coalson * Copyright (C) 2000-2009 Josh Coalson
* Copyright (C) 2011-2022 Xiph.Org Foundation * Copyright (C) 2011-2014 Xiph.Org Foundation
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@@ -35,8 +35,8 @@
#include "export.h" #include "export.h"
#include "assert.h"
#include "callback.h" #include "callback.h"
#include "flac_assert.h"
#include "format.h" #include "format.h"
#include "metadata.h" #include "metadata.h"
#include "ordinals.h" #include "ordinals.h"
@@ -52,7 +52,7 @@
* level idea of the structure and how to find the information you * level idea of the structure and how to find the information you
* need. As a prerequisite you should have at least a basic * need. As a prerequisite you should have at least a basic
* knowledge of the FLAC format, documented * knowledge of the FLAC format, documented
* <A HREF="https://xiph.org/flac/format.html">here</A>. * <A HREF="../format.html">here</A>.
* *
* \section c_api FLAC C API * \section c_api FLAC C API
* *
@@ -64,7 +64,7 @@
* *
* By writing a little code and linking against libFLAC, it is * By writing a little code and linking against libFLAC, it is
* relatively easy to add FLAC support to another program. The * relatively easy to add FLAC support to another program. The
* library is licensed under <A HREF="https://xiph.org/flac/license.html">Xiph's BSD license</A>. * library is licensed under <A HREF="../license.html">Xiph's BSD license</A>.
* Complete source code of libFLAC as well as the command-line * Complete source code of libFLAC as well as the command-line
* encoder and plugins is available and is a useful source of * encoder and plugins is available and is a useful source of
* examples. * examples.
@@ -97,7 +97,7 @@
* example /usr/include/FLAC++/...). * example /usr/include/FLAC++/...).
* *
* libFLAC++ is also licensed under * libFLAC++ is also licensed under
* <A HREF="https://xiph.org/flac/license.html">Xiph's BSD license</A>. * <A HREF="../license.html">Xiph's BSD license</A>.
* *
* \section getting_started Getting Started * \section getting_started Getting Started
* *
@@ -113,7 +113,7 @@
* functions through the links in top bar across this page. * functions through the links in top bar across this page.
* *
* If you prefer a more hands-on approach, you can jump right to some * If you prefer a more hands-on approach, you can jump right to some
* <A HREF="https://xiph.org/flac/documentation_example_code.html">example code</A>. * <A HREF="../documentation_example_code.html">example code</A>.
* *
* \section porting_guide Porting Guide * \section porting_guide Porting Guide
* *
@@ -147,7 +147,7 @@
* library. * library.
* *
* Also, there are several places in the libFLAC code with comments marked * Also, there are several places in the libFLAC code with comments marked
* with "OPT:" where a \#define can be changed to enable code that might be * with "OPT:" where a #define can be changed to enable code that might be
* faster on a specific platform. Experimenting with these can yield faster * faster on a specific platform. Experimenting with these can yield faster
* binaries. * binaries.
*/ */
@@ -159,9 +159,9 @@
* the libraries to newer versions of FLAC. * the libraries to newer versions of FLAC.
* *
* One simple facility for making porting easier that has been added * One simple facility for making porting easier that has been added
* in FLAC 1.1.3 is a set of \#defines in \c export.h of each * in FLAC 1.1.3 is a set of \c #defines in \c export.h of each
* library's includes (e.g. \c include/FLAC/export.h). The * library's includes (e.g. \c include/FLAC/export.h). The
* \#defines mirror the libraries' * \c #defines mirror the libraries'
* <A HREF="http://www.gnu.org/software/libtool/manual/libtool.html#Libtool-versioning">libtool version numbers</A>, * <A HREF="http://www.gnu.org/software/libtool/manual/libtool.html#Libtool-versioning">libtool version numbers</A>,
* e.g. in libFLAC there are \c FLAC_API_VERSION_CURRENT, * e.g. in libFLAC there are \c FLAC_API_VERSION_CURRENT,
* \c FLAC_API_VERSION_REVISION, and \c FLAC_API_VERSION_AGE. * \c FLAC_API_VERSION_REVISION, and \c FLAC_API_VERSION_AGE.
@@ -176,7 +176,7 @@
* #endif * #endif
* \endcode * \endcode
* *
* The source will work for multiple versions and the legacy code can * The the source will work for multiple versions and the legacy code can
* easily be removed when the transition is complete. * easily be removed when the transition is complete.
* *
* Another available symbol is FLAC_API_SUPPORTS_OGG_FLAC (defined in * Another available symbol is FLAC_API_SUPPORTS_OGG_FLAC (defined in
@@ -321,7 +321,7 @@
* *
* The \a bytes parameter to FLAC__StreamDecoderReadCallback, * The \a bytes parameter to FLAC__StreamDecoderReadCallback,
* FLAC__StreamEncoderReadCallback, and FLAC__StreamEncoderWriteCallback * FLAC__StreamEncoderReadCallback, and FLAC__StreamEncoderWriteCallback
* is now \c size_t instead of \c uint32_t. * is now \c size_t instead of \c unsigned.
*/ */
/** \defgroup porting_1_1_3_to_1_1_4 Porting from FLAC 1.1.3 to 1.1.4 /** \defgroup porting_1_1_3_to_1_1_4 Porting from FLAC 1.1.3 to 1.1.4
@@ -357,85 +357,6 @@
* \c FLAC__FRAME_HEADER_BLOCKING_STRATEGY_LEN * \c FLAC__FRAME_HEADER_BLOCKING_STRATEGY_LEN
*/ */
/** \defgroup porting_1_3_4_to_1_4_0 Porting from FLAC 1.3.4 to 1.4.0
* \ingroup porting
*
* \brief
* This module describes porting from FLAC 1.3.4 to FLAC 1.4.0.
*
* \section porting_1_3_4_to_1_4_0_summary Summary
*
* Between FLAC 1.3.4 and FLAC 1.4.0, there have four breaking changes
* - the function get_client_data_from_decoder has been renamed to
* FLAC__get_decoder_client_data
* - some data types in the FLAC__Frame struct have changed
* - all functions resizing metadata blocks now return the object
* untouched if memory allocation fails, whereas previously the
* handling varied and was more or less undefined
* - all functions accepting a filename now take UTF-8 encoded filenames
* on Windows instead of filenames in the current codepage
*
* Furthermore, there have been the following additions
* - the functions FLAC__stream_encoder_set_limit_min_bitrate,
* FLAC__stream_encoder_get_limit_min_bitrate,
* FLAC::encoder::file::set_limit_min_bitrate() and
* FLAC::encoder::file::get_limit_min_bitrate() have been added
* - Added FLAC__STREAM_DECODER_ERROR_STATUS_BAD_METADATA to the
* FLAC__StreamDecoderErrorStatus enum
*
* \section porting_1_3_4_to_1_4_0_breaking Breaking changes
*
* The function \b get_client_data_from_decoder was added in FLAC 1.3.3
* but did not follow the API naming convention and was not properly
* exported. The function is now renamed and properly integrated as
* FLAC__stream_decoder_get_client_data
*
* To accomodate encoding and decoding 32-bit int PCM, some data types
* in the \b FLAC__frame struct were changed. Specifically, warmup
* in both the FLAC__Subframe_Fixed struc and the FLAC__Subframe_LPC
* struct is changed from FLAC__int32 to FLAC__int64. Also, value
* in the FLAC__Subframe_Constant is changed from FLAC__int32 to
* FLAC__int64. Finally, in FLAC__Subframe_Verbatim struct data is
* changes from a FLAC__int32 array to a union containing a FLAC__int32
* array and a FLAC__int64 array. Also, a new member is added,
* data_type, which clarifies whether the FLAC__int32 or FLAC__int64
* array is in use.
*
* Furthermore, the following functions now return the object untouched
* if memory allocation fails, whereas previously the handling varied
* and was more or less undefined
*
* - FLAC__metadata_object_seektable_resize_points
* - FLAC__metadata_object_vorbiscomment_resize_comments
* - FLAC__metadata_object_cuesheet_track_resize_indices
* - FLAC__metadata_object_cuesheet_resize_tracks
*
* The last breaking change is that all API functions taking a filename
* as an argument now, on Windows, must be supplied with that filename
* in the UTF-8 character encoding instead of using the current code
* page. libFLAC internally translates these UTF-8 encoded filenames to
* an appropriate representation to use with _wfopen. On all other
* systems, filename is passed to fopen without any translation, as it
* in libFLAC 1.3.4 and earlier.
*
* \section porting_1_3_4_to_1_4_0_additions Additions
*
* To aid in creating properly streamable FLAC files, a set of functions
* was added to make it possible to enfore a minimum bitrate to files
* created through libFLAC's stream_encoder.h interface. With this
* function enabled the resulting FLAC files have a minimum bitrate of
* 1bit/sample independent of the number of channels, i.e. 48kbit/s for
* 48kHz. This can be beneficial for streaming, as very low bitrates for
* silent sections compressed with 'constant' subframes can result in a
* bitrate of 1kbit/s, creating problems with clients that aren't aware
* of this possibility and buffer too much data.
*
* Finally, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_METADATA was added to
* the FLAC__StreamDecoderErrorStatus enum to signal that the decoder
* encountered unreadable metadata.
*
*/
/** \defgroup flac FLAC C API /** \defgroup flac FLAC C API
* *
* The FLAC C API is the interface to libFLAC, a set of structures * The FLAC C API is the interface to libFLAC, a set of structures

View File

@@ -1,6 +1,6 @@
/* libFLAC - Free Lossless Audio Codec library /* libFLAC - Free Lossless Audio Codec library
* Copyright (C) 2004-2009 Josh Coalson * Copyright (C) 2004-2009 Josh Coalson
* Copyright (C) 2011-2022 Xiph.Org Foundation * Copyright (C) 2011-2014 Xiph.Org Foundation
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@@ -165,15 +165,15 @@ typedef int (*FLAC__IOCallback_Close) (FLAC__IOHandle handle);
* required may be set to NULL. * required may be set to NULL.
* *
* If the seek requirement for an interface is optional, you can signify that * If the seek requirement for an interface is optional, you can signify that
* a data source is not seekable by setting the \a seek field to \c NULL. * a data sorce is not seekable by setting the \a seek field to \c NULL.
*/ */
typedef struct { typedef struct {
FLAC__IOCallback_Read read; /**< See FLAC__IOCallbacks */ FLAC__IOCallback_Read read;
FLAC__IOCallback_Write write; /**< See FLAC__IOCallbacks */ FLAC__IOCallback_Write write;
FLAC__IOCallback_Seek seek; /**< See FLAC__IOCallbacks */ FLAC__IOCallback_Seek seek;
FLAC__IOCallback_Tell tell; /**< See FLAC__IOCallbacks */ FLAC__IOCallback_Tell tell;
FLAC__IOCallback_Eof eof; /**< See FLAC__IOCallbacks */ FLAC__IOCallback_Eof eof;
FLAC__IOCallback_Close close; /**< See FLAC__IOCallbacks */ FLAC__IOCallback_Close close;
} FLAC__IOCallbacks; } FLAC__IOCallbacks;
/* \} */ /* \} */

View File

@@ -1,6 +1,6 @@
/* libFLAC - Free Lossless Audio Codec library /* libFLAC - Free Lossless Audio Codec library
* Copyright (C) 2000-2009 Josh Coalson * Copyright (C) 2000-2009 Josh Coalson
* Copyright (C) 2011-2022 Xiph.Org Foundation * Copyright (C) 2011-2014 Xiph.Org Foundation
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@@ -36,7 +36,7 @@
/** \file include/FLAC/export.h /** \file include/FLAC/export.h
* *
* \brief * \brief
* This module contains \#defines and symbols for exporting function * This module contains #defines and symbols for exporting function
* calls, and providing version information and compiled-in features. * calls, and providing version information and compiled-in features.
* *
* See the \link flac_export export \endlink module. * See the \link flac_export export \endlink module.
@@ -46,43 +46,25 @@
* \ingroup flac * \ingroup flac
* *
* \brief * \brief
* This module contains \#defines and symbols for exporting function * This module contains #defines and symbols for exporting function
* calls, and providing version information and compiled-in features. * calls, and providing version information and compiled-in features.
* *
* If you are compiling for Windows (with Visual Studio or MinGW for * If you are compiling with MSVC and will link to the static library
* example) and will link to the static library (libFLAC++.lib) you * (libFLAC.lib) you should define FLAC__NO_DLL in your project to
* should define FLAC__NO_DLL in your project to make sure the symbols * make sure the symbols are exported properly.
* are exported properly.
* *
* \{ * \{
*/ */
/** This \#define is used internally in libFLAC and its headers to make #if defined(FLAC__NO_DLL)
* sure the correct symbols are exported when working with shared
* libraries. On Windows, this \#define is set to __declspec(dllexport)
* when compiling libFLAC into a library and to __declspec(dllimport)
* when the headers are used to link to that DLL. On non-Windows systems
* it is used to set symbol visibility.
*
* Because of this, the define FLAC__NO_DLL must be defined when linking
* to libFLAC statically or linking will fail.
*/
/* This has grown quite complicated. FLAC__NO_DLL is used by MSVC sln
* files and CMake, which build either static or shared. autotools can
* build static, shared or **both**. Therefore, DLL_EXPORT, which is set
* by libtool, must override FLAC__NO_DLL on building shared components
*/
#if defined(_WIN32)
#if defined(FLAC__NO_DLL) && !(defined(DLL_EXPORT))
#define FLAC_API #define FLAC_API
#else
#elif defined(_MSC_VER)
#ifdef FLAC_API_EXPORTS #ifdef FLAC_API_EXPORTS
#define FLAC_API __declspec(dllexport) #define FLAC_API __declspec(dllexport)
#else #else
#define FLAC_API __declspec(dllimport) #define FLAC_API __declspec(dllimport)
#endif #endif
#endif
#elif defined(FLAC__USE_VISIBILITY_ATTR) #elif defined(FLAC__USE_VISIBILITY_ATTR)
#define FLAC_API __attribute__ ((visibility ("default"))) #define FLAC_API __attribute__ ((visibility ("default")))
@@ -92,12 +74,12 @@
#endif #endif
/** These \#defines will mirror the libtool-based library version number, see /** These #defines will mirror the libtool-based library version number, see
* http://www.gnu.org/software/libtool/manual/libtool.html#Libtool-versioning * http://www.gnu.org/software/libtool/manual/libtool.html#Libtool-versioning
*/ */
#define FLAC_API_VERSION_CURRENT 12 #define FLAC_API_VERSION_CURRENT 11
#define FLAC_API_VERSION_REVISION 0 /**< see above */ #define FLAC_API_VERSION_REVISION 0 /**< see above */
#define FLAC_API_VERSION_AGE 0 /**< see above */ #define FLAC_API_VERSION_AGE 3 /**< see above */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View File

@@ -1,6 +1,6 @@
/* libFLAC - Free Lossless Audio Codec library /* libFLAC - Free Lossless Audio Codec library
* Copyright (C) 2001-2009 Josh Coalson * Copyright (C) 2001-2009 Josh Coalson
* Copyright (C) 2011-2022 Xiph.Org Foundation * Copyright (C) 2011-2014 Xiph.Org Foundation
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@@ -34,11 +34,7 @@
#define FLAC__ASSERT_H #define FLAC__ASSERT_H
/* we need this since some compilers (like MSVC) leave assert()s on release code (and we don't want to use their ASSERT) */ /* we need this since some compilers (like MSVC) leave assert()s on release code (and we don't want to use their ASSERT) */
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION #ifdef DEBUG
#define FLAC__ASSERT(x) if(!(x)) __builtin_abort();
#define FLAC__ASSERT_DECLARATION(x) x
#else
#ifndef NDEBUG
#include <assert.h> #include <assert.h>
#define FLAC__ASSERT(x) assert(x) #define FLAC__ASSERT(x) assert(x)
#define FLAC__ASSERT_DECLARATION(x) x #define FLAC__ASSERT_DECLARATION(x) x
@@ -46,6 +42,5 @@
#define FLAC__ASSERT(x) #define FLAC__ASSERT(x)
#define FLAC__ASSERT_DECLARATION(x) #define FLAC__ASSERT_DECLARATION(x)
#endif #endif
#endif
#endif #endif

View File

@@ -1,6 +1,6 @@
/* libFLAC - Free Lossless Audio Codec library /* libFLAC - Free Lossless Audio Codec library
* Copyright (C) 2000-2009 Josh Coalson * Copyright (C) 2000-2009 Josh Coalson
* Copyright (C) 2011-2022 Xiph.Org Foundation * Copyright (C) 2011-2014 Xiph.Org Foundation
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@@ -60,7 +60,7 @@ extern "C" {
* structures used by the rest of the interfaces. * structures used by the rest of the interfaces.
* *
* First, you should be familiar with the * First, you should be familiar with the
* <A HREF="https://xiph.org/flac/format.html">FLAC format</A>. Many of the values here * <A HREF="../format.html">FLAC format</A>. Many of the values here
* follow directly from the specification. As a user of libFLAC, the * follow directly from the specification. As a user of libFLAC, the
* interesting parts really are the structures that describe the frame * interesting parts really are the structures that describe the frame
* header and metadata blocks. * header and metadata blocks.
@@ -113,16 +113,19 @@ extern "C" {
/** The maximum sample resolution permitted by libFLAC. /** The maximum sample resolution permitted by libFLAC.
* *
* \warning
* FLAC__MAX_BITS_PER_SAMPLE is the limit of the FLAC format. However, * FLAC__MAX_BITS_PER_SAMPLE is the limit of the FLAC format. However,
* the reference encoder/decoder used to be limited to 24 bits. This * the reference encoder/decoder is currently limited to 24 bits because
* value was used to signal that limit. * of prevalent 32-bit math, so make sure and use this value when
* appropriate.
*/ */
#define FLAC__REFERENCE_CODEC_MAX_BITS_PER_SAMPLE (32u) #define FLAC__REFERENCE_CODEC_MAX_BITS_PER_SAMPLE (24u)
/** The maximum sample rate permitted by the format. The value is /** The maximum sample rate permitted by the format. The value is
* ((2 ^ 20) - 1) * ((2 ^ 16) - 1) * 10; see <A HREF="../format.html">FLAC format</A>
* as to why.
*/ */
#define FLAC__MAX_SAMPLE_RATE (1048575u) #define FLAC__MAX_SAMPLE_RATE (655350u)
/** The maximum LPC order permitted by the format. */ /** The maximum LPC order permitted by the format. */
#define FLAC__MAX_LPC_ORDER (32u) #define FLAC__MAX_LPC_ORDER (32u)
@@ -170,10 +173,10 @@ extern FLAC_API const FLAC__byte FLAC__STREAM_SYNC_STRING[4]; /* = "fLaC" */
/** The 32-bit integer big-endian representation of the beginning of /** The 32-bit integer big-endian representation of the beginning of
* a FLAC stream. * a FLAC stream.
*/ */
extern FLAC_API const uint32_t FLAC__STREAM_SYNC; /* = 0x664C6143 */ extern FLAC_API const unsigned FLAC__STREAM_SYNC; /* = 0x664C6143 */
/** The length of the FLAC signature in bits. */ /** The length of the FLAC signature in bits. */
extern FLAC_API const uint32_t FLAC__STREAM_SYNC_LEN; /* = 32 bits */ extern FLAC_API const unsigned FLAC__STREAM_SYNC_LEN; /* = 32 bits */
/** The length of the FLAC signature in bytes. */ /** The length of the FLAC signature in bytes. */
#define FLAC__STREAM_SYNC_LENGTH (4u) #define FLAC__STREAM_SYNC_LENGTH (4u)
@@ -210,26 +213,26 @@ extern FLAC_API const char * const FLAC__EntropyCodingMethodTypeString[];
*/ */
typedef struct { typedef struct {
uint32_t *parameters; unsigned *parameters;
/**< The Rice parameters for each context. */ /**< The Rice parameters for each context. */
uint32_t *raw_bits; unsigned *raw_bits;
/**< Widths for escape-coded partitions. Will be non-zero for escaped /**< Widths for escape-coded partitions. Will be non-zero for escaped
* partitions and zero for unescaped partitions. * partitions and zero for unescaped partitions.
*/ */
uint32_t capacity_by_order; unsigned capacity_by_order;
/**< The capacity of the \a parameters and \a raw_bits arrays /**< The capacity of the \a parameters and \a raw_bits arrays
* specified as an order, i.e. the number of array elements * specified as an order, i.e. the number of array elements
* allocated is 2 ^ \a capacity_by_order. * allocated is 2 ^ \a capacity_by_order.
*/ */
} FLAC__EntropyCodingMethod_PartitionedRiceContents; } FLAC__EntropyCodingMethod_PartitionedRiceContents;
/** Header for a Rice partitioned residual. (c.f. <A HREF="https://xiph.org/flac/format.html#partitioned_rice">format specification</A>) /** Header for a Rice partitioned residual. (c.f. <A HREF="../format.html#partitioned_rice">format specification</A>)
*/ */
typedef struct { typedef struct {
uint32_t order; unsigned order;
/**< The partition order, i.e. # of contexts = 2 ^ \a order. */ /**< The partition order, i.e. # of contexts = 2 ^ \a order. */
const FLAC__EntropyCodingMethod_PartitionedRiceContents *contents; const FLAC__EntropyCodingMethod_PartitionedRiceContents *contents;
@@ -237,17 +240,17 @@ typedef struct {
} FLAC__EntropyCodingMethod_PartitionedRice; } FLAC__EntropyCodingMethod_PartitionedRice;
extern FLAC_API const uint32_t FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN; /**< == 4 (bits) */ extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN; /**< == 4 (bits) */
extern FLAC_API const uint32_t FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN; /**< == 4 (bits) */ extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN; /**< == 4 (bits) */
extern FLAC_API const uint32_t FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN; /**< == 5 (bits) */ extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN; /**< == 5 (bits) */
extern FLAC_API const uint32_t FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN; /**< == 5 (bits) */ extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN; /**< == 5 (bits) */
extern FLAC_API const uint32_t FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER; extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER;
/**< == (1<<FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN)-1 */ /**< == (1<<FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN)-1 */
extern FLAC_API const uint32_t FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_ESCAPE_PARAMETER; extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_ESCAPE_PARAMETER;
/**< == (1<<FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN)-1 */ /**< == (1<<FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN)-1 */
/** Header for the entropy coding method. (c.f. <A HREF="https://xiph.org/flac/format.html#residual">format specification</A>) /** Header for the entropy coding method. (c.f. <A HREF="../format.html#residual">format specification</A>)
*/ */
typedef struct { typedef struct {
FLAC__EntropyCodingMethodType type; FLAC__EntropyCodingMethodType type;
@@ -256,7 +259,7 @@ typedef struct {
} data; } data;
} FLAC__EntropyCodingMethod; } FLAC__EntropyCodingMethod;
extern FLAC_API const uint32_t FLAC__ENTROPY_CODING_METHOD_TYPE_LEN; /**< == 2 (bits) */ extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_TYPE_LEN; /**< == 2 (bits) */
/*****************************************************************************/ /*****************************************************************************/
@@ -276,40 +279,30 @@ typedef enum {
extern FLAC_API const char * const FLAC__SubframeTypeString[]; extern FLAC_API const char * const FLAC__SubframeTypeString[];
/** CONSTANT subframe. (c.f. <A HREF="https://xiph.org/flac/format.html#subframe_constant">format specification</A>) /** CONSTANT subframe. (c.f. <A HREF="../format.html#subframe_constant">format specification</A>)
*/ */
typedef struct { typedef struct {
FLAC__int64 value; /**< The constant signal value. */ FLAC__int32 value; /**< The constant signal value. */
} FLAC__Subframe_Constant; } FLAC__Subframe_Constant;
/** An enumeration of the possible verbatim subframe data types. */
typedef enum {
FLAC__VERBATIM_SUBFRAME_DATA_TYPE_INT32, /**< verbatim subframe has 32-bit int */
FLAC__VERBATIM_SUBFRAME_DATA_TYPE_INT64 /**< verbatim subframe has 64-bit int */
} FLAC__VerbatimSubframeDataType;
/** VERBATIM subframe. (c.f. <A HREF="../format.html#subframe_verbatim">format specification</A>)
/** VERBATIM subframe. (c.f. <A HREF="https://xiph.org/flac/format.html#subframe_verbatim">format specification</A>)
*/ */
typedef struct { typedef struct {
union { const FLAC__int32 *data; /**< A pointer to verbatim signal. */
const FLAC__int32 *int32; /**< A FLAC__int32 pointer to verbatim signal. */
const FLAC__int64 *int64; /**< A FLAC__int64 pointer to verbatim signal. */
} data;
FLAC__VerbatimSubframeDataType data_type;
} FLAC__Subframe_Verbatim; } FLAC__Subframe_Verbatim;
/** FIXED subframe. (c.f. <A HREF="https://xiph.org/flac/format.html#subframe_fixed">format specification</A>) /** FIXED subframe. (c.f. <A HREF="../format.html#subframe_fixed">format specification</A>)
*/ */
typedef struct { typedef struct {
FLAC__EntropyCodingMethod entropy_coding_method; FLAC__EntropyCodingMethod entropy_coding_method;
/**< The residual coding method. */ /**< The residual coding method. */
uint32_t order; unsigned order;
/**< The polynomial order. */ /**< The polynomial order. */
FLAC__int64 warmup[FLAC__MAX_FIXED_ORDER]; FLAC__int32 warmup[FLAC__MAX_FIXED_ORDER];
/**< Warmup samples to prime the predictor, length == order. */ /**< Warmup samples to prime the predictor, length == order. */
const FLAC__int32 *residual; const FLAC__int32 *residual;
@@ -317,16 +310,16 @@ typedef struct {
} FLAC__Subframe_Fixed; } FLAC__Subframe_Fixed;
/** LPC subframe. (c.f. <A HREF="https://xiph.org/flac/format.html#subframe_lpc">format specification</A>) /** LPC subframe. (c.f. <A HREF="../format.html#subframe_lpc">format specification</A>)
*/ */
typedef struct { typedef struct {
FLAC__EntropyCodingMethod entropy_coding_method; FLAC__EntropyCodingMethod entropy_coding_method;
/**< The residual coding method. */ /**< The residual coding method. */
uint32_t order; unsigned order;
/**< The FIR order. */ /**< The FIR order. */
uint32_t qlp_coeff_precision; unsigned qlp_coeff_precision;
/**< Quantized FIR filter coefficient precision in bits. */ /**< Quantized FIR filter coefficient precision in bits. */
int quantization_level; int quantization_level;
@@ -335,18 +328,18 @@ typedef struct {
FLAC__int32 qlp_coeff[FLAC__MAX_LPC_ORDER]; FLAC__int32 qlp_coeff[FLAC__MAX_LPC_ORDER];
/**< FIR filter coefficients. */ /**< FIR filter coefficients. */
FLAC__int64 warmup[FLAC__MAX_LPC_ORDER]; FLAC__int32 warmup[FLAC__MAX_LPC_ORDER];
/**< Warmup samples to prime the predictor, length == order. */ /**< Warmup samples to prime the predictor, length == order. */
const FLAC__int32 *residual; const FLAC__int32 *residual;
/**< The residual signal, length == (blocksize minus order) samples. */ /**< The residual signal, length == (blocksize minus order) samples. */
} FLAC__Subframe_LPC; } FLAC__Subframe_LPC;
extern FLAC_API const uint32_t FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN; /**< == 4 (bits) */ extern FLAC_API const unsigned FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN; /**< == 4 (bits) */
extern FLAC_API const uint32_t FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN; /**< == 5 (bits) */ extern FLAC_API const unsigned FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN; /**< == 5 (bits) */
/** FLAC subframe structure. (c.f. <A HREF="https://xiph.org/flac/format.html#subframe">format specification</A>) /** FLAC subframe structure. (c.f. <A HREF="../format.html#subframe">format specification</A>)
*/ */
typedef struct { typedef struct {
FLAC__SubframeType type; FLAC__SubframeType type;
@@ -356,7 +349,7 @@ typedef struct {
FLAC__Subframe_LPC lpc; FLAC__Subframe_LPC lpc;
FLAC__Subframe_Verbatim verbatim; FLAC__Subframe_Verbatim verbatim;
} data; } data;
uint32_t wasted_bits; unsigned wasted_bits;
} FLAC__Subframe; } FLAC__Subframe;
/** == 1 (bit) /** == 1 (bit)
@@ -366,14 +359,14 @@ typedef struct {
* mandatory value of \c 0 but in the future may take on the value \c 0 or \c 1 * mandatory value of \c 0 but in the future may take on the value \c 0 or \c 1
* to mean something else. * to mean something else.
*/ */
extern FLAC_API const uint32_t FLAC__SUBFRAME_ZERO_PAD_LEN; extern FLAC_API const unsigned FLAC__SUBFRAME_ZERO_PAD_LEN;
extern FLAC_API const uint32_t FLAC__SUBFRAME_TYPE_LEN; /**< == 6 (bits) */ extern FLAC_API const unsigned FLAC__SUBFRAME_TYPE_LEN; /**< == 6 (bits) */
extern FLAC_API const uint32_t FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN; /**< == 1 (bit) */ extern FLAC_API const unsigned FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN; /**< == 1 (bit) */
extern FLAC_API const uint32_t FLAC__SUBFRAME_TYPE_CONSTANT_BYTE_ALIGNED_MASK; /**< = 0x00 */ extern FLAC_API const unsigned FLAC__SUBFRAME_TYPE_CONSTANT_BYTE_ALIGNED_MASK; /**< = 0x00 */
extern FLAC_API const uint32_t FLAC__SUBFRAME_TYPE_VERBATIM_BYTE_ALIGNED_MASK; /**< = 0x02 */ extern FLAC_API const unsigned FLAC__SUBFRAME_TYPE_VERBATIM_BYTE_ALIGNED_MASK; /**< = 0x02 */
extern FLAC_API const uint32_t FLAC__SUBFRAME_TYPE_FIXED_BYTE_ALIGNED_MASK; /**< = 0x10 */ extern FLAC_API const unsigned FLAC__SUBFRAME_TYPE_FIXED_BYTE_ALIGNED_MASK; /**< = 0x10 */
extern FLAC_API const uint32_t FLAC__SUBFRAME_TYPE_LPC_BYTE_ALIGNED_MASK; /**< = 0x40 */ extern FLAC_API const unsigned FLAC__SUBFRAME_TYPE_LPC_BYTE_ALIGNED_MASK; /**< = 0x40 */
/*****************************************************************************/ /*****************************************************************************/
@@ -413,22 +406,22 @@ typedef enum {
extern FLAC_API const char * const FLAC__FrameNumberTypeString[]; extern FLAC_API const char * const FLAC__FrameNumberTypeString[];
/** FLAC frame header structure. (c.f. <A HREF="https://xiph.org/flac/format.html#frame_header">format specification</A>) /** FLAC frame header structure. (c.f. <A HREF="../format.html#frame_header">format specification</A>)
*/ */
typedef struct { typedef struct {
uint32_t blocksize; unsigned blocksize;
/**< The number of samples per subframe. */ /**< The number of samples per subframe. */
uint32_t sample_rate; unsigned sample_rate;
/**< The sample rate in Hz. */ /**< The sample rate in Hz. */
uint32_t channels; unsigned channels;
/**< The number of channels (== number of subframes). */ /**< The number of channels (== number of subframes). */
FLAC__ChannelAssignment channel_assignment; FLAC__ChannelAssignment channel_assignment;
/**< The channel assignment for the frame. */ /**< The channel assignment for the frame. */
uint32_t bits_per_sample; unsigned bits_per_sample;
/**< The sample resolution. */ /**< The sample resolution. */
FLAC__FrameNumberType number_type; FLAC__FrameNumberType number_type;
@@ -450,19 +443,19 @@ typedef struct {
*/ */
} FLAC__FrameHeader; } FLAC__FrameHeader;
extern FLAC_API const uint32_t FLAC__FRAME_HEADER_SYNC; /**< == 0x3ffe; the frame header sync code */ extern FLAC_API const unsigned FLAC__FRAME_HEADER_SYNC; /**< == 0x3ffe; the frame header sync code */
extern FLAC_API const uint32_t FLAC__FRAME_HEADER_SYNC_LEN; /**< == 14 (bits) */ extern FLAC_API const unsigned FLAC__FRAME_HEADER_SYNC_LEN; /**< == 14 (bits) */
extern FLAC_API const uint32_t FLAC__FRAME_HEADER_RESERVED_LEN; /**< == 1 (bits) */ extern FLAC_API const unsigned FLAC__FRAME_HEADER_RESERVED_LEN; /**< == 1 (bits) */
extern FLAC_API const uint32_t FLAC__FRAME_HEADER_BLOCKING_STRATEGY_LEN; /**< == 1 (bits) */ extern FLAC_API const unsigned FLAC__FRAME_HEADER_BLOCKING_STRATEGY_LEN; /**< == 1 (bits) */
extern FLAC_API const uint32_t FLAC__FRAME_HEADER_BLOCK_SIZE_LEN; /**< == 4 (bits) */ extern FLAC_API const unsigned FLAC__FRAME_HEADER_BLOCK_SIZE_LEN; /**< == 4 (bits) */
extern FLAC_API const uint32_t FLAC__FRAME_HEADER_SAMPLE_RATE_LEN; /**< == 4 (bits) */ extern FLAC_API const unsigned FLAC__FRAME_HEADER_SAMPLE_RATE_LEN; /**< == 4 (bits) */
extern FLAC_API const uint32_t FLAC__FRAME_HEADER_CHANNEL_ASSIGNMENT_LEN; /**< == 4 (bits) */ extern FLAC_API const unsigned FLAC__FRAME_HEADER_CHANNEL_ASSIGNMENT_LEN; /**< == 4 (bits) */
extern FLAC_API const uint32_t FLAC__FRAME_HEADER_BITS_PER_SAMPLE_LEN; /**< == 3 (bits) */ extern FLAC_API const unsigned FLAC__FRAME_HEADER_BITS_PER_SAMPLE_LEN; /**< == 3 (bits) */
extern FLAC_API const uint32_t FLAC__FRAME_HEADER_ZERO_PAD_LEN; /**< == 1 (bit) */ extern FLAC_API const unsigned FLAC__FRAME_HEADER_ZERO_PAD_LEN; /**< == 1 (bit) */
extern FLAC_API const uint32_t FLAC__FRAME_HEADER_CRC_LEN; /**< == 8 (bits) */ extern FLAC_API const unsigned FLAC__FRAME_HEADER_CRC_LEN; /**< == 8 (bits) */
/** FLAC frame footer structure. (c.f. <A HREF="https://xiph.org/flac/format.html#frame_footer">format specification</A>) /** FLAC frame footer structure. (c.f. <A HREF="../format.html#frame_footer">format specification</A>)
*/ */
typedef struct { typedef struct {
FLAC__uint16 crc; FLAC__uint16 crc;
@@ -472,10 +465,10 @@ typedef struct {
*/ */
} FLAC__FrameFooter; } FLAC__FrameFooter;
extern FLAC_API const uint32_t FLAC__FRAME_FOOTER_CRC_LEN; /**< == 16 (bits) */ extern FLAC_API const unsigned FLAC__FRAME_FOOTER_CRC_LEN; /**< == 16 (bits) */
/** FLAC frame structure. (c.f. <A HREF="https://xiph.org/flac/format.html#frame">format specification</A>) /** FLAC frame structure. (c.f. <A HREF="../format.html#frame">format specification</A>)
*/ */
typedef struct { typedef struct {
FLAC__FrameHeader header; FLAC__FrameHeader header;
@@ -496,31 +489,31 @@ typedef struct {
typedef enum { typedef enum {
FLAC__METADATA_TYPE_STREAMINFO = 0, FLAC__METADATA_TYPE_STREAMINFO = 0,
/**< <A HREF="https://xiph.org/flac/format.html#metadata_block_streaminfo">STREAMINFO</A> block */ /**< <A HREF="../format.html#metadata_block_streaminfo">STREAMINFO</A> block */
FLAC__METADATA_TYPE_PADDING = 1, FLAC__METADATA_TYPE_PADDING = 1,
/**< <A HREF="https://xiph.org/flac/format.html#metadata_block_padding">PADDING</A> block */ /**< <A HREF="../format.html#metadata_block_padding">PADDING</A> block */
FLAC__METADATA_TYPE_APPLICATION = 2, FLAC__METADATA_TYPE_APPLICATION = 2,
/**< <A HREF="https://xiph.org/flac/format.html#metadata_block_application">APPLICATION</A> block */ /**< <A HREF="../format.html#metadata_block_application">APPLICATION</A> block */
FLAC__METADATA_TYPE_SEEKTABLE = 3, FLAC__METADATA_TYPE_SEEKTABLE = 3,
/**< <A HREF="https://xiph.org/flac/format.html#metadata_block_seektable">SEEKTABLE</A> block */ /**< <A HREF="../format.html#metadata_block_seektable">SEEKTABLE</A> block */
FLAC__METADATA_TYPE_VORBIS_COMMENT = 4, FLAC__METADATA_TYPE_VORBIS_COMMENT = 4,
/**< <A HREF="https://xiph.org/flac/format.html#metadata_block_vorbis_comment">VORBISCOMMENT</A> block (a.k.a. FLAC tags) */ /**< <A HREF="../format.html#metadata_block_vorbis_comment">VORBISCOMMENT</A> block (a.k.a. FLAC tags) */
FLAC__METADATA_TYPE_CUESHEET = 5, FLAC__METADATA_TYPE_CUESHEET = 5,
/**< <A HREF="https://xiph.org/flac/format.html#metadata_block_cuesheet">CUESHEET</A> block */ /**< <A HREF="../format.html#metadata_block_cuesheet">CUESHEET</A> block */
FLAC__METADATA_TYPE_PICTURE = 6, FLAC__METADATA_TYPE_PICTURE = 6,
/**< <A HREF="https://xiph.org/flac/format.html#metadata_block_picture">PICTURE</A> block */ /**< <A HREF="../format.html#metadata_block_picture">PICTURE</A> block */
FLAC__METADATA_TYPE_UNDEFINED = 7, FLAC__METADATA_TYPE_UNDEFINED = 7,
/**< marker to denote beginning of undefined type range; this number will increase as new metadata types are added */ /**< marker to denote beginning of undefined type range; this number will increase as new metadata types are added */
FLAC__MAX_METADATA_TYPE = FLAC__MAX_METADATA_TYPE_CODE, FLAC__MAX_METADATA_TYPE = FLAC__MAX_METADATA_TYPE_CODE,
/**< No type will ever be greater than this. There is not enough room in the protocol block. */ /**< No type will ever be greater than this. There is not enough room in the protocol block. */
} FLAC__MetadataType; } FLAC__MetadataType;
/** Maps a FLAC__MetadataType to a C string. /** Maps a FLAC__MetadataType to a C string.
@@ -531,32 +524,32 @@ typedef enum {
extern FLAC_API const char * const FLAC__MetadataTypeString[]; extern FLAC_API const char * const FLAC__MetadataTypeString[];
/** FLAC STREAMINFO structure. (c.f. <A HREF="https://xiph.org/flac/format.html#metadata_block_streaminfo">format specification</A>) /** FLAC STREAMINFO structure. (c.f. <A HREF="../format.html#metadata_block_streaminfo">format specification</A>)
*/ */
typedef struct { typedef struct {
uint32_t min_blocksize, max_blocksize; unsigned min_blocksize, max_blocksize;
uint32_t min_framesize, max_framesize; unsigned min_framesize, max_framesize;
uint32_t sample_rate; unsigned sample_rate;
uint32_t channels; unsigned channels;
uint32_t bits_per_sample; unsigned bits_per_sample;
FLAC__uint64 total_samples; FLAC__uint64 total_samples;
FLAC__byte md5sum[16]; FLAC__byte md5sum[16];
} FLAC__StreamMetadata_StreamInfo; } FLAC__StreamMetadata_StreamInfo;
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN; /**< == 16 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN; /**< == 16 (bits) */
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN; /**< == 16 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN; /**< == 16 (bits) */
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN; /**< == 24 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN; /**< == 24 (bits) */
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN; /**< == 24 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN; /**< == 24 (bits) */
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN; /**< == 20 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN; /**< == 20 (bits) */
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN; /**< == 3 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN; /**< == 3 (bits) */
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN; /**< == 5 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN; /**< == 5 (bits) */
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN; /**< == 36 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN; /**< == 36 (bits) */
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_STREAMINFO_MD5SUM_LEN; /**< == 128 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MD5SUM_LEN; /**< == 128 (bits) */
/** The total stream length of the STREAMINFO block in bytes. */ /** The total stream length of the STREAMINFO block in bytes. */
#define FLAC__STREAM_METADATA_STREAMINFO_LENGTH (34u) #define FLAC__STREAM_METADATA_STREAMINFO_LENGTH (34u)
/** FLAC PADDING structure. (c.f. <A HREF="https://xiph.org/flac/format.html#metadata_block_padding">format specification</A>) /** FLAC PADDING structure. (c.f. <A HREF="../format.html#metadata_block_padding">format specification</A>)
*/ */
typedef struct { typedef struct {
int dummy; int dummy;
@@ -567,16 +560,16 @@ typedef struct {
} FLAC__StreamMetadata_Padding; } FLAC__StreamMetadata_Padding;
/** FLAC APPLICATION structure. (c.f. <A HREF="https://xiph.org/flac/format.html#metadata_block_application">format specification</A>) /** FLAC APPLICATION structure. (c.f. <A HREF="../format.html#metadata_block_application">format specification</A>)
*/ */
typedef struct { typedef struct {
FLAC__byte id[4]; FLAC__byte id[4];
FLAC__byte *data; FLAC__byte *data;
} FLAC__StreamMetadata_Application; } FLAC__StreamMetadata_Application;
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_APPLICATION_ID_LEN; /**< == 32 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_APPLICATION_ID_LEN; /**< == 32 (bits) */
/** SeekPoint structure used in SEEKTABLE blocks. (c.f. <A HREF="https://xiph.org/flac/format.html#seekpoint">format specification</A>) /** SeekPoint structure used in SEEKTABLE blocks. (c.f. <A HREF="../format.html#seekpoint">format specification</A>)
*/ */
typedef struct { typedef struct {
FLAC__uint64 sample_number; FLAC__uint64 sample_number;
@@ -586,13 +579,13 @@ typedef struct {
/**< The offset, in bytes, of the target frame with respect to /**< The offset, in bytes, of the target frame with respect to
* beginning of the first frame. */ * beginning of the first frame. */
uint32_t frame_samples; unsigned frame_samples;
/**< The number of samples in the target frame. */ /**< The number of samples in the target frame. */
} FLAC__StreamMetadata_SeekPoint; } FLAC__StreamMetadata_SeekPoint;
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN; /**< == 64 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN; /**< == 64 (bits) */
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN; /**< == 64 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN; /**< == 64 (bits) */
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN; /**< == 16 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN; /**< == 16 (bits) */
/** The total stream length of a seek point in bytes. */ /** The total stream length of a seek point in bytes. */
#define FLAC__STREAM_METADATA_SEEKPOINT_LENGTH (18u) #define FLAC__STREAM_METADATA_SEEKPOINT_LENGTH (18u)
@@ -604,7 +597,7 @@ extern FLAC_API const uint32_t FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN
extern FLAC_API const FLAC__uint64 FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER; extern FLAC_API const FLAC__uint64 FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER;
/** FLAC SEEKTABLE structure. (c.f. <A HREF="https://xiph.org/flac/format.html#metadata_block_seektable">format specification</A>) /** FLAC SEEKTABLE structure. (c.f. <A HREF="../format.html#metadata_block_seektable">format specification</A>)
* *
* \note From the format specification: * \note From the format specification:
* - The seek points must be sorted by ascending sample number. * - The seek points must be sorted by ascending sample number.
@@ -617,12 +610,12 @@ extern FLAC_API const FLAC__uint64 FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER;
* present in a stream. * present in a stream.
*/ */
typedef struct { typedef struct {
uint32_t num_points; unsigned num_points;
FLAC__StreamMetadata_SeekPoint *points; FLAC__StreamMetadata_SeekPoint *points;
} FLAC__StreamMetadata_SeekTable; } FLAC__StreamMetadata_SeekTable;
/** Vorbis comment entry structure used in VORBIS_COMMENT blocks. (c.f. <A HREF="https://xiph.org/flac/format.html#metadata_block_vorbis_comment">format specification</A>) /** Vorbis comment entry structure used in VORBIS_COMMENT blocks. (c.f. <A HREF="../format.html#metadata_block_vorbis_comment">format specification</A>)
* *
* For convenience, the APIs maintain a trailing NUL character at the end of * For convenience, the APIs maintain a trailing NUL character at the end of
* \a entry which is not counted toward \a length, i.e. * \a entry which is not counted toward \a length, i.e.
@@ -633,10 +626,10 @@ typedef struct {
FLAC__byte *entry; FLAC__byte *entry;
} FLAC__StreamMetadata_VorbisComment_Entry; } FLAC__StreamMetadata_VorbisComment_Entry;
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN; /**< == 32 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN; /**< == 32 (bits) */
/** FLAC VORBIS_COMMENT structure. (c.f. <A HREF="https://xiph.org/flac/format.html#metadata_block_vorbis_comment">format specification</A>) /** FLAC VORBIS_COMMENT structure. (c.f. <A HREF="../format.html#metadata_block_vorbis_comment">format specification</A>)
*/ */
typedef struct { typedef struct {
FLAC__StreamMetadata_VorbisComment_Entry vendor_string; FLAC__StreamMetadata_VorbisComment_Entry vendor_string;
@@ -644,11 +637,11 @@ typedef struct {
FLAC__StreamMetadata_VorbisComment_Entry *comments; FLAC__StreamMetadata_VorbisComment_Entry *comments;
} FLAC__StreamMetadata_VorbisComment; } FLAC__StreamMetadata_VorbisComment;
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN; /**< == 32 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN; /**< == 32 (bits) */
/** FLAC CUESHEET track index structure. (See the /** FLAC CUESHEET track index structure. (See the
* <A HREF="https://xiph.org/flac/format.html#cuesheet_track_index">format specification</A> for * <A HREF="../format.html#cuesheet_track_index">format specification</A> for
* the full description of each field.) * the full description of each field.)
*/ */
typedef struct { typedef struct {
@@ -661,13 +654,13 @@ typedef struct {
/**< The index point number. */ /**< The index point number. */
} FLAC__StreamMetadata_CueSheet_Index; } FLAC__StreamMetadata_CueSheet_Index;
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN; /**< == 64 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN; /**< == 64 (bits) */
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN; /**< == 8 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN; /**< == 8 (bits) */
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN; /**< == 3*8 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN; /**< == 3*8 (bits) */
/** FLAC CUESHEET track structure. (See the /** FLAC CUESHEET track structure. (See the
* <A HREF="https://xiph.org/flac/format.html#cuesheet_track">format specification</A> for * <A HREF="../format.html#cuesheet_track">format specification</A> for
* the full description of each field.) * the full description of each field.)
*/ */
typedef struct { typedef struct {
@@ -680,10 +673,10 @@ typedef struct {
char isrc[13]; char isrc[13];
/**< Track ISRC. This is a 12-digit alphanumeric code plus a trailing \c NUL byte */ /**< Track ISRC. This is a 12-digit alphanumeric code plus a trailing \c NUL byte */
uint32_t type:1; unsigned type:1;
/**< The track type: 0 for audio, 1 for non-audio. */ /**< The track type: 0 for audio, 1 for non-audio. */
uint32_t pre_emphasis:1; unsigned pre_emphasis:1;
/**< The pre-emphasis flag: 0 for no pre-emphasis, 1 for pre-emphasis. */ /**< The pre-emphasis flag: 0 for no pre-emphasis, 1 for pre-emphasis. */
FLAC__byte num_indices; FLAC__byte num_indices;
@@ -694,17 +687,17 @@ typedef struct {
} FLAC__StreamMetadata_CueSheet_Track; } FLAC__StreamMetadata_CueSheet_Track;
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN; /**< == 64 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN; /**< == 64 (bits) */
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN; /**< == 8 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN; /**< == 8 (bits) */
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN; /**< == 12*8 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN; /**< == 12*8 (bits) */
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN; /**< == 1 (bit) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN; /**< == 1 (bit) */
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN; /**< == 1 (bit) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN; /**< == 1 (bit) */
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN; /**< == 6+13*8 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN; /**< == 6+13*8 (bits) */
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN; /**< == 8 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN; /**< == 8 (bits) */
/** FLAC CUESHEET structure. (See the /** FLAC CUESHEET structure. (See the
* <A HREF="https://xiph.org/flac/format.html#metadata_block_cuesheet">format specification</A> * <A HREF="../format.html#metadata_block_cuesheet">format specification</A>
* for the full description of each field.) * for the full description of each field.)
*/ */
typedef struct { typedef struct {
@@ -720,7 +713,7 @@ typedef struct {
FLAC__bool is_cd; FLAC__bool is_cd;
/**< \c true if CUESHEET corresponds to a Compact Disc, else \c false. */ /**< \c true if CUESHEET corresponds to a Compact Disc, else \c false. */
uint32_t num_tracks; unsigned num_tracks;
/**< The number of tracks. */ /**< The number of tracks. */
FLAC__StreamMetadata_CueSheet_Track *tracks; FLAC__StreamMetadata_CueSheet_Track *tracks;
@@ -728,11 +721,11 @@ typedef struct {
} FLAC__StreamMetadata_CueSheet; } FLAC__StreamMetadata_CueSheet;
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN; /**< == 128*8 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN; /**< == 128*8 (bits) */
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN; /**< == 64 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN; /**< == 64 (bits) */
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN; /**< == 1 (bit) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN; /**< == 1 (bit) */
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN; /**< == 7+258*8 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN; /**< == 7+258*8 (bits) */
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN; /**< == 8 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN; /**< == 8 (bits) */
/** An enumeration of the PICTURE types (see FLAC__StreamMetadataPicture and id3 v2.4 APIC tag). */ /** An enumeration of the PICTURE types (see FLAC__StreamMetadataPicture and id3 v2.4 APIC tag). */
@@ -770,7 +763,7 @@ typedef enum {
extern FLAC_API const char * const FLAC__StreamMetadata_Picture_TypeString[]; extern FLAC_API const char * const FLAC__StreamMetadata_Picture_TypeString[];
/** FLAC PICTURE structure. (See the /** FLAC PICTURE structure. (See the
* <A HREF="https://xiph.org/flac/format.html#metadata_block_picture">format specification</A> * <A HREF="../format.html#metadata_block_picture">format specification</A>
* for the full description of each field.) * for the full description of each field.)
*/ */
typedef struct { typedef struct {
@@ -817,14 +810,14 @@ typedef struct {
} FLAC__StreamMetadata_Picture; } FLAC__StreamMetadata_Picture;
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_PICTURE_TYPE_LEN; /**< == 32 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_TYPE_LEN; /**< == 32 (bits) */
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN; /**< == 32 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN; /**< == 32 (bits) */
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN; /**< == 32 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN; /**< == 32 (bits) */
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN; /**< == 32 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN; /**< == 32 (bits) */
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN; /**< == 32 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN; /**< == 32 (bits) */
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN; /**< == 32 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN; /**< == 32 (bits) */
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_PICTURE_COLORS_LEN; /**< == 32 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_COLORS_LEN; /**< == 32 (bits) */
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN; /**< == 32 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN; /**< == 32 (bits) */
/** Structure that is used when a metadata block of unknown type is loaded. /** Structure that is used when a metadata block of unknown type is loaded.
@@ -836,9 +829,9 @@ typedef struct {
} FLAC__StreamMetadata_Unknown; } FLAC__StreamMetadata_Unknown;
/** FLAC metadata block structure. (c.f. <A HREF="https://xiph.org/flac/format.html#metadata_block">format specification</A>) /** FLAC metadata block structure. (c.f. <A HREF="../format.html#metadata_block">format specification</A>)
*/ */
typedef struct FLAC__StreamMetadata { typedef struct {
FLAC__MetadataType type; FLAC__MetadataType type;
/**< The type of the metadata block; used determine which member of the /**< The type of the metadata block; used determine which member of the
* \a data union to dereference. If type >= FLAC__METADATA_TYPE_UNDEFINED * \a data union to dereference. If type >= FLAC__METADATA_TYPE_UNDEFINED
@@ -847,7 +840,7 @@ typedef struct FLAC__StreamMetadata {
FLAC__bool is_last; FLAC__bool is_last;
/**< \c true if this metadata block is the last, else \a false */ /**< \c true if this metadata block is the last, else \a false */
uint32_t length; unsigned length;
/**< Length, in bytes, of the block data as it appears in the stream. */ /**< Length, in bytes, of the block data as it appears in the stream. */
union { union {
@@ -864,9 +857,9 @@ typedef struct FLAC__StreamMetadata {
* to use. */ * to use. */
} FLAC__StreamMetadata; } FLAC__StreamMetadata;
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_IS_LAST_LEN; /**< == 1 (bit) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_IS_LAST_LEN; /**< == 1 (bit) */
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_TYPE_LEN; /**< == 7 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_TYPE_LEN; /**< == 7 (bits) */
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_LENGTH_LEN; /**< == 24 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_LENGTH_LEN; /**< == 24 (bits) */
/** The total stream length of a metadata block header in bytes. */ /** The total stream length of a metadata block header in bytes. */
#define FLAC__STREAM_METADATA_HEADER_LENGTH (4u) #define FLAC__STREAM_METADATA_HEADER_LENGTH (4u)
@@ -887,7 +880,7 @@ extern FLAC_API const uint32_t FLAC__STREAM_METADATA_LENGTH_LEN; /**< == 24 (bit
* \c true if the given sample rate conforms to the specification, else * \c true if the given sample rate conforms to the specification, else
* \c false. * \c false.
*/ */
FLAC_API FLAC__bool FLAC__format_sample_rate_is_valid(uint32_t sample_rate); FLAC_API FLAC__bool FLAC__format_sample_rate_is_valid(unsigned sample_rate);
/** Tests that a blocksize at the given sample rate is valid for the FLAC /** Tests that a blocksize at the given sample rate is valid for the FLAC
* subset. * subset.
@@ -899,7 +892,7 @@ FLAC_API FLAC__bool FLAC__format_sample_rate_is_valid(uint32_t sample_rate);
* \c true if the given blocksize conforms to the specification for the * \c true if the given blocksize conforms to the specification for the
* subset at the given sample rate, else \c false. * subset at the given sample rate, else \c false.
*/ */
FLAC_API FLAC__bool FLAC__format_blocksize_is_subset(uint32_t blocksize, uint32_t sample_rate); FLAC_API FLAC__bool FLAC__format_blocksize_is_subset(unsigned blocksize, unsigned sample_rate);
/** Tests that a sample rate is valid for the FLAC subset. The subset rules /** Tests that a sample rate is valid for the FLAC subset. The subset rules
* for valid sample rates are slightly more complex since the rate has to * for valid sample rates are slightly more complex since the rate has to
@@ -910,7 +903,7 @@ FLAC_API FLAC__bool FLAC__format_blocksize_is_subset(uint32_t blocksize, uint32_
* \c true if the given sample rate conforms to the specification for the * \c true if the given sample rate conforms to the specification for the
* subset, else \c false. * subset, else \c false.
*/ */
FLAC_API FLAC__bool FLAC__format_sample_rate_is_subset(uint32_t sample_rate); FLAC_API FLAC__bool FLAC__format_sample_rate_is_subset(unsigned sample_rate);
/** Check a Vorbis comment entry name to see if it conforms to the Vorbis /** Check a Vorbis comment entry name to see if it conforms to the Vorbis
* comment specification. * comment specification.
@@ -933,14 +926,14 @@ FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_name_is_legal(const char *n
* *
* \param value A string to be checked. * \param value A string to be checked.
* \param length A the length of \a value in bytes. May be * \param length A the length of \a value in bytes. May be
* \c (uint32_t)(-1) to indicate that \a value is a plain * \c (unsigned)(-1) to indicate that \a value is a plain
* UTF-8 NUL-terminated string. * UTF-8 NUL-terminated string.
* \assert * \assert
* \code value != NULL \endcode * \code value != NULL \endcode
* \retval FLAC__bool * \retval FLAC__bool
* \c false if entry name is illegal, else \c true. * \c false if entry name is illegal, else \c true.
*/ */
FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_value_is_legal(const FLAC__byte *value, uint32_t length); FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_value_is_legal(const FLAC__byte *value, unsigned length);
/** Check a Vorbis comment entry to see if it conforms to the Vorbis /** Check a Vorbis comment entry to see if it conforms to the Vorbis
* comment specification. * comment specification.
@@ -957,7 +950,7 @@ FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_value_is_legal(const FLAC__
* \retval FLAC__bool * \retval FLAC__bool
* \c false if entry name is illegal, else \c true. * \c false if entry name is illegal, else \c true.
*/ */
FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_is_legal(const FLAC__byte *entry, uint32_t length); FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_is_legal(const FLAC__byte *entry, unsigned length);
/** Check a seek table to see if it conforms to the FLAC specification. /** Check a seek table to see if it conforms to the FLAC specification.
* See the format specification for limits on the contents of the * See the format specification for limits on the contents of the
@@ -980,10 +973,10 @@ FLAC_API FLAC__bool FLAC__format_seektable_is_legal(const FLAC__StreamMetadata_S
* \param seek_table A pointer to a seek table to be sorted. * \param seek_table A pointer to a seek table to be sorted.
* \assert * \assert
* \code seek_table != NULL \endcode * \code seek_table != NULL \endcode
* \retval uint32_t * \retval unsigned
* The number of duplicate seek points converted into placeholders. * The number of duplicate seek points converted into placeholders.
*/ */
FLAC_API uint32_t FLAC__format_seektable_sort(FLAC__StreamMetadata_SeekTable *seek_table); FLAC_API unsigned FLAC__format_seektable_sort(FLAC__StreamMetadata_SeekTable *seek_table);
/** Check a cue sheet to see if it conforms to the FLAC specification. /** Check a cue sheet to see if it conforms to the FLAC specification.
* See the format specification for limits on the contents of the * See the format specification for limits on the contents of the

View File

@@ -1,6 +1,6 @@
/* libFLAC - Free Lossless Audio Codec library /* libFLAC - Free Lossless Audio Codec library
* Copyright (C) 2001-2009 Josh Coalson * Copyright (C) 2001-2009 Josh Coalson
* Copyright (C) 2011-2022 Xiph.Org Foundation * Copyright (C) 2011-2014 Xiph.Org Foundation
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@@ -93,7 +93,7 @@
* Efficient means the whole file is rewritten at most one time, and only * Efficient means the whole file is rewritten at most one time, and only
* when necessary. Level 1 is not efficient only in the case that you * when necessary. Level 1 is not efficient only in the case that you
* cause more than one metadata block to grow or shrink beyond what can * cause more than one metadata block to grow or shrink beyond what can
* be accommodated by padding. In this case you should probably use level * be accomodated by padding. In this case you should probably use level
* 2, which allows you to edit all the metadata for a file in memory and * 2, which allows you to edit all the metadata for a file in memory and
* write it out all at once. * write it out all at once.
* *
@@ -134,11 +134,6 @@ extern "C" {
* STREAMINFO, VORBIS_COMMENT, CUESHEET, and PICTURE blocks, requiring * STREAMINFO, VORBIS_COMMENT, CUESHEET, and PICTURE blocks, requiring
* only a filename. * only a filename.
* *
* On Windows, filename must be a UTF-8 encoded filename, which libFLAC
* internally translates to an appropriate representation to use with
* _wfopen. On all other systems, filename is passed to fopen without
* any translation.
*
* They try to skip any ID3v2 tag at the head of the file. * They try to skip any ID3v2 tag at the head of the file.
* *
* \{ * \{
@@ -222,13 +217,13 @@ FLAC_API FLAC__bool FLAC__metadata_get_cuesheet(const char *filename, FLAC__Stre
* matched exactly. Use \c NULL to mean "any * matched exactly. Use \c NULL to mean "any
* description". * description".
* \param max_width The maximum width in pixels desired. Use * \param max_width The maximum width in pixels desired. Use
* \c (uint32_t)(-1) to mean "any width". * \c (unsigned)(-1) to mean "any width".
* \param max_height The maximum height in pixels desired. Use * \param max_height The maximum height in pixels desired. Use
* \c (uint32_t)(-1) to mean "any height". * \c (unsigned)(-1) to mean "any height".
* \param max_depth The maximum color depth in bits-per-pixel desired. * \param max_depth The maximum color depth in bits-per-pixel desired.
* Use \c (uint32_t)(-1) to mean "any depth". * Use \c (unsigned)(-1) to mean "any depth".
* \param max_colors The maximum number of colors desired. Use * \param max_colors The maximum number of colors desired. Use
* \c (uint32_t)(-1) to mean "any number of colors". * \c (unsigned)(-1) to mean "any number of colors".
* \assert * \assert
* \code filename != NULL \endcode * \code filename != NULL \endcode
* \code picture != NULL \endcode * \code picture != NULL \endcode
@@ -239,7 +234,7 @@ FLAC_API FLAC__bool FLAC__metadata_get_cuesheet(const char *filename, FLAC__Stre
* error, a file decoder error, or the file contained no PICTURE * error, a file decoder error, or the file contained no PICTURE
* block, and \a *picture will be set to \c NULL. * block, and \a *picture will be set to \c NULL.
*/ */
FLAC_API FLAC__bool FLAC__metadata_get_picture(const char *filename, FLAC__StreamMetadata **picture, FLAC__StreamMetadata_Picture_Type type, const char *mime_type, const FLAC__byte *description, uint32_t max_width, uint32_t max_height, uint32_t max_depth, uint32_t max_colors); FLAC_API FLAC__bool FLAC__metadata_get_picture(const char *filename, FLAC__StreamMetadata **picture, FLAC__StreamMetadata_Picture_Type type, const char *mime_type, const FLAC__byte *description, unsigned max_width, unsigned max_height, unsigned max_depth, unsigned max_colors);
/* \} */ /* \} */
@@ -392,11 +387,6 @@ FLAC_API FLAC__Metadata_SimpleIteratorStatus FLAC__metadata_simple_iterator_stat
/** Initialize the iterator to point to the first metadata block in the /** Initialize the iterator to point to the first metadata block in the
* given FLAC file. * given FLAC file.
* *
* On Windows, filename must be a UTF-8 encoded filename, which libFLAC
* internally translates to an appropriate representation to use with
* _wfopen. On all other systems, filename is passed to fopen without
* any translation.
*
* \param iterator A pointer to an existing iterator. * \param iterator A pointer to an existing iterator.
* \param filename The path to the FLAC file. * \param filename The path to the FLAC file.
* \param read_only If \c true, the FLAC file will be opened * \param read_only If \c true, the FLAC file will be opened
@@ -507,13 +497,13 @@ FLAC_API FLAC__MetadataType FLAC__metadata_simple_iterator_get_block_type(const
* \code iterator != NULL \endcode * \code iterator != NULL \endcode
* \a iterator has been successfully initialized with * \a iterator has been successfully initialized with
* FLAC__metadata_simple_iterator_init() * FLAC__metadata_simple_iterator_init()
* \retval uint32_t * \retval unsigned
* The length of the metadata block at the current iterator position. * The length of the metadata block at the current iterator position.
* The is same length as that in the * The is same length as that in the
* <a href="http://xiph.org/flhttps://xiph.org/flac/format.html#metadata_block_header">metadata block header</a>, * <a href="http://xiph.org/flac/format.html#metadata_block_header">metadata block header</a>,
* i.e. the length of the metadata body that follows the header. * i.e. the length of the metadata body that follows the header.
*/ */
FLAC_API uint32_t FLAC__metadata_simple_iterator_get_block_length(const FLAC__Metadata_SimpleIterator *iterator); FLAC_API unsigned FLAC__metadata_simple_iterator_get_block_length(const FLAC__Metadata_SimpleIterator *iterator);
/** Get the application ID of the \c APPLICATION block at the current /** Get the application ID of the \c APPLICATION block at the current
* position. This avoids reading the actual block data which can save * position. This avoids reading the actual block data which can save
@@ -677,7 +667,7 @@ FLAC_API FLAC__bool FLAC__metadata_simple_iterator_delete_block(FLAC__Metadata_S
* *
* - Create a new chain using FLAC__metadata_chain_new(). A chain is a * - Create a new chain using FLAC__metadata_chain_new(). A chain is a
* linked list of FLAC metadata blocks. * linked list of FLAC metadata blocks.
* - Read all metadata into the chain from a FLAC file using * - Read all metadata into the the chain from a FLAC file using
* FLAC__metadata_chain_read() or FLAC__metadata_chain_read_ogg() and * FLAC__metadata_chain_read() or FLAC__metadata_chain_read_ogg() and
* check the status. * check the status.
* - Optionally, consolidate the padding using * - Optionally, consolidate the padding using
@@ -774,7 +764,7 @@ typedef enum {
FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH, FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH,
/**< FLAC__metadata_chain_write() was called on a chain read by /**< FLAC__metadata_chain_write() was called on a chain read by
* FLAC__metadata_chain_read_with_callbacks()/FLAC__metadata_chain_read_ogg_with_callbacks(), * FLAC__metadata_chain_read_with_callbacks()/FLAC__metadata_chain_read_ogg_with_callbacks(),
* or * or
* FLAC__metadata_chain_write_with_callbacks()/FLAC__metadata_chain_write_with_callbacks_and_tempfile() * FLAC__metadata_chain_write_with_callbacks()/FLAC__metadata_chain_write_with_callbacks_and_tempfile()
* was called on a chain read by * was called on a chain read by
* FLAC__metadata_chain_read()/FLAC__metadata_chain_read_ogg(). * FLAC__metadata_chain_read()/FLAC__metadata_chain_read_ogg().
@@ -829,11 +819,6 @@ FLAC_API void FLAC__metadata_chain_delete(FLAC__Metadata_Chain *chain);
FLAC_API FLAC__Metadata_ChainStatus FLAC__metadata_chain_status(FLAC__Metadata_Chain *chain); FLAC_API FLAC__Metadata_ChainStatus FLAC__metadata_chain_status(FLAC__Metadata_Chain *chain);
/** Read all metadata from a FLAC file into the chain. /** Read all metadata from a FLAC file into the chain.
*
* On Windows, filename must be a UTF-8 encoded filename, which libFLAC
* internally translates to an appropriate representation to use with
* _wfopen. On all other systems, filename is passed to fopen without
* any translation.
* *
* \param chain A pointer to an existing chain. * \param chain A pointer to an existing chain.
* \param filename The path to the FLAC file to read. * \param filename The path to the FLAC file to read.
@@ -848,11 +833,6 @@ FLAC_API FLAC__Metadata_ChainStatus FLAC__metadata_chain_status(FLAC__Metadata_C
FLAC_API FLAC__bool FLAC__metadata_chain_read(FLAC__Metadata_Chain *chain, const char *filename); FLAC_API FLAC__bool FLAC__metadata_chain_read(FLAC__Metadata_Chain *chain, const char *filename);
/** Read all metadata from an Ogg FLAC file into the chain. /** Read all metadata from an Ogg FLAC file into the chain.
*
* On Windows, filename must be a UTF-8 encoded filename, which libFLAC
* internally translates to an appropriate representation to use with
* _wfopen. On all other systems, filename is passed to fopen without
* any translation.
* *
* \note Ogg FLAC metadata data writing is not supported yet and * \note Ogg FLAC metadata data writing is not supported yet and
* FLAC__metadata_chain_write() will fail. * FLAC__metadata_chain_write() will fail.
@@ -1393,13 +1373,12 @@ FLAC_API FLAC__bool FLAC__metadata_object_is_equal(const FLAC__StreamMetadata *b
* \retval FLAC__bool * \retval FLAC__bool
* \c false if \a copy is \c true and malloc() fails, else \c true. * \c false if \a copy is \c true and malloc() fails, else \c true.
*/ */
FLAC_API FLAC__bool FLAC__metadata_object_application_set_data(FLAC__StreamMetadata *object, FLAC__byte *data, uint32_t length, FLAC__bool copy); FLAC_API FLAC__bool FLAC__metadata_object_application_set_data(FLAC__StreamMetadata *object, FLAC__byte *data, unsigned length, FLAC__bool copy);
/** Resize the seekpoint array. /** Resize the seekpoint array.
* *
* If the size shrinks, elements will truncated; if it grows, new placeholder * If the size shrinks, elements will truncated; if it grows, new placeholder
* points will be added to the end. If this function returns false, the * points will be added to the end.
* object is left untouched.
* *
* \param object A pointer to an existing SEEKTABLE object. * \param object A pointer to an existing SEEKTABLE object.
* \param new_num_points The desired length of the array; may be \c 0. * \param new_num_points The desired length of the array; may be \c 0.
@@ -1411,7 +1390,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_application_set_data(FLAC__StreamMetad
* \retval FLAC__bool * \retval FLAC__bool
* \c false if memory allocation error, else \c true. * \c false if memory allocation error, else \c true.
*/ */
FLAC_API FLAC__bool FLAC__metadata_object_seektable_resize_points(FLAC__StreamMetadata *object, uint32_t new_num_points); FLAC_API FLAC__bool FLAC__metadata_object_seektable_resize_points(FLAC__StreamMetadata *object, unsigned new_num_points);
/** Set a seekpoint in a seektable. /** Set a seekpoint in a seektable.
* *
@@ -1423,7 +1402,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_seektable_resize_points(FLAC__StreamMe
* \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode * \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode
* \code object->data.seek_table.num_points > point_num \endcode * \code object->data.seek_table.num_points > point_num \endcode
*/ */
FLAC_API void FLAC__metadata_object_seektable_set_point(FLAC__StreamMetadata *object, uint32_t point_num, FLAC__StreamMetadata_SeekPoint point); FLAC_API void FLAC__metadata_object_seektable_set_point(FLAC__StreamMetadata *object, unsigned point_num, FLAC__StreamMetadata_SeekPoint point);
/** Insert a seekpoint into a seektable. /** Insert a seekpoint into a seektable.
* *
@@ -1437,7 +1416,7 @@ FLAC_API void FLAC__metadata_object_seektable_set_point(FLAC__StreamMetadata *ob
* \retval FLAC__bool * \retval FLAC__bool
* \c false if memory allocation error, else \c true. * \c false if memory allocation error, else \c true.
*/ */
FLAC_API FLAC__bool FLAC__metadata_object_seektable_insert_point(FLAC__StreamMetadata *object, uint32_t point_num, FLAC__StreamMetadata_SeekPoint point); FLAC_API FLAC__bool FLAC__metadata_object_seektable_insert_point(FLAC__StreamMetadata *object, unsigned point_num, FLAC__StreamMetadata_SeekPoint point);
/** Delete a seekpoint from a seektable. /** Delete a seekpoint from a seektable.
* *
@@ -1450,7 +1429,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_seektable_insert_point(FLAC__StreamMet
* \retval FLAC__bool * \retval FLAC__bool
* \c false if memory allocation error, else \c true. * \c false if memory allocation error, else \c true.
*/ */
FLAC_API FLAC__bool FLAC__metadata_object_seektable_delete_point(FLAC__StreamMetadata *object, uint32_t point_num); FLAC_API FLAC__bool FLAC__metadata_object_seektable_delete_point(FLAC__StreamMetadata *object, unsigned point_num);
/** Check a seektable to see if it conforms to the FLAC specification. /** Check a seektable to see if it conforms to the FLAC specification.
* See the format specification for limits on the contents of the * See the format specification for limits on the contents of the
@@ -1480,7 +1459,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_seektable_is_legal(const FLAC__StreamM
* \retval FLAC__bool * \retval FLAC__bool
* \c false if memory allocation fails, else \c true. * \c false if memory allocation fails, else \c true.
*/ */
FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_placeholders(FLAC__StreamMetadata *object, uint32_t num); FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_placeholders(FLAC__StreamMetadata *object, unsigned num);
/** Append a specific seek point template to the end of a seek table. /** Append a specific seek point template to the end of a seek table.
* *
@@ -1515,7 +1494,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_point(FLAC__
* \retval FLAC__bool * \retval FLAC__bool
* \c false if memory allocation fails, else \c true. * \c false if memory allocation fails, else \c true.
*/ */
FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_points(FLAC__StreamMetadata *object, FLAC__uint64 sample_numbers[], uint32_t num); FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_points(FLAC__StreamMetadata *object, FLAC__uint64 sample_numbers[], unsigned num);
/** Append a set of evenly-spaced seek point templates to the end of a /** Append a set of evenly-spaced seek point templates to the end of a
* seek table. * seek table.
@@ -1537,7 +1516,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_points(FLAC_
* \retval FLAC__bool * \retval FLAC__bool
* \c false if memory allocation fails, else \c true. * \c false if memory allocation fails, else \c true.
*/ */
FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_spaced_points(FLAC__StreamMetadata *object, uint32_t num, FLAC__uint64 total_samples); FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_spaced_points(FLAC__StreamMetadata *object, unsigned num, FLAC__uint64 total_samples);
/** Append a set of evenly-spaced seek point templates to the end of a /** Append a set of evenly-spaced seek point templates to the end of a
* seek table. * seek table.
@@ -1565,7 +1544,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_spaced_point
* \retval FLAC__bool * \retval FLAC__bool
* \c false if memory allocation fails, else \c true. * \c false if memory allocation fails, else \c true.
*/ */
FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_spaced_points_by_samples(FLAC__StreamMetadata *object, uint32_t samples, FLAC__uint64 total_samples); FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_spaced_points_by_samples(FLAC__StreamMetadata *object, unsigned samples, FLAC__uint64 total_samples);
/** Sort a seek table's seek points according to the format specification, /** Sort a seek table's seek points according to the format specification,
* removing duplicates. * removing duplicates.
@@ -1612,8 +1591,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_set_vendor_string(FLAC__
/** Resize the comment array. /** Resize the comment array.
* *
* If the size shrinks, elements will truncated; if it grows, new empty * If the size shrinks, elements will truncated; if it grows, new empty
* fields will be added to the end. If this function returns false, the * fields will be added to the end.
* object is left untouched.
* *
* \param object A pointer to an existing VORBIS_COMMENT object. * \param object A pointer to an existing VORBIS_COMMENT object.
* \param new_num_comments The desired length of the array; may be \c 0. * \param new_num_comments The desired length of the array; may be \c 0.
@@ -1625,7 +1603,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_set_vendor_string(FLAC__
* \retval FLAC__bool * \retval FLAC__bool
* \c false if memory allocation fails, else \c true. * \c false if memory allocation fails, else \c true.
*/ */
FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_resize_comments(FLAC__StreamMetadata *object, uint32_t new_num_comments); FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_resize_comments(FLAC__StreamMetadata *object, unsigned new_num_comments);
/** Sets a comment in a VORBIS_COMMENT block. /** Sets a comment in a VORBIS_COMMENT block.
* *
@@ -1652,7 +1630,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_resize_comments(FLAC__St
* \c false if memory allocation fails or \a entry does not comply with the * \c false if memory allocation fails or \a entry does not comply with the
* Vorbis comment specification, else \c true. * Vorbis comment specification, else \c true.
*/ */
FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_set_comment(FLAC__StreamMetadata *object, uint32_t comment_num, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool copy); FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_set_comment(FLAC__StreamMetadata *object, unsigned comment_num, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool copy);
/** Insert a comment in a VORBIS_COMMENT block at the given index. /** Insert a comment in a VORBIS_COMMENT block at the given index.
* *
@@ -1682,7 +1660,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_set_comment(FLAC__Stream
* \c false if memory allocation fails or \a entry does not comply with the * \c false if memory allocation fails or \a entry does not comply with the
* Vorbis comment specification, else \c true. * Vorbis comment specification, else \c true.
*/ */
FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_insert_comment(FLAC__StreamMetadata *object, uint32_t comment_num, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool copy); FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_insert_comment(FLAC__StreamMetadata *object, unsigned comment_num, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool copy);
/** Appends a comment to a VORBIS_COMMENT block. /** Appends a comment to a VORBIS_COMMENT block.
* *
@@ -1714,7 +1692,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_append_comment(FLAC__Str
* For convenience, a trailing NUL is added to the entry if it doesn't have * For convenience, a trailing NUL is added to the entry if it doesn't have
* one already. * one already.
* *
* Depending on the value of \a all, either all or just the first comment * Depending on the the value of \a all, either all or just the first comment
* whose field name(s) match the given entry's name will be replaced by the * whose field name(s) match the given entry's name will be replaced by the
* given entry. If no comments match, \a entry will simply be appended. * given entry. If no comments match, \a entry will simply be appended.
* *
@@ -1755,7 +1733,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_replace_comment(FLAC__St
* \retval FLAC__bool * \retval FLAC__bool
* \c false if realloc() fails, else \c true. * \c false if realloc() fails, else \c true.
*/ */
FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_delete_comment(FLAC__StreamMetadata *object, uint32_t comment_num); FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_delete_comment(FLAC__StreamMetadata *object, unsigned comment_num);
/** Creates a Vorbis comment entry from NUL-terminated name and value strings. /** Creates a Vorbis comment entry from NUL-terminated name and value strings.
* *
@@ -1811,7 +1789,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_entry_to_name_value_pair
* \retval FLAC__bool * \retval FLAC__bool
* \c true if the field names match, else \c false * \c true if the field names match, else \c false
*/ */
FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_entry_matches(const FLAC__StreamMetadata_VorbisComment_Entry entry, const char *field_name, uint32_t field_name_length); FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_entry_matches(const FLAC__StreamMetadata_VorbisComment_Entry entry, const char *field_name, unsigned field_name_length);
/** Find a Vorbis comment with the given field name. /** Find a Vorbis comment with the given field name.
* *
@@ -1830,7 +1808,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_entry_matches(const FLAC
* The offset in the comment array of the first comment whose field * The offset in the comment array of the first comment whose field
* name matches \a field_name, or \c -1 if no match was found. * name matches \a field_name, or \c -1 if no match was found.
*/ */
FLAC_API int FLAC__metadata_object_vorbiscomment_find_entry_from(const FLAC__StreamMetadata *object, uint32_t offset, const char *field_name); FLAC_API int FLAC__metadata_object_vorbiscomment_find_entry_from(const FLAC__StreamMetadata *object, unsigned offset, const char *field_name);
/** Remove first Vorbis comment matching the given field name. /** Remove first Vorbis comment matching the given field name.
* *
@@ -1893,8 +1871,7 @@ FLAC_API void FLAC__metadata_object_cuesheet_track_delete(FLAC__StreamMetadata_C
/** Resize a track's index point array. /** Resize a track's index point array.
* *
* If the size shrinks, elements will truncated; if it grows, new blank * If the size shrinks, elements will truncated; if it grows, new blank
* indices will be added to the end. If this function returns false, the * indices will be added to the end.
* track object is left untouched.
* *
* \param object A pointer to an existing CUESHEET object. * \param object A pointer to an existing CUESHEET object.
* \param track_num The index of the track to modify. NOTE: this is not * \param track_num The index of the track to modify. NOTE: this is not
@@ -1909,7 +1886,7 @@ FLAC_API void FLAC__metadata_object_cuesheet_track_delete(FLAC__StreamMetadata_C
* \retval FLAC__bool * \retval FLAC__bool
* \c false if memory allocation error, else \c true. * \c false if memory allocation error, else \c true.
*/ */
FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_resize_indices(FLAC__StreamMetadata *object, uint32_t track_num, uint32_t new_num_indices); FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_resize_indices(FLAC__StreamMetadata *object, unsigned track_num, unsigned new_num_indices);
/** Insert an index point in a CUESHEET track at the given index. /** Insert an index point in a CUESHEET track at the given index.
* *
@@ -1932,7 +1909,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_resize_indices(FLAC__St
* \retval FLAC__bool * \retval FLAC__bool
* \c false if realloc() fails, else \c true. * \c false if realloc() fails, else \c true.
*/ */
FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_insert_index(FLAC__StreamMetadata *object, uint32_t track_num, uint32_t index_num, FLAC__StreamMetadata_CueSheet_Index index); FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_insert_index(FLAC__StreamMetadata *object, unsigned track_num, unsigned index_num, FLAC__StreamMetadata_CueSheet_Index index);
/** Insert a blank index point in a CUESHEET track at the given index. /** Insert a blank index point in a CUESHEET track at the given index.
* *
@@ -1956,7 +1933,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_insert_index(FLAC__Stre
* \retval FLAC__bool * \retval FLAC__bool
* \c false if realloc() fails, else \c true. * \c false if realloc() fails, else \c true.
*/ */
FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_insert_blank_index(FLAC__StreamMetadata *object, uint32_t track_num, uint32_t index_num); FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_insert_blank_index(FLAC__StreamMetadata *object, unsigned track_num, unsigned index_num);
/** Delete an index point in a CUESHEET track at the given index. /** Delete an index point in a CUESHEET track at the given index.
* *
@@ -1975,13 +1952,12 @@ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_insert_blank_index(FLAC
* \retval FLAC__bool * \retval FLAC__bool
* \c false if realloc() fails, else \c true. * \c false if realloc() fails, else \c true.
*/ */
FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_delete_index(FLAC__StreamMetadata *object, uint32_t track_num, uint32_t index_num); FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_delete_index(FLAC__StreamMetadata *object, unsigned track_num, unsigned index_num);
/** Resize the track array. /** Resize the track array.
* *
* If the size shrinks, elements will truncated; if it grows, new blank * If the size shrinks, elements will truncated; if it grows, new blank
* tracks will be added to the end. If this function returns false, the * tracks will be added to the end.
* object is left untouched.
* *
* \param object A pointer to an existing CUESHEET object. * \param object A pointer to an existing CUESHEET object.
* \param new_num_tracks The desired length of the array; may be \c 0. * \param new_num_tracks The desired length of the array; may be \c 0.
@@ -1993,7 +1969,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_delete_index(FLAC__Stre
* \retval FLAC__bool * \retval FLAC__bool
* \c false if memory allocation error, else \c true. * \c false if memory allocation error, else \c true.
*/ */
FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_resize_tracks(FLAC__StreamMetadata *object, uint32_t new_num_tracks); FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_resize_tracks(FLAC__StreamMetadata *object, unsigned new_num_tracks);
/** Sets a track in a CUESHEET block. /** Sets a track in a CUESHEET block.
* *
@@ -2015,7 +1991,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_resize_tracks(FLAC__StreamMet
* \retval FLAC__bool * \retval FLAC__bool
* \c false if \a copy is \c true and malloc() fails, else \c true. * \c false if \a copy is \c true and malloc() fails, else \c true.
*/ */
FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_set_track(FLAC__StreamMetadata *object, uint32_t track_num, FLAC__StreamMetadata_CueSheet_Track *track, FLAC__bool copy); FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_set_track(FLAC__StreamMetadata *object, unsigned track_num, FLAC__StreamMetadata_CueSheet_Track *track, FLAC__bool copy);
/** Insert a track in a CUESHEET block at the given index. /** Insert a track in a CUESHEET block at the given index.
* *
@@ -2038,7 +2014,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_set_track(FLAC__StreamMetadat
* \retval FLAC__bool * \retval FLAC__bool
* \c false if \a copy is \c true and malloc() fails, else \c true. * \c false if \a copy is \c true and malloc() fails, else \c true.
*/ */
FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_insert_track(FLAC__StreamMetadata *object, uint32_t track_num, FLAC__StreamMetadata_CueSheet_Track *track, FLAC__bool copy); FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_insert_track(FLAC__StreamMetadata *object, unsigned track_num, FLAC__StreamMetadata_CueSheet_Track *track, FLAC__bool copy);
/** Insert a blank track in a CUESHEET block at the given index. /** Insert a blank track in a CUESHEET block at the given index.
* *
@@ -2057,7 +2033,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_insert_track(FLAC__StreamMeta
* \retval FLAC__bool * \retval FLAC__bool
* \c false if \a copy is \c true and malloc() fails, else \c true. * \c false if \a copy is \c true and malloc() fails, else \c true.
*/ */
FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_insert_blank_track(FLAC__StreamMetadata *object, uint32_t track_num); FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_insert_blank_track(FLAC__StreamMetadata *object, unsigned track_num);
/** Delete a track in a CUESHEET block at the given index. /** Delete a track in a CUESHEET block at the given index.
* *
@@ -2072,7 +2048,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_insert_blank_track(FLAC__Stre
* \retval FLAC__bool * \retval FLAC__bool
* \c false if realloc() fails, else \c true. * \c false if realloc() fails, else \c true.
*/ */
FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_delete_track(FLAC__StreamMetadata *object, uint32_t track_num); FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_delete_track(FLAC__StreamMetadata *object, unsigned track_num);
/** Check a cue sheet to see if it conforms to the FLAC specification. /** Check a cue sheet to see if it conforms to the FLAC specification.
* See the format specification for limits on the contents of the * See the format specification for limits on the contents of the
@@ -2197,34 +2173,6 @@ FLAC_API FLAC__bool FLAC__metadata_object_picture_set_data(FLAC__StreamMetadata
*/ */
FLAC_API FLAC__bool FLAC__metadata_object_picture_is_legal(const FLAC__StreamMetadata *object, const char **violation); FLAC_API FLAC__bool FLAC__metadata_object_picture_is_legal(const FLAC__StreamMetadata *object, const char **violation);
/** Get the raw (binary) representation of a FLAC__StreamMetadata objeect.
* After use, free() the returned buffer. The length of the buffer is
* the length of the input metadata object plus 4 bytes for the header.
*
* \param object A pointer to metadata block to be converted.
* \assert
* \code object != NULL \endcode
* \retval FLAC__byte*
* \c NULL if there was an error, else a pointer to a buffer holding
* the requested data.
*/
FLAC_API FLAC__byte * FLAC__metadata_object_get_raw(const FLAC__StreamMetadata *object);
/** Turn a raw (binary) representation into a FLAC__StreamMetadata objeect.
* The returned object must be deleted with FLAC__metadata_object_delete()
* after use.
*
* \param buffer A pointer to a buffer containing a binary representation
* to be converted to a FLAC__StreamMetadata object
* \param length The length of the supplied buffer
* \retval FLAC__StreamMetadata*
* \c NULL if there was an error, else a pointer to a FLAC__StreamMetadata
* holding the requested data.
*/
FLAC_API FLAC__StreamMetadata * FLAC__metadata_object_set_raw(FLAC__byte *buffer, FLAC__uint32 length);
/* \} */ /* \} */
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -1,6 +1,6 @@
/* libFLAC - Free Lossless Audio Codec library /* libFLAC - Free Lossless Audio Codec library
* Copyright (C) 2000-2009 Josh Coalson * Copyright (C) 2000-2009 Josh Coalson
* Copyright (C) 2011-2022 Xiph.Org Foundation * Copyright (C) 2011-2014 Xiph.Org Foundation
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@@ -33,10 +33,27 @@
#ifndef FLAC__ORDINALS_H #ifndef FLAC__ORDINALS_H
#define FLAC__ORDINALS_H #define FLAC__ORDINALS_H
/* This of course assumes C99 headers */ #if defined(_MSC_VER) && _MSC_VER < 1600
/* Microsoft Visual Studio earlier than the 2010 version did not provide
* the 1999 ISO C Standard header file <stdint.h>.
*/
typedef __int8 FLAC__int8;
typedef unsigned __int8 FLAC__uint8;
typedef __int16 FLAC__int16;
typedef __int32 FLAC__int32;
typedef __int64 FLAC__int64;
typedef unsigned __int16 FLAC__uint16;
typedef unsigned __int32 FLAC__uint32;
typedef unsigned __int64 FLAC__uint64;
#else
/* For MSVC 2010 and everything else which provides <stdint.h>. */
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
typedef int8_t FLAC__int8; typedef int8_t FLAC__int8;
typedef uint8_t FLAC__uint8; typedef uint8_t FLAC__uint8;
@@ -48,8 +65,22 @@ typedef uint16_t FLAC__uint16;
typedef uint32_t FLAC__uint32; typedef uint32_t FLAC__uint32;
typedef uint64_t FLAC__uint64; typedef uint64_t FLAC__uint64;
#endif
typedef int FLAC__bool; typedef int FLAC__bool;
typedef FLAC__uint8 FLAC__byte; typedef FLAC__uint8 FLAC__byte;
#ifdef true
#undef true
#endif
#ifdef false
#undef false
#endif
#ifndef __cplusplus
#define true 1
#define false 0
#endif
#endif #endif

View File

@@ -1,6 +1,6 @@
/* libFLAC - Free Lossless Audio Codec library /* libFLAC - Free Lossless Audio Codec library
* Copyright (C) 2000-2009 Josh Coalson * Copyright (C) 2000-2009 Josh Coalson
* Copyright (C) 2011-2022 Xiph.Org Foundation * Copyright (C) 2011-2014 Xiph.Org Foundation
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@@ -228,7 +228,7 @@ typedef enum {
*/ */
FLAC__STREAM_DECODER_ABORTED, FLAC__STREAM_DECODER_ABORTED,
/**< The decoder was aborted by the read or write callback. */ /**< The decoder was aborted by the read callback. */
FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR, FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR,
/**< An error occurred allocating memory. The decoder is in an invalid /**< An error occurred allocating memory. The decoder is in an invalid
@@ -422,11 +422,7 @@ extern FLAC_API const char * const FLAC__StreamDecoderWriteStatusString[];
* could be because the decoder encountered a valid frame made by a future * could be because the decoder encountered a valid frame made by a future
* version of the encoder which it cannot parse, or because of a false * version of the encoder which it cannot parse, or because of a false
* sync making it appear as though an encountered frame was generated by * sync making it appear as though an encountered frame was generated by
* a future encoder. \c FLAC__STREAM_DECODER_ERROR_STATUS_BAD_METADATA is * a future encoder.
* caused by finding data that doesn't fit a metadata block (too large
* or too small) or finding inconsistencies in the metadata, for example
* a PICTURE block with an image that exceeds the size of the metadata
* block.
*/ */
typedef enum { typedef enum {
@@ -439,12 +435,9 @@ typedef enum {
FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH, FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH,
/**< The frame's data did not match the CRC in the footer. */ /**< The frame's data did not match the CRC in the footer. */
FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM, FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM
/**< The decoder encountered reserved fields in use in the stream. */ /**< The decoder encountered reserved fields in use in the stream. */
FLAC__STREAM_DECODER_ERROR_STATUS_BAD_METADATA
/**< The decoder encountered a corrupted metadata block. */
} FLAC__StreamDecoderErrorStatus; } FLAC__StreamDecoderErrorStatus;
/** Maps a FLAC__StreamDecoderErrorStatus to a C string. /** Maps a FLAC__StreamDecoderErrorStatus to a C string.
@@ -681,7 +674,7 @@ typedef FLAC__bool (*FLAC__StreamDecoderEofCallback)(const FLAC__StreamDecoder *
* samples of length \a frame->header.blocksize. * samples of length \a frame->header.blocksize.
* Channels will be ordered according to the FLAC * Channels will be ordered according to the FLAC
* specification; see the documentation for the * specification; see the documentation for the
* <A HREF="https://xiph.org/flac/format.html#frame_header">frame header</A>. * <A HREF="../format.html#frame_header">frame header</A>.
* \param client_data The callee's client data set through * \param client_data The callee's client data set through
* FLAC__stream_decoder_init_*(). * FLAC__stream_decoder_init_*().
* \retval FLAC__StreamDecoderWriteStatus * \retval FLAC__StreamDecoderWriteStatus
@@ -927,7 +920,7 @@ FLAC_API FLAC__bool FLAC__stream_decoder_get_md5_checking(const FLAC__StreamDeco
* \param decoder A decoder instance to query. * \param decoder A decoder instance to query.
* \assert * \assert
* \code decoder != NULL \endcode * \code decoder != NULL \endcode
* \retval uint32_t * \retval unsigned
* See above. * See above.
*/ */
FLAC_API FLAC__uint64 FLAC__stream_decoder_get_total_samples(const FLAC__StreamDecoder *decoder); FLAC_API FLAC__uint64 FLAC__stream_decoder_get_total_samples(const FLAC__StreamDecoder *decoder);
@@ -939,10 +932,10 @@ FLAC_API FLAC__uint64 FLAC__stream_decoder_get_total_samples(const FLAC__StreamD
* \param decoder A decoder instance to query. * \param decoder A decoder instance to query.
* \assert * \assert
* \code decoder != NULL \endcode * \code decoder != NULL \endcode
* \retval uint32_t * \retval unsigned
* See above. * See above.
*/ */
FLAC_API uint32_t FLAC__stream_decoder_get_channels(const FLAC__StreamDecoder *decoder); FLAC_API unsigned FLAC__stream_decoder_get_channels(const FLAC__StreamDecoder *decoder);
/** Get the current channel assignment in the stream being decoded. /** Get the current channel assignment in the stream being decoded.
* Will only be valid after decoding has started and will contain the * Will only be valid after decoding has started and will contain the
@@ -963,10 +956,10 @@ FLAC_API FLAC__ChannelAssignment FLAC__stream_decoder_get_channel_assignment(con
* \param decoder A decoder instance to query. * \param decoder A decoder instance to query.
* \assert * \assert
* \code decoder != NULL \endcode * \code decoder != NULL \endcode
* \retval uint32_t * \retval unsigned
* See above. * See above.
*/ */
FLAC_API uint32_t FLAC__stream_decoder_get_bits_per_sample(const FLAC__StreamDecoder *decoder); FLAC_API unsigned FLAC__stream_decoder_get_bits_per_sample(const FLAC__StreamDecoder *decoder);
/** Get the current sample rate in Hz of the stream being decoded. /** Get the current sample rate in Hz of the stream being decoded.
* Will only be valid after decoding has started and will contain the * Will only be valid after decoding has started and will contain the
@@ -975,10 +968,10 @@ FLAC_API uint32_t FLAC__stream_decoder_get_bits_per_sample(const FLAC__StreamDec
* \param decoder A decoder instance to query. * \param decoder A decoder instance to query.
* \assert * \assert
* \code decoder != NULL \endcode * \code decoder != NULL \endcode
* \retval uint32_t * \retval unsigned
* See above. * See above.
*/ */
FLAC_API uint32_t FLAC__stream_decoder_get_sample_rate(const FLAC__StreamDecoder *decoder); FLAC_API unsigned FLAC__stream_decoder_get_sample_rate(const FLAC__StreamDecoder *decoder);
/** Get the current blocksize of the stream being decoded. /** Get the current blocksize of the stream being decoded.
* Will only be valid after decoding has started and will contain the * Will only be valid after decoding has started and will contain the
@@ -987,10 +980,10 @@ FLAC_API uint32_t FLAC__stream_decoder_get_sample_rate(const FLAC__StreamDecoder
* \param decoder A decoder instance to query. * \param decoder A decoder instance to query.
* \assert * \assert
* \code decoder != NULL \endcode * \code decoder != NULL \endcode
* \retval uint32_t * \retval unsigned
* See above. * See above.
*/ */
FLAC_API uint32_t FLAC__stream_decoder_get_blocksize(const FLAC__StreamDecoder *decoder); FLAC_API unsigned FLAC__stream_decoder_get_blocksize(const FLAC__StreamDecoder *decoder);
/** Returns the decoder's current read position within the stream. /** Returns the decoder's current read position within the stream.
* The position is the byte offset from the start of the stream. * The position is the byte offset from the start of the stream.
@@ -1013,16 +1006,6 @@ FLAC_API uint32_t FLAC__stream_decoder_get_blocksize(const FLAC__StreamDecoder *
*/ */
FLAC_API FLAC__bool FLAC__stream_decoder_get_decode_position(const FLAC__StreamDecoder *decoder, FLAC__uint64 *position); FLAC_API FLAC__bool FLAC__stream_decoder_get_decode_position(const FLAC__StreamDecoder *decoder, FLAC__uint64 *position);
/** Return client_data from decoder.
* The data pointed to by the pointer should not be modified.
*
* \param decoder A decoder instance.
* \retval const void *
* The callee's client data set through FLAC__stream_decoder_init_*().
* Do not modify the contents.
*/
FLAC_API const void *FLAC__stream_decoder_get_client_data(FLAC__StreamDecoder *decoder);
/** Initialize the decoder instance to decode native FLAC streams. /** Initialize the decoder instance to decode native FLAC streams.
* *
* This flavor of initialization sets up the decoder to decode from a * This flavor of initialization sets up the decoder to decode from a
@@ -1201,7 +1184,7 @@ FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_ogg_stream(
* Unless \a file is \c stdin, it will be closed * Unless \a file is \c stdin, it will be closed
* when FLAC__stream_decoder_finish() is called. * when FLAC__stream_decoder_finish() is called.
* Note however that seeking will not work when * Note however that seeking will not work when
* decoding from \c stdin since it is not seekable. * decoding from \c stdout since it is not seekable.
* \param write_callback See FLAC__StreamDecoderWriteCallback. This * \param write_callback See FLAC__StreamDecoderWriteCallback. This
* pointer must not be \c NULL. * pointer must not be \c NULL.
* \param metadata_callback See FLAC__StreamDecoderMetadataCallback. This * \param metadata_callback See FLAC__StreamDecoderMetadataCallback. This
@@ -1251,7 +1234,7 @@ FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_FILE(
* Unless \a file is \c stdin, it will be closed * Unless \a file is \c stdin, it will be closed
* when FLAC__stream_decoder_finish() is called. * when FLAC__stream_decoder_finish() is called.
* Note however that seeking will not work when * Note however that seeking will not work when
* decoding from \c stdin since it is not seekable. * decoding from \c stdout since it is not seekable.
* \param write_callback See FLAC__StreamDecoderWriteCallback. This * \param write_callback See FLAC__StreamDecoderWriteCallback. This
* pointer must not be \c NULL. * pointer must not be \c NULL.
* \param metadata_callback See FLAC__StreamDecoderMetadataCallback. This * \param metadata_callback See FLAC__StreamDecoderMetadataCallback. This
@@ -1280,15 +1263,11 @@ FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_ogg_FILE(
/** Initialize the decoder instance to decode native FLAC files. /** Initialize the decoder instance to decode native FLAC files.
* *
* This flavor of initialization sets up the decoder to decode from a plain * This flavor of initialization sets up the decoder to decode from a plain
* native FLAC file. If POSIX fopen() semantics are not sufficient, you must * native FLAC file. If POSIX fopen() semantics are not sufficient, (for
* use FLAC__stream_decoder_init_FILE(), or FLAC__stream_decoder_init_stream() * example, with Unicode filenames on Windows), you must use
* FLAC__stream_decoder_init_FILE(), or FLAC__stream_decoder_init_stream()
* and provide callbacks for the I/O. * and provide callbacks for the I/O.
* *
* On Windows, filename must be a UTF-8 encoded filename, which libFLAC
* internally translates to an appropriate representation to use with
* _wfopen. On all other systems, filename is passed to fopen without
* any translation.
*
* This function should be called after FLAC__stream_decoder_new() and * This function should be called after FLAC__stream_decoder_new() and
* FLAC__stream_decoder_set_*() but before any of the * FLAC__stream_decoder_set_*() but before any of the
* FLAC__stream_decoder_process_*() functions. Will set and return the * FLAC__stream_decoder_process_*() functions. Will set and return the
@@ -1326,15 +1305,11 @@ FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_file(
/** Initialize the decoder instance to decode Ogg FLAC files. /** Initialize the decoder instance to decode Ogg FLAC files.
* *
* This flavor of initialization sets up the decoder to decode from a plain * This flavor of initialization sets up the decoder to decode from a plain
* Ogg FLAC file. If POSIX fopen() semantics are not sufficient, you must use * Ogg FLAC file. If POSIX fopen() semantics are not sufficient, (for
* example, with Unicode filenames on Windows), you must use
* FLAC__stream_decoder_init_ogg_FILE(), or FLAC__stream_decoder_init_ogg_stream() * FLAC__stream_decoder_init_ogg_FILE(), or FLAC__stream_decoder_init_ogg_stream()
* and provide callbacks for the I/O. * and provide callbacks for the I/O.
* *
* On Windows, filename must be a UTF-8 encoded filename, which libFLAC
* internally translates to an appropriate representation to use with
* _wfopen. On all other systems, filename is passed to fopen without
* any translation.
*
* This function should be called after FLAC__stream_decoder_new() and * This function should be called after FLAC__stream_decoder_new() and
* FLAC__stream_decoder_set_*() but before any of the * FLAC__stream_decoder_set_*() but before any of the
* FLAC__stream_decoder_process_*() functions. Will set and return the * FLAC__stream_decoder_process_*() functions. Will set and return the
@@ -1428,7 +1403,8 @@ FLAC_API FLAC__bool FLAC__stream_decoder_flush(FLAC__StreamDecoder *decoder);
* and is not seekable (i.e. no seek callback was provided or the seek * and is not seekable (i.e. no seek callback was provided or the seek
* callback returns \c FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED), it * callback returns \c FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED), it
* is the duty of the client to start feeding data from the beginning of * is the duty of the client to start feeding data from the beginning of
* the stream on the next FLAC__stream_decoder_process_*() call. * the stream on the next FLAC__stream_decoder_process() or
* FLAC__stream_decoder_process_interleaved() call.
* *
* \param decoder A decoder instance. * \param decoder A decoder instance.
* \assert * \assert

View File

@@ -1,6 +1,6 @@
/* libFLAC - Free Lossless Audio Codec library /* libFLAC - Free Lossless Audio Codec library
* Copyright (C) 2000-2009 Josh Coalson * Copyright (C) 2000-2009 Josh Coalson
* Copyright (C) 2011-2022 Xiph.Org Foundation * Copyright (C) 2011-2014 Xiph.Org Foundation
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@@ -129,8 +129,8 @@ extern "C" {
* Unlike the decoders, the stream encoder has many options that can * Unlike the decoders, the stream encoder has many options that can
* affect the speed and compression ratio. When setting these parameters * affect the speed and compression ratio. When setting these parameters
* you should have some basic knowledge of the format (see the * you should have some basic knowledge of the format (see the
* <A HREF="https://xiph.org/flac/documentation_format_overview.html">user-level documentation</A> * <A HREF="../documentation_format_overview.html">user-level documentation</A>
* or the <A HREF="https://xiph.org/flac/format.html">formal description</A>). The * or the <A HREF="../format.html">formal description</A>). The
* FLAC__stream_encoder_set_*() functions themselves do not validate the * FLAC__stream_encoder_set_*() functions themselves do not validate the
* values as many are interdependent. The FLAC__stream_encoder_init_*() * values as many are interdependent. The FLAC__stream_encoder_init_*()
* functions will do this, so make sure to pay attention to the state * functions will do this, so make sure to pay attention to the state
@@ -311,7 +311,8 @@ typedef enum {
FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BITS_PER_SAMPLE, FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BITS_PER_SAMPLE,
/**< The encoder has an invalid setting for bits-per-sample. /**< The encoder has an invalid setting for bits-per-sample.
* FLAC supports 4-32 bps. * FLAC supports 4-32 bps but the reference encoder currently supports
* only up to 24 bps.
*/ */
FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_SAMPLE_RATE, FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_SAMPLE_RATE,
@@ -330,7 +331,7 @@ typedef enum {
/**< The specified block size is less than the maximum LPC order. */ /**< The specified block size is less than the maximum LPC order. */
FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE, FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE,
/**< The encoder is bound to the <A HREF="https://xiph.org/flac/format.html#subset">Subset</A> but other settings violate it. */ /**< The encoder is bound to the <A HREF="../format.html#subset">Subset</A> but other settings violate it. */
FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA, FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA,
/**< The metadata input to the encoder is invalid, in one of the following ways: /**< The metadata input to the encoder is invalid, in one of the following ways:
@@ -553,7 +554,7 @@ typedef FLAC__StreamEncoderReadStatus (*FLAC__StreamEncoderReadCallback)(const F
* \retval FLAC__StreamEncoderWriteStatus * \retval FLAC__StreamEncoderWriteStatus
* The callee's return status. * The callee's return status.
*/ */
typedef FLAC__StreamEncoderWriteStatus (*FLAC__StreamEncoderWriteCallback)(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, uint32_t samples, uint32_t current_frame, void *client_data); typedef FLAC__StreamEncoderWriteStatus (*FLAC__StreamEncoderWriteCallback)(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame, void *client_data);
/** Signature for the seek callback. /** Signature for the seek callback.
* *
@@ -674,7 +675,7 @@ typedef void (*FLAC__StreamEncoderMetadataCallback)(const FLAC__StreamEncoder *e
* \param client_data The callee's client data set through * \param client_data The callee's client data set through
* FLAC__stream_encoder_init_*(). * FLAC__stream_encoder_init_*().
*/ */
typedef void (*FLAC__StreamEncoderProgressCallback)(const FLAC__StreamEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, uint32_t frames_written, uint32_t total_frames_estimate, void *client_data); typedef void (*FLAC__StreamEncoderProgressCallback)(const FLAC__StreamEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data);
/*********************************************************************** /***********************************************************************
@@ -742,7 +743,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_ogg_serial_number(FLAC__StreamEncod
*/ */
FLAC_API FLAC__bool FLAC__stream_encoder_set_verify(FLAC__StreamEncoder *encoder, FLAC__bool value); FLAC_API FLAC__bool FLAC__stream_encoder_set_verify(FLAC__StreamEncoder *encoder, FLAC__bool value);
/** Set the <A HREF="https://xiph.org/flac/format.html#subset">Subset</A> flag. If \c true, /** Set the <A HREF="../format.html#subset">Subset</A> flag. If \c true,
* the encoder will comply with the Subset and will check the * the encoder will comply with the Subset and will check the
* settings during FLAC__stream_encoder_init_*() to see if all settings * settings during FLAC__stream_encoder_init_*() to see if all settings
* comply. If \c false, the settings may take advantage of the full * comply. If \c false, the settings may take advantage of the full
@@ -770,7 +771,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_streamable_subset(FLAC__StreamEncod
* \retval FLAC__bool * \retval FLAC__bool
* \c false if the encoder is already initialized, else \c true. * \c false if the encoder is already initialized, else \c true.
*/ */
FLAC_API FLAC__bool FLAC__stream_encoder_set_channels(FLAC__StreamEncoder *encoder, uint32_t value); FLAC_API FLAC__bool FLAC__stream_encoder_set_channels(FLAC__StreamEncoder *encoder, unsigned value);
/** Set the sample resolution of the input to be encoded. /** Set the sample resolution of the input to be encoded.
* *
@@ -786,7 +787,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_channels(FLAC__StreamEncoder *encod
* \retval FLAC__bool * \retval FLAC__bool
* \c false if the encoder is already initialized, else \c true. * \c false if the encoder is already initialized, else \c true.
*/ */
FLAC_API FLAC__bool FLAC__stream_encoder_set_bits_per_sample(FLAC__StreamEncoder *encoder, uint32_t value); FLAC_API FLAC__bool FLAC__stream_encoder_set_bits_per_sample(FLAC__StreamEncoder *encoder, unsigned value);
/** Set the sample rate (in Hz) of the input to be encoded. /** Set the sample rate (in Hz) of the input to be encoded.
* *
@@ -798,7 +799,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_bits_per_sample(FLAC__StreamEncoder
* \retval FLAC__bool * \retval FLAC__bool
* \c false if the encoder is already initialized, else \c true. * \c false if the encoder is already initialized, else \c true.
*/ */
FLAC_API FLAC__bool FLAC__stream_encoder_set_sample_rate(FLAC__StreamEncoder *encoder, uint32_t value); FLAC_API FLAC__bool FLAC__stream_encoder_set_sample_rate(FLAC__StreamEncoder *encoder, unsigned value);
/** Set the compression level /** Set the compression level
* *
@@ -842,15 +843,15 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_sample_rate(FLAC__StreamEncoder *en
* <td>max residual partition order</td> * <td>max residual partition order</td>
* <td>rice parameter search dist</td> * <td>rice parameter search dist</td>
* </tr> * </tr>
* <tr> <td><b>0</b></td> <td>false</td> <td>false</td> <td>tukey(0.5)</td> <td>0</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>3</td> <td>0</td> </tr> * <tr> <td><b>0</b></td> <td>false</td> <td>false</td> <td>tukey(0.5)<td> <td>0</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>3</td> <td>0</td> </tr>
* <tr> <td><b>1</b></td> <td>true</td> <td>true</td> <td>tukey(0.5)</td> <td>0</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>3</td> <td>0</td> </tr> * <tr> <td><b>1</b></td> <td>true</td> <td>true</td> <td>tukey(0.5)<td> <td>0</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>3</td> <td>0</td> </tr>
* <tr> <td><b>2</b></td> <td>true</td> <td>false</td> <td>tukey(0.5)</td> <td>0</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>3</td> <td>0</td> </tr> * <tr> <td><b>2</b></td> <td>true</td> <td>false</td> <td>tukey(0.5)<td> <td>0</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>3</td> <td>0</td> </tr>
* <tr> <td><b>3</b></td> <td>false</td> <td>false</td> <td>tukey(0.5)</td> <td>6</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>4</td> <td>0</td> </tr> * <tr> <td><b>3</b></td> <td>false</td> <td>false</td> <td>tukey(0.5)<td> <td>6</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>4</td> <td>0</td> </tr>
* <tr> <td><b>4</b></td> <td>true</td> <td>true</td> <td>tukey(0.5)</td> <td>8</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>4</td> <td>0</td> </tr> * <tr> <td><b>4</b></td> <td>true</td> <td>true</td> <td>tukey(0.5)<td> <td>8</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>4</td> <td>0</td> </tr>
* <tr> <td><b>5</b></td> <td>true</td> <td>false</td> <td>tukey(0.5)</td> <td>8</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>5</td> <td>0</td> </tr> * <tr> <td><b>5</b></td> <td>true</td> <td>false</td> <td>tukey(0.5)<td> <td>8</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>5</td> <td>0</td> </tr>
* <tr> <td><b>6</b></td> <td>true</td> <td>false</td> <td>subdivide_tukey(2)</td> <td>8</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>6</td> <td>0</td> </tr> * <tr> <td><b>6</b></td> <td>true</td> <td>false</td> <td>tukey(0.5);partial_tukey(2)<td> <td>8</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>6</td> <td>0</td> </tr>
* <tr> <td><b>7</b></td> <td>true</td> <td>false</td> <td>subdivide_tukey(2)</td> <td>12</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>6</td> <td>0</td> </tr> * <tr> <td><b>7</b></td> <td>true</td> <td>false</td> <td>tukey(0.5);partial_tukey(2)<td> <td>12</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>6</td> <td>0</td> </tr>
* <tr> <td><b>8</b></td> <td>true</td> <td>false</td> <td>subdivide_tukey(2)</td> <td>12</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>6</td> <td>0</td> </tr> * <tr> <td><b>8</b></td> <td>true</td> <td>false</td> <td>tukey(0.5);partial_tukey(2);punchout_tukey(3)</td> <td>12</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>6</td> <td>0</td> </tr>
* </table> * </table>
* *
* \default \c 5 * \default \c 5
@@ -861,7 +862,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_sample_rate(FLAC__StreamEncoder *en
* \retval FLAC__bool * \retval FLAC__bool
* \c false if the encoder is already initialized, else \c true. * \c false if the encoder is already initialized, else \c true.
*/ */
FLAC_API FLAC__bool FLAC__stream_encoder_set_compression_level(FLAC__StreamEncoder *encoder, uint32_t value); FLAC_API FLAC__bool FLAC__stream_encoder_set_compression_level(FLAC__StreamEncoder *encoder, unsigned value);
/** Set the blocksize to use while encoding. /** Set the blocksize to use while encoding.
* *
@@ -876,13 +877,13 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_compression_level(FLAC__StreamEncod
* \retval FLAC__bool * \retval FLAC__bool
* \c false if the encoder is already initialized, else \c true. * \c false if the encoder is already initialized, else \c true.
*/ */
FLAC_API FLAC__bool FLAC__stream_encoder_set_blocksize(FLAC__StreamEncoder *encoder, uint32_t value); FLAC_API FLAC__bool FLAC__stream_encoder_set_blocksize(FLAC__StreamEncoder *encoder, unsigned value);
/** Set to \c true to enable mid-side encoding on stereo input. The /** Set to \c true to enable mid-side encoding on stereo input. The
* number of channels must be 2 for this to have any effect. Set to * number of channels must be 2 for this to have any effect. Set to
* \c false to use only independent channel coding. * \c false to use only independent channel coding.
* *
* \default \c true * \default \c false
* \param encoder An encoder instance to set. * \param encoder An encoder instance to set.
* \param value Flag value (see above). * \param value Flag value (see above).
* \assert * \assert
@@ -920,7 +921,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_loose_mid_side_stereo(FLAC__StreamE
* \c blackman, \c blackman_harris_4term_92db, \c connes, \c flattop, * \c blackman, \c blackman_harris_4term_92db, \c connes, \c flattop,
* \c gauss(STDDEV), \c hamming, \c hann, \c kaiser_bessel, \c nuttall, * \c gauss(STDDEV), \c hamming, \c hann, \c kaiser_bessel, \c nuttall,
* \c rectangle, \c triangle, \c tukey(P), \c partial_tukey(n[/ov[/P]]), * \c rectangle, \c triangle, \c tukey(P), \c partial_tukey(n[/ov[/P]]),
* \c punchout_tukey(n[/ov[/P]]), \c subdivide_tukey(n[/P]), \c welch. * \c punchout_tukey(n[/ov[/P]]), \c welch.
* *
* For \c gauss(STDDEV), STDDEV specifies the standard deviation * For \c gauss(STDDEV), STDDEV specifies the standard deviation
* (0<STDDEV<=0.5). * (0<STDDEV<=0.5).
@@ -947,20 +948,6 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_loose_mid_side_stereo(FLAC__StreamE
* and partial_tukey(3/0.3/0.5) are all valid. ov should be smaller than 1 * and partial_tukey(3/0.3/0.5) are all valid. ov should be smaller than 1
* and can be negative. * and can be negative.
* *
* subdivide_tukey(n) is a more efficient reimplementation of
* partial_tukey and punchout_tukey taken together, recycling as much data
* as possible. It combines all possible non-redundant partial_tukey(n)
* and punchout_tukey(n) up to the n specified. Specifying
* subdivide_tukey(3) is equivalent to specifying tukey, partial_tukey(2),
* partial_tukey(3) and punchout_tukey(3), specifying subdivide_tukey(5)
* equivalently adds partial_tukey(4), punchout_tukey(4), partial_tukey(5)
* and punchout_tukey(5). To be able to reuse data as much as possible,
* the tukey taper is taken equal for all windows, and the P specified is
* applied for the smallest used window. In other words,
* subdivide_tukey(2/0.5) results in a taper equal to that of tukey(0.25)
* and subdivide_tukey(5) in a taper equal to that of tukey(0.1). The
* default P for subdivide_tukey when none is specified is 0.5.
*
* Example specifications are \c "blackman" or * Example specifications are \c "blackman" or
* \c "hann;triangle;tukey(0.5);tukey(0.25);tukey(0.125)" * \c "hann;triangle;tukey(0.5);tukey(0.25);tukey(0.125)"
* *
@@ -976,8 +963,6 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_loose_mid_side_stereo(FLAC__StreamE
* floating point array in which to store the window. Also note that the * floating point array in which to store the window. Also note that the
* values of P, STDDEV and ov are locale-specific, so if the comma * values of P, STDDEV and ov are locale-specific, so if the comma
* separator specified by the locale is a comma, a comma should be used. * separator specified by the locale is a comma, a comma should be used.
* A locale-independent way is to specify using scientific notation,
* e.g. 5e-1 instad of 0.5 or 0,5.
* *
* \default \c "tukey(0.5)" * \default \c "tukey(0.5)"
* \param encoder An encoder instance to set. * \param encoder An encoder instance to set.
@@ -992,7 +977,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_apodization(FLAC__StreamEncoder *en
/** Set the maximum LPC order, or \c 0 to use only the fixed predictors. /** Set the maximum LPC order, or \c 0 to use only the fixed predictors.
* *
* \default \c 8 * \default \c 0
* \param encoder An encoder instance to set. * \param encoder An encoder instance to set.
* \param value See above. * \param value See above.
* \assert * \assert
@@ -1000,12 +985,16 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_apodization(FLAC__StreamEncoder *en
* \retval FLAC__bool * \retval FLAC__bool
* \c false if the encoder is already initialized, else \c true. * \c false if the encoder is already initialized, else \c true.
*/ */
FLAC_API FLAC__bool FLAC__stream_encoder_set_max_lpc_order(FLAC__StreamEncoder *encoder, uint32_t value); FLAC_API FLAC__bool FLAC__stream_encoder_set_max_lpc_order(FLAC__StreamEncoder *encoder, unsigned value);
/** Set the precision, in bits, of the quantized linear predictor /** Set the precision, in bits, of the quantized linear predictor
* coefficients, or \c 0 to let the encoder select it based on the * coefficients, or \c 0 to let the encoder select it based on the
* blocksize. * blocksize.
* *
* \note
* In the current implementation, qlp_coeff_precision + bits_per_sample must
* be less than 32.
*
* \default \c 0 * \default \c 0
* \param encoder An encoder instance to set. * \param encoder An encoder instance to set.
* \param value See above. * \param value See above.
@@ -1014,7 +1003,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_max_lpc_order(FLAC__StreamEncoder *
* \retval FLAC__bool * \retval FLAC__bool
* \c false if the encoder is already initialized, else \c true. * \c false if the encoder is already initialized, else \c true.
*/ */
FLAC_API FLAC__bool FLAC__stream_encoder_set_qlp_coeff_precision(FLAC__StreamEncoder *encoder, uint32_t value); FLAC_API FLAC__bool FLAC__stream_encoder_set_qlp_coeff_precision(FLAC__StreamEncoder *encoder, unsigned value);
/** Set to \c false to use only the specified quantized linear predictor /** Set to \c false to use only the specified quantized linear predictor
* coefficient precision, or \c true to search neighboring precision * coefficient precision, or \c true to search neighboring precision
@@ -1077,7 +1066,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_do_exhaustive_model_search(FLAC__St
* \retval FLAC__bool * \retval FLAC__bool
* \c false if the encoder is already initialized, else \c true. * \c false if the encoder is already initialized, else \c true.
*/ */
FLAC_API FLAC__bool FLAC__stream_encoder_set_min_residual_partition_order(FLAC__StreamEncoder *encoder, uint32_t value); FLAC_API FLAC__bool FLAC__stream_encoder_set_min_residual_partition_order(FLAC__StreamEncoder *encoder, unsigned value);
/** Set the maximum partition order to search when coding the residual. /** Set the maximum partition order to search when coding the residual.
* This is used in tandem with * This is used in tandem with
@@ -1092,7 +1081,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_min_residual_partition_order(FLAC__
* all orders, using the mean of each context for its Rice parameter, * all orders, using the mean of each context for its Rice parameter,
* and use the best. * and use the best.
* *
* \default \c 5 * \default \c 0
* \param encoder An encoder instance to set. * \param encoder An encoder instance to set.
* \param value See above. * \param value See above.
* \assert * \assert
@@ -1100,7 +1089,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_min_residual_partition_order(FLAC__
* \retval FLAC__bool * \retval FLAC__bool
* \c false if the encoder is already initialized, else \c true. * \c false if the encoder is already initialized, else \c true.
*/ */
FLAC_API FLAC__bool FLAC__stream_encoder_set_max_residual_partition_order(FLAC__StreamEncoder *encoder, uint32_t value); FLAC_API FLAC__bool FLAC__stream_encoder_set_max_residual_partition_order(FLAC__StreamEncoder *encoder, unsigned value);
/** Deprecated. Setting this value has no effect. /** Deprecated. Setting this value has no effect.
* *
@@ -1112,7 +1101,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_max_residual_partition_order(FLAC__
* \retval FLAC__bool * \retval FLAC__bool
* \c false if the encoder is already initialized, else \c true. * \c false if the encoder is already initialized, else \c true.
*/ */
FLAC_API FLAC__bool FLAC__stream_encoder_set_rice_parameter_search_dist(FLAC__StreamEncoder *encoder, uint32_t value); FLAC_API FLAC__bool FLAC__stream_encoder_set_rice_parameter_search_dist(FLAC__StreamEncoder *encoder, unsigned value);
/** Set an estimate of the total samples that will be encoded. /** Set an estimate of the total samples that will be encoded.
* This is merely an estimate and may be set to \c 0 if unknown. * This is merely an estimate and may be set to \c 0 if unknown.
@@ -1211,25 +1200,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_total_samples_estimate(FLAC__Stream
* \c false if the encoder is already initialized, or if * \c false if the encoder is already initialized, or if
* \a num_blocks > 65535 if encoding to Ogg FLAC, else \c true. * \a num_blocks > 65535 if encoding to Ogg FLAC, else \c true.
*/ */
FLAC_API FLAC__bool FLAC__stream_encoder_set_metadata(FLAC__StreamEncoder *encoder, FLAC__StreamMetadata **metadata, uint32_t num_blocks); FLAC_API FLAC__bool FLAC__stream_encoder_set_metadata(FLAC__StreamEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks);
/** Set to \c true to make the encoder not output frames which contain
* only constant subframes. This is beneficial for streaming
* applications: very small frames can cause problems with buffering
* as bitrates can drop as low 1kbit/s for CDDA audio encoded within
* subset. The minimum bitrate for a FLAC file encoded with this
* function used is raised to 1bit/sample (i.e. 48kbit/s for 48kHz
* material).
*
* \default \c false
* \param encoder An encoder instance to set.
* \param value Flag value (see above).
* \assert
* \code encoder != NULL \endcode
* \retval FLAC__bool
* \c false if the encoder is already initialized, else \c true.
*/
FLAC_API FLAC__bool FLAC__stream_encoder_set_limit_min_bitrate(FLAC__StreamEncoder *encoder, FLAC__bool value);
/** Get the current encoder state. /** Get the current encoder state.
* *
@@ -1283,7 +1254,7 @@ FLAC_API const char *FLAC__stream_encoder_get_resolved_state_string(const FLAC__
* \assert * \assert
* \code encoder != NULL \endcode * \code encoder != NULL \endcode
*/ */
FLAC_API void FLAC__stream_encoder_get_verify_decoder_error_stats(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_sample, uint32_t *frame_number, uint32_t *channel, uint32_t *sample, FLAC__int32 *expected, FLAC__int32 *got); FLAC_API void FLAC__stream_encoder_get_verify_decoder_error_stats(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got);
/** Get the "verify" flag. /** Get the "verify" flag.
* *
@@ -1295,7 +1266,7 @@ FLAC_API void FLAC__stream_encoder_get_verify_decoder_error_stats(const FLAC__St
*/ */
FLAC_API FLAC__bool FLAC__stream_encoder_get_verify(const FLAC__StreamEncoder *encoder); FLAC_API FLAC__bool FLAC__stream_encoder_get_verify(const FLAC__StreamEncoder *encoder);
/** Get the <A HREF="https://xiph.org/flac/format.html#subset">Subset</A> flag. /** Get the <A HREF="../format.html#subset>Subset</A> flag.
* *
* \param encoder An encoder instance to query. * \param encoder An encoder instance to query.
* \assert * \assert
@@ -1310,40 +1281,40 @@ FLAC_API FLAC__bool FLAC__stream_encoder_get_streamable_subset(const FLAC__Strea
* \param encoder An encoder instance to query. * \param encoder An encoder instance to query.
* \assert * \assert
* \code encoder != NULL \endcode * \code encoder != NULL \endcode
* \retval uint32_t * \retval unsigned
* See FLAC__stream_encoder_set_channels(). * See FLAC__stream_encoder_set_channels().
*/ */
FLAC_API uint32_t FLAC__stream_encoder_get_channels(const FLAC__StreamEncoder *encoder); FLAC_API unsigned FLAC__stream_encoder_get_channels(const FLAC__StreamEncoder *encoder);
/** Get the input sample resolution setting. /** Get the input sample resolution setting.
* *
* \param encoder An encoder instance to query. * \param encoder An encoder instance to query.
* \assert * \assert
* \code encoder != NULL \endcode * \code encoder != NULL \endcode
* \retval uint32_t * \retval unsigned
* See FLAC__stream_encoder_set_bits_per_sample(). * See FLAC__stream_encoder_set_bits_per_sample().
*/ */
FLAC_API uint32_t FLAC__stream_encoder_get_bits_per_sample(const FLAC__StreamEncoder *encoder); FLAC_API unsigned FLAC__stream_encoder_get_bits_per_sample(const FLAC__StreamEncoder *encoder);
/** Get the input sample rate setting. /** Get the input sample rate setting.
* *
* \param encoder An encoder instance to query. * \param encoder An encoder instance to query.
* \assert * \assert
* \code encoder != NULL \endcode * \code encoder != NULL \endcode
* \retval uint32_t * \retval unsigned
* See FLAC__stream_encoder_set_sample_rate(). * See FLAC__stream_encoder_set_sample_rate().
*/ */
FLAC_API uint32_t FLAC__stream_encoder_get_sample_rate(const FLAC__StreamEncoder *encoder); FLAC_API unsigned FLAC__stream_encoder_get_sample_rate(const FLAC__StreamEncoder *encoder);
/** Get the blocksize setting. /** Get the blocksize setting.
* *
* \param encoder An encoder instance to query. * \param encoder An encoder instance to query.
* \assert * \assert
* \code encoder != NULL \endcode * \code encoder != NULL \endcode
* \retval uint32_t * \retval unsigned
* See FLAC__stream_encoder_set_blocksize(). * See FLAC__stream_encoder_set_blocksize().
*/ */
FLAC_API uint32_t FLAC__stream_encoder_get_blocksize(const FLAC__StreamEncoder *encoder); FLAC_API unsigned FLAC__stream_encoder_get_blocksize(const FLAC__StreamEncoder *encoder);
/** Get the "mid/side stereo coding" flag. /** Get the "mid/side stereo coding" flag.
* *
@@ -1370,20 +1341,20 @@ FLAC_API FLAC__bool FLAC__stream_encoder_get_loose_mid_side_stereo(const FLAC__S
* \param encoder An encoder instance to query. * \param encoder An encoder instance to query.
* \assert * \assert
* \code encoder != NULL \endcode * \code encoder != NULL \endcode
* \retval uint32_t * \retval unsigned
* See FLAC__stream_encoder_set_max_lpc_order(). * See FLAC__stream_encoder_set_max_lpc_order().
*/ */
FLAC_API uint32_t FLAC__stream_encoder_get_max_lpc_order(const FLAC__StreamEncoder *encoder); FLAC_API unsigned FLAC__stream_encoder_get_max_lpc_order(const FLAC__StreamEncoder *encoder);
/** Get the quantized linear predictor coefficient precision setting. /** Get the quantized linear predictor coefficient precision setting.
* *
* \param encoder An encoder instance to query. * \param encoder An encoder instance to query.
* \assert * \assert
* \code encoder != NULL \endcode * \code encoder != NULL \endcode
* \retval uint32_t * \retval unsigned
* See FLAC__stream_encoder_set_qlp_coeff_precision(). * See FLAC__stream_encoder_set_qlp_coeff_precision().
*/ */
FLAC_API uint32_t FLAC__stream_encoder_get_qlp_coeff_precision(const FLAC__StreamEncoder *encoder); FLAC_API unsigned FLAC__stream_encoder_get_qlp_coeff_precision(const FLAC__StreamEncoder *encoder);
/** Get the qlp coefficient precision search flag. /** Get the qlp coefficient precision search flag.
* *
@@ -1420,30 +1391,30 @@ FLAC_API FLAC__bool FLAC__stream_encoder_get_do_exhaustive_model_search(const FL
* \param encoder An encoder instance to query. * \param encoder An encoder instance to query.
* \assert * \assert
* \code encoder != NULL \endcode * \code encoder != NULL \endcode
* \retval uint32_t * \retval unsigned
* See FLAC__stream_encoder_set_min_residual_partition_order(). * See FLAC__stream_encoder_set_min_residual_partition_order().
*/ */
FLAC_API uint32_t FLAC__stream_encoder_get_min_residual_partition_order(const FLAC__StreamEncoder *encoder); FLAC_API unsigned FLAC__stream_encoder_get_min_residual_partition_order(const FLAC__StreamEncoder *encoder);
/** Get maximum residual partition order setting. /** Get maximum residual partition order setting.
* *
* \param encoder An encoder instance to query. * \param encoder An encoder instance to query.
* \assert * \assert
* \code encoder != NULL \endcode * \code encoder != NULL \endcode
* \retval uint32_t * \retval unsigned
* See FLAC__stream_encoder_set_max_residual_partition_order(). * See FLAC__stream_encoder_set_max_residual_partition_order().
*/ */
FLAC_API uint32_t FLAC__stream_encoder_get_max_residual_partition_order(const FLAC__StreamEncoder *encoder); FLAC_API unsigned FLAC__stream_encoder_get_max_residual_partition_order(const FLAC__StreamEncoder *encoder);
/** Get the Rice parameter search distance setting. /** Get the Rice parameter search distance setting.
* *
* \param encoder An encoder instance to query. * \param encoder An encoder instance to query.
* \assert * \assert
* \code encoder != NULL \endcode * \code encoder != NULL \endcode
* \retval uint32_t * \retval unsigned
* See FLAC__stream_encoder_set_rice_parameter_search_dist(). * See FLAC__stream_encoder_set_rice_parameter_search_dist().
*/ */
FLAC_API uint32_t FLAC__stream_encoder_get_rice_parameter_search_dist(const FLAC__StreamEncoder *encoder); FLAC_API unsigned FLAC__stream_encoder_get_rice_parameter_search_dist(const FLAC__StreamEncoder *encoder);
/** Get the previously set estimate of the total samples to be encoded. /** Get the previously set estimate of the total samples to be encoded.
* The encoder merely mimics back the value given to * The encoder merely mimics back the value given to
@@ -1458,16 +1429,6 @@ FLAC_API uint32_t FLAC__stream_encoder_get_rice_parameter_search_dist(const FLAC
*/ */
FLAC_API FLAC__uint64 FLAC__stream_encoder_get_total_samples_estimate(const FLAC__StreamEncoder *encoder); FLAC_API FLAC__uint64 FLAC__stream_encoder_get_total_samples_estimate(const FLAC__StreamEncoder *encoder);
/** Get the "limit_min_bitrate" flag.
*
* \param encoder An encoder instance to query.
* \assert
* \code encoder != NULL \endcode
* \retval FLAC__bool
* See FLAC__stream_encoder_set_limit_min_bitrate().
*/
FLAC_API FLAC__bool FLAC__stream_encoder_get_limit_min_bitrate(const FLAC__StreamEncoder *encoder);
/** Initialize the encoder instance to encode native FLAC streams. /** Initialize the encoder instance to encode native FLAC streams.
* *
* This flavor of initialization sets up the encoder to encode to a * This flavor of initialization sets up the encoder to encode to a
@@ -1672,15 +1633,11 @@ FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_ogg_FILE(FLAC__
/** Initialize the encoder instance to encode native FLAC files. /** Initialize the encoder instance to encode native FLAC files.
* *
* This flavor of initialization sets up the encoder to encode to a plain * This flavor of initialization sets up the encoder to encode to a plain
* FLAC file. If POSIX fopen() semantics are not sufficient you must use * FLAC file. If POSIX fopen() semantics are not sufficient (for example,
* with Unicode filenames on Windows), you must use
* FLAC__stream_encoder_init_FILE(), or FLAC__stream_encoder_init_stream() * FLAC__stream_encoder_init_FILE(), or FLAC__stream_encoder_init_stream()
* and provide callbacks for the I/O. * and provide callbacks for the I/O.
* *
* On Windows, filename must be a UTF-8 encoded filename, which libFLAC
* internally translates to an appropriate representation to use with
* _wfopen. On all other systems, filename is passed to fopen without
* any translation.
*
* This function should be called after FLAC__stream_encoder_new() and * This function should be called after FLAC__stream_encoder_new() and
* FLAC__stream_encoder_set_*() but before FLAC__stream_encoder_process() * FLAC__stream_encoder_set_*() but before FLAC__stream_encoder_process()
* or FLAC__stream_encoder_process_interleaved(). * or FLAC__stream_encoder_process_interleaved().
@@ -1708,15 +1665,11 @@ FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_file(FLAC__Stre
/** Initialize the encoder instance to encode Ogg FLAC files. /** Initialize the encoder instance to encode Ogg FLAC files.
* *
* This flavor of initialization sets up the encoder to encode to a plain * This flavor of initialization sets up the encoder to encode to a plain
* Ogg FLAC file. If POSIX fopen() semantics are not sufficient, you must use * Ogg FLAC file. If POSIX fopen() semantics are not sufficient (for example,
* with Unicode filenames on Windows), you must use
* FLAC__stream_encoder_init_ogg_FILE(), or FLAC__stream_encoder_init_ogg_stream() * FLAC__stream_encoder_init_ogg_FILE(), or FLAC__stream_encoder_init_ogg_stream()
* and provide callbacks for the I/O. * and provide callbacks for the I/O.
* *
* On Windows, filename must be a UTF-8 encoded filename, which libFLAC
* internally translates to an appropriate representation to use with
* _wfopen. On all other systems, filename is passed to fopen without
* any translation.
*
* This function should be called after FLAC__stream_encoder_new() and * This function should be called after FLAC__stream_encoder_new() and
* FLAC__stream_encoder_set_*() but before FLAC__stream_encoder_process() * FLAC__stream_encoder_set_*() but before FLAC__stream_encoder_process()
* or FLAC__stream_encoder_process_interleaved(). * or FLAC__stream_encoder_process_interleaved().
@@ -1781,7 +1734,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_finish(FLAC__StreamEncoder *encoder);
* *
* For applications where channel order is important, channels must * For applications where channel order is important, channels must
* follow the order as described in the * follow the order as described in the
* <A HREF="https://xiph.org/flac/format.html#frame_header">frame header</A>. * <A HREF="../format.html#frame_header">frame header</A>.
* *
* \param encoder An initialized encoder instance in the OK state. * \param encoder An initialized encoder instance in the OK state.
* \param buffer An array of pointers to each channel's signal. * \param buffer An array of pointers to each channel's signal.
@@ -1794,7 +1747,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_finish(FLAC__StreamEncoder *encoder);
* encoder state with FLAC__stream_encoder_get_state() to see what * encoder state with FLAC__stream_encoder_get_state() to see what
* went wrong. * went wrong.
*/ */
FLAC_API FLAC__bool FLAC__stream_encoder_process(FLAC__StreamEncoder *encoder, const FLAC__int32 * const buffer[], uint32_t samples); FLAC_API FLAC__bool FLAC__stream_encoder_process(FLAC__StreamEncoder *encoder, const FLAC__int32 * const buffer[], unsigned samples);
/** Submit data for encoding. /** Submit data for encoding.
* This version allows you to supply the input data where the channels * This version allows you to supply the input data where the channels
@@ -1810,7 +1763,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_process(FLAC__StreamEncoder *encoder, c
* *
* For applications where channel order is important, channels must * For applications where channel order is important, channels must
* follow the order as described in the * follow the order as described in the
* <A HREF="https://xiph.org/flac/format.html#frame_header">frame header</A>. * <A HREF="../format.html#frame_header">frame header</A>.
* *
* \param encoder An initialized encoder instance in the OK state. * \param encoder An initialized encoder instance in the OK state.
* \param buffer An array of channel-interleaved data (see above). * \param buffer An array of channel-interleaved data (see above).
@@ -1826,7 +1779,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_process(FLAC__StreamEncoder *encoder, c
* encoder state with FLAC__stream_encoder_get_state() to see what * encoder state with FLAC__stream_encoder_get_state() to see what
* went wrong. * went wrong.
*/ */
FLAC_API FLAC__bool FLAC__stream_encoder_process_interleaved(FLAC__StreamEncoder *encoder, const FLAC__int32 buffer[], uint32_t samples); FLAC_API FLAC__bool FLAC__stream_encoder_process_interleaved(FLAC__StreamEncoder *encoder, const FLAC__int32 buffer[], unsigned samples);
/* \} */ /* \} */

View File

@@ -1,7 +1,7 @@
#ifndef __CONFIG_TYPES_H__ #ifndef __CONFIG_TYPES_H__
#define __CONFIG_TYPES_H__ #define __CONFIG_TYPES_H__
/* these are filled in by configure or cmake*/ /* these are filled in by configure */
#define INCLUDE_INTTYPES_H 1 #define INCLUDE_INTTYPES_H 1
#define INCLUDE_STDINT_H 1 #define INCLUDE_STDINT_H 1
#define INCLUDE_SYS_TYPES_H 1 #define INCLUDE_SYS_TYPES_H 1
@@ -21,6 +21,5 @@ typedef uint16_t ogg_uint16_t;
typedef int32_t ogg_int32_t; typedef int32_t ogg_int32_t;
typedef uint32_t ogg_uint32_t; typedef uint32_t ogg_uint32_t;
typedef int64_t ogg_int64_t; typedef int64_t ogg_int64_t;
typedef uint64_t ogg_uint64_t;
#endif #endif

View File

@@ -11,6 +11,7 @@
******************************************************************** ********************************************************************
function: toplevel libogg include function: toplevel libogg include
last mod: $Id$
********************************************************************/ ********************************************************************/
#ifndef _OGG_H #ifndef _OGG_H

View File

@@ -10,7 +10,8 @@
* * * *
******************************************************************** ********************************************************************
function: Define a consistent set of types on each platform. function: #ifdef jail to whip a few platforms into the UNIX ideal.
last mod: $Id$
********************************************************************/ ********************************************************************/
#ifndef _OS_TYPES_H #ifndef _OS_TYPES_H
@@ -43,7 +44,6 @@
typedef unsigned long long ogg_uint64_t; typedef unsigned long long ogg_uint64_t;
# elif defined(__MWERKS__) # elif defined(__MWERKS__)
typedef long long ogg_int64_t; typedef long long ogg_int64_t;
typedef unsigned long long ogg_uint64_t;
typedef int ogg_int32_t; typedef int ogg_int32_t;
typedef unsigned int ogg_uint32_t; typedef unsigned int ogg_uint32_t;
typedef short ogg_int16_t; typedef short ogg_int16_t;
@@ -62,7 +62,6 @@
typedef __int64 ogg_int64_t; typedef __int64 ogg_int64_t;
typedef __int32 ogg_int32_t; typedef __int32 ogg_int32_t;
typedef unsigned __int32 ogg_uint32_t; typedef unsigned __int32 ogg_uint32_t;
typedef unsigned __int64 ogg_uint64_t;
typedef __int16 ogg_int16_t; typedef __int16 ogg_int16_t;
typedef unsigned __int16 ogg_uint16_t; typedef unsigned __int16 ogg_uint16_t;
# endif # endif
@@ -70,13 +69,12 @@
#elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */ #elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */
# include <sys/types.h> # include <inttypes.h>
typedef int16_t ogg_int16_t; typedef int16_t ogg_int16_t;
typedef u_int16_t ogg_uint16_t; typedef uint16_t ogg_uint16_t;
typedef int32_t ogg_int32_t; typedef int32_t ogg_int32_t;
typedef u_int32_t ogg_uint32_t; typedef uint32_t ogg_uint32_t;
typedef int64_t ogg_int64_t; typedef int64_t ogg_int64_t;
typedef u_int64_t ogg_uint64_t;
#elif defined(__HAIKU__) #elif defined(__HAIKU__)
@@ -87,7 +85,6 @@
typedef int ogg_int32_t; typedef int ogg_int32_t;
typedef unsigned int ogg_uint32_t; typedef unsigned int ogg_uint32_t;
typedef long long ogg_int64_t; typedef long long ogg_int64_t;
typedef unsigned long long ogg_uint64_t;
#elif defined(__BEOS__) #elif defined(__BEOS__)
@@ -98,7 +95,6 @@
typedef int32_t ogg_int32_t; typedef int32_t ogg_int32_t;
typedef uint32_t ogg_uint32_t; typedef uint32_t ogg_uint32_t;
typedef int64_t ogg_int64_t; typedef int64_t ogg_int64_t;
typedef uint64_t ogg_uint64_t;
#elif defined (__EMX__) #elif defined (__EMX__)
@@ -108,8 +104,6 @@
typedef int ogg_int32_t; typedef int ogg_int32_t;
typedef unsigned int ogg_uint32_t; typedef unsigned int ogg_uint32_t;
typedef long long ogg_int64_t; typedef long long ogg_int64_t;
typedef unsigned long long ogg_uint64_t;
#elif defined (DJGPP) #elif defined (DJGPP)
@@ -118,13 +112,11 @@
typedef int ogg_int32_t; typedef int ogg_int32_t;
typedef unsigned int ogg_uint32_t; typedef unsigned int ogg_uint32_t;
typedef long long ogg_int64_t; typedef long long ogg_int64_t;
typedef unsigned long long ogg_uint64_t;
#elif defined(R5900) #elif defined(R5900)
/* PS2 EE */ /* PS2 EE */
typedef long ogg_int64_t; typedef long ogg_int64_t;
typedef unsigned long ogg_uint64_t;
typedef int ogg_int32_t; typedef int ogg_int32_t;
typedef unsigned ogg_uint32_t; typedef unsigned ogg_uint32_t;
typedef short ogg_int16_t; typedef short ogg_int16_t;
@@ -137,7 +129,6 @@
typedef signed int ogg_int32_t; typedef signed int ogg_int32_t;
typedef unsigned int ogg_uint32_t; typedef unsigned int ogg_uint32_t;
typedef long long int ogg_int64_t; typedef long long int ogg_int64_t;
typedef unsigned long long int ogg_uint64_t;
#elif defined(__TMS320C6X__) #elif defined(__TMS320C6X__)
@@ -147,7 +138,6 @@
typedef signed int ogg_int32_t; typedef signed int ogg_int32_t;
typedef unsigned int ogg_uint32_t; typedef unsigned int ogg_uint32_t;
typedef long long int ogg_int64_t; typedef long long int ogg_int64_t;
typedef unsigned long long int ogg_uint64_t;
#else #else

View File

@@ -198,7 +198,7 @@ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_encoder_get_size(int channels);
* This must be one of 8000, 12000, 16000, * This must be one of 8000, 12000, 16000,
* 24000, or 48000. * 24000, or 48000.
* @param [in] channels <tt>int</tt>: Number of channels (1 or 2) in input signal * @param [in] channels <tt>int</tt>: Number of channels (1 or 2) in input signal
* @param [in] application <tt>int</tt>: Coding mode (one of @ref OPUS_APPLICATION_VOIP, @ref OPUS_APPLICATION_AUDIO, or @ref OPUS_APPLICATION_RESTRICTED_LOWDELAY) * @param [in] application <tt>int</tt>: Coding mode (@ref OPUS_APPLICATION_VOIP/@ref OPUS_APPLICATION_AUDIO/@ref OPUS_APPLICATION_RESTRICTED_LOWDELAY)
* @param [out] error <tt>int*</tt>: @ref opus_errorcodes * @param [out] error <tt>int*</tt>: @ref opus_errorcodes
* @note Regardless of the sampling rate and number channels selected, the Opus encoder * @note Regardless of the sampling rate and number channels selected, the Opus encoder
* can switch to a lower audio bandwidth or number of channels if the bitrate * can switch to a lower audio bandwidth or number of channels if the bitrate
@@ -222,7 +222,7 @@ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusEncoder *opus_encoder_create(
* This must be one of 8000, 12000, 16000, * This must be one of 8000, 12000, 16000,
* 24000, or 48000. * 24000, or 48000.
* @param [in] channels <tt>int</tt>: Number of channels (1 or 2) in input signal * @param [in] channels <tt>int</tt>: Number of channels (1 or 2) in input signal
* @param [in] application <tt>int</tt>: Coding mode (one of OPUS_APPLICATION_VOIP, OPUS_APPLICATION_AUDIO, or OPUS_APPLICATION_RESTRICTED_LOWDELAY) * @param [in] application <tt>int</tt>: Coding mode (OPUS_APPLICATION_VOIP/OPUS_APPLICATION_AUDIO/OPUS_APPLICATION_RESTRICTED_LOWDELAY)
* @retval #OPUS_OK Success or @ref opus_errorcodes * @retval #OPUS_OK Success or @ref opus_errorcodes
*/ */
OPUS_EXPORT int opus_encoder_init( OPUS_EXPORT int opus_encoder_init(

View File

@@ -104,8 +104,7 @@ typedef struct OpusCustomDecoder OpusCustomDecoder;
/** The mode contains all the information necessary to create an /** The mode contains all the information necessary to create an
encoder. Both the encoder and decoder need to be initialized encoder. Both the encoder and decoder need to be initialized
with exactly the same mode, otherwise the output will be with exactly the same mode, otherwise the output will be
corrupted. The mode MUST NOT BE DESTROYED until the encoders and corrupted.
decoders that use it are destroyed as well.
@brief Mode configuration @brief Mode configuration
*/ */
typedef struct OpusCustomMode OpusCustomMode; typedef struct OpusCustomMode OpusCustomMode;
@@ -179,7 +178,7 @@ OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomEncoder *opus_custom_encode
) OPUS_ARG_NONNULL(1); ) OPUS_ARG_NONNULL(1);
/** Destroys an encoder state. /** Destroys a an encoder state.
* @param[in] st <tt>OpusCustomEncoder*</tt>: State to be freed. * @param[in] st <tt>OpusCustomEncoder*</tt>: State to be freed.
*/ */
OPUS_CUSTOM_EXPORT void opus_custom_encoder_destroy(OpusCustomEncoder *st); OPUS_CUSTOM_EXPORT void opus_custom_encoder_destroy(OpusCustomEncoder *st);
@@ -287,7 +286,7 @@ OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomDecoder *opus_custom_decode
int *error int *error
) OPUS_ARG_NONNULL(1); ) OPUS_ARG_NONNULL(1);
/** Destroys a decoder state. /** Destroys a an decoder state.
* @param[in] st <tt>OpusCustomDecoder*</tt>: State to be freed. * @param[in] st <tt>OpusCustomDecoder*</tt>: State to be freed.
*/ */
OPUS_CUSTOM_EXPORT void opus_custom_decoder_destroy(OpusCustomDecoder *st); OPUS_CUSTOM_EXPORT void opus_custom_decoder_destroy(OpusCustomDecoder *st);

View File

@@ -64,7 +64,7 @@ extern "C" {
/**Export control for opus functions */ /**Export control for opus functions */
#ifndef OPUS_EXPORT #ifndef OPUS_EXPORT
# if defined(_WIN32) # if defined(WIN32)
# if defined(OPUS_BUILD) && defined(DLL_EXPORT) # if defined(OPUS_BUILD) && defined(DLL_EXPORT)
# define OPUS_EXPORT __declspec(dllexport) # define OPUS_EXPORT __declspec(dllexport)
# else # else
@@ -482,8 +482,7 @@ extern "C" {
* @param[in] x <tt>opus_int32</tt>: Allowed values: * @param[in] x <tt>opus_int32</tt>: Allowed values:
* <dl> * <dl>
* <dt>0</dt><dd>Disable inband FEC (default).</dd> * <dt>0</dt><dd>Disable inband FEC (default).</dd>
* <dt>1</dt><dd>Inband FEC enabled. If the packet loss rate is sufficiently high, Opus will automatically switch to SILK even at high rates to enable use of that FEC.</dd> * <dt>1</dt><dd>Enable inband FEC.</dd>
* <dt>2</dt><dd>Inband FEC enabled, but does not necessarily switch to SILK if we have music.</dd>
* </dl> * </dl>
* @hideinitializer */ * @hideinitializer */
#define OPUS_SET_INBAND_FEC(x) OPUS_SET_INBAND_FEC_REQUEST, __opus_check_int(x) #define OPUS_SET_INBAND_FEC(x) OPUS_SET_INBAND_FEC_REQUEST, __opus_check_int(x)
@@ -492,8 +491,7 @@ extern "C" {
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values: * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
* <dl> * <dl>
* <dt>0</dt><dd>Inband FEC disabled (default).</dd> * <dt>0</dt><dd>Inband FEC disabled (default).</dd>
* <dt>1</dt><dd>Inband FEC enabled. If the packet loss rate is sufficiently high, Opus will automatically switch to SILK even at high rates to enable use of that FEC.</dd> * <dt>1</dt><dd>Inband FEC enabled.</dd>
* <dt>2</dt><dd>Inband FEC enabled, but does not necessarily switch to SILK if we have music.</dd>
* </dl> * </dl>
* @hideinitializer */ * @hideinitializer */
#define OPUS_GET_INBAND_FEC(x) OPUS_GET_INBAND_FEC_REQUEST, __opus_check_int_ptr(x) #define OPUS_GET_INBAND_FEC(x) OPUS_GET_INBAND_FEC_REQUEST, __opus_check_int_ptr(x)

View File

@@ -6,7 +6,7 @@
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* * * *
* THE libopusfile SOURCE CODE IS (C) COPYRIGHT 1994-2012 * * THE libopusfile SOURCE CODE IS (C) COPYRIGHT 1994-2012 *
* by the Xiph.Org Foundation and contributors https://xiph.org/ * * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
* * * *
******************************************************************** ********************************************************************
@@ -28,7 +28,7 @@
reference reference
<tt><a href="https://www.xiph.org/ogg/doc/libogg/reference.html">libogg</a></tt> <tt><a href="https://www.xiph.org/ogg/doc/libogg/reference.html">libogg</a></tt>
and and
<tt><a href="https://opus-codec.org/docs/opus_api-1.3.1/">libopus</a></tt> <tt><a href="https://mf4.xiph.org/jenkins/view/opus/job/opus/ws/doc/html/index.html">libopus</a></tt>
libraries. libraries.
<tt>libopusfile</tt> provides several sets of built-in routines for <tt>libopusfile</tt> provides several sets of built-in routines for
@@ -58,7 +58,7 @@
it is stored in the header to allow you to resample to it after decoding it is stored in the header to allow you to resample to it after decoding
(the <tt>libopusfile</tt> API does not currently provide a resampler, (the <tt>libopusfile</tt> API does not currently provide a resampler,
but the but the
<a href="https://www.speex.org/docs/manual/speex-manual/node7.html#SECTION00760000000000000000">the <a href="http://www.speex.org/docs/manual/speex-manual/node7.html#SECTION00760000000000000000">the
Speex resampler</a> is a good choice if you need one). Speex resampler</a> is a good choice if you need one).
In general, if you are playing back the audio, you should leave it at In general, if you are playing back the audio, you should leave it at
48&nbsp;kHz, provided your audio hardware supports it. 48&nbsp;kHz, provided your audio hardware supports it.
@@ -68,7 +68,7 @@
Opus files can contain anywhere from 1 to 255 channels of audio. Opus files can contain anywhere from 1 to 255 channels of audio.
The channel mappings for up to 8 channels are the same as the The channel mappings for up to 8 channels are the same as the
<a href="https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-810004.3.9">Vorbis <a href="http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-800004.3.9">Vorbis
mappings</a>. mappings</a>.
A special stereo API can convert everything to 2 channels, making it simple A special stereo API can convert everything to 2 channels, making it simple
to support multichannel files in an application which only has stereo to support multichannel files in an application which only has stereo
@@ -147,18 +147,18 @@ typedef struct OggOpusFile OggOpusFile;
/**@endcond*/ /**@endcond*/
/**\defgroup error_codes Error Codes*/ /**\defgroup error_codes Error Codes*/
/**@{*/ /*@{*/
/**\name List of possible error codes /**\name List of possible error codes
Many of the functions in this library return a negative error code when a Many of the functions in this library return a negative error code when a
function fails. function fails.
This list provides a brief explanation of the common errors. This list provides a brief explanation of the common errors.
See each individual function for more details on what a specific error code See each individual function for more details on what a specific error code
means in that context.*/ means in that context.*/
/**@{*/ /*@{*/
/**A request did not succeed.*/ /**A request did not succeed.*/
#define OP_FALSE (-1) #define OP_FALSE (-1)
/**Currently not used externally.**/ /*Currently not used externally.*/
#define OP_EOF (-2) #define OP_EOF (-2)
/**There was a hole in the page sequence numbers (e.g., a page was corrupt or /**There was a hole in the page sequence numbers (e.g., a page was corrupt or
missing).*/ missing).*/
@@ -185,7 +185,7 @@ typedef struct OggOpusFile OggOpusFile;
#define OP_EBADHEADER (-133) #define OP_EBADHEADER (-133)
/**The ID header contained an unrecognized version number.*/ /**The ID header contained an unrecognized version number.*/
#define OP_EVERSION (-134) #define OP_EVERSION (-134)
/**Currently not used at all.**/ /*Currently not used at all.*/
#define OP_ENOTAUDIO (-135) #define OP_ENOTAUDIO (-135)
/**An audio packet failed to decode properly. /**An audio packet failed to decode properly.
This is usually caused by a multistream Ogg packet where the durations of This is usually caused by a multistream Ogg packet where the durations of
@@ -200,11 +200,11 @@ typedef struct OggOpusFile OggOpusFile;
/**The first or last granule position of a link failed basic validity checks.*/ /**The first or last granule position of a link failed basic validity checks.*/
#define OP_EBADTIMESTAMP (-139) #define OP_EBADTIMESTAMP (-139)
/**@}*/ /*@}*/
/**@}*/ /*@}*/
/**\defgroup header_info Header Information*/ /**\defgroup header_info Header Information*/
/**@{*/ /*@{*/
/**The maximum number of channels in an Ogg Opus stream.*/ /**The maximum number of channels in an Ogg Opus stream.*/
#define OPUS_CHANNEL_COUNT_MAX (255) #define OPUS_CHANNEL_COUNT_MAX (255)
@@ -284,7 +284,7 @@ struct OpusHead{
A particular tag may occur more than once, and order is significant. A particular tag may occur more than once, and order is significant.
The character set encoding for the strings is always UTF-8, but the tag The character set encoding for the strings is always UTF-8, but the tag
names are limited to ASCII, and treated as case-insensitive. names are limited to ASCII, and treated as case-insensitive.
See <a href="https://www.xiph.org/vorbis/doc/v-comment.html">the Vorbis See <a href="http://www.xiph.org/vorbis/doc/v-comment.html">the Vorbis
comment header specification</a> for details. comment header specification</a> for details.
In filling in this structure, <tt>libopusfile</tt> will null-terminate the In filling in this structure, <tt>libopusfile</tt> will null-terminate the
@@ -311,7 +311,7 @@ struct OpusTags{
}; };
/**\name Picture tag image formats*/ /**\name Picture tag image formats*/
/**@{*/ /*@{*/
/**The MIME type was not recognized, or the image data did not match the /**The MIME type was not recognized, or the image data did not match the
declared MIME type.*/ declared MIME type.*/
@@ -325,7 +325,7 @@ struct OpusTags{
/**The image is a GIF.*/ /**The image is a GIF.*/
#define OP_PIC_FORMAT_GIF (3) #define OP_PIC_FORMAT_GIF (3)
/**@}*/ /*@}*/
/**The contents of a METADATA_BLOCK_PICTURE tag.*/ /**The contents of a METADATA_BLOCK_PICTURE tag.*/
struct OpusPictureTag{ struct OpusPictureTag{
@@ -398,7 +398,7 @@ struct OpusPictureTag{
These can be used to query the headers returned by <tt>libopusfile</tt>, or These can be used to query the headers returned by <tt>libopusfile</tt>, or
to parse Opus headers from sources other than an Ogg Opus stream, provided to parse Opus headers from sources other than an Ogg Opus stream, provided
they use the same format.*/ they use the same format.*/
/**@{*/ /*@{*/
/**Parses the contents of the ID header packet of an Ogg Opus stream. /**Parses the contents of the ID header packet of an Ogg Opus stream.
\param[out] _head Returns the contents of the parsed packet. \param[out] _head Returns the contents of the parsed packet.
@@ -671,12 +671,12 @@ void opus_picture_tag_init(OpusPictureTag *_pic) OP_ARG_NONNULL(1);
\param _pic The #OpusPictureTag structure to clear.*/ \param _pic The #OpusPictureTag structure to clear.*/
void opus_picture_tag_clear(OpusPictureTag *_pic) OP_ARG_NONNULL(1); void opus_picture_tag_clear(OpusPictureTag *_pic) OP_ARG_NONNULL(1);
/**@}*/ /*@}*/
/**@}*/ /*@}*/
/**\defgroup url_options URL Reading Options*/ /**\defgroup url_options URL Reading Options*/
/**@{*/ /*@{*/
/**\name URL reading options /**\name URL reading options
Options for op_url_stream_create() and associated functions. Options for op_url_stream_create() and associated functions.
These allow you to provide proxy configuration parameters, skip SSL These allow you to provide proxy configuration parameters, skip SSL
@@ -685,7 +685,7 @@ void opus_picture_tag_clear(OpusPictureTag *_pic) OP_ARG_NONNULL(1);
times, only the value specified by the last occurrence has an effect times, only the value specified by the last occurrence has an effect
(unless otherwise specified). (unless otherwise specified).
They may be expanded in the future.*/ They may be expanded in the future.*/
/**@{*/ /*@{*/
/**@cond PRIVATE*/ /**@cond PRIVATE*/
@@ -698,7 +698,7 @@ void opus_picture_tag_clear(OpusPictureTag *_pic) OP_ARG_NONNULL(1);
#define OP_HTTP_PROXY_PASS_REQUEST (6720) #define OP_HTTP_PROXY_PASS_REQUEST (6720)
#define OP_GET_SERVER_INFO_REQUEST (6784) #define OP_GET_SERVER_INFO_REQUEST (6784)
#define OP_URL_OPT(_request) ((char *)(_request)) #define OP_URL_OPT(_request) ((_request)+(char *)0)
/*These macros trigger compilation errors or warnings if the wrong types are /*These macros trigger compilation errors or warnings if the wrong types are
provided to one of the URL options.*/ provided to one of the URL options.*/
@@ -843,11 +843,11 @@ void opus_server_info_clear(OpusServerInfo *_info) OP_ARG_NONNULL(1);
#define OP_GET_SERVER_INFO(_info) \ #define OP_GET_SERVER_INFO(_info) \
OP_URL_OPT(OP_GET_SERVER_INFO_REQUEST),OP_CHECK_SERVER_INFO_PTR(_info) OP_URL_OPT(OP_GET_SERVER_INFO_REQUEST),OP_CHECK_SERVER_INFO_PTR(_info)
/**@}*/ /*@}*/
/**@}*/ /*@}*/
/**\defgroup stream_callbacks Abstract Stream Reading Interface*/ /**\defgroup stream_callbacks Abstract Stream Reading Interface*/
/**@{*/ /*@{*/
/**\name Functions for reading from streams /**\name Functions for reading from streams
These functions define the interface used to read from and seek in a stream These functions define the interface used to read from and seek in a stream
of data. of data.
@@ -856,7 +856,7 @@ void opus_server_info_clear(OpusServerInfo *_info) OP_ARG_NONNULL(1);
These functions also include some convenience routines for working with These functions also include some convenience routines for working with
standard <code>FILE</code> pointers, complete streams stored in a single standard <code>FILE</code> pointers, complete streams stored in a single
block of memory, or URLs.*/ block of memory, or URLs.*/
/**@{*/ /*@{*/
/**Reads up to \a _nbytes bytes of data from \a _stream. /**Reads up to \a _nbytes bytes of data from \a _stream.
\param _stream The stream to read from. \param _stream The stream to read from.
@@ -1034,18 +1034,18 @@ OP_WARN_UNUSED_RESULT void *op_url_stream_vcreate(OpusFileCallbacks *_cb,
OP_WARN_UNUSED_RESULT void *op_url_stream_create(OpusFileCallbacks *_cb, OP_WARN_UNUSED_RESULT void *op_url_stream_create(OpusFileCallbacks *_cb,
const char *_url,...) OP_ARG_NONNULL(1) OP_ARG_NONNULL(2); const char *_url,...) OP_ARG_NONNULL(1) OP_ARG_NONNULL(2);
/**@}*/ /*@}*/
/**@}*/ /*@}*/
/**\defgroup stream_open_close Opening and Closing*/ /**\defgroup stream_open_close Opening and Closing*/
/**@{*/ /*@{*/
/**\name Functions for opening and closing streams /**\name Functions for opening and closing streams
These functions allow you to test a stream to see if it is Opus, open it, These functions allow you to test a stream to see if it is Opus, open it,
and close it. and close it.
Several flavors are provided for each of the built-in stream types, plus a Several flavors are provided for each of the built-in stream types, plus a
more general version which takes a set of application-provided callbacks.*/ more general version which takes a set of application-provided callbacks.*/
/**@{*/ /*@{*/
/**Test to see if this is an Opus stream. /**Test to see if this is an Opus stream.
For good results, you will need at least 57 bytes (for a pure Opus-only For good results, you will need at least 57 bytes (for a pure Opus-only
@@ -1159,16 +1159,20 @@ OP_WARN_UNUSED_RESULT OggOpusFile *op_open_url(const char *_url,
This value will be passed verbatim as the first This value will be passed verbatim as the first
argument to all of the callbacks. argument to all of the callbacks.
\param _cb The callbacks with which to access the stream. \param _cb The callbacks with which to access the stream.
\ref op_read_func "read()" must be implemented. <code><a href="#op_read_func">read()</a></code> must
\ref op_seek_func "seek()" and \ref op_tell_func be implemented.
"tell()" may be <code>NULL</code>, or may always <code><a href="#op_seek_func">seek()</a></code> and
return -1 to indicate a stream is unseekable, but if <code><a href="#op_tell_func">tell()</a></code> may
\ref op_seek_func "seek()" is implemented and be <code>NULL</code>, or may always return -1 to
succeeds on a particular stream, then \ref indicate a stream is unseekable, but if
op_tell_func "tell()" must also. <code><a href="#op_seek_func">seek()</a></code> is
\ref op_close_func "close()" may be <code>NULL</code>, implemented and succeeds on a particular stream, then
but if it is not, it will be called when the \c <code><a href="#op_tell_func">tell()</a></code> must
OggOpusFile is destroyed by op_free(). also.
<code><a href="#op_close_func">close()</a></code> may
be <code>NULL</code>, but if it is not, it will be
called when the \c OggOpusFile is destroyed by
op_free().
It will not be called if op_open_callbacks() fails It will not be called if op_open_callbacks() fails
with an error. with an error.
\param _initial_data An initial buffer of data from the start of the \param _initial_data An initial buffer of data from the start of the
@@ -1179,8 +1183,10 @@ OP_WARN_UNUSED_RESULT OggOpusFile *op_open_url(const char *_url,
stream to be opened, even if it is unseekable. stream to be opened, even if it is unseekable.
\param _initial_bytes The number of bytes in \a _initial_data. \param _initial_bytes The number of bytes in \a _initial_data.
If the stream is seekable, its current position (as If the stream is seekable, its current position (as
reported by \ref op_tell_func "tell()" at the start reported by
of this function) must be equal to \a _initial_bytes. <code><a href="#opus_tell_func">tell()</a></code>
at the start of this function) must be equal to
\a _initial_bytes.
Otherwise, seeking to absolute positions will Otherwise, seeking to absolute positions will
generate inconsistent results. generate inconsistent results.
\param[out] _error Returns 0 on success, or a failure code on error. \param[out] _error Returns 0 on success, or a failure code on error.
@@ -1200,10 +1206,11 @@ OP_WARN_UNUSED_RESULT OggOpusFile *op_open_url(const char *_url,
implemented, such as an unsupported channel implemented, such as an unsupported channel
family.</dd> family.</dd>
<dt>#OP_EINVAL</dt> <dt>#OP_EINVAL</dt>
<dd>\ref op_seek_func "seek()" was implemented and <dd><code><a href="#op_seek_func">seek()</a></code>
succeeded on this source, but \ref op_tell_func was implemented and succeeded on this source, but
"tell()" did not, or the starting position <code><a href="#op_tell_func">tell()</a></code>
indicator was not equal to \a _initial_bytes.</dd> did not, or the starting position indicator was
not equal to \a _initial_bytes.</dd>
<dt>#OP_ENOTFORMAT</dt> <dt>#OP_ENOTFORMAT</dt>
<dd>The stream contained a link that did not have <dd>The stream contained a link that did not have
any logical Opus streams in it.</dd> any logical Opus streams in it.</dd>
@@ -1334,16 +1341,20 @@ OP_WARN_UNUSED_RESULT OggOpusFile *op_test_url(const char *_url,
This value will be passed verbatim as the first This value will be passed verbatim as the first
argument to all of the callbacks. argument to all of the callbacks.
\param _cb The callbacks with which to access the stream. \param _cb The callbacks with which to access the stream.
\ref op_read_func "read()" must be implemented. <code><a href="#op_read_func">read()</a></code> must
\ref op_seek_func "seek()" and \ref op_tell_func be implemented.
"tell()" may be <code>NULL</code>, or may always <code><a href="#op_seek_func">seek()</a></code> and
return -1 to indicate a stream is unseekable, but if <code><a href="#op_tell_func">tell()</a></code> may
\ref op_seek_func "seek()" is implemented and be <code>NULL</code>, or may always return -1 to
succeeds on a particular stream, then \ref indicate a stream is unseekable, but if
op_tell_func "tell()" must also. <code><a href="#op_seek_func">seek()</a></code> is
\ref op_close_func "close()" may be <code>NULL</code>, implemented and succeeds on a particular stream, then
but if it is not, it will be called when the \c <code><a href="#op_tell_func">tell()</a></code> must
OggOpusFile is destroyed by op_free(). also.
<code><a href="#op_close_func">close()</a></code> may
be <code>NULL</code>, but if it is not, it will be
called when the \c OggOpusFile is destroyed by
op_free().
It will not be called if op_open_callbacks() fails It will not be called if op_open_callbacks() fails
with an error. with an error.
\param _initial_data An initial buffer of data from the start of the \param _initial_data An initial buffer of data from the start of the
@@ -1356,8 +1367,9 @@ OP_WARN_UNUSED_RESULT OggOpusFile *op_test_url(const char *_url,
\param _initial_bytes The number of bytes in \a _initial_data. \param _initial_bytes The number of bytes in \a _initial_data.
If the stream is seekable, its current position (as If the stream is seekable, its current position (as
reported by reported by
\ref op_tell_func "tell()" at the start of this <code><a href="#opus_tell_func">tell()</a></code>
function) must be equal to \a _initial_bytes. at the start of this function) must be equal to
\a _initial_bytes.
Otherwise, seeking to absolute positions will Otherwise, seeking to absolute positions will
generate inconsistent results. generate inconsistent results.
\param[out] _error Returns 0 on success, or a failure code on error. \param[out] _error Returns 0 on success, or a failure code on error.
@@ -1406,11 +1418,11 @@ int op_test_open(OggOpusFile *_of) OP_ARG_NONNULL(1);
\param _of The \c OggOpusFile to free.*/ \param _of The \c OggOpusFile to free.*/
void op_free(OggOpusFile *_of); void op_free(OggOpusFile *_of);
/**@}*/ /*@}*/
/**@}*/ /*@}*/
/**\defgroup stream_info Stream Information*/ /**\defgroup stream_info Stream Information*/
/**@{*/ /*@{*/
/**\name Functions for obtaining information about streams /**\name Functions for obtaining information about streams
These functions allow you to get basic information about a stream, including These functions allow you to get basic information about a stream, including
@@ -1425,17 +1437,18 @@ void op_free(OggOpusFile *_of);
streams returned by op_test_callbacks() or one of the associated streams returned by op_test_callbacks() or one of the associated
convenience functions. convenience functions.
Their documention will indicate so explicitly.*/ Their documention will indicate so explicitly.*/
/**@{*/ /*@{*/
/**Returns whether or not the stream being read is seekable. /**Returns whether or not the stream being read is seekable.
This is true if This is true if
<ol> <ol>
<li>The \ref op_seek_func "seek()" and \ref op_tell_func "tell()" <li>The <code><a href="#op_seek_func">seek()</a></code> and
callbacks are both non-<code>NULL</code>,</li> <code><a href="#op_tell_func">tell()</a></code> callbacks are both
<li>The \ref op_seek_func "seek()" callback was successfully executed at non-<code>NULL</code>,</li>
least once, and</li> <li>The <code><a href="#op_seek_func">seek()</a></code> callback was
<li>The \ref op_tell_func "tell()" callback was successfully able to report successfully executed at least once, and</li>
the position indicator afterwards.</li> <li>The <code><a href="#op_tell_func">tell()</a></code> callback was
successfully able to report the position indicator afterwards.</li>
</ol> </ol>
This function may be called on partially-opened streams. This function may be called on partially-opened streams.
\param _of The \c OggOpusFile whose seekable status is to be returned. \param _of The \c OggOpusFile whose seekable status is to be returned.
@@ -1625,11 +1638,11 @@ opus_int64 op_raw_tell(const OggOpusFile *_of) OP_ARG_NONNULL(1);
\retval #OP_EINVAL The stream was only partially open.*/ \retval #OP_EINVAL The stream was only partially open.*/
ogg_int64_t op_pcm_tell(const OggOpusFile *_of) OP_ARG_NONNULL(1); ogg_int64_t op_pcm_tell(const OggOpusFile *_of) OP_ARG_NONNULL(1);
/**@}*/ /*@}*/
/**@}*/ /*@}*/
/**\defgroup stream_seeking Seeking*/ /**\defgroup stream_seeking Seeking*/
/**@{*/ /*@{*/
/**\name Functions for seeking in Opus streams /**\name Functions for seeking in Opus streams
These functions let you seek in Opus streams, if the underlying stream These functions let you seek in Opus streams, if the underlying stream
@@ -1654,7 +1667,7 @@ ogg_int64_t op_pcm_tell(const OggOpusFile *_of) OP_ARG_NONNULL(1);
values as would be obtained by decoding the stream straight through. values as would be obtained by decoding the stream straight through.
However, such differences are expected to be smaller than the loss However, such differences are expected to be smaller than the loss
introduced by Opus's lossy compression.*/ introduced by Opus's lossy compression.*/
/**@{*/ /*@{*/
/**Seek to a byte offset relative to the <b>compressed</b> data. /**Seek to a byte offset relative to the <b>compressed</b> data.
This also scans packets to update the PCM cursor. This also scans packets to update the PCM cursor.
@@ -1689,11 +1702,11 @@ int op_raw_seek(OggOpusFile *_of,opus_int64 _byte_offset) OP_ARG_NONNULL(1);
seeking to the target destination was impossible.*/ seeking to the target destination was impossible.*/
int op_pcm_seek(OggOpusFile *_of,ogg_int64_t _pcm_offset) OP_ARG_NONNULL(1); int op_pcm_seek(OggOpusFile *_of,ogg_int64_t _pcm_offset) OP_ARG_NONNULL(1);
/**@}*/ /*@}*/
/**@}*/ /*@}*/
/**\defgroup stream_decoding Decoding*/ /**\defgroup stream_decoding Decoding*/
/**@{*/ /*@{*/
/**\name Functions for decoding audio data /**\name Functions for decoding audio data
These functions retrieve actual decoded audio data from the stream. These functions retrieve actual decoded audio data from the stream.
@@ -1731,7 +1744,7 @@ int op_pcm_seek(OggOpusFile *_of,ogg_int64_t _pcm_offset) OP_ARG_NONNULL(1);
If you are reading from an <https:> URL (particularly if seeking is not If you are reading from an <https:> URL (particularly if seeking is not
supported), you should make sure to check for this error and warn the user supported), you should make sure to check for this error and warn the user
appropriately.*/ appropriately.*/
/**@{*/ /*@{*/
/**Indicates that the decoding callback should produce signed 16-bit /**Indicates that the decoding callback should produce signed 16-bit
native-endian output samples.*/ native-endian output samples.*/
@@ -1877,7 +1890,7 @@ void op_set_dither_enabled(OggOpusFile *_of,int _enabled) OP_ARG_NONNULL(1);
signed native-endian 16-bit values at 48&nbsp;kHz signed native-endian 16-bit values at 48&nbsp;kHz
with a nominal range of <code>[-32768,32767)</code>. with a nominal range of <code>[-32768,32767)</code>.
Multiple channels are interleaved using the Multiple channels are interleaved using the
<a href="https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-810004.3.9">Vorbis <a href="http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-800004.3.9">Vorbis
channel ordering</a>. channel ordering</a>.
This must have room for at least \a _buf_size values. This must have room for at least \a _buf_size values.
\param _buf_size The number of values that can be stored in \a _pcm. \param _buf_size The number of values that can be stored in \a _pcm.
@@ -1959,7 +1972,7 @@ OP_WARN_UNUSED_RESULT int op_read(OggOpusFile *_of,
signed floats at 48&nbsp;kHz with a nominal range of signed floats at 48&nbsp;kHz with a nominal range of
<code>[-1.0,1.0]</code>. <code>[-1.0,1.0]</code>.
Multiple channels are interleaved using the Multiple channels are interleaved using the
<a href="https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-810004.3.9">Vorbis <a href="http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-800004.3.9">Vorbis
channel ordering</a>. channel ordering</a>.
This must have room for at least \a _buf_size floats. This must have room for at least \a _buf_size floats.
\param _buf_size The number of floats that can be stored in \a _pcm. \param _buf_size The number of floats that can be stored in \a _pcm.
@@ -2137,8 +2150,8 @@ OP_WARN_UNUSED_RESULT int op_read_stereo(OggOpusFile *_of,
OP_WARN_UNUSED_RESULT int op_read_float_stereo(OggOpusFile *_of, OP_WARN_UNUSED_RESULT int op_read_float_stereo(OggOpusFile *_of,
float *_pcm,int _buf_size) OP_ARG_NONNULL(1); float *_pcm,int _buf_size) OP_ARG_NONNULL(1);
/**@}*/ /*@}*/
/**@}*/ /*@}*/
# if OP_GNUC_PREREQ(4,0) # if OP_GNUC_PREREQ(4,0)
# pragma GCC visibility pop # pragma GCC visibility pop

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -136,7 +136,7 @@ const static actrls_t controls = {
NULL, NULL, // rew, fwd NULL, NULL, // rew, fwd
bt_prev, bt_next, // prev, next bt_prev, bt_next, // prev, next
NULL, NULL, NULL, NULL, // left, right, up, down NULL, NULL, NULL, NULL, // left, right, up, down
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // pre1-10 NULL, NULL, NULL, NULL, NULL, NULL, // pre1-6
bt_volume_down, bt_volume_up, bt_toggle// knob left, knob_right, knob push bt_volume_down, bt_volume_up, bt_toggle// knob left, knob_right, knob push
}; };

View File

@@ -121,7 +121,7 @@ void config_start_timer(){
nvs_type_t config_get_item_type(cJSON * entry){ nvs_type_t config_get_item_type(cJSON * entry){
if(entry==NULL){ if(entry==NULL){
ESP_LOGE(TAG,"null pointer received!"); ESP_LOGE(TAG,"null pointer received!");
return 0; return true;
} }
cJSON * item_type = cJSON_GetObjectItemCaseSensitive(entry, "type"); cJSON * item_type = cJSON_GetObjectItemCaseSensitive(entry, "type");
if(item_type ==NULL ) { if(item_type ==NULL ) {
@@ -142,7 +142,7 @@ cJSON * config_set_value_safe(nvs_type_t nvs_type, const char *key, const void
return NULL; return NULL;
} }
cJSON * existing = cJSON_GetObjectItemCaseSensitive(nvs_json, key); cJSON * existing = cJSON_GetObjectItemCaseSensitive(nvs_json, key);
if(existing !=NULL && nvs_type == NVS_TYPE_STR && config_get_item_type(existing) != NVS_TYPE_STR ) { if(existing !=NULL && nvs_type == NVS_TYPE_STR && config_get_item_type(existing) != NVS_TYPE_STR ) {
ESP_LOGW(TAG, "Storing numeric value from string"); ESP_LOGW(TAG, "Storing numeric value from string");
numvalue = atof((char *)value); numvalue = atof((char *)value);

View File

@@ -5,6 +5,7 @@ idf_component_register( SRCS
cmd_system.c cmd_system.c
cmd_wifi.c cmd_wifi.c
platform_console.c platform_console.c
improv_console.c
cmd_config.c cmd_config.c
INCLUDE_DIRS . INCLUDE_DIRS .
REQUIRES nvs_flash REQUIRES nvs_flash

View File

@@ -1,7 +1,7 @@
idf_build_get_property(idf_path IDF_PATH) idf_build_get_property(idf_path IDF_PATH)
idf_component_register( SRCS cmd_squeezelite.c idf_component_register( SRCS cmd_squeezelite.c
INCLUDE_DIRS . INCLUDE_DIRS .
PRIV_REQUIRES spi_flash bootloader_support partition_table bootloader_support console codecs squeezelite newlib pthread tools platform_config display tools services) PRIV_REQUIRES spi_flash bootloader_support partition_table bootloader_support console codecs squeezelite newlib pthread tools platform_config display tools)
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--undefined=feof") target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--undefined=feof")

View File

@@ -12,7 +12,6 @@
#include "platform_config.h" #include "platform_config.h"
#include "esp_app_format.h" #include "esp_app_format.h"
#include "tools.h" #include "tools.h"
#include "messaging.h"
extern esp_err_t process_recovery_ota(const char * bin_url, char * bin_buffer, uint32_t length); extern esp_err_t process_recovery_ota(const char * bin_url, char * bin_buffer, uint32_t length);
static const char * TAG = "squeezelite_cmd"; static const char * TAG = "squeezelite_cmd";
@@ -40,8 +39,7 @@ const __attribute__((section(".rodata_desc"))) esp_app_desc_t esp_app_desc = {
#endif #endif
}; };
extern int squeezelite_main(int argc, char **argv); extern int main(int argc, char **argv);
static int launchsqueezelite(int argc, char **argv); static int launchsqueezelite(int argc, char **argv);
/** Arguments used by 'squeezelite' function */ /** Arguments used by 'squeezelite' function */
@@ -55,32 +53,31 @@ static struct {
} thread_parms ; } thread_parms ;
#define ADDITIONAL_SQUEEZELITE_ARGS 5 #define ADDITIONAL_SQUEEZELITE_ARGS 5
static void squeezelite_thread(void *arg){ static void squeezelite_thread(void *arg){
ESP_LOGV(TAG ,"Number of args received: %u",thread_parms.argc ); ESP_LOGV(TAG ,"Number of args received: %u",thread_parms.argc );
ESP_LOGV(TAG ,"Values:"); ESP_LOGV(TAG ,"Values:");
for(int i = 0;i<thread_parms.argc; i++){ for(int i = 0;i<thread_parms.argc; i++){
ESP_LOGV(TAG ," %s",thread_parms.argv[i]); ESP_LOGV(TAG ," %s",thread_parms.argv[i]);
} }
ESP_LOGI(TAG ,"Calling squeezelite");
int ret = squeezelite_main(thread_parms.argc, thread_parms.argv);
cmd_send_messaging("cfg-audio-tmpl",ret > 1 ? MESSAGING_ERROR : MESSAGING_WARNING,"squeezelite exited with error code %d\n", ret);
if (ret <= 1) { ESP_LOGI(TAG ,"Calling squeezelite");
int wait = 60; main(thread_parms.argc,thread_parms.argv);
wait_for_commit(); ESP_LOGV(TAG ,"Exited from squeezelite's main(). Freeing argv structure.");
cmd_send_messaging("cfg-audio-tmpl",MESSAGING_ERROR,"Rebooting in %d sec\n", wait);
vTaskDelay( pdMS_TO_TICKS(wait * 1000));
esp_restart();
} else {
cmd_send_messaging("cfg-audio-tmpl",MESSAGING_ERROR,"Correct command line and reboot\n");
vTaskSuspend(NULL);
}
ESP_LOGV(TAG, "Exited from squeezelite's main(). Freeing argv structure."); for(int i=0;i<thread_parms.argc;i++){
ESP_LOGV(TAG ,"Freeing char buffer for parameter %u", i+1);
for(int i=0;i<thread_parms.argc;i++) free(thread_parms.argv[i]); free(thread_parms.argv[i]);
}
ESP_LOGV(TAG ,"Freeing argv pointer");
free(thread_parms.argv); free(thread_parms.argv);
ESP_LOGE(TAG, "Exited from squeezelite thread, something's wrong ... rebooting (wait 30s for user to take action)");
if(!wait_for_commit()){
ESP_LOGW(TAG,"Unable to commit configuration. ");
}
vTaskDelay( pdMS_TO_TICKS( 30*1000 ) );
esp_restart();
} }
static int launchsqueezelite(int argc, char **argv) { static int launchsqueezelite(int argc, char **argv) {

View File

@@ -69,6 +69,7 @@ static void register_deep_sleep();
static void register_light_sleep(); static void register_light_sleep();
static void register_factory_boot(); static void register_factory_boot();
static void register_restart_ota(); static void register_restart_ota();
static void register_update_certs();
static void register_set_services(); static void register_set_services();
#if WITH_TASKS_INFO #if WITH_TASKS_INFO
static void register_tasks(); static void register_tasks();
@@ -85,6 +86,7 @@ void register_system()
register_restart(); register_restart();
register_deep_sleep(); register_deep_sleep();
register_light_sleep(); register_light_sleep();
register_update_certs();
register_factory_boot(); register_factory_boot();
register_restart_ota(); register_restart_ota();
#if WITH_TASKS_INFO #if WITH_TASKS_INFO
@@ -560,6 +562,23 @@ static void register_tasks()
#endif // WITH_TASKS_INFO #endif // WITH_TASKS_INFO
extern esp_err_t update_certificates(bool force);
static int force_update_cert(int argc, char **argv){
return update_certificates(true);
}
static void register_update_certs()
{
const esp_console_cmd_t cmd = {
.command = "update_certificates",
.help = "Force updating the certificates from binary",
.hint = NULL,
.func = &force_update_cert,
};
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
}
/** 'deep_sleep' command puts the chip into deep sleep mode */ /** 'deep_sleep' command puts the chip into deep sleep mode */

View File

@@ -33,6 +33,7 @@
#include "esp_netif.h" #include "esp_netif.h"
#include "esp_event.h" #include "esp_event.h"
#include "led.h" #include "led.h"
#include "improv.h"
extern bool bypass_network_manager; extern bool bypass_network_manager;
#define JOIN_TIMEOUT_MS (10000) #define JOIN_TIMEOUT_MS (10000)
#include "platform_console.h" #include "platform_console.h"
@@ -48,6 +49,15 @@ static struct {
struct arg_str *password; struct arg_str *password;
struct arg_end *end; struct arg_end *end;
} join_args; } join_args;
static struct {
struct arg_lit * conect;
struct arg_lit * state;
struct arg_lit * info;
struct arg_lit * list;
struct arg_str *ssid;
struct arg_str *password;
struct arg_end *end;
} improv_args;
@@ -185,6 +195,44 @@ static int connect(int argc, char **argv)
return 0; return 0;
} }
extern bool on_improv_command(ImprovCommandStruct_t *command); // command callback
static int do_improv(int argc, char **argv)
{
ImprovCommandStruct_t command;
int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&improv_args);
if (nerrors != 0) {
return 1;
}
if(improv_args.info->count>0){
memset(&command,0x00,sizeof(command));
command.command = IMPROV_CMD_GET_DEVICE_INFO;
on_improv_command(&command);
}
if(improv_args.conect->count>0){
if(improv_args.ssid->count == 0){
ESP_LOGE(__func__,"Parameter ssid is required to connect");
return 1;
}
command.ssid = improv_args.ssid->sval[0];
if(improv_args.password->count == 0){
command.password= improv_args.password->sval[0];
}
command.command = IMPROV_CMD_WIFI_SETTINGS;
on_improv_command(&command);
}
if(improv_args.state->count>0){
memset(&command,0x00,sizeof(command));
command.command = IMPROV_CMD_GET_CURRENT_STATE;
on_improv_command(&command);
}
if(improv_args.list->count>0){
memset(&command,0x00,sizeof(command));
command.command = IMPROV_CMD_GET_WIFI_NETWORKS;
on_improv_command(&command);
}
return 0;
}
void register_wifi_join() void register_wifi_join()
{ {
join_args.timeout = arg_int0(NULL, "timeout", "<t>", "Connection timeout, ms"); join_args.timeout = arg_int0(NULL, "timeout", "<t>", "Connection timeout, ms");
@@ -201,10 +249,28 @@ void register_wifi_join()
}; };
ESP_ERROR_CHECK( esp_console_cmd_register(&join_cmd) ); ESP_ERROR_CHECK( esp_console_cmd_register(&join_cmd) );
} }
static void register_improv_debug(){
improv_args.conect = arg_lit0(NULL,"connect","Connects to the specified wifi ssid and password");
improv_args.ssid = arg_str0(NULL, NULL, "<ssid>", "SSID of AP");
improv_args.password = arg_str0(NULL, NULL, "<pass>", "Password of AP");
improv_args.info = arg_lit0(NULL,"info","Request the info packet");
improv_args.list = arg_lit0(NULL,"list","Request the wifi list packet");
improv_args.state = arg_lit0(NULL,"state","Requests the state packet");
improv_args.end = arg_end(2);
const esp_console_cmd_t improv_cmd = {
.command = "improv",
.help = "Send an improv-wifi serial command to the system",
.hint = NULL,
.func = &do_improv,
.argtable = &improv_args
};
ESP_ERROR_CHECK( esp_console_cmd_register(&improv_cmd) );
}
void register_wifi() void register_wifi()
{ {
register_wifi_join(); register_wifi_join();
register_improv_debug();
if(bypass_network_manager){ if(bypass_network_manager){
initialise_wifi(); initialise_wifi();
} }

View File

@@ -0,0 +1,162 @@
#include "platform_console.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "esp_log.h"
#include "esp_console.h"
#include "esp_vfs_dev.h"
#include "driver/uart.h"
#include "linenoise/linenoise.h"
#include "argtable3/argtable3.h"
#include "nvs.h"
#include "nvs_flash.h"
#include "pthread.h"
#include "platform_esp32.h"
#include "cmd_decl.h"
#include "trace.h"
#include "platform_config.h"
#include "telnet.h"
#include "tools.h"
#include "improv.h"
#include "messaging.h"
#include "config.h"
#include "improv_console.h"
#include "network_status.h"
static const char * TAG ="improv_console";
const time_t improv_timeout_ms = 50;
TickType_t improv_timeout_tick = pdMS_TO_TICKS(improv_timeout_ms);
ImprovState_t improv_state = IMPROV_STATE_READY_AUTHORIZED;
const size_t improv_buffer_size = 121;
size_t improv_buffer_len = 0;
uint8_t * improv_buffer_data = NULL;
TickType_t improv_delay = portMAX_DELAY;
void cb_improv_got_ip(nm_state_t new_state, int sub_state){
if(improv_state == IMPROV_STATE_PROVISIONING){
char * url = network_status_alloc_get_system_url();
ESP_LOGI(TAG,"Signaling improv state connected state with url: %s",STR_OR_BLANK(url));
improv_send_device_url(IMPROV_CMD_WIFI_SETTINGS,url);
FREE_AND_NULL(url);
}
}
void cb_improv_disconnected(nm_state_t new_state, int sub_state){
if(improv_state == IMPROV_STATE_PROVISIONING){
ESP_LOGI(TAG,"Signalling improv connect failure ");
improv_state = IMPROV_STATE_READY_AUTHORIZED;
improv_send_error(IMPROV_ERROR_UNABLE_TO_CONNECT);
}
}
bool on_improv_command(ImprovCommandStruct_t *command){
esp_err_t err = ESP_OK;
wifi_connect_state_t wifi_state = network_wifi_get_connect_state();
const esp_app_desc_t* desc = esp_ota_get_app_description();
improv_buffer_len = 0;
char * url=NULL;
char * host_name = NULL;
ESP_LOGI(TAG, "Processing improv command %s",improv_get_command_desc(command->command));
if(!command){
return false;
}
switch (command->command)
{
case IMPROV_CMD_WIFI_SETTINGS:
// attempt to connect to the provided SSID+password
improv_state = IMPROV_STATE_PROVISIONING;
ESP_LOGI(TAG,"Improv connect to %s",command->ssid );
network_async_connect(command->ssid, command->password);
FREE_AND_NULL(command->ssid);
FREE_AND_NULL(command->password);
break;
case IMPROV_CMD_GET_CURRENT_STATE:
if(wifi_state !=NETWORK_WIFI_STATE_CONNECTING){
network_async_scan();
}
switch (wifi_state)
{
case NETWORK_WIFI_STATE_CONNECTING:
ESP_LOGI(TAG,"Signaling improv state " );
return improv_send_current_state(improv_state);
break;
case NETWORK_WIFI_STATE_INVALID_CONFIG:
improv_state = IMPROV_STATE_READY_AUTHORIZED;
ESP_LOGW(TAG,"Signaling improv state IMPROV_ERROR_UNABLE_TO_CONNECT" );
return improv_send_error(IMPROV_ERROR_UNABLE_TO_CONNECT);
break;
case NETWORK_WIFI_STATE_FAILED:
ESP_LOGW(TAG,"Signaling improv state IMPROV_ERROR_NOT_AUTHORIZED" );
network_async_scan();
improv_state = IMPROV_STATE_READY_AUTHORIZED;
return improv_send_error(IMPROV_ERROR_NOT_AUTHORIZED);
break;
case NETWORK_WIFI_STATE_CONNECTED:
network_async_scan();
url = network_status_alloc_get_system_url();
ESP_LOGI(TAG,"Signaling improv state connected state with url: %s",STR_OR_BLANK(url));
improv_state = IMPROV_STATE_PROVISIONED;
improv_send_current_state(improv_state);
// also send url
improv_send_device_url(IMPROV_CMD_GET_CURRENT_STATE,url);
FREE_AND_NULL(url);
break;
default:
ESP_LOGI(TAG,"Signaling improv state " );
return improv_send_current_state(improv_state);
break;
}
break;
case IMPROV_CMD_GET_DEVICE_INFO:
ESP_LOGI(TAG,"Signaling improv with device info. Firmware Name: %s, Version: %s ",desc->project_name,desc->version );
host_name = config_alloc_get_str("host_name",NULL,"Squeezelite");
improv_send_device_info(desc->project_name,desc->version,"ESP32",host_name);
FREE_AND_NULL(host_name);
break;
case IMPROV_CMD_GET_WIFI_NETWORKS:
ESP_LOGI(TAG,"Signaling improv with list of wifi networks " );
improv_wifi_list_send();
break;
default:
ESP_LOGE(TAG,"Signaling improv with invalid RPC call received" );
improv_send_error(IMPROV_ERROR_INVALID_RPC);
break;
}
return false;
}
void on_improv_error(ImprovError_t error){
improv_send_error(error);
ESP_LOGE(TAG,"Error processing improv-wifi packet : %s", improv_get_error_desc(error));
}
#if BUFFER_DEBUG
void dump_buffer(const char * prefix, const char * buff, size_t len){
printf("\n%s (%d): ",prefix, len);
for(int i=0;i<len;i++){
printf(" %c ",isprint(buff[i])?buff[i]:'.');
}
printf("\n%s (%d): ",prefix, len);
for(int i=0;i<len;i++){
printf("0x%03x ",buff[i]);
}
printf("\n");
}
#else
#define dump_buffer(prefix,buff,size)
#endif
bool improv_send_callback(uint8_t * buffer, size_t length){
dump_buffer("send", (const char *) buffer, length);
uart_write_bytes(CONFIG_ESP_CONSOLE_UART_NUM,buffer,length );
return true;
}
void improv_console_init(){
ESP_LOGI(TAG,"Initializing improv callbacks");
network_register_state_callback(NETWORK_WIFI_ACTIVE_STATE,WIFI_CONNECTED_STATE, "improv_got_ip", &cb_improv_got_ip);
network_register_state_callback(NETWORK_WIFI_ACTIVE_STATE,WIFI_CONNECTING_NEW_FAILED_STATE, "improv_disconnect", &cb_improv_disconnected);
network_register_state_callback(NETWORK_WIFI_CONFIGURING_ACTIVE_STATE,WIFI_CONFIGURING_CONNECT_FAILED_STATE, "improv_disconnect", &cb_improv_disconnected);
}

View File

@@ -0,0 +1,24 @@
extern TickType_t improv_timeout_tick;
#pragma once
#include "network_manager.h"
#include "improv.h"
#include "freertos/FreeRTOS.h"
#include <stdio.h>
#include <stdlib.h>
#define BUFFER_DEBUG 0
extern TickType_t improv_timeout_tick;
extern const size_t improv_buffer_size;
extern size_t improv_buffer_len;
extern uint8_t * improv_buffer_data;
extern const time_t improv_timeout_ms;
extern TickType_t improv_delay;
void cb_improv_got_ip(nm_state_t new_state, int sub_state);
bool on_improv_command(ImprovCommandStruct_t *command);
void on_improv_error(ImprovError_t error);
void dump_buffer(const char * prefix, const char * buff, size_t len);
bool improv_send_callback(uint8_t * buffer, size_t length);
void improv_console_init();

View File

@@ -27,17 +27,18 @@
#include "platform_config.h" #include "platform_config.h"
#include "telnet.h" #include "telnet.h"
#include "tools.h" #include "tools.h"
#include "improv.h"
#include "messaging.h" #include "messaging.h"
#include "network_manager.h"
#include "config.h" #include "config.h"
#include "improv_console.h"
static pthread_t thread_console; static pthread_t thread_console;
static void * console_thread(); static void * console_thread();
void console_start(); void console_start();
static const char * TAG = "console"; static const char * TAG = "console";
extern bool bypass_network_manager; extern bool bypass_network_manager;
extern void register_squeezelite(); extern void register_squeezelite();
bool improv=false;
static EXT_RAM_ATTR QueueHandle_t uart_queue; static EXT_RAM_ATTR QueueHandle_t uart_queue;
static EXT_RAM_ATTR struct { static EXT_RAM_ATTR struct {
uint8_t _buf[512]; uint8_t _buf[512];
@@ -249,31 +250,77 @@ void process_autoexec(){
} }
} }
#define BUFFERDEBUG 0
static ssize_t stdin_read(int fd, void* data, size_t size) { static ssize_t stdin_read(int fd, void* data, size_t size) {
size_t bytes = -1; size_t bytes = -1;
uint32_t improv_next_timeout = 0;
if(!improv_buffer_data){
improv_buffer_data = (uint8_t * )malloc_init_external(improv_buffer_size);
memset(improv_buffer_data,0x00,improv_buffer_size);
improv_set_send_callback(improv_send_callback);
}
size_t read_size = 0;
while (1) { while (1) {
QueueSetMemberHandle_t activated = xQueueSelectFromSet(stdin_redir.queue_set, portMAX_DELAY); QueueSetMemberHandle_t activated = xQueueSelectFromSet(stdin_redir.queue_set, improv_delay);
uint32_t now = esp_timer_get_time() / 1000; uart_event_t event;
if (activated == uart_queue) { xQueueReceive(uart_queue, &event, 0);
uart_event_t event; //esp_rom_printf(".");
//esp_rom_printf("\n********Activated: 0x%6X, type: %d\n",(unsigned int)activated, event.type);
xQueueReceive(uart_queue, &event, 0);
if (event.type == UART_DATA) {
if (event.type == UART_DATA) { //esp_rom_printf("uart.");
bytes = uart_read_bytes(CONFIG_ESP_CONSOLE_UART_NUM, data, size < event.size ? size : event.size, 0); #if BUFFERDEBUG
// we have to do our own line ending translation here printf("\n********event: %d, read: %d\n", event.size,bytes);
for (int i = 0; i < bytes; i++) if (((char*)data)[i] == '\r') ((char*)data)[i] = '\n'; #endif
break; bytes = uart_read_bytes(CONFIG_ESP_CONSOLE_UART_NUM, improv_buffer_data+improv_buffer_len,1, 0);
} while(bytes>0){
} else if (xRingbufferCanRead(stdin_redir.handle, activated)) { //esp_rom_printf("rb[%c]\n",*(bufferdata+buffer_len));
improv_buffer_len++;
if(!improv_parse_serial_byte(improv_buffer_len-1,improv_buffer_data[improv_buffer_len-1],improv_buffer_data,on_improv_command,on_improv_error)){
#if BUFFERDEBUG
//dump_buffer("improv invalid",(const char *)bufferdata,buffer_len);
#endif
if(improv_buffer_len>0){
//esp_rom_printf("not improv\n");
xRingbufferSend(stdin_redir.handle, improv_buffer_data,improv_buffer_len, pdMS_TO_TICKS(100));
}
improv_buffer_len=0;
}
bytes = uart_read_bytes(CONFIG_ESP_CONSOLE_UART_NUM, improv_buffer_data+improv_buffer_len,1, 0);
}
improv_next_timeout = esp_timer_get_time() / 1000+improv_timeout_ms;
#if BUFFERDEBUG
//dump_buffer("after event",(const char *)bufferdata,buffer_len);
#endif
}
if ( xRingbufferCanRead(stdin_redir.handle, activated)) {
//esp_rom_printf("\n********rbr!\n");
char *p = xRingbufferReceiveUpTo(stdin_redir.handle, &bytes, 0, size); char *p = xRingbufferReceiveUpTo(stdin_redir.handle, &bytes, 0, size);
// we might receive strings, replace null by \n // we might receive strings, replace null by \n
#if BUFFERDEBUG
//dump_buffer("Ringbuf read",p,bytes);
#endif
for (int i = 0; i < bytes; i++) if (p[i] == '\0' || p[i] == '\r') p[i] = '\n'; for (int i = 0; i < bytes; i++) if (p[i] == '\0' || p[i] == '\r') p[i] = '\n';
memcpy(data, p, bytes); memcpy(data, p, bytes);
vRingbufferReturnItem(stdin_redir.handle, p); vRingbufferReturnItem(stdin_redir.handle, p);
break; break;
} }
if(improv_buffer_len>0){
improv_delay = improv_timeout_tick;
}
else {
improv_delay = portMAX_DELAY;
}
if (now > improv_next_timeout && improv_buffer_len > 0) {
#if BUFFERDEBUG
//dump_buffer("improv timeout",(const char *)bufferdata,buffer_len);
#endif
//esp_rom_printf("\n********QueueSent\n");
xRingbufferSendFromISR(stdin_redir.handle, improv_buffer_data, improv_buffer_len, pdMS_TO_TICKS(100));
improv_buffer_len = 0;
}
} }
return bytes; return bytes;
@@ -304,6 +351,9 @@ void initialize_console() {
/* re-direct stdin to our own driver so we can gather data from various sources */ /* re-direct stdin to our own driver so we can gather data from various sources */
stdin_redir.queue_set = xQueueCreateSet(2); stdin_redir.queue_set = xQueueCreateSet(2);
if(!stdin_redir.queue_set){
ESP_LOGE(TAG,"Serial event queue set could not be created");
}
stdin_redir.handle = xRingbufferCreateStatic(sizeof(stdin_redir._buf), RINGBUF_TYPE_BYTEBUF, stdin_redir._buf, &stdin_redir._ringbuf); stdin_redir.handle = xRingbufferCreateStatic(sizeof(stdin_redir._buf), RINGBUF_TYPE_BYTEBUF, stdin_redir._buf, &stdin_redir._ringbuf);
xRingbufferAddToQueueSetRead(stdin_redir.handle, stdin_redir.queue_set); xRingbufferAddToQueueSetRead(stdin_redir.handle, stdin_redir.queue_set);
xQueueAddToSet(uart_queue, stdin_redir.queue_set); xQueueAddToSet(uart_queue, stdin_redir.queue_set);
@@ -312,7 +362,6 @@ void initialize_console() {
vfs.flags = ESP_VFS_FLAG_DEFAULT; vfs.flags = ESP_VFS_FLAG_DEFAULT;
vfs.open = stdin_dummy; vfs.open = stdin_dummy;
vfs.read = stdin_read; vfs.read = stdin_read;
ESP_ERROR_CHECK(esp_vfs_register("/dev/console", &vfs, NULL)); ESP_ERROR_CHECK(esp_vfs_register("/dev/console", &vfs, NULL));
freopen("/dev/console", "r", stdin); freopen("/dev/console", "r", stdin);
@@ -352,6 +401,7 @@ bool console_push(const char *data, size_t size) {
void console_start() { void console_start() {
/* we always run console b/c telnet sends commands to stdin */ /* we always run console b/c telnet sends commands to stdin */
initialize_console(); initialize_console();
improv_console_init();
/* Register commands */ /* Register commands */
MEMTRACE_PRINT_DELTA_MESSAGE("Registering help command"); MEMTRACE_PRINT_DELTA_MESSAGE("Registering help command");
@@ -449,6 +499,7 @@ static esp_err_t run_command(char * line){
} }
static void * console_thread() { static void * console_thread() {
if(!is_recovery_running){ if(!is_recovery_running){
MEMTRACE_PRINT_DELTA_MESSAGE("Running autoexec"); MEMTRACE_PRINT_DELTA_MESSAGE("Running autoexec");
process_autoexec(); process_autoexec();

View File

@@ -50,7 +50,6 @@ static const dmap_field dmap_fields[] = {
{ "abar", DMAP_DICT, DMAP_STR, "daap.browseartistlisting" }, { "abar", DMAP_DICT, DMAP_STR, "daap.browseartistlisting" },
{ "abcp", DMAP_DICT, DMAP_STR, "daap.browsecomposerlisting" }, { "abcp", DMAP_DICT, DMAP_STR, "daap.browsecomposerlisting" },
{ "abgn", DMAP_DICT, DMAP_STR, "daap.browsegenrelisting" }, { "abgn", DMAP_DICT, DMAP_STR, "daap.browsegenrelisting" },
#ifdef DMAP_FULL
{ "abpl", DMAP_UINT, 0, "daap.baseplaylist" }, { "abpl", DMAP_UINT, 0, "daap.baseplaylist" },
{ "abro", DMAP_DICT, 0, "daap.databasebrowse" }, { "abro", DMAP_DICT, 0, "daap.databasebrowse" },
{ "adbs", DMAP_DICT, 0, "daap.databasesongs" }, { "adbs", DMAP_DICT, 0, "daap.databasesongs" },
@@ -257,12 +256,10 @@ static const dmap_field dmap_fields[] = {
{ "meia", DMAP_UINT, 0, "dmap.itemdateadded" }, { "meia", DMAP_UINT, 0, "dmap.itemdateadded" },
{ "meip", DMAP_UINT, 0, "dmap.itemdateplayed" }, { "meip", DMAP_UINT, 0, "dmap.itemdateplayed" },
{ "mext", DMAP_UINT, 0, "dmap.objectextradata" }, { "mext", DMAP_UINT, 0, "dmap.objectextradata" },
#endif
{ "miid", DMAP_UINT, 0, "dmap.itemid" }, { "miid", DMAP_UINT, 0, "dmap.itemid" },
{ "mikd", DMAP_UINT, 0, "dmap.itemkind" }, { "mikd", DMAP_UINT, 0, "dmap.itemkind" },
{ "mimc", DMAP_UINT, 0, "dmap.itemcount" }, { "mimc", DMAP_UINT, 0, "dmap.itemcount" },
{ "minm", DMAP_STR, 0, "dmap.itemname" }, { "minm", DMAP_STR, 0, "dmap.itemname" },
#ifdef DMAP_FULL
{ "mlcl", DMAP_DICT, DMAP_DICT, "dmap.listing" }, { "mlcl", DMAP_DICT, DMAP_DICT, "dmap.listing" },
{ "mlid", DMAP_UINT, 0, "dmap.sessionid" }, { "mlid", DMAP_UINT, 0, "dmap.sessionid" },
{ "mlit", DMAP_ITEM, 0, "dmap.listingitem" }, { "mlit", DMAP_ITEM, 0, "dmap.listingitem" },
@@ -317,7 +314,6 @@ static const dmap_field dmap_fields[] = {
{ "prat", DMAP_UINT, 0, "dpap.imagerating" }, { "prat", DMAP_UINT, 0, "dpap.imagerating" },
{ "pret", DMAP_DICT, 0, "dpap.retryids" }, { "pret", DMAP_DICT, 0, "dpap.retryids" },
{ "pwth", DMAP_UINT, 0, "dpap.imagepixelwidth" } { "pwth", DMAP_UINT, 0, "dpap.imagepixelwidth" }
#endif
}; };
static const size_t dmap_field_count = sizeof(dmap_fields) / sizeof(dmap_field); static const size_t dmap_field_count = sizeof(dmap_fields) / sizeof(dmap_field);

View File

@@ -959,7 +959,7 @@ static int base64_decode(const char *str, void *data)
*q++ = (val >> 8) & 0xff; *q++ = (val >> 8) & 0xff;
if (marker < 1) if (marker < 1)
*q++ = val & 0xff; *q++ = val & 0xff;
} }
return q - (unsigned char *) data; return q - (unsigned char *) data;
} }

View File

@@ -90,7 +90,7 @@ const static actrls_t controls = {
NULL, NULL, // rew, fwd NULL, NULL, // rew, fwd
raop_prev, raop_next, // prev, next raop_prev, raop_next, // prev, next
NULL, NULL, NULL, NULL, // left, right, up, down NULL, NULL, NULL, NULL, // left, right, up, down
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // pre1-10 NULL, NULL, NULL, NULL, NULL, NULL, // pre1-6
raop_volume_down, raop_volume_up, raop_toggle// knob left, knob_right, knob push raop_volume_down, raop_volume_up, raop_toggle// knob left, knob_right, knob push
}; };

View File

@@ -71,8 +71,7 @@ static log_level *loglevel = &raop_loglevel;
//#define __RTP_STORE //#define __RTP_STORE
// default buffer size // default buffer size
#define BUFFER_FRAMES_MAX ((RAOP_SAMPLE_RATE * 10) / 352 ) #define BUFFER_FRAMES ( (150 * RAOP_SAMPLE_RATE * 2) / (352 * 100) )
#define BUFFER_FRAMES_MIN ( (150 * RAOP_SAMPLE_RATE * 2) / (352 * 100) )
#define MAX_PACKET 1408 #define MAX_PACKET 1408
#define MIN_LATENCY 11025 #define MIN_LATENCY 11025
#define MAX_LATENCY ( (120 * RAOP_SAMPLE_RATE * 2) / 100 ) #define MAX_LATENCY ( (120 * RAOP_SAMPLE_RATE * 2) / 100 )
@@ -87,15 +86,14 @@ static log_level *loglevel = &raop_loglevel;
enum { DATA = 0, CONTROL, TIMING }; enum { DATA = 0, CONTROL, TIMING };
static const u8_t silence_frame[MAX_PACKET] = { 0 }; static const u8_t silence_frame[MAX_PACKET] = { 0 };
uint32_t buffer_frames = ((150 * RAOP_SAMPLE_RATE * 2) / (352 * 100));
typedef u16_t seq_t; typedef u16_t seq_t;
typedef struct __attribute__((__packed__)) audio_buffer_entry { // decoded audio packets typedef struct audio_buffer_entry { // decoded audio packets
int ready;
u32_t rtptime, last_resend; u32_t rtptime, last_resend;
s16_t *data; s16_t *data;
u16_t len; int len;
u8_t ready; bool allocated;
u8_t allocated;
} abuf_t; } abuf_t;
typedef struct rtp_s { typedef struct rtp_s {
@@ -135,7 +133,7 @@ typedef struct rtp_s {
u32_t resent_req, resent_rec; // total resent + recovered frames u32_t resent_req, resent_rec; // total resent + recovered frames
u32_t silent_frames; // total silence frames u32_t silent_frames; // total silence frames
u32_t discarded; u32_t discarded;
abuf_t audio_buffer[BUFFER_FRAMES_MAX]; abuf_t audio_buffer[BUFFER_FRAMES];
seq_t ab_read, ab_write; seq_t ab_read, ab_write;
pthread_mutex_t ab_mutex; pthread_mutex_t ab_mutex;
#ifdef WIN32 #ifdef WIN32
@@ -154,7 +152,7 @@ typedef struct rtp_s {
} rtp_t; } rtp_t;
#define BUFIDX(seqno) ((seq_t)(seqno) % buffer_frames) #define BUFIDX(seqno) ((seq_t)(seqno) % BUFFER_FRAMES)
static void buffer_alloc(abuf_t *audio_buffer, int size, uint8_t *buf, size_t buf_size); static void buffer_alloc(abuf_t *audio_buffer, int size, uint8_t *buf, size_t buf_size);
static void buffer_release(abuf_t *audio_buffer); static void buffer_release(abuf_t *audio_buffer);
static void buffer_reset(abuf_t *audio_buffer); static void buffer_reset(abuf_t *audio_buffer);
@@ -375,27 +373,25 @@ void rtp_record(rtp_t *ctx, unsigned short seqno, unsigned rtptime) {
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static void buffer_alloc(abuf_t *audio_buffer, int size, uint8_t *buf, size_t buf_size) { static void buffer_alloc(abuf_t *audio_buffer, int size, uint8_t *buf, size_t buf_size) {
for (buffer_frames = 0; buf && buf_size >= size && buffer_frames < BUFFER_FRAMES_MAX; buffer_frames++) { int i;
audio_buffer[buffer_frames].data = (s16_t*) buf; for (i = 0; i < BUFFER_FRAMES; i++) {
audio_buffer[buffer_frames].allocated = 0; if (buf && buf_size >= size) {
audio_buffer[buffer_frames].ready = 0; audio_buffer[i].data = (s16_t*) buf;
buf += size; audio_buffer[i].allocated = false;
buf_size -= size; buf += size;
} buf_size -= size;
} else {
LOG_INFO("allocated %d buffers (min=%d) from buffer of %zu bytes", buffer_frames, BUFFER_FRAMES_MIN, buf_size + buffer_frames * size); audio_buffer[i].allocated = true;
audio_buffer[i].data = malloc(size);
for(; buffer_frames < BUFFER_FRAMES_MIN; buffer_frames++) { }
audio_buffer[buffer_frames].data = malloc(size); audio_buffer[i].ready = 0;
audio_buffer[buffer_frames].allocated = 1;
audio_buffer[buffer_frames].ready = 0;
} }
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static void buffer_release(abuf_t *audio_buffer) { static void buffer_release(abuf_t *audio_buffer) {
int i; int i;
for (i = 0; i < buffer_frames; i++) { for (i = 0; i < BUFFER_FRAMES; i++) {
if (audio_buffer[i].allocated) free(audio_buffer[i].data); if (audio_buffer[i].allocated) free(audio_buffer[i].data);
} }
} }
@@ -403,7 +399,7 @@ static void buffer_release(abuf_t *audio_buffer) {
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static void buffer_reset(abuf_t *audio_buffer) { static void buffer_reset(abuf_t *audio_buffer) {
int i; int i;
for (i = 0; i < buffer_frames; i++) audio_buffer[i].ready = 0; for (i = 0; i < BUFFER_FRAMES; i++) audio_buffer[i].ready = 0;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@@ -415,7 +411,7 @@ static int seq_order(seq_t a, seq_t b) {
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static void alac_decode(rtp_t *ctx, s16_t *dest, char *buf, int len, u16_t *outsize) { static void alac_decode(rtp_t *ctx, s16_t *dest, char *buf, int len, int *outsize) {
unsigned char iv[16]; unsigned char iv[16];
int aeslen; int aeslen;
assert(len<=MAX_PACKET); assert(len<=MAX_PACKET);
@@ -807,7 +803,7 @@ static bool rtp_request_resend(rtp_t *ctx, seq_t first, seq_t last) {
static bool rtp_request_resend(rtp_t *ctx, seq_t first, seq_t last) { static bool rtp_request_resend(rtp_t *ctx, seq_t first, seq_t last) {
unsigned char req[8]; // *not* a standard RTCP NACK unsigned char req[8]; // *not* a standard RTCP NACK
// do not request silly ranges (happens in case of network large blackouts) // do not request silly ranges (happens in case of network large blackouts)
if (seq_order(last, first) || last - first > BUFFER_FRAMES / 2) return false; if (seq_order(last, first) || last - first > BUFFER_FRAMES / 2) return false;
ctx->resent_req += (seq_t) (last - first) + 1; ctx->resent_req += (seq_t) (last - first) + 1;

View File

@@ -60,7 +60,7 @@ static const actrls_config_map_t actrls_config_map[] =
static const char * actrls_action_s[ ] = { EP(ACTRLS_POWER),EP(ACTRLS_VOLUP),EP(ACTRLS_VOLDOWN),EP(ACTRLS_TOGGLE),EP(ACTRLS_PLAY), static const char * actrls_action_s[ ] = { EP(ACTRLS_POWER),EP(ACTRLS_VOLUP),EP(ACTRLS_VOLDOWN),EP(ACTRLS_TOGGLE),EP(ACTRLS_PLAY),
EP(ACTRLS_PAUSE),EP(ACTRLS_STOP),EP(ACTRLS_REW),EP(ACTRLS_FWD),EP(ACTRLS_PREV),EP(ACTRLS_NEXT), EP(ACTRLS_PAUSE),EP(ACTRLS_STOP),EP(ACTRLS_REW),EP(ACTRLS_FWD),EP(ACTRLS_PREV),EP(ACTRLS_NEXT),
EP(BCTRLS_UP),EP(BCTRLS_DOWN),EP(BCTRLS_LEFT),EP(BCTRLS_RIGHT), EP(BCTRLS_UP),EP(BCTRLS_DOWN),EP(BCTRLS_LEFT),EP(BCTRLS_RIGHT),
EP(BCTRLS_PS0),EP(BCTRLS_PS1),EP(BCTRLS_PS2),EP(BCTRLS_PS3),EP(BCTRLS_PS4),EP(BCTRLS_PS5),EP(BCTRLS_PS6),EP(BCTRLS_PS7),EP(BCTRLS_PS8),EP(BCTRLS_PS9), EP(BCTRLS_PS1),EP(BCTRLS_PS2),EP(BCTRLS_PS3),EP(BCTRLS_PS4),EP(BCTRLS_PS5),EP(BCTRLS_PS6),
EP(KNOB_LEFT),EP(KNOB_RIGHT),EP(KNOB_PUSH), EP(KNOB_LEFT),EP(KNOB_RIGHT),EP(KNOB_PUSH),
""} ; ""} ;

View File

@@ -14,7 +14,7 @@
typedef enum { ACTRLS_NONE = -1, ACTRLS_POWER,ACTRLS_VOLUP, ACTRLS_VOLDOWN, ACTRLS_TOGGLE, ACTRLS_PLAY, typedef enum { ACTRLS_NONE = -1, ACTRLS_POWER,ACTRLS_VOLUP, ACTRLS_VOLDOWN, ACTRLS_TOGGLE, ACTRLS_PLAY,
ACTRLS_PAUSE, ACTRLS_STOP, ACTRLS_REW, ACTRLS_FWD, ACTRLS_PREV, ACTRLS_NEXT, ACTRLS_PAUSE, ACTRLS_STOP, ACTRLS_REW, ACTRLS_FWD, ACTRLS_PREV, ACTRLS_NEXT,
BCTRLS_UP, BCTRLS_DOWN, BCTRLS_LEFT, BCTRLS_RIGHT, BCTRLS_UP, BCTRLS_DOWN, BCTRLS_LEFT, BCTRLS_RIGHT,
BCTRLS_PS0,BCTRLS_PS1,BCTRLS_PS2,BCTRLS_PS3,BCTRLS_PS4,BCTRLS_PS5,BCTRLS_PS6,BCTRLS_PS7,BCTRLS_PS8,BCTRLS_PS9, BCTRLS_PS1,BCTRLS_PS2,BCTRLS_PS3,BCTRLS_PS4,BCTRLS_PS5,BCTRLS_PS6,
KNOB_LEFT, KNOB_RIGHT, KNOB_PUSH, KNOB_LEFT, KNOB_RIGHT, KNOB_PUSH,
ACTRLS_REMAP, ACTRLS_MAX ACTRLS_REMAP, ACTRLS_MAX
} actrls_action_e; } actrls_action_e;

View File

@@ -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 // 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); if (SW != -1) button_create(id, SW, BUTTON_LOW, true, 0, rotary_button_handler, long_press, -1);
ESP_LOGI(TAG, "Created rotary encoder A:%d B:%d, SW:%d", A, B, SW); ESP_LOGI(TAG, "Creating rotary encoder A:%d B:%d, SW:%d", A, B, SW);
return true; return true;
} }
@@ -432,7 +432,5 @@ bool create_infrared(int gpio, infrared_handler handler) {
common_task_init(); common_task_init();
xRingbufferAddToQueueSetRead(infrared.rb, common_queue_set); xRingbufferAddToQueueSetRead(infrared.rb, common_queue_set);
ESP_LOGI(TAG, "Created infrared receiver using GPIO %u", gpio);
return (infrared.rb != NULL); return (infrared.rb != NULL);
} }

View File

@@ -219,23 +219,18 @@ esp_err_t messaging_post_to_queue(messaging_handle_t subscriber_handle, single_m
} }
return ESP_LOG_DEBUG; return ESP_LOG_DEBUG;
} }
void messaging_post_message(messaging_types type,messaging_classes msg_class, const char *fmt, ...){ void messaging_post_message(messaging_types type,messaging_classes msg_class, const char *fmt, ...){
va_list va;
va_start(va, fmt);
vmessaging_post_message(type, msg_class, fmt, va);
va_end(va);
}
void vmessaging_post_message(messaging_types type,messaging_classes msg_class, const char *fmt, va_list va){
single_message_t * message=NULL; single_message_t * message=NULL;
size_t msg_size=0; size_t msg_size=0;
size_t ln =0; size_t ln =0;
messaging_list_t * cur=&top; messaging_list_t * cur=&top;
va_list va;
va_start(va, fmt);
ln = vsnprintf(NULL, 0, fmt, va)+1; ln = vsnprintf(NULL, 0, fmt, va)+1;
msg_size = sizeof(single_message_t)+ln; msg_size = sizeof(single_message_t)+ln;
message = (single_message_t *)malloc_init_external(msg_size); message = (single_message_t *)malloc_init_external(msg_size);
vsprintf(message->message, fmt, va); vsprintf(message->message, fmt, va);
va_end(va);
message->msg_size = msg_size; message->msg_size = msg_size;
message->type = type; message->type = type;
message->msg_class = msg_class; message->msg_class = msg_class;

View File

@@ -34,7 +34,6 @@ cJSON * messaging_retrieve_messages(RingbufHandle_t buf_handle);
messaging_handle_t messaging_register_subscriber(uint8_t max_count, char * name); messaging_handle_t messaging_register_subscriber(uint8_t max_count, char * name);
esp_err_t messaging_post_to_queue(messaging_handle_t subscriber_handle, single_message_t * message, size_t message_size); esp_err_t messaging_post_to_queue(messaging_handle_t subscriber_handle, single_message_t * message, size_t message_size);
void messaging_post_message(messaging_types type,messaging_classes msg_class, const char * fmt, ...); void messaging_post_message(messaging_types type,messaging_classes msg_class, const char * fmt, ...);
void vmessaging_post_message(messaging_types type,messaging_classes msg_class, const char *fmt, va_list va);
cJSON * messaging_retrieve_messages(RingbufHandle_t buf_handle); cJSON * messaging_retrieve_messages(RingbufHandle_t buf_handle);
single_message_t * messaging_retrieve_message(RingbufHandle_t buf_handle); single_message_t * messaging_retrieve_message(RingbufHandle_t buf_handle);
void log_send_messaging(messaging_types msgtype,const char *fmt, ...); void log_send_messaging(messaging_types msgtype,const char *fmt, ...);

View File

@@ -1,28 +1,20 @@
# this must be set *before* idf_component_register # this must be set *before* idf_component_register
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 17)
idf_component_register( idf_component_register(
SRC_DIRS . SRC_DIRS .
INCLUDE_DIRS . "cspot/include" INCLUDE_DIRS . "cspot/include" "cspot/bell/include"
PRIV_REQUIRES mbedtls mdns nvs_flash platform_config services esp_http_server tools codecs PRIV_REQUIRES mbedtls mdns nvs_flash platform_config services esp_http_server tools codecs
LDFRAGMENTS "linker.lf" LDFRAGMENTS "linker.lf"
) )
#INCLUDE_DIRS . "cspot/include" "cspot/bell/include"
add_definitions(-Wno-unused-variable -Wno-unused-const-variable -Wchar-subscripts -Wunused-label -Wmaybe-uninitialized -Wmisleading-indentation) add_definitions(-Wno-unused-variable -Wno-unused-const-variable -Wchar-subscripts -Wunused-label -Wmaybe-uninitialized -Wmisleading-indentation)
set(BELL_DISABLE_CODECS ON) set(BELL_DISABLE_CODECS ON)
set(BELL_DISABLE_SINKS ON) set(BELL_DISABLE_SINKS ON)
set(BELL_DISABLE_FMT ON)
set(BELL_DISABLE_REGEX ON)
set(BELL_ONLY_CJSON ON)
set(BELL_DISABLE_MQTT ON)
set(BELL_DISABLE_WEBSERVER ON)
set(CSPOT_TARGET_ESP32 ON) set(CSPOT_TARGET_ESP32 ON)
# becase CMake is so broken, the cache set below overrides a normal "set" for the first build
# because CMake is so broken, the cache set below overrides a normal "set" for the first build set(BELL_EXTERNAL_TREMOR "idf::codecs" CACHE STRING "provide own codecs")
set(BELL_EXTERNAL_VORBIS "idf::codecs" CACHE STRING "provide own codecs")
set(BELL_EXTERNAL_CJSON "idf::json" CACHE STRING "provide own CJSON") set(BELL_EXTERNAL_CJSON "idf::json" CACHE STRING "provide own CJSON")
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/cspot ${CMAKE_CURRENT_BINARY_DIR}/cspot) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/cspot ${CMAKE_CURRENT_BINARY_DIR}/cspot)

View File

@@ -1,410 +1,390 @@
/* /*
* This software is released under the MIT License. * This software is released under the MIT License.
* https://opensource.org/licenses/MIT * https://opensource.org/licenses/MIT
* *
*/ */
#include <string> #include <stdio.h>
#include <streambuf> #include <string.h>
#include <Session.h>
#include <PlainConnection.h>
#include <memory>
#include <vector>
#include <iostream>
#include <inttypes.h> #include <inttypes.h>
#include <fstream> #include "sdkconfig.h"
#include <stdarg.h> #include "freertos/FreeRTOS.h"
#include <ApResolve.h> #include "freertos/task.h"
#include "esp_system.h"
#include "BellTask.h" #include "esp_wifi.h"
#include "MDNSService.h" #include "esp_event.h"
#include "TrackPlayer.h" #include "esp_log.h"
#include "CSpotContext.h"
#include "SpircHandler.h"
#include "LoginBlob.h"
#include "CentralAudioBuffer.h"
#include "Logger.h"
#include "Utils.h"
#include "esp_http_server.h" #include "esp_http_server.h"
#include "cspot_private.h"
#include "cspot_sink.h" #include <ConstantParameters.h>
#include <Session.h>
#include <SpircController.h>
#include <MercuryManager.h>
#include <ZeroconfAuthenticator.h>
#include <ApResolve.h>
#include <HTTPServer.h>
#include "ConfigJSON.h"
#include "Logger.h"
#include "platform_config.h" #include "platform_config.h"
#include "tools.h" #include "tools.h"
#include "cspot_private.h"
static class cspotPlayer *player; #include "cspot_sink.h"
#include "Shim.h"
/****************************************************************************************
* Player's main class & task
*/
class cspotPlayer : public bell::Task {
private:
std::string name;
bell::WrappedSemaphore clientConnected;
std::atomic<bool> isPaused, isConnected;
int startOffset, volume = 0, bitrate = 160;
httpd_handle_t serverHandle;
int serverPort;
cspot_cmd_cb_t cmdHandler;
cspot_data_cb_t dataHandler;
std::string lastTrackId;
std::shared_ptr<cspot::LoginBlob> blob;
std::unique_ptr<cspot::SpircHandler> spirc;
void eventHandler(std::unique_ptr<cspot::SpircHandler::Event> event);
void trackHandler(void);
size_t pcmWrite(uint8_t *pcm, size_t bytes, std::string_view trackId);
void runTask();
public:
typedef enum {TRACK_INIT, TRACK_NOTIFY, TRACK_STREAM, TRACK_END} TrackStatus;
std::atomic<TrackStatus> trackStatus = TRACK_INIT;
cspotPlayer(const char*, httpd_handle_t, int, cspot_cmd_cb_t, cspot_data_cb_t);
esp_err_t handleGET(httpd_req_t *request);
esp_err_t handlePOST(httpd_req_t *request);
void command(cspot_event_t event);
};
cspotPlayer::cspotPlayer(const char* name, httpd_handle_t server, int port, cspot_cmd_cb_t cmdHandler, cspot_data_cb_t dataHandler) :
bell::Task("playerInstance", 32 * 1024, 0, 0),
serverHandle(server), serverPort(port),
cmdHandler(cmdHandler), dataHandler(dataHandler) {
cJSON *item, *config = config_alloc_get_cjson("cspot_config");
if ((item = cJSON_GetObjectItem(config, "volume")) != NULL) volume = item->valueint;
if ((item = cJSON_GetObjectItem(config, "bitrate")) != NULL) bitrate = item->valueint;
if ((item = cJSON_GetObjectItem(config, "deviceName") ) != NULL) this->name = item->valuestring;
else this->name = name;
cJSON_Delete(config);
if (bitrate != 96 && bitrate != 160 && bitrate != 320) bitrate = 160;
}
size_t cspotPlayer::pcmWrite(uint8_t *pcm, size_t bytes, std::string_view trackId) {
if (lastTrackId != trackId) {
CSPOT_LOG(info, "new track started <%s> => <%s>", lastTrackId.c_str(), trackId.data());
lastTrackId = trackId;
trackHandler();
}
dataHandler(pcm, bytes);
return bytes;
}
extern "C" { extern "C" {
static esp_err_t handleGET(httpd_req_t *request) { httpd_handle_t get_http_server(int *port);
return player->handleGET(request); static esp_err_t handlerWrapper(httpd_req_t *req);
} };
static esp_err_t handlePOST(httpd_req_t *request) { #define CSPOT_STACK_SIZE (8*1024)
return player->handlePOST(request);
}
}
esp_err_t cspotPlayer::handleGET(httpd_req_t *request) { static const char *TAG = "cspot";
std::string body = this->blob->buildZeroconfInfo();
if (body.size() == 0) { // using a global is pretty ugly, but it's easier with all Lambda below
CSPOT_LOG(info, "cspot empty blob's body on GET"); static EXT_RAM_ATTR struct cspot_s {
return ESP_ERR_HTTPD_INVALID_REQ; char name[32];
} cspot_cmd_cb_t cHandler;
cspot_data_cb_t dHandler;
TaskHandle_t TaskHandle;
std::shared_ptr<LoginBlob> blob;
} cspot;
httpd_resp_set_hdr(request, "Content-type", "application/json"); std::shared_ptr<ConfigJSON> configMan;
httpd_resp_send(request, body.c_str(), body.size()); std::shared_ptr<NVSFile> file;
std::shared_ptr<MercuryManager> mercuryManager;
std::shared_ptr<SpircController> spircController;
return ESP_OK; /****************************************************************************************
} * Main task (could it be deleted after spirc has started?)
*/
static void cspotTask(void *pvParameters) {
char configName[] = "cspot_config";
std::string jsonConfig;
// Config file
file = std::make_shared<NVSFile>();
configMan = std::make_shared<ConfigJSON>(configName, file);
// We might have no config at all
if (!file->readFile(configName, jsonConfig) || !jsonConfig.length()) {
ESP_LOGW(TAG, "Cannot load config, using default");
configMan->deviceName = cspot.name;
configMan->format = AudioFormat_OGG_VORBIS_160;
configMan->volume = 32767;
esp_err_t cspotPlayer::handlePOST(httpd_req_t *request) { configMan->save();
cJSON* response= cJSON_CreateObject(); }
//see https://developer.spotify.com/documentation/commercial-hardware/implementation/guides/zeroconf
// safely load config now
configMan->load();
if (!configMan->deviceName.length()) configMan->deviceName = cspot.name;
ESP_LOGI(TAG, "Started CSpot with %s (bitrate %d)", configMan->deviceName.c_str(), configMan->format == AudioFormat_OGG_VORBIS_320 ? 320 : (configMan->format == AudioFormat_OGG_VORBIS_160 ? 160 : 96));
if (cmdHandler(CSPOT_BUSY)) { // All we do here is notify the task to start the mercury loop
cJSON_AddNumberToObject(response, "status", 101); auto createPlayerCallback = [](std::shared_ptr<LoginBlob> blob) {
cJSON_AddStringToObject(response, "statusString", "OK"); // TODO: handle/refuse that another user takes ownership
cJSON_AddNumberToObject(response, "spotifyError", 0); cspot.blob = blob;
xTaskNotifyGive(cspot.TaskHandle);
};
// get body if any (add '\0' at the end if used as string) int port;
if (request->content_len) { httpd_handle_t server = get_http_server(&port);
char* body = (char*) calloc(1, request->content_len + 1); auto httpServer = std::make_shared<ShimHTTPServer>(server, port);
int size = httpd_req_recv(request, body, request->content_len);
// I know this is very crude and unsafe... auto authenticator = std::make_shared<ZeroconfAuthenticator>(createPlayerCallback, httpServer);
url_decode(body); authenticator->registerHandlers();
char *key = strtok(body, "&");
std::map<std::string, std::string> queryMap; // wait to be notified and have a mercury loop
while (1) {
ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
while (key) { auto session = std::make_unique<Session>();
char *value = strchr(key, '='); session->connectWithRandomAp();
*value++ = '\0'; auto token = session->authenticate(cspot.blob);
queryMap[key] = value;
key = strtok(NULL, "&"); ESP_LOGI(TAG, "Creating Spotify (using CSpot) player");
// Auth successful
if (token.size() > 0 && cspot.cHandler(CSPOT_SETUP, 44100)) {
auto audioSink = std::make_shared<ShimAudioSink>();
mercuryManager = std::make_shared<MercuryManager>(std::move(session));
mercuryManager->startTask();
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);
cspot.cHandler(CSPOT_TRACK, 44100, track.duration, track.artist.c_str(),
track.album.c_str(), track.name.c_str(), track.imageUrl.c_str());
break;
}
case CSpotEventType::PLAY_PAUSE: {
bool isPaused = std::get<bool>(event.data);
if (isPaused) cspot.cHandler(CSPOT_PAUSE);
else cspot.cHandler(CSPOT_PLAY, false);
break;
}
case CSpotEventType::PLAYBACK_START:
cspot.cHandler(CSPOT_PLAY, (int) std::get<bool>(event.data));
break;
case CSpotEventType::LOAD:
cspot.cHandler(CSPOT_LOAD, std::get<int>(event.data), -1);
break;
case CSpotEventType::SEEK:
cspot.cHandler(CSPOT_SEEK, std::get<int>(event.data));
break;
case CSpotEventType::DISC:
cspot.cHandler(CSPOT_DISC);
spircController->stopPlayer();
mercuryManager->stop();
break;
case CSpotEventType::PREV:
case CSpotEventType::NEXT:
cspot.cHandler(CSPOT_FLUSH);
break;
/*
// we use volume from sink which is a 16 bits value
case CSpotEventType::VOLUME: {
int volume = std::get<int>(event.data);
cspot.cHandler(CSPOT_VOLUME, volume);
ESP_LOGW(TAG, "cspot volume : %d", volume);
break;
}
*/
default:
break;
}
});
// 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();
}; };
free(body); mercuryManager->handleQueue();
// Pass user's credentials to the blob and give the token
blob->loadZeroconfQuery(queryMap);
clientConnected.give();
}
} else {
cJSON_AddNumberToObject(response, "status", 202);
cJSON_AddStringToObject(response, "statusString", "ERROR-LOGIN-FAILED");
cJSON_AddNumberToObject(response, "spotifyError", 0);
CSPOT_LOG(info, "sink is busy, can't accept request"); // release controllers
} mercuryManager.reset();
spircController.reset();
}
char *responseStr = cJSON_PrintUnformatted(response); // release auth blob and flush files
cJSON_Delete(response); cspot.blob.reset();
file->flush();
httpd_resp_set_hdr(request, "Content-type", "application/json");
esp_err_t rc = httpd_resp_send(request, responseStr, strlen(responseStr));
free(responseStr);
return rc; ESP_LOGI(TAG, "Shutting down CSpot player");
}
void cspotPlayer::eventHandler(std::unique_ptr<cspot::SpircHandler::Event> event) {
switch (event->eventType) {
case cspot::SpircHandler::EventType::PLAYBACK_START: {
lastTrackId.clear();
// we are not playing anymore
trackStatus = TRACK_INIT;
// memorize position for when track's beginning will be detected
startOffset = std::get<int>(event->data);
// Spotify servers do not send volume at connection
spirc->setRemoteVolume(volume);
cmdHandler(CSPOT_START, 44100);
CSPOT_LOG(info, "(re)start playing");
break;
}
case cspot::SpircHandler::EventType::PLAY_PAUSE: {
isPaused = std::get<bool>(event->data);
cmdHandler(isPaused ? CSPOT_PAUSE : CSPOT_PLAY);
break;
}
case cspot::SpircHandler::EventType::TRACK_INFO: {
auto trackInfo = std::get<cspot::TrackInfo>(event->data);
cmdHandler(CSPOT_TRACK_INFO, trackInfo.duration, startOffset, trackInfo.artist.c_str(),
trackInfo.album.c_str(), trackInfo.name.c_str(), trackInfo.imageUrl.c_str());
spirc->updatePositionMs(startOffset);
startOffset = 0;
break;
}
case cspot::SpircHandler::EventType::NEXT:
case cspot::SpircHandler::EventType::PREV:
case cspot::SpircHandler::EventType::FLUSH: {
// FLUSH is sent when there is no next, just clean everything
cmdHandler(CSPOT_FLUSH);
break;
}
case cspot::SpircHandler::EventType::DISC:
cmdHandler(CSPOT_DISC);
isConnected = false;
break;
case cspot::SpircHandler::EventType::SEEK: {
cmdHandler(CSPOT_SEEK, std::get<int>(event->data));
break;
}
case cspot::SpircHandler::EventType::DEPLETED:
trackStatus = TRACK_END;
CSPOT_LOG(info, "playlist ended, no track left to play");
break;
case cspot::SpircHandler::EventType::VOLUME:
volume = std::get<int>(event->data);
cmdHandler(CSPOT_VOLUME, volume);
break;
default:
break;
}
}
void cspotPlayer::trackHandler(void) {
// this is just informative
uint32_t remains;
cmdHandler(CSPOT_QUERY_REMAINING, &remains);
CSPOT_LOG(info, "next track will play in %d ms", remains);
// inform sink of track beginning
trackStatus = TRACK_NOTIFY;
cmdHandler(CSPOT_TRACK_MARK);
}
void cspotPlayer::command(cspot_event_t event) {
if (!spirc) return;
// switch...case consume a ton of extra .rodata
switch (event) {
// nextSong/previousSong come back through cspot::event as a FLUSH
case CSPOT_PREV:
spirc->previousSong();
break;
case CSPOT_NEXT:
spirc->nextSong();
break;
// setPause comes back through cspot::event with PLAY/PAUSE
case CSPOT_TOGGLE:
isPaused = !isPaused;
spirc->setPause(isPaused);
break;
case CSPOT_STOP:
case CSPOT_PAUSE:
spirc->setPause(true);
break;
case CSPOT_PLAY:
spirc->setPause(false);
break;
/* Calling spirc->disconnect() might have been logical but it does not
* generate any cspot::event */
case CSPOT_DISC:
cmdHandler(CSPOT_DISC);
isConnected = false;
break;
// spirc->setRemoteVolume does not generate a cspot::event so call cmdHandler
case CSPOT_VOLUME_UP:
volume += (UINT16_MAX / 50);
volume = std::min(volume, UINT16_MAX);
cmdHandler(CSPOT_VOLUME, volume);
spirc->setRemoteVolume(volume);
break;
case CSPOT_VOLUME_DOWN:
volume -= (UINT16_MAX / 50);
volume = std::max(volume, 0);
cmdHandler(CSPOT_VOLUME, volume);
spirc->setRemoteVolume(volume);
break;
default:
break;
} }
}
void cspotPlayer::runTask() { // we should not be here
httpd_uri_t request = { vTaskDelete(NULL);
.uri = "/spotify_info",
.method = HTTP_GET,
.handler = ::handleGET,
.user_ctx = NULL,
};
// register GET and POST handler for built-in server
httpd_register_uri_handler(serverHandle, &request);
request.method = HTTP_POST;
request.handler = ::handlePOST;
httpd_register_uri_handler(serverHandle, &request);
// construct blob for that player
blob = std::make_unique<cspot::LoginBlob>(name);
// Register mdns service, for spotify to find us
bell::MDNSService::registerService( blob->getDeviceName(), "_spotify-connect", "_tcp", "", serverPort,
{ {"VERSION", "1.0"}, {"CPath", "/spotify_info"}, {"Stack", "SP"} });
static int count = 0;
// gone with the wind...
while (1) {
clientConnected.wait();
CSPOT_LOG(info, "Spotify client connected for %s", name.c_str());
auto ctx = cspot::Context::createFromBlob(blob);
if (bitrate == 320) ctx->config.audioFormat = AudioFormat_OGG_VORBIS_320;
else if (bitrate == 96) ctx->config.audioFormat = AudioFormat_OGG_VORBIS_96;
else ctx->config.audioFormat = AudioFormat_OGG_VORBIS_160;
ctx->session->connectWithRandomAp();
auto token = ctx->session->authenticate(blob);
// Auth successful
if (token.size() > 0) {
spirc = std::make_unique<cspot::SpircHandler>(ctx);
isConnected = true;
// set call back to calculate a hash on trackId
spirc->getTrackPlayer()->setDataCallback(
[this](uint8_t* data, size_t bytes, std::string_view trackId) {
return pcmWrite(data, bytes, trackId);
});
// set event (PLAY, VOLUME...) handler
spirc->setEventHandler(
[this](std::unique_ptr<cspot::SpircHandler::Event> event) {
eventHandler(std::move(event));
});
// Start handling mercury messages
ctx->session->startTask();
// set volume at connection
cmdHandler(CSPOT_VOLUME, volume);
// exit when player has stopped (received a DISC)
while (isConnected) {
ctx->session->handlePacket();
// low-accuracy polling events
if (trackStatus == TRACK_NOTIFY) {
// inform Spotify that next track has started (don't need to be super accurate)
uint32_t started;
cmdHandler(CSPOT_QUERY_STARTED, &started);
if (started) {
CSPOT_LOG(info, "next track's audio has reached DAC");
spirc->notifyAudioReachedPlayback();
trackStatus = TRACK_STREAM;
}
} else if (trackStatus == TRACK_END) {
// wait for end of last track
uint32_t remains;
cmdHandler(CSPOT_QUERY_REMAINING, &remains);
if (!remains) {
CSPOT_LOG(info, "last track finished");
trackStatus = TRACK_INIT;
cmdHandler(CSPOT_STOP);
spirc->setPause(true);
}
}
}
spirc->disconnect();
spirc.reset();
CSPOT_LOG(info, "disconnecting player %s", name.c_str());
}
// we want to release memory ASAP and for sure
ctx.reset();
token.clear();
// update volume when we disconnect
cJSON *config = config_alloc_get_cjson("cspot_config");
cJSON_DeleteItemFromObject(config, "volume");
cJSON_AddNumberToObject(config, "volume", volume);
config_set_cjson_str_and_free("cspot_config", config);
}
} }
/**************************************************************************************** /****************************************************************************************
* API to create and start a cspot instance * API to create and start a cspot instance
*/ */
struct cspot_s* cspot_create(const char *name, httpd_handle_t server, int port, cspot_cmd_cb_t cmd_cb, cspot_data_cb_t data_cb) { struct cspot_s* cspot_create(const char *name, cspot_cmd_cb_t cmd_cb, cspot_data_cb_t data_cb) {
static DRAM_ATTR StaticTask_t xTaskBuffer __attribute__ ((aligned (4)));
static EXT_RAM_ATTR StackType_t xStack[CSPOT_STACK_SIZE] __attribute__ ((aligned (4)));
bell::setDefaultLogger(); bell::setDefaultLogger();
player = new cspotPlayer(name, server, port, cmd_cb, data_cb);
player->startTask(); cspot.cHandler = cmd_cb;
return (cspot_s*) player; cspot.dHandler = data_cb;
strncpy(cspot.name, name, sizeof(cspot.name) - 1);
cspot.TaskHandle = xTaskCreateStatic(&cspotTask, "cspot", CSPOT_STACK_SIZE, NULL, CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT - 2, xStack, &xTaskBuffer);
return &cspot;
} }
/**************************************************************************************** /****************************************************************************************
* Commands sent by local buttons/actions * Commands sent by local buttons/actions
*/ */
bool cspot_cmd(struct cspot_s* ctx, cspot_event_t event, void *param) { bool cspot_cmd(struct cspot_s* ctx, cspot_event_t event, void *param) {
player->command(event); // we might have not controller left
if (!spircController.use_count()) return false;
switch(event) {
case CSPOT_PREV:
spircController->prevSong();
break;
case CSPOT_NEXT:
spircController->nextSong();
break;
case CSPOT_TOGGLE:
spircController->playToggle();
break;
case CSPOT_PAUSE:
spircController->setPause(true);
break;
case CSPOT_PLAY:
spircController->setPause(false);
break;
case CSPOT_DISC:
spircController->disconnect();
break;
case CSPOT_STOP:
spircController->stopPlayer();
break;
case CSPOT_VOLUME_UP:
spircController->adjustVolume(MAX_VOLUME / 100 + 1);
break;
case CSPOT_VOLUME_DOWN:
spircController->adjustVolume(-(MAX_VOLUME / 100 + 1));
break;
default:
break;
}
return true; return true;
} }
/****************************************************************************************
* AudioSink class to push data to squeezelite backend (decode_external)
*/
void ShimAudioSink::volumeChanged(uint16_t volume) {
cspot.cHandler(CSPOT_VOLUME, volume);
}
void ShimAudioSink::feedPCMFrames(const uint8_t *data, size_t bytes) {
cspot.dHandler(data, bytes);
}
/****************************************************************************************
* NVSFile class to store config
*/
bool NVSFile::readFile(std::string filename, std::string &fileContent) {
auto search = files.find(filename);
// cache
if (search == files.end()) {
char *content = (char*) config_alloc_get(NVS_TYPE_STR, filename.c_str());
if (!content) return false;
fileContent = content;
free(content);
} else {
fileContent = search->second;
}
return true;
}
bool NVSFile::writeFile(std::string filename, std::string fileContent) {
auto search = files.find(filename);
files[filename] = fileContent;
if (search == files.end()) return (ESP_OK == config_set_value(NVS_TYPE_STR, filename.c_str(), fileContent.c_str()));
return true;
}
bool NVSFile::flush() {
esp_err_t err = ESP_OK;
for (auto it = files.begin(); it != files.end(); ++it) {
err |= config_set_value(NVS_TYPE_STR, it->first.c_str(), it->second.c_str());
}
return (err == ESP_OK);
}
/****************************************************************************************
* Shim HTTP server for spirc
*/
static esp_err_t handlerWrapper(httpd_req_t *req) {
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);
// 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;
ESP_LOGD(TAG,"wrapper received body %d/%d", size, req->content_len);
}
// parse query if any (can be in body as well for url-encoded)
if (query_len) {
query = (char*) malloc(query_len + 1);
httpd_req_get_url_query_str(req, query, query_len + 1);
} else if (body && strchr(body, '&')) {
query = body;
body = NULL;
}
// I know this is very crude and unsafe...
url_decode(query);
char *key = strtok(query, "&");
while (key) {
char *value = strchr(key, '=');
*value++ = '\0';
request->queryParams[key] = value;
ESP_LOGD(TAG,"wrapper received key:%s value:%s", key, value);
key = strtok(NULL, "&");
};
if (query) free(query);
if (body) free(body);
/*
This is a strange construct as the C++ handler will call the ShimHTTPSer::respond
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)(std::move(request));
return ESP_OK;
}
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),
.handler = handlerWrapper,
.user_ctx = NULL,
};
// find the first free spot and register handler
for (int i = 0; i < sizeof(uriHandlers)/sizeof(bell::httpHandler); i++) {
if (!uriHandlers[i]) {
uriHandlers[i] = handler;
request.user_ctx = uriHandlers + i;
httpd_register_uri_handler(serverHandle, &request);
break;
}
}
if (!request.user_ctx) ESP_LOGW(TAG, "Cannot add handler for %s", routeUrl.c_str());
}
void ShimHTTPServer::respond(const bell::HTTPResponse &response) {
char *buf;
size_t len = asprintf(&buf, "HTTP/1.1 %d OK\r\n"
"Server: SQUEEZEESP32\r\n"
"Connection: close\r\n"
"Content-type: %s\r\n"
"Content-length: %d\r\n"
"Access-Control-Allow-Origin: *\r\n"
"Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS\r\n"
"Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token\r\n"
"\r\n%s",
response.status, response.contentType.c_str(),
response.body.size(), response.body.c_str()
);
// use raw socket send and close connection
httpd_socket_send(serverHandle, response.connectionFd, buf, len, 0);
free(buf);
// we want to close the socket due to the strange construct
httpd_sess_trigger_close(serverHandle, response.connectionFd);
}

49
components/spotify/Shim.h Normal file
View File

@@ -0,0 +1,49 @@
/*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*
*/
#pragma once
#include <vector>
#include <iostream>
#include <map>
#include "AudioSink.h"
#include "FileHelper.h"
#include "BaseHTTPServer.h"
#include <stdio.h>
#include <string.h>
#include <sys/unistd.h>
#include <sys/stat.h>
#include "esp_err.h"
#include "esp_http_server.h"
#include "esp_log.h"
class ShimAudioSink : public AudioSink {
public:
ShimAudioSink(void) { softwareVolumeControl = false; }
void feedPCMFrames(const uint8_t *data, size_t bytes);
virtual void volumeChanged(uint16_t volume);
};
class NVSFile : public FileHelper {
private:
std::map<std::string, std::string> files;
public:
bool readFile(std::string filename, std::string &fileContent);
bool writeFile(std::string filename, std::string fileContent);
bool flush();
};
class ShimHTTPServer : public bell::BaseHTTPServer {
private:
httpd_handle_t serverHandle;
bell::httpHandler uriHandlers[4];
public:
ShimHTTPServer(httpd_handle_t server, int port) { serverHandle = server; serverPort = port; }
void registerHandler(bell::RequestType requestType, const std::string &, bell::httpHandler, bool readDataToStr = false);
void respond(const bell::HTTPResponse &);
};

View File

@@ -16,6 +16,11 @@ endif()
# Main library sources # Main library sources
file(GLOB SOURCES "src/*.cpp" "src/*.c") 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 # Use externally specified bell library or the submodule
if(CSPOT_EXTERNAL_BELL) if(CSPOT_EXTERNAL_BELL)
list(APPEND EXTRA_LIBS ${CSPOT_EXTERNAL_BELL}) list(APPEND EXTRA_LIBS ${CSPOT_EXTERNAL_BELL})
@@ -24,12 +29,24 @@ else()
list(APPEND EXTRA_LIBS bell) list(APPEND EXTRA_LIBS bell)
endif() endif()
# Add Apple Bonjour compatibility library for Linux
if(UNIX AND NOT APPLE)
list(APPEND EXTRA_LIBS dns_sd)
# TODO: migrate from this to native linux mDNS
endif()
# Build protobuf code # Build protobuf code
if(0)
set(NANOPB_OPTIONS "-I${CMAKE_CURRENT_SOURCE_DIR}") set(NANOPB_OPTIONS "-I${CMAKE_CURRENT_SOURCE_DIR}")
file(GLOB PROTOS protobuf/*.proto) file(GLOB PROTOS protobuf/*.proto)
nanopb_generate_cpp(PROTO_SRCS PROTO_HDRS RELPATH ${CMAKE_CURRENT_SOURCE_DIR} ${PROTOS}) nanopb_generate_cpp(PROTO_SRCS PROTO_HDRS RELPATH ${CMAKE_CURRENT_SOURCE_DIR} ${PROTOS})
add_custom_target(generate_proto_sources DEPENDS ${PROTO_SRCS} ${PROTO_HDRS}) add_custom_target(generate_proto_sources DEPENDS ${PROTO_SRCS} ${PROTO_HDRS})
set_source_files_properties(${PROTO_SRCS} ${PROTO_HDRS} PROPERTIES GENERATED TRUE) 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}) add_library(cspot STATIC ${SOURCES} ${PROTO_SRCS})
# PUBLIC to propagate includes from bell to cspot dependents # PUBLIC to propagate includes from bell to cspot dependents

View File

@@ -1,3 +0,0 @@
# Base CSpot library
CSpot Spotify-Connect receiver library further integrated in ../targets/

View File

@@ -1,3 +0,0 @@
CompileFlags:
CompilationDatabase: example/build # Search build/ directory for compile_commands.json

View File

@@ -1,52 +0,0 @@
name: C/C++ CI
on: [push, pull_request]
jobs:
build:
strategy:
matrix:
os: [macos-latest, ubuntu-latest]
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
with:
submodules: recursive
- name: Install Protoc
uses: arduino/setup-protoc@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }} # https://github.com/arduino/setup-protoc/issues/6
- name: Setup cmake
uses: jwlawson/actions-setup-cmake@v1.4
with:
cmake-version: '3.18.x'
- name: Install avachi libraries (mDNS), mbedtls and asound
run: sudo apt-get install libavahi-compat-libdnssd-dev libasound2-dev libmbedtls-dev
if: ${{ matrix.os == 'ubuntu-latest' }}
- name: Install openssl on macos
run: |
brew install mbedtls@3
brew link --force mbedtls@3
brew install portaudio
brew link --force portaudio
export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/local/Cellar/portaudio/19.6.0/lib/pkgconfig"
pkg-config --modversion portaudio-2.0
echo "PKG_CONFIG_PATH=$PKG_CONFIG_PATH" >> $GITHUB_ENV
if: ${{ matrix.os == 'macos-latest' }}
- name: Install python dependencies
run: python3 -m pip install --upgrade pip setuptools wheel
- name: Install grpcio-tools
run: sudo pip3 install grpcio-tools
- name: cmake
run: mkdir -p build && cd build && cmake ..
- name: make
run: cd build && make

View File

@@ -22,6 +22,7 @@
*.pch *.pch
# Libraries # Libraries
*.lib
*.a *.a
*.la *.la
*.lo *.lo
@@ -123,5 +124,3 @@ Temporary Items
# End of https://www.toptal.com/developers/gitignore/api/c,c++,cmake,macos # End of https://www.toptal.com/developers/gitignore/api/c,c++,cmake,macos
build/ build/
__history/
*.bak

View File

@@ -1,9 +1,10 @@
[submodule "external/lws"] [submodule "tremor"]
path = external/lws path = tremor
url = https://github.com/warmcat/libwebsockets url = https://gitlab.xiph.org/xiph/tremor.git
[submodule "external/nlohmann_json"] branch = lowmem
path = external/nlohmann_json [submodule "cJSON"]
url = https://github.com/nlohmann/json path = cJSON
[submodule "external/mdnssvc"] url = https://github.com/DaveGamble/cJSON
path = external/mdnssvc [submodule "nanopb"]
url = https://github.com/philippe44/mdnssvc path = nanopb
url = https://github.com/nanopb/nanopb

View File

@@ -1,65 +0,0 @@
{
"files.associations": {
"array": "cpp",
"atomic": "cpp",
"bit": "cpp",
"*.tcc": "cpp",
"bitset": "cpp",
"cctype": "cpp",
"chrono": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"compare": "cpp",
"concepts": "cpp",
"condition_variable": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"deque": "cpp",
"map": "cpp",
"set": "cpp",
"string": "cpp",
"unordered_map": "cpp",
"vector": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"functional": "cpp",
"iterator": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"numeric": "cpp",
"optional": "cpp",
"random": "cpp",
"ratio": "cpp",
"regex": "cpp",
"string_view": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"fstream": "cpp",
"initializer_list": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"limits": "cpp",
"mutex": "cpp",
"new": "cpp",
"numbers": "cpp",
"ostream": "cpp",
"semaphore": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"stop_token": "cpp",
"streambuf": "cpp",
"thread": "cpp",
"typeinfo": "cpp",
"cinttypes": "cpp"
}
}

View File

@@ -7,38 +7,27 @@ project(bell)
option(BELL_DISABLE_CODECS "Disable the entire audio codec wrapper" OFF) option(BELL_DISABLE_CODECS "Disable the entire audio codec wrapper" OFF)
option(BELL_CODEC_AAC "Support libhelix-aac codec" ON) option(BELL_CODEC_AAC "Support libhelix-aac codec" ON)
option(BELL_CODEC_MP3 "Support libhelix-mp3 codec" ON) option(BELL_CODEC_MP3 "Support libhelix-mp3 codec" ON)
option(BELL_DISABLE_MQTT "Disable the built-in MQTT wrapper" OFF)
option(BELL_DISABLE_WEBSERVER "Disable the built-in Web server" OFF)
option(BELL_CODEC_VORBIS "Support tremor Vorbis codec" ON) option(BELL_CODEC_VORBIS "Support tremor Vorbis codec" ON)
option(BELL_CODEC_ALAC "Support Apple ALAC codec" ON) option(BELL_CODEC_ALAC "Support Apple ALAC codec" ON)
option(BELL_CODEC_OPUS "Support Opus codec" ON) option(BELL_CODEC_OPUS "Support Opus codec" ON)
option(BELL_DISABLE_SINKS "Disable all built-in audio sink implementations" OFF) 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) # 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_ALSA "Enable ALSA audio sink" OFF)
option(BELL_SINK_PORTAUDIO "Enable PortAudio sink" OFF) option(BELL_SINK_PORTAUDIO "Enable PortAudio sink" OFF)
# cJSON wrapper # cJSON wrapper
option(BELL_ONLY_CJSON "Use only cJSON, not Nlohmann") 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_CJSON "" CACHE STRING "External cJSON library target name, optional")
# vorbis if(BELL_EXTERNAL_MBEDTLS)
set(BELL_EXTERNAL_VORBIS "" CACHE STRING "External Vorbis library target name, optional") set(MbedTLS_DIR ${BELL_EXTERNAL_MBEDTLS})
option(BELL_VORBIS_FLOAT "Use floating point Vorbis API" OFF) message(STATUS "Setting local mbedtls ${MbedTLS_DIR}")
endif()
# fmt & regex
option(BELL_DISABLE_FMT "Don't use std::fmt (saves space)" OFF)
option(BELL_DISABLE_REGEX "Don't use std::regex (saves space)" OFF)
# disable json tests
set(JSON_BuildTests OFF CACHE INTERNAL "")
# Backwards compatibility with deprecated options # Backwards compatibility with deprecated options
if(BELL_USE_ALSA) if(BELL_USE_ALSA)
message(WARNING "Deprecated Bell options used, replace BELL_USE_ALSA with BELL_SINK_ALSA") message(WARNING "Deprecated Bell options used, replace BELL_USE_ALSA with BELL_SINK_ALSA")
set(BELL_SINK_ALSA ${BELL_USE_ALSA}) set(BELL_SINK_ALSA ${BELL_USE_ALSA})
endif() endif()
if(BELL_USE_PORTAUDIO) if(BELL_USE_PORTAUDIO)
message(WARNING "Deprecated Bell options used, replace BELL_USE_PORTAUDIO with BELL_SINK_PORTAUDIO") message(WARNING "Deprecated Bell options used, replace BELL_USE_PORTAUDIO with BELL_SINK_PORTAUDIO")
set(BELL_SINK_PORTAUDIO ${BELL_USE_PORTAUDIO}) set(BELL_SINK_PORTAUDIO ${BELL_USE_PORTAUDIO})
@@ -46,7 +35,6 @@ endif()
message(STATUS "Bell options:") message(STATUS "Bell options:")
message(STATUS " Disable all codecs: ${BELL_DISABLE_CODECS}") message(STATUS " Disable all codecs: ${BELL_DISABLE_CODECS}")
if(NOT BELL_DISABLE_CODECS) if(NOT BELL_DISABLE_CODECS)
message(STATUS " - AAC audio codec: ${BELL_CODEC_AAC}") message(STATUS " - AAC audio codec: ${BELL_CODEC_AAC}")
message(STATUS " - MP3 audio codec: ${BELL_CODEC_MP3}") message(STATUS " - MP3 audio codec: ${BELL_CODEC_MP3}")
@@ -54,77 +42,51 @@ if(NOT BELL_DISABLE_CODECS)
message(STATUS " - Opus audio codec: ${BELL_CODEC_OPUS}") message(STATUS " - Opus audio codec: ${BELL_CODEC_OPUS}")
message(STATUS " - ALAC audio codec: ${BELL_CODEC_ALAC}") message(STATUS " - ALAC audio codec: ${BELL_CODEC_ALAC}")
endif() endif()
message(STATUS " Disable built-in audio sinks: ${BELL_DISABLE_SINKS}") message(STATUS " Disable built-in audio sinks: ${BELL_DISABLE_SINKS}")
message(STATUS " Use Vorbis float version: ${BELL_VORBIS_FLOAT}")
if(NOT BELL_DISABLE_SINKS) if(NOT BELL_DISABLE_SINKS)
message(STATUS " - ALSA sink: ${BELL_SINK_ALSA}") message(STATUS " - ALSA sink: ${BELL_SINK_ALSA}")
message(STATUS " - PortAudio sink: ${BELL_SINK_PORTAUDIO}") message(STATUS " - PortAudio sink: ${BELL_SINK_PORTAUDIO}")
endif() endif()
message(STATUS " Disable cJSON and JSONObject: ${BELL_DISABLE_CJSON}")
message(STATUS " Use cJSON only: ${BELL_ONLY_CJSON}")
message(STATUS " Disable Fmt: ${BELL_DISABLE_FMT}")
message(STATUS " Disable Mqtt: ${BELL_DISABLE_MQTT}")
message(STATUS " Disable Regex: ${BELL_DISABLE_REGEX}")
message(STATUS " Disable Web server: ${BELL_DISABLE_WEBSERVER}")
# Include nanoPB library # Include nanoPB library
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/external/nanopb/extra") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/nanopb/extra")
find_package(Nanopb REQUIRED) find_package(Nanopb REQUIRED)
message(${NANOPB_INCLUDE_DIRS}) list(APPEND EXTRA_INCLUDES ${NANOPB_INCLUDE_DIRS})
list(APPEND EXTERNAL_INCLUDES ${NANOPB_INCLUDE_DIRS})
# CMake options # CMake options
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED 20)
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
set(AUDIO_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/audio")
set(AUDIO_CODEC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/main/audio-codec") add_definitions("-DUSE_DEFAULT_STDLIB=1")
set(AUDIO_CONTAINERS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/main/audio-containers")
set(AUDIO_DSP_DIR "${CMAKE_CURRENT_SOURCE_DIR}/main/audio-dsp")
set(AUDIO_SINKS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/main/audio-sinks")
set(IO_DIR "${CMAKE_CURRENT_SOURCE_DIR}/main/io")
set(PLATFORM_DIR "${CMAKE_CURRENT_SOURCE_DIR}/main/platform")
set(UTILITIES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/main/utilities")
add_definitions("-DUSE_DEFAULT_STDLIB=1 -DTARGET_OS_IPHONE=0")
# Main library sources # Main library sources
file(GLOB SOURCES file(GLOB SOURCES "src/*.cpp" "src/*.c" "nanopb/*.c")
"external/nanopb/*.c" list(APPEND EXTRA_INCLUDES "include/platform")
"main/utilities/*.cpp" "main/utilities/*.c" list(APPEND EXTRA_INCLUDES "include/audio/container")
"main/io/*.cpp" "main/io/*.c"
)
list(APPEND EXTRA_INCLUDES "main/audio-codec/include")
list(APPEND EXTRA_INCLUDES "main/audio-dsp/include")
list(APPEND EXTRA_INCLUDES "main/audio-sinks/include")
list(APPEND EXTRA_INCLUDES "main/io/include")
list(APPEND EXTRA_INCLUDES "main/utilities/include")
list(APPEND EXTRA_INCLUDES "main/platform")
# Add platform specific sources # Add platform specific sources
if(ESP_PLATFORM) if(ESP_PLATFORM)
file(GLOB ESP_PLATFORM_SOURCES "main/platform/esp/*.cpp" "main/platform/esp/*.c" "main/asm/biquad_f32_ae32.S") 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}) list(APPEND SOURCES ${ESP_PLATFORM_SOURCES})
endif() endif()
if(UNIX)
if(APPLE) file(GLOB UNIX_PLATFORM_SOURCES "src/platform/unix/*.cpp" "src/platform/unix/*.c")
file(GLOB APPLE_PLATFORM_SOURCES "main/platform/apple/*.cpp" "main/platform/apple/*.c") list(APPEND SOURCES ${UNIX_PLATFORM_SOURCES})
list(APPEND SOURCES ${APPLE_PLATFORM_SOURCES}) endif()
list(APPEND EXTERNAL_INCLUDES "/usr/local/opt/mbedtls@3/include") if(APPLE)
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() endif()
if(UNIX AND NOT APPLE) if(UNIX AND NOT APPLE)
file(GLOB LINUX_PLATFORM_SOURCES "main/platform/linux/*.cpp" "main/platform/linux/*.c") file(GLOB LINUX_PLATFORM_SOURCES "src/platform/linux/*.cpp" "src/platform/linux/*.c")
list(APPEND SOURCES ${LINUX_PLATFORM_SOURCES}) list(APPEND SOURCES ${LINUX_PLATFORM_SOURCES})
endif() endif()
if(WIN32) if(WIN32)
file(GLOB WIN32_PLATFORM_SOURCES "main/platform/win32/*.cpp" "main/platform/win32/*.c") file(GLOB WIN32_PLATFORM_SOURCES "src/platform/win32/*.cpp" "src/platform/win32/*.c")
list(APPEND SOURCES ${WIN32_PLATFORM_SOURCES}) list(APPEND SOURCES ${WIN32_PLATFORM_SOURCES})
list(APPEND EXTERNAL_INCLUDES "main/platform/win32") list(APPEND EXTRA_INCLUDES "include/platform/win32")
endif() endif()
# A hack to make Opus keep quiet # A hack to make Opus keep quiet
@@ -134,83 +96,90 @@ function(message)
endif() endif()
endfunction() endfunction()
if(ESP_PLATFORM) if(ESP_PLATFORM)
list(APPEND EXTRA_LIBS idf::mdns idf::mbedtls idf::pthread idf::driver idf::lwip) list(APPEND EXTRA_LIBS idf::mbedtls idf::pthread idf::mdns)
add_definitions(-Wunused-const-variable -Wchar-subscripts -Wunused-label -Wmaybe-uninitialized -Wmisleading-indentation -Wno-stringop-overflow -Wno-error=format -Wno-format -Wno-stringop-overread -Wno-stringop-overflow) add_definitions(-Wunused-const-variable -Wchar-subscripts -Wunused-label -Wmaybe-uninitialized -Wmisleading-indentation)
else() else()
find_package(Threads REQUIRED) find_package(Threads REQUIRED)
find_package(MbedTLS REQUIRED)
list(APPEND EXTERNAL_INCLUDES ${MBEDTLS_INCLUDE_DIRS})
set(THREADS_PREFER_PTHREAD_FLAG ON) set(THREADS_PREFER_PTHREAD_FLAG ON)
list(APPEND EXTRA_LIBS ${MBEDTLS_LIBRARIES} 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) if(MSVC)
add_compile_definitions(NOMINMAX _CRT_SECURE_NO_WARNINGS _USE_MATH_DEFINES) add_compile_definitions(NOMINMAX _CRT_SECURE_NO_WARNINGS)
add_definitions(/wd4068 /wd4244 /wd4018 /wd4101 /wd4102 /wd4142) add_definitions(/wd4068 /wd4244 /wd4018 /wd4101 /wd4102 /wd4142)
endif() endif()
endif()
if (NOT BELL_DISABLE_MQTT)
file(GLOB MQTT_SOURCES "external/mqtt/*.c")
list(APPEND SOURCES ${MQTT_SOURCES})
list(APPEND EXTRA_INCLUDES "external/mqtt/include")
else()
list(REMOVE_ITEM SOURCES "${IO_DIR}/BellMQTTClient.cpp")
endif() endif()
if(NOT BELL_DISABLE_CODECS) if(NOT BELL_DISABLE_CODECS)
file(GLOB EXTRA_SOURCES "main/audio-containers/*.cpp" "main/audio-codec/*.cpp" "main/audio-codec/*.c" "main/audio-dsp/*.cpp" "main/audio-dsp/*.c") file(GLOB EXTRA_SOURCES "src/audio/container/*.cpp")
list(APPEND SOURCES "${EXTRA_SOURCES}")
list(APPEND SOURCES "${EXTRA_SOURCES}") list(APPEND SOURCES "${AUDIO_DIR}/codec/DecoderGlobals.cpp")
list(APPEND SOURCES "${AUDIO_CODEC_DIR}/DecoderGlobals.cpp") list(APPEND SOURCES "${AUDIO_DIR}/codec/BaseCodec.cpp")
list(APPEND SOURCES "${AUDIO_CODEC_DIR}/BaseCodec.cpp") list(APPEND SOURCES "${AUDIO_DIR}/codec/AudioCodecs.cpp")
list(APPEND SOURCES "${AUDIO_CODEC_DIR}/AudioCodecs.cpp") list(APPEND EXTRA_INCLUDES "include/audio/codec")
list(APPEND EXTRA_INCLUDES "main/audio-containers/include")
# AAC-LC codec # AAC-LC codec
if(BELL_CODEC_AAC) if(BELL_CODEC_AAC)
file(GLOB LIBHELIX_AAC_SOURCES "external/libhelix-aac/*.c") file(GLOB LIBHELIX_AAC_SOURCES "libhelix-aac/*.c")
list(APPEND LIBHELIX_SOURCES ${LIBHELIX_AAC_SOURCES}) list(APPEND LIBHELIX_SOURCES ${LIBHELIX_AAC_SOURCES})
list(APPEND EXTERNAL_INCLUDES "external/libhelix-aac") list(APPEND EXTRA_INCLUDES "libhelix-aac")
list(APPEND SOURCES "${AUDIO_CODEC_DIR}/AACDecoder.cpp") list(APPEND SOURCES "${AUDIO_DIR}/codec/AACDecoder.cpp")
list(APPEND CODEC_FLAGS "-DBELL_CODEC_AAC") list(APPEND CODEC_FLAGS "-DBELL_CODEC_AAC")
endif() endif()
# MP3 codec # MP3 codec
if(BELL_CODEC_MP3) if(BELL_CODEC_MP3)
file(GLOB LIBHELIX_MP3_SOURCES "external/libhelix-mp3/*.c") file(GLOB LIBHELIX_MP3_SOURCES "libhelix-mp3/*.c")
list(APPEND LIBHELIX_SOURCES ${LIBHELIX_MP3_SOURCES}) list(APPEND LIBHELIX_SOURCES ${LIBHELIX_MP3_SOURCES})
list(APPEND EXTERNAL_INCLUDES "external/libhelix-mp3") list(APPEND EXTRA_INCLUDES "libhelix-mp3")
list(APPEND SOURCES "${AUDIO_CODEC_DIR}/MP3Decoder.cpp") list(APPEND SOURCES "${AUDIO_DIR}/codec/MP3Decoder.cpp")
list(APPEND CODEC_FLAGS "-DBELL_CODEC_MP3") list(APPEND CODEC_FLAGS "-DBELL_CODEC_MP3")
endif() endif()
# MP3 codec # MP3 codec
# if(BELL_CODEC_ALAC) if(BELL_CODEC_ALAC)
# file(GLOB ALAC_SOURCES "external/alac/*.c" "external/alac/*.cpp") file(GLOB ALAC_SOURCES "alac/*.c" "alac/*.cpp")
# list(APPEND ALAC_SOURCES ${ALAC_SOURCES}) list(APPEND ALAC_SOURCES ${ALAC_SOURCES})
# list(APPEND EXTRA_INCLUDES "external/alac") list(APPEND EXTRA_INCLUDES "alac")
# list(APPEND SOURCES "${AUDIO_DIR}/codec/ALACDecoder.cpp")
# # list(APPEND SOURCES "${AUDIO_DIR}/codec/ALACDecoder.cpp") list(APPEND CODEC_FLAGS "-DBELL_CODEC_ALAC")
# list(APPEND CODEC_FLAGS "-DBELL_CODEC_ALAC") endif()
# endif()
# libhelix Cygwin workaround # libhelix Cygwin workaround
if(CYGWIN) if(CYGWIN)
# Both Cygwin and ESP are Unix-like so this seems to work (or, at least, compile) # Both Cygwin and ESP are Unix-like so this seems to work (or, at least, compile)
set_source_files_properties("${AUDIO_CODEC_DIR}/DecoderGlobals.cpp" ${LIBHELIX_SOURCES} PROPERTIES COMPILE_FLAGS "-DESP_PLATFORM") set_source_files_properties("${AUDIO_DIR}/codec/DecoderGlobals.cpp" ${LIBHELIX_SOURCES} PROPERTIES COMPILE_FLAGS "-DESP_PLATFORM")
endif() endif()
list(APPEND SOURCES ${LIBHELIX_SOURCES}) list(APPEND SOURCES ${LIBHELIX_SOURCES})
list(APPEND SOURCES ${ALAC_SOURCES}) list(APPEND SOURCES ${ALAC_SOURCES})
# Vorbis codec # Vorbis codec
if(BELL_CODEC_VORBIS) if(BELL_CODEC_VORBIS)
list(APPEND SOURCES "${AUDIO_CODEC_DIR}/VorbisDecoder.cpp") 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") list(APPEND CODEC_FLAGS "-DBELL_CODEC_VORBIS")
endif() endif()
# Opus codec # Opus codec
if(BELL_CODEC_OPUS) if(BELL_CODEC_OPUS)
set(OPUS_INSTALL_CMAKE_CONFIG_MODULE OFF CACHE BOOL "") set(OPUS_INSTALL_CMAKE_CONFIG_MODULE OFF CACHE BOOL "")
@@ -218,130 +187,72 @@ if(NOT BELL_DISABLE_CODECS)
set(OPUS_INSTALL_PKG_CONFIG_MODULE OFF CACHE BOOL "") set(OPUS_INSTALL_PKG_CONFIG_MODULE OFF CACHE BOOL "")
set(OPUS_INSTALL_PKG_CONFIG_MODULE OFF) set(OPUS_INSTALL_PKG_CONFIG_MODULE OFF)
set(MESSAGE_QUIET ON) set(MESSAGE_QUIET ON)
add_subdirectory("external/opus") add_subdirectory("opus")
unset(MESSAGE_QUIET) unset(MESSAGE_QUIET)
target_compile_options(opus PRIVATE "-O3") target_compile_options(opus PRIVATE "-O3")
list(APPEND EXTRA_LIBS Opus::opus) list(APPEND EXTRA_LIBS Opus::opus)
list(APPEND SOURCES "${AUDIO_CODEC_DIR}/OPUSDecoder.cpp") list(APPEND SOURCES "${AUDIO_DIR}/codec/OPUSDecoder.cpp")
list(APPEND CODEC_FLAGS -DBELL_CODEC_OPUS) list(APPEND CODEC_FLAGS -DBELL_CODEC_OPUS)
endif() endif()
# Enable global codecs # Enable global codecs
string(REPLACE ";" " " CODEC_FLAGS "${CODEC_FLAGS}") string(REPLACE ";" " " CODEC_FLAGS "${CODEC_FLAGS}")
set_source_files_properties("${AUDIO_CODEC_DIR}/AudioCodecs.cpp" PROPERTIES COMPILE_FLAGS "${CODEC_FLAGS}") set_source_files_properties("${AUDIO_DIR}/codec/AudioCodecs.cpp" PROPERTIES COMPILE_FLAGS "${CODEC_FLAGS}")
else() elseif(BELL_EXTERNAL_TREMOR)
list(REMOVE_ITEM SOURCES "${IO_DIR}/EncodedAudioStream.cpp") list(APPEND EXTRA_LIBS ${BELL_EXTERNAL_TREMOR})
endif()
if(NOT BELL_EXTERNAL_VORBIS STREQUAL "")
message(STATUS "Using external Vorbis codec ${BELL_EXTERNAL_VORBIS}")
list(APPEND EXTRA_LIBS ${BELL_EXTERNAL_VORBIS})
else()
file(GLOB TREMOR_SOURCES "external/tremor/*.c")
list(REMOVE_ITEM TREMOR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/external/tremor/ivorbisfile_example.c")
list(APPEND SOURCES ${TREMOR_SOURCES})
list(APPEND EXTERNAL_INCLUDES "external/tremor")
endif() endif()
if(NOT BELL_DISABLE_SINKS) if(NOT BELL_DISABLE_SINKS)
set(PLATFORM "unix") set(PLATFORM "unix")
if(ESP_PLATFORM) if(ESP_PLATFORM)
set(PLATFORM "esp") set(PLATFORM "esp")
endif() endif()
# Add all built-in audio sinks # Add all built-in audio sinks
file(GLOB SINK_SOURCES "${AUDIO_SINKS_DIR}/${PLATFORM}/*.cpp" "${AUDIO_SINKS_DIR}/${PLATFORM}/*.c") file(GLOB SINK_SOURCES "${AUDIO_DIR}/sinks/${PLATFORM}/*.cpp" "${AUDIO_DIR}/sinks/${PLATFORM}/*.c")
list(APPEND EXTRA_INCLUDES "main/audio-sinks/include/${PLATFORM}") list(APPEND EXTRA_INCLUDES "include/audio/sinks/${PLATFORM}")
# Find ALSA if required, else remove the sink # Find ALSA if required, else remove the sink
if(BELL_SINK_ALSA) if(BELL_SINK_ALSA)
find_package(ALSA REQUIRED) find_package(ALSA REQUIRED)
list(APPEND EXTERNAL_INCLUDES ${ALSA_INCLUDE_DIRS}) list(APPEND EXTRA_INCLUDES ${ALSA_INCLUDE_DIRS})
list(APPEND EXTRA_LIBS ${ALSA_LIBRARIES}) list(APPEND EXTRA_LIBS ${ALSA_LIBRARIES})
else() else()
list(REMOVE_ITEM SINK_SOURCES "${AUDIO_SINKS_DIR}/unix/ALSAAudioSink.cpp") list(REMOVE_ITEM SINK_SOURCES "${AUDIO_DIR}/sinks/unix/ALSAAudioSink.cpp")
endif() endif()
# Find PortAudio if required, else remove the sink # Find PortAudio if required, else remove the sink
if(BELL_SINK_PORTAUDIO) if(BELL_SINK_PORTAUDIO)
find_package(Portaudio REQUIRED) if(WIN32)
list(APPEND EXTERNAL_INCLUDES ${PORTAUDIO_INCLUDE_DIRS}) list(APPEND EXTRA_INCLUDES "portaudio/include")
list(APPEND EXTRA_LIBS ${PORTAUDIO_LIBRARIES}) 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() else()
list(REMOVE_ITEM SINK_SOURCES "${AUDIO_SINKS_DIR}/unix/PortAudioSink.cpp") list(REMOVE_ITEM SINK_SOURCES "${AUDIO_DIR}/sinks/unix/PortAudioSink.cpp")
endif() endif()
list(APPEND SOURCES ${SINK_SOURCES}) list(APPEND SOURCES ${SINK_SOURCES})
endif() endif()
if(NOT BELL_ONLY_CJSON) if(BELL_DISABLE_CJSON)
set(JSON_SystemInclude ON CACHE INTERNAL "") list(REMOVE_ITEM SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/JSONObject.cpp")
add_subdirectory(external/nlohmann_json)
list(APPEND EXTRA_LIBS nlohmann_json::nlohmann_json)
endif()
if(BELL_EXTERNAL_CJSON)
list(APPEND EXTRA_LIBS ${BELL_EXTERNAL_CJSON})
else()
list(APPEND SOURCES "external/cJSON/cJSON.c")
list(APPEND EXTERNAL_INCLUDES "external/cJSON")
endif()
if (NOT BELL_DISABLE_FMT)
list(APPEND EXTERNAL_INCLUDES "external/fmt/include")
endif()
if(WIN32 OR UNIX)
list(APPEND SOURCES "external/mdnssvc/mdns.c" "external/mdnssvc/mdnsd.c")
list(APPEND EXTERNAL_INCLUDES "external/mdnssvc")
endif()
if(NOT BELL_DISABLE_WEBSERVER)
file(GLOB CIVET_SRC "external/civetweb/*.c" "external/civetweb/*.inl" "external/civetweb/*.cpp")
list(APPEND SOURCES ${CIVET_SRC})
list(APPEND EXTRA_INCLUDES "external/civetweb/include")
else() else()
list(REMOVE_ITEM SOURCES "${IO_DIR}/BellHTTPServer.cpp") if(BELL_EXTERNAL_CJSON)
endif() list(APPEND EXTRA_LIBS ${BELL_EXTERNAL_CJSON})
add_library(bell STATIC ${SOURCES})
# Add Apple Bonjour compatibility library for Linux
if(UNIX AND NOT APPLE)
if (BELL_DISABLE_AVAHI)
add_compile_definitions(BELL_DISABLE_AVAHI)
else() else()
list(APPEND EXTRA_LIBS avahi-client avahi-common) list(APPEND SOURCES "cJSON/cJSON.c")
list(APPEND EXTRA_INCLUDES "cJSON")
endif() endif()
endif() endif()
add_library(bell STATIC ${SOURCES})
# PUBLIC to propagate esp-idf includes to bell dependents # PUBLIC to propagate esp-idf includes to bell dependents
target_link_libraries(bell PUBLIC ${EXTRA_LIBS}) target_link_libraries(bell PUBLIC ${EXTRA_LIBS})
target_include_directories(bell PUBLIC ${EXTRA_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR}) target_include_directories(bell PUBLIC "include" ${EXTRA_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR})
target_include_directories(bell SYSTEM PUBLIC ${EXTERNAL_INCLUDES}) target_compile_definitions(bell PUBLIC PB_ENABLE_MALLOC)
target_compile_definitions(bell PUBLIC PB_ENABLE_MALLOC FMT_HEADER_ONLY) if(WIN32)
if(BELL_DISABLE_CODECS)
target_compile_definitions(bell PUBLIC BELL_DISABLE_CODECS)
endif()
if(BELL_VORBIS_FLOAT)
target_compile_definitions(bell PUBLIC BELL_VORBIS_FLOAT)
endif()
if(BELL_DISABLE_FMT)
target_compile_definitions(bell PUBLIC BELL_DISABLE_FMT)
endif()
if(BELL_DISABLE_REGEX)
target_compile_definitions(bell PUBLIC BELL_DISABLE_REGEX)
endif()
if(BELL_ONLY_CJSON)
target_compile_definitions(bell PUBLIC BELL_ONLY_CJSON)
endif()
if(WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "SunOS")
target_compile_definitions(bell PUBLIC PB_NO_STATIC_ASSERT) target_compile_definitions(bell PUBLIC PB_NO_STATIC_ASSERT)
endif() endif()

View File

@@ -0,0 +1,9 @@
# bell
Core audio utils library used in cspot and euphonium projects.
Implemented utilities:
- HTTPServer
- Crypto (openssl and mbedtls backed)
- Semaphore implementations

View File

@@ -121,6 +121,7 @@ set(SOURCES cJSON.c)
option(BUILD_SHARED_AND_STATIC_LIBS "Build both shared and static libraries" Off) 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_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(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)) 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) set(CJSON_LIBRARY_TYPE SHARED)
@@ -155,17 +156,23 @@ install(TARGETS "${CJSON_LIB}"
INCLUDES DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}" INCLUDES DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}"
) )
if (BUILD_SHARED_AND_STATIC_LIBS) 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() endif()
if(ENABLE_TARGET_EXPORT) if(ENABLE_TARGET_EXPORT)
# export library information for CMake projects # export library information for CMake projects
install(EXPORT "${CJSON_LIB}" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cJSON") install(EXPORT "${CJSON_LIB}" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cJSON")
endif() endif()
set_target_properties("${CJSON_LIB}" if(ENABLE_CJSON_VERSION_SO)
PROPERTIES set_target_properties("${CJSON_LIB}"
SOVERSION "${CJSON_VERSION_SO}" PROPERTIES
VERSION "${PROJECT_VERSION}") SOVERSION "${CJSON_VERSION_SO}"
VERSION "${PROJECT_VERSION}")
endif()
#cJSON_Utils #cJSON_Utils
option(ENABLE_CJSON_UTILS "Enable building the cJSON_Utils library." OFF) 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}" INCLUDES DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}"
) )
if (BUILD_SHARED_AND_STATIC_LIBS) 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() endif()
install(FILES cJSON_Utils.h DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/cjson") 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") 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") install(EXPORT "${CJSON_UTILS_LIB}" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cJSON")
endif() endif()
set_target_properties("${CJSON_UTILS_LIB}" if(ENABLE_CJSON_VERSION_SO)
PROPERTIES set_target_properties("${CJSON_UTILS_LIB}"
SOVERSION "${CJSON_UTILS_VERSION_SO}" PROPERTIES
VERSION "${PROJECT_VERSION}") SOVERSION "${CJSON_UTILS_VERSION_SO}"
VERSION "${PROJECT_VERSION}")
endif()
endif() endif()
# create the other package config files # create the other package config files

View File

@@ -0,0 +1,163 @@
CJSON_OBJ = cJSON.o
UTILS_OBJ = cJSON_Utils.o
CJSON_LIBNAME = libcjson
UTILS_LIBNAME = libcjson_utils
CJSON_TEST = cJSON_test
CJSON_TEST_SRC = cJSON.c test.c
LDLIBS = -lm
LIBVERSION = 1.7.15
CJSON_SOVERSION = 1
UTILS_SOVERSION = 1
CJSON_SO_LDFLAG=-Wl,-soname=$(CJSON_LIBNAME).so.$(CJSON_SOVERSION)
UTILS_SO_LDFLAG=-Wl,-soname=$(UTILS_LIBNAME).so.$(UTILS_SOVERSION)
PREFIX ?= /usr/local
INCLUDE_PATH ?= include/cjson
LIBRARY_PATH ?= lib
INSTALL_INCLUDE_PATH = $(DESTDIR)$(PREFIX)/$(INCLUDE_PATH)
INSTALL_LIBRARY_PATH = $(DESTDIR)$(PREFIX)/$(LIBRARY_PATH)
INSTALL ?= cp -a
CC = gcc -std=c89
# validate gcc version for use fstack-protector-strong
MIN_GCC_VERSION = "4.9"
GCC_VERSION := "`$(CC) -dumpversion`"
IS_GCC_ABOVE_MIN_VERSION := $(shell expr "$(GCC_VERSION)" ">=" "$(MIN_GCC_VERSION)")
ifeq "$(IS_GCC_ABOVE_MIN_VERSION)" "1"
CFLAGS += -fstack-protector-strong
else
CFLAGS += -fstack-protector
endif
PIC_FLAGS = -fPIC
R_CFLAGS = $(PIC_FLAGS) -pedantic -Wall -Werror -Wstrict-prototypes -Wwrite-strings -Wshadow -Winit-self -Wcast-align -Wformat=2 -Wmissing-prototypes -Wstrict-overflow=2 -Wcast-qual -Wc++-compat -Wundef -Wswitch-default -Wconversion $(CFLAGS)
uname := $(shell sh -c 'uname -s 2>/dev/null || echo false')
#library file extensions
SHARED = so
STATIC = a
## create dynamic (shared) library on Darwin (base OS for MacOSX and IOS)
ifeq (Darwin, $(uname))
SHARED = dylib
CJSON_SO_LDFLAG = ""
UTILS_SO_LDFLAG = ""
endif
#cJSON library names
CJSON_SHARED = $(CJSON_LIBNAME).$(SHARED)
CJSON_SHARED_VERSION = $(CJSON_LIBNAME).$(SHARED).$(LIBVERSION)
CJSON_SHARED_SO = $(CJSON_LIBNAME).$(SHARED).$(CJSON_SOVERSION)
CJSON_STATIC = $(CJSON_LIBNAME).$(STATIC)
#cJSON_Utils library names
UTILS_SHARED = $(UTILS_LIBNAME).$(SHARED)
UTILS_SHARED_VERSION = $(UTILS_LIBNAME).$(SHARED).$(LIBVERSION)
UTILS_SHARED_SO = $(UTILS_LIBNAME).$(SHARED).$(UTILS_SOVERSION)
UTILS_STATIC = $(UTILS_LIBNAME).$(STATIC)
SHARED_CMD = $(CC) -shared -o
.PHONY: all shared static tests clean install
all: shared static tests
shared: $(CJSON_SHARED) $(UTILS_SHARED)
static: $(CJSON_STATIC) $(UTILS_STATIC)
tests: $(CJSON_TEST)
test: tests
./$(CJSON_TEST)
.c.o:
$(CC) -c $(R_CFLAGS) $<
#tests
#cJSON
$(CJSON_TEST): $(CJSON_TEST_SRC) cJSON.h
$(CC) $(R_CFLAGS) $(CJSON_TEST_SRC) -o $@ $(LDLIBS) -I.
#static libraries
#cJSON
$(CJSON_STATIC): $(CJSON_OBJ)
$(AR) rcs $@ $<
#cJSON_Utils
$(UTILS_STATIC): $(UTILS_OBJ)
$(AR) rcs $@ $<
#shared libraries .so.1.0.0
#cJSON
$(CJSON_SHARED_VERSION): $(CJSON_OBJ)
$(CC) -shared -o $@ $< $(CJSON_SO_LDFLAG) $(LDFLAGS)
#cJSON_Utils
$(UTILS_SHARED_VERSION): $(UTILS_OBJ)
$(CC) -shared -o $@ $< $(CJSON_OBJ) $(UTILS_SO_LDFLAG) $(LDFLAGS)
#objects
#cJSON
$(CJSON_OBJ): cJSON.c cJSON.h
#cJSON_Utils
$(UTILS_OBJ): cJSON_Utils.c cJSON_Utils.h cJSON.h
#links .so -> .so.1 -> .so.1.0.0
#cJSON
$(CJSON_SHARED_SO): $(CJSON_SHARED_VERSION)
ln -s $(CJSON_SHARED_VERSION) $(CJSON_SHARED_SO)
$(CJSON_SHARED): $(CJSON_SHARED_SO)
ln -s $(CJSON_SHARED_SO) $(CJSON_SHARED)
#cJSON_Utils
$(UTILS_SHARED_SO): $(UTILS_SHARED_VERSION)
ln -s $(UTILS_SHARED_VERSION) $(UTILS_SHARED_SO)
$(UTILS_SHARED): $(UTILS_SHARED_SO)
ln -s $(UTILS_SHARED_SO) $(UTILS_SHARED)
#install
#cJSON
install-cjson:
mkdir -p $(INSTALL_LIBRARY_PATH) $(INSTALL_INCLUDE_PATH)
$(INSTALL) cJSON.h $(INSTALL_INCLUDE_PATH)
$(INSTALL) $(CJSON_SHARED) $(CJSON_SHARED_SO) $(CJSON_SHARED_VERSION) $(INSTALL_LIBRARY_PATH)
#cJSON_Utils
install-utils: install-cjson
$(INSTALL) cJSON_Utils.h $(INSTALL_INCLUDE_PATH)
$(INSTALL) $(UTILS_SHARED) $(UTILS_SHARED_SO) $(UTILS_SHARED_VERSION) $(INSTALL_LIBRARY_PATH)
install: install-cjson install-utils
#uninstall
#cJSON
uninstall-cjson: uninstall-utils
$(RM) $(INSTALL_LIBRARY_PATH)/$(CJSON_SHARED)
$(RM) $(INSTALL_LIBRARY_PATH)/$(CJSON_SHARED_VERSION)
$(RM) $(INSTALL_LIBRARY_PATH)/$(CJSON_SHARED_SO)
$(RM) $(INSTALL_INCLUDE_PATH)/cJSON.h
#cJSON_Utils
uninstall-utils:
$(RM) $(INSTALL_LIBRARY_PATH)/$(UTILS_SHARED)
$(RM) $(INSTALL_LIBRARY_PATH)/$(UTILS_SHARED_VERSION)
$(RM) $(INSTALL_LIBRARY_PATH)/$(UTILS_SHARED_SO)
$(RM) $(INSTALL_INCLUDE_PATH)/cJSON_Utils.h
remove-dir:
$(if $(wildcard $(INSTALL_LIBRARY_PATH)/*.*),,rmdir $(INSTALL_LIBRARY_PATH))
$(if $(wildcard $(INSTALL_INCLUDE_PATH)/*.*),,rmdir $(INSTALL_INCLUDE_PATH))
uninstall: uninstall-utils uninstall-cjson remove-dir
clean:
$(RM) $(CJSON_OBJ) $(UTILS_OBJ) #delete object files
$(RM) $(CJSON_SHARED) $(CJSON_SHARED_VERSION) $(CJSON_SHARED_SO) $(CJSON_STATIC) #delete cJSON
$(RM) $(UTILS_SHARED) $(UTILS_SHARED_VERSION) $(UTILS_SHARED_SO) $(UTILS_STATIC) #delete cJSON_Utils
$(RM) $(CJSON_TEST) #delete test

View File

@@ -96,9 +96,9 @@ CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
return (const char*) (global_error.json + global_error.position); 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; return NULL;
} }
@@ -106,9 +106,9 @@ CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item)
return item->valuestring; 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; return (double) NAN;
} }
@@ -511,7 +511,7 @@ static unsigned char* ensure(printbuffer * const p, size_t needed)
return NULL; return NULL;
} }
memcpy(newbuffer, p->buffer, p->offset + 1); memcpy(newbuffer, p->buffer, p->offset + 1);
p->hooks.deallocate(p->buffer); 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"); length = sprintf((char*)number_buffer, "null");
} }
else if(d == (double)item->valueint)
{
length = sprintf((char*)number_buffer, "%d", item->valueint);
}
else else
{ {
/* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */ /* 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.content = (const unsigned char*)value;
buffer.length = buffer_length; buffer.length = buffer_length;
buffer.offset = 0; buffer.offset = 0;
buffer.hooks = global_hooks; 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); cJSON_free(replacement->string);
} }
replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
if (replacement->string == NULL)
{
return false;
}
replacement->type &= ~cJSON_StringIsConst; replacement->type &= ~cJSON_StringIsConst;
return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement); 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) { if (a && a->child) {
a->child->prev = n; a->child->prev = n;
} }
return a; return a;
} }

View File

@@ -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 */ /* 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); 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 */ /* 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) #define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)

Some files were not shown because too many files have changed in this diff Show More