Compare commits

..

53 Commits

Author SHA1 Message Date
Jamie Hardt 742c0b91fb Update CONTRIBUTING.md
Updated agents policy
2026-05-03 12:18:23 -07:00
Jamie Hardt 8e56a1aeb2 Update python-package.yml 2026-04-03 10:41:38 -07:00
Jamie Hardt 6bc3636814 Update .readthedocs.yaml
Updating RTD build to `ubuntu-lts-latest`
2026-03-30 11:57:04 -07:00
Jamie Hardt e12ae4519e Update contribution guidelines regarding ML systems 2026-02-15 15:48:07 -08:00
Jamie Hardt 8926274c50 Update CONTRIBUTING.md
No LLM/ML contributions
2026-02-14 06:30:13 -08:00
jamie 95ba34187a Docs 2025-10-09 23:22:26 -07:00
jamie 4d2dfcd370 Docs 2025-10-09 23:21:43 -07:00
jamie 717b6a4117 Docs 2025-10-09 23:19:05 -07:00
jamie 7393afac95 Docs 2025-10-09 23:17:46 -07:00
jamie e9450cd65a Docs 2025-10-09 23:16:11 -07:00
jamie 51b1a2e8b4 Docs 2025-10-09 23:15:19 -07:00
jamie 53303232b4 Docs 2025-10-09 23:11:00 -07:00
jamie 3519a0251f Docs 2025-10-09 23:09:51 -07:00
jamie 79ec1649c4 Docs 2025-10-09 23:09:04 -07:00
jamie 7c3f4c9b5e Docs 2025-10-09 23:08:32 -07:00
jamie 2e8224cb3c Docs fix 2025-10-09 23:07:39 -07:00
jamie 8ef4186b4c Merge branch 'master' of https://github.com/iluvcapra/wavinfo 2025-10-09 23:02:32 -07:00
jamie cd5346c1cb Docs fixups 2025-10-09 23:02:15 -07:00
Jamie Hardt 925bf4f8a6 Update pythonpublish.yml 2025-10-09 22:55:13 -07:00
Jamie Hardt e98ba0bf07 Update pythonpublish.yml 2025-10-09 22:48:40 -07:00
jamie afca634dc3 modernized build action 2025-10-09 22:44:58 -07:00
Jamie Hardt df9ae0f4d6 Update pyproject.toml 2025-10-09 22:34:45 -07:00
Jamie Hardt 2f23bcb982 Merge pull request #40 from iluvcapra/maint-uv
Build modernization
2025-10-09 22:33:55 -07:00
jamie 5e641b0963 Removing .flake8 file 2025-10-09 22:32:10 -07:00
jamie 1b57ad0fac Typo 2025-10-09 22:26:04 -07:00
jamie c7a34e0064 Added 3.14 to test matrix and dropped 3.8 2025-10-09 22:24:45 -07:00
jamie 6b788484da Typo 2025-10-09 22:22:12 -07:00
jamie 76905f1a40 Updated name of lint workflow 2025-10-09 22:21:11 -07:00
jamie 9ac06040a2 Making changes to the workflows 2025-10-09 22:16:12 -07:00
jamie 1b78f5b821 Reorganized pyproject, nudged version 2025-10-09 22:08:36 -07:00
jamie 03d718b4ad Fixed dumb typo 2025-10-09 22:06:48 -07:00
jamie 61f79760e6 Initial work on uv build system
Moved module into src/ and modernized pyproject.toml
2025-10-09 21:49:33 -07:00
Jamie Hardt afe5ea9ed3 Update pythonpublish.yml
Updated publish action to latest version
2025-09-08 12:49:05 -07:00
Jamie Hardt c1205d52e8 Merge pull request #38 from iluvcapra/maint-no-mastodon
Workflow Spruce-up
2024-11-26 12:00:18 -08:00
Jamie Hardt b82b6b6d43 Fixed publish to Bluesky worksflow 2024-11-26 11:56:51 -08:00
Jamie Hardt 8ef664266f Updated flake8 step to use python 3.13 2024-11-26 10:30:24 -08:00
Jamie Hardt dfb7e34fc7 Update pythonpublish.yml
Updated `checkout` and `setup-python` versions
2024-11-25 18:41:36 -08:00
Jamie Hardt 2ebdefaab5 Update pythonpublish.yml 2024-11-25 18:37:15 -08:00
Jamie Hardt c609e22270 Update pythonpublish.yml 2024-11-25 18:33:53 -08:00
Jamie Hardt ef9c39f1b6 Update pythonpublish.yml
Adding posting to Bluesky
2024-11-25 18:32:19 -08:00
Jamie Hardt cc9d884ea8 Update pythonpublish.yml
Removed Mastodon notification step
2024-11-25 18:07:17 -08:00
Jamie Hardt 94563f69a9 Merge pull request #37 from iluvcapra/feature-interactive
Feature: interactive shell
2024-11-25 11:17:20 -08:00
Jamie Hardt 2830cb87a4 flake8 2024-11-25 11:15:16 -08:00
Jamie Hardt 1c8581ff35 Merge branch 'master' of https://github.com/iluvcapra/wavinfo into feature-interactive 2024-11-25 11:11:04 -08:00
Jamie Hardt 1d499d9741 Merge pull request #36 from iluvcapra/feature-smpl
Feature: smpl Metadata
2024-11-25 11:09:43 -08:00
Jamie Hardt 8cabf948ff Merge branch 'master' of https://github.com/iluvcapra/wavinfo into feature-interactive 2024-11-25 10:38:43 -08:00
Jamie Hardt c13b07e4a3 typing fix for python 3.8/3.9 2024-11-25 10:33:07 -08:00
Jamie Hardt ac37c14b3d flake8 2024-11-25 10:30:02 -08:00
Jamie Hardt 36e4a02ab8 Documenation of base64 output 2024-11-25 10:27:25 -08:00
Jamie Hardt ffc0c48af7 A small change to report umids as binary data 2024-11-25 10:18:24 -08:00
Jamie Hardt 206962b218 More documentation changes. 2024-11-25 10:16:26 -08:00
Jamie Hardt d560e5a9f0 Added documentation. 2024-11-25 10:04:50 -08:00
Jamie Hardt 98ca1ec462 Implementing an interactive shell
...for browsing metadata
2024-11-24 16:23:39 -08:00
26 changed files with 320 additions and 139 deletions
-3
View File
@@ -1,3 +0,0 @@
[flake8]
per-file-ignores =
wavinfo/__init__.py: F401
+6 -6
View File
@@ -16,21 +16,21 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
steps: steps:
- uses: actions/checkout@v2.5.0 - uses: actions/checkout@v6.0.2
- name: Set up Python ${{ matrix.python-version }} - name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4.3.0 uses: actions/setup-python@v6.2.0
with: with:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
- name: Install dependencies - name: Install dependencies
run: | run: |
python -m pip install --upgrade pip python -m pip install --upgrade pip
python -m pip install pytest python -m pip install --group dev
python -m pip install -e . python -m pip install .
- name: Setup FFmpeg - name: Setup FFmpeg
uses: FedericoCarboni/setup-ffmpeg@v2 uses: federicocarboni/setup-ffmpeg@v3.1
- name: Test with pytest - name: Test with pytest
run: | run: |
pytest pytest
@@ -1,7 +1,7 @@
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions # This workflow will install Python dependencies, run tests and lint with a variety of Python versions
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
name: Flake8 name: Lint with Ruff
on: on:
push: push:
@@ -11,12 +11,11 @@ on:
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
python-version: ["3.11"] python-version: ["3.13", "3.14"]
steps: steps:
- uses: actions/checkout@v2.5.0 - uses: actions/checkout@v2.5.0
@@ -27,14 +26,8 @@ jobs:
- name: Install dependencies - name: Install dependencies
run: | run: |
python -m pip install --upgrade pip python -m pip install --upgrade pip
python -m pip install flake8 python -m pip install --group dev
python -m pip install -e . python -m pip install .
- name: Lint with flake8 - name: Lint with ruff
run: | run: |
# stop the build if there are Python syntax errors or undefined names ruff check src
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Lint with flake8
run: |
flake8 wavinfo
+22 -18
View File
@@ -8,29 +8,33 @@ jobs:
deploy: deploy:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v4.2.2
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v1 uses: actions/setup-python@v5.3.0
with: with:
python-version: '3.x' python-version: '3.x'
- name: Install dependencies - name: Install dependencies
run: | run: |
python -m pip install --upgrade pip python -m pip install --upgrade pip
pip install setuptools build wheel twine lxml - name: Setup uv and Handle Its Cache
- name: Build and publish # You may pin to the exact commit or the version.
env: # uses: hynek/setup-cached-uv@757bedc3f972eb7227a1aa657651f15a8527c817
TWINE_USERNAME: __token__ uses: hynek/setup-cached-uv@v2.3.0
TWINE_PASSWORD: ${{ secrets.PYPI_APIKEY }} - name: Build
run: | run: |
python -m build . uv build --wheel
twine upload dist/* - name: Publish to Pypi
- name: Report to Mastodon uses: pypa/gh-action-pypi-publish@v1.13.0
uses: cbrgm/mastodon-github-action@v1.0.1
with: with:
message: | password: ${{ secrets.PYPI_APIKEY }}
I just released a new version of wavinfo, my library for reading WAVE file metadata! # - name: Send Bluesky Post
#sounddesign #filmmaking #audio #python # uses: myConsciousness/bluesky-post@v5
${{ github.server_url }}/${{ github.repository }} # with:
env: # text: |
MASTODON_URL: ${{ secrets.MASTODON_URL }} # I've released a new version of wavinfo, my module for
MASTODON_ACCESS_TOKEN: ${{ secrets.MASTODON_ACCESS_TOKEN }} # reading WAVE metadata.
# link-preview-url: ${{ github.server_url }}/${{ github.repository }}
# identifier: ${{ secrets.BLUESKY_APP_USER }}
# password: ${{ secrets.BLUESKY_APP_PASSWORD }}
# service: bsky.social
# retry-count: 1
+6 -8
View File
@@ -7,13 +7,13 @@ version: 2
# Set the version of Python and other tools you might need # Set the version of Python and other tools you might need
build: build:
os: ubuntu-20.04 os: ubuntu-lts-latest
tools: tools:
python: "3.10" python: "3.13"
# You can also specify other tool versions: jobs:
# nodejs: "16" install:
# rust: "1.55" - pip install --upgrade pip
# golang: "1.17" - pip install --group 'doc'
# Build documentation in the docs/ directory with Sphinx # Build documentation in the docs/ directory with Sphinx
sphinx: sphinx:
@@ -28,5 +28,3 @@ python:
install: install:
- method: pip - method: pip
path: . path: .
extra_requirements:
- doc
+32
View File
@@ -13,3 +13,35 @@ If you discover a bug or would like better support for a feature, please do the
review it as soon as I can. There's a `.devcontainer` available so you can creates commits review it as soon as I can. There's a `.devcontainer` available so you can creates commits
on this project in a GitHub codespace. on this project in a GitHub codespace.
## Regarding use of Agents
`wavinfo` is an open-source project that is offered free for no commerical gain, and
is developed and maintained for educational and creative reasons.
If you use an agent or LLM to produce code for it you are missing out on the benefits
of contributing to an open-source project, particularly community, collaboration with
other developers and designers, and being able to learn and experiment without the
burden of deadlines or worrying about business cases or profits.
This project is supposed to be fun, do not let machines have fun for you.
We can't prevent you from using LLMs to contribute to this project but we ask you
abide by the following eitiquette when doing so:
* All communication with the maintainers must be written by a human in their own
voice. Never use an LLM to craft thread comments, discussion posts, issues, emails
or other correspondence with other developers or the maintainers.
* PRs must be submitted by a person. Do not allow an agent to submit its own PRs to
this project.
* Especially if you are a new contributor to this project, please submit only one PR
at a time and please restrict the subject matter of the PR to a specific unit,
module or tool. All submissions have to be reviewed and understood by the
maintainers before they can be merged.
Obviously we can't verify if you follow all of these rules but certain telltale
traits of LLM-predicted text or code will raise a flag: lack of brevity in
descriptions or code comments, large amounts of text describing your process or
steps that add little to understanding the changes you've made, use of an
obsequious tone or being excessively accomodating, immediately doing requests
without further discussion or clarifications.
+1 -1
View File
@@ -2,7 +2,7 @@
![GitHub last commit](https://img.shields.io/github/last-commit/iluvcapra/wavinfo) [![Documentation Status](https://readthedocs.org/projects/wavinfo/badge/?version=latest)](https://wavinfo.readthedocs.io/en/latest/?badge=latest) ![](https://img.shields.io/github/license/iluvcapra/wavinfo.svg) ![GitHub last commit](https://img.shields.io/github/last-commit/iluvcapra/wavinfo) [![Documentation Status](https://readthedocs.org/projects/wavinfo/badge/?version=latest)](https://wavinfo.readthedocs.io/en/latest/?badge=latest) ![](https://img.shields.io/github/license/iluvcapra/wavinfo.svg)
[![Tests](https://github.com/iluvcapra/wavinfo/actions/workflows/python-package.yml/badge.svg)](https://github.com/iluvcapra/wavinfo/actions/workflows/python-package.yml) [![Tests](https://github.com/iluvcapra/wavinfo/actions/workflows/python-package.yml/badge.svg)](https://github.com/iluvcapra/wavinfo/actions/workflows/python-package.yml)
[![Flake8](https://github.com/iluvcapra/wavinfo/actions/workflows/python-flake8.yml/badge.svg)](https://github.com/iluvcapra/wavinfo/actions/workflows/python-flake8.yml) [![Ruff](https://github.com/iluvcapra/wavinfo/actions/workflows/python-ruff.yml/badge.svg)](https://github.com/iluvcapra/wavinfo/actions/workflows/python-ruff.yml)
[![codecov](https://codecov.io/gh/iluvcapra/wavinfo/branch/master/graph/badge.svg?token=9DZQfZENYv)](https://codecov.io/gh/iluvcapra/wavinfo) [![codecov](https://codecov.io/gh/iluvcapra/wavinfo/branch/master/graph/badge.svg?token=9DZQfZENYv)](https://codecov.io/gh/iluvcapra/wavinfo)
# wavinfo # wavinfo
+106 -60
View File
@@ -6,89 +6,135 @@ from the command line and output metadata to stdout.
.. code-block:: shell .. code-block:: shell
$ wavinfo [--ixml | --adm] INFILE + $ wavinfo [[-i] | [--ixml | --adm]] INFILE +
By default, `wavinfo` will output a JSON dictionary for each file argument.
Options Options
------- -------
Two option flags will change the behavior of the command: By default, `wavinfo` will output a JSON dictionary for each file argument.
``-i``
`wavinfo` will run in `interactive mode`_.
Two option flags will change the behavior of the command in non-interactive
mode:
``--ixml`` ``--ixml``
The *\-\-ixml* flag will cause `wavinfo` to output the iXML metadata payload The *\-\-ixml* flag will cause `wavinfo` to output the iXML metadata
of each input wave file, or will emit an error message to stderr if iXML payload of each input wave file, or will emit an error message to stderr if
metadata is not present. iXML metadata is not present.
``--adm`` ``--adm``
The *\-\-adm* flag will cause `wavinfo` to output the ADM XML metadata The *\-\-adm* flag will cause `wavinfo` to output the ADM XML metadata
payload of each input wave file, or will emit an error message to stderr if payload of each input wave file, or will emit an error message to stderr if
ADM XML metadata is not present. ADM XML metadata is not present.
These options are mutually-exclusive, with `\-\-adm` taking precedence. These options are mutually-exclusive, with `\-\-adm` taking precedence. The
``--ixml`` and ``--adm`` flags futher take precedence over ``-i``.
Interactive Mode
-----------------
In interactive mode, `wavinfo` will present a command prompt which allows you
to query the files provided on the command line and explore the metadata tree
interactively. Each file on the command line is scanned and presented as a
tree of metadata records.
Commands include:
``ls``
List the available metadata keys at the current level.
``cd``
Traverse to a metadata key in the current level (or enter `..` to go up
to the prevvious level).
``bye``
Exit to the shell.
Type `help` or `?` at the prompt to get a full list of commands.
Example Output Example Output
-------------- --------------
.. attention::
Metadata fields containing binary data, such as the Broadcast-WAV UMID, will
be included in the JSON output as a base-64 encoded string, preceded by the
marker "base64:".
.. code-block:: javascript .. code-block:: javascript
{ {
"filename": "tests/test_files/sounddevices/A101_1.WAV", "filename": "../tests/test_files/nuendo/wavinfo Test Project - Audio - 1OA.wav",
"run_date": "2022-11-26T17:56:38.342935", "run_date": "2024-11-25T10:26:11.280053",
"application": "wavinfo 2.1.0", "application": "wavinfo 3.0.0",
"scopes": { "scopes": {
"fmt": { "fmt": {
"audio_format": 1, "audio_format": 65534,
"channel_count": 2, "channel_count": 4,
"sample_rate": 48000, "sample_rate": 48000,
"byte_rate": 288000, "byte_rate": 576000,
"block_align": 6, "block_align": 12,
"bits_per_sample": 24 "bits_per_sample": 24
},
"data": {
"byte_count": 576000,
"frame_count": 48000
},
"ixml": {
"track_list": [
{
"channel_index": "1",
"interleave_index": "1",
"name": "",
"function": "ACN0-FOA"
}, },
"data": { {
"byte_count": 1441434, "channel_index": "2",
"frame_count": 240239 "interleave_index": "2",
"name": "",
"function": "ACN1-FOA"
}, },
"ixml": { {
"track_list": [ "channel_index": "3",
{ "interleave_index": "3",
"channel_index": "1", "name": "",
"interleave_index": "1", "function": "ACN2-FOA"
"name": "MKH516 A",
"function": ""
},
{
"channel_index": "2",
"interleave_index": "2",
"name": "Boom",
"function": ""
}
],
"project": "BMH",
"scene": "A101",
"take": "1",
"tape": "18Y12M31",
"family_uid": "USSDVGR1112089007124001008206300",
"family_name": null
}, },
"bext": { {
"description": "sSPEED=023.976-ND\r\nsTAKE=1\r\nsUBITS=$12311801\r\nsSWVER=2.67\r\nsPROJECT=BMH\r\nsSCENE=A101\r\nsFILENAME=A101_1.WAV\r\nsTAPE=18Y12M31\r\nsTRK1=MKH516 A\r\nsTRK2=Boom\r\nsNOTE=\r\n", "channel_index": "4",
"originator": "Sound Dev: 702T S#GR1112089007", "interleave_index": "4",
"originator_ref": "USSDVGR1112089007124001008206301", "name": "",
"originator_date": "2018-12-31", "function": "ACN3-FOA"
"originator_time": "12:40:00",
"time_reference": 2190940753,
"version": 1,
"umid": "0000000000000000000000000000000000000000000000000000000000000000",
"coding_history": "A=PCM,F=48000,W=24,M=stereo,R=48000,T=2 Ch\r\n",
"loudness_value": null,
"loudness_range": null,
"max_true_peak": null,
"max_momentary_loudness": null,
"max_shortterm_loudness": null
} }
],
"project": "wavinfo Test Project",
"scene": null,
"take": null,
"tape": null,
"family_uid": "E5DDE719B9484A758162FF7B652383A3",
"family_name": null
},
"bext": {
"description": "wavinfo Test Project Nuendo output",
"originator": "Nuendo",
"originator_ref": "USJPHNNNNNNNNN202829RRRRRRRRR",
"originator_date": "2022-12-02",
"originator_time": "10:21:06",
"time_reference": 172800000,
"version": 2,
"umid": "base64:k/zr4qE4RiaXyd/fO7GuCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
"coding_history": "A=PCM,F=48000,W=24,T=Nuendo\r\n",
"loudness_value": 327.67,
"loudness_range": 327.67,
"max_true_peak": 327.67,
"max_momentary_loudness": 327.67,
"max_shortterm_loudness": 327.67
} }
} }
}
+7 -8
View File
@@ -12,25 +12,24 @@
# add these directories to sys.path here. If the directory is relative to the # add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here. # documentation root, use os.path.abspath to make it absolute, like shown here.
# #
import importlib # import importlib
import os import os
import sys import sys
sys.path.insert(0, os.path.abspath('../..')) sys.path.insert(0, os.path.abspath('../../src'))
sys.path.insert(0, os.path.abspath("../../..")) sys.path.insert(0, os.path.abspath("../../../src"))
print(sys.path) print(sys.path)
import importlib
# -- Project information ----------------------------------------------------- # -- Project information -----------------------------------------------------
project = u'wavinfo' project = u'wavinfo'
copyright = u'2018-2024, Jamie Hardt' copyright = u'2018-2025, Jamie Hardt'
author = u'Jamie Hardt' author = u'Jamie Hardt'
# The short X.Y version # The short X.Y version
version = "3.1" version = "4.0"
# The full version, including alpha/beta/rc tags # The full version, including alpha/beta/rc tags
release = importlib.metadata.version("wavinfo") release = "4.0.0"
# release = importlib.metadata.version("wavinfo")
# -- General configuration --------------------------------------------------- # -- General configuration ---------------------------------------------------
+23 -18
View File
@@ -1,27 +1,26 @@
# https://python-poetry.org/docs/pyproject/
[build-system] [build-system]
requires = ["poetry-core"] requires = ["uv_build>=0.8.18,<0.9.0"]
build-backend = "poetry.core.masonry.api" build-backend = "uv_build"
[tool.poetry] [project]
name = "wavinfo" name = "wavinfo"
version = "3.1.0" version = "4.0.0"
description = "Probe WAVE files for all metadata" description = "Probe WAVE files for all metadata"
authors = ["Jamie Hardt <jamiehardt@me.com>"] authors = [{ name = "Jamie Hardt", email = "jamiehardt@me.com"}]
license = "MIT" license = "MIT"
readme = "README.md" readme = "README.md"
requires-python = ">=3.8"
classifiers = [ classifiers = [
'Development Status :: 5 - Production/Stable', 'Development Status :: 5 - Production/Stable',
'License :: OSI Approved :: MIT License', 'License :: OSI Approved :: MIT License',
'Topic :: Multimedia', 'Topic :: Multimedia',
'Topic :: Multimedia :: Sound/Audio', 'Topic :: Multimedia :: Sound/Audio',
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13" "Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14"
] ]
homepage = "https://github.com/iluvcapra/wavinfo" homepage = "https://github.com/iluvcapra/wavinfo"
repository = "https://github.com/iluvcapra/wavinfo.git" repository = "https://github.com/iluvcapra/wavinfo.git"
@@ -39,17 +38,22 @@ keywords = [
'broadcast' 'broadcast'
] ]
[tool.poetry.extras] dependencies = [
doc = ['sphinx', 'sphinx_rtd_theme'] "lxml>=6.0.2",
]
[tool.poetry.scripts] [dependency-groups]
wavinfo = 'wavinfo.__main__:main' dev = [
"pytest>=8.3.5",
"ruff>=0.14.0",
]
doc = [
"sphinx>=7.1.2",
"sphinx-rtd-theme>=3.0.2",
]
[tool.poetry.dependencies] [project.scripts]
python = "^3.8" wavinfo = "wavinfo:__main__.main"
lxml = "~= 5.3.0"
sphinx_rtd_theme = {version= '>= 1.1.1', optional=true}
sphinx = {version= '>= 5.3.0', optional=true}
[tool.pyright] [tool.pyright]
typeCheckingMode = "basic" typeCheckingMode = "basic"
@@ -65,3 +69,4 @@ disable = [
"R0913", # (too-many-arguments) "R0913", # (too-many-arguments)
"W0105", # (pointless-string-statement) "W0105", # (pointless-string-statement)
] ]
@@ -2,5 +2,8 @@
Probe WAVE Files for iXML, Broadcast-WAVE and other metadata. Probe WAVE Files for iXML, Broadcast-WAVE and other metadata.
""" """
__all__ = ['WavInfoReader', 'WavInfoEOFError']
from .wave_reader import WavInfoReader from .wave_reader import WavInfoReader
from .riff_parser import WavInfoEOFError from .riff_parser import WavInfoEOFError
+100 -1
View File
@@ -8,6 +8,9 @@ import json
from enum import Enum from enum import Enum
import importlib.metadata import importlib.metadata
from base64 import b64encode from base64 import b64encode
from cmd import Cmd
from shlex import split
from typing import List, Dict, Union
class MyJSONEncoder(json.JSONEncoder): class MyJSONEncoder(json.JSONEncoder):
@@ -24,6 +27,85 @@ class MissingDataError(RuntimeError):
pass pass
class MetaBrowser(Cmd):
prompt = "(wavinfo) "
metadata: Union[List, Dict]
path: List[str] = []
@property
def cwd(self):
root: List | Dict = self.metadata
for key in self.path:
if isinstance(root, list):
root = root[int(key)]
else:
root = root[key]
return root
@staticmethod
def print_value(collection, key):
val = collection[key]
if isinstance(val, int):
print(f" - {key}: {val}")
elif isinstance(val, str):
print(f" - {key}: \"{val}\"")
elif isinstance(val, dict):
print(f" - {key}: Dict ({len(val)} keys)")
elif isinstance(val, list):
print(f" - {key}: List ({len(val)} keys)")
elif isinstance(val, bytes):
print(f" - {key}: ({len(val)} bytes)")
elif val is None:
print(f" - {key}: (NO VALUE)")
else:
print(f" - {key}: Unknown")
def do_ls(self, _):
'List items at the current node: LS'
root = self.cwd
if isinstance(root, list):
print("List:")
for i in range(len(root)):
self.print_value(root, i)
elif isinstance(root, dict):
print("Dictionary:")
for key in root:
self.print_value(root, key)
else:
print("Cannot print node, is not a list or dictionary.")
def do_cd(self, args):
'Switch to a different node: CD node-name | ".."'
argv = split(args)
if argv[0] == "..":
self.path = self.path[0:-1]
else:
if isinstance(self.cwd, list):
if int(argv[0]) < len(self.cwd):
self.path = self.path + [argv[0]]
else:
print(f"Index {argv[0]} does not exist")
elif isinstance(self.cwd, dict):
if argv[0] in self.cwd.keys():
self.path = self.path + [argv[0]]
else:
print(f"Key \"{argv[0]}\" does not exist")
if len(self.path) > 0:
self.prompt = "(" + "/".join(self.path) + ") "
else:
self.prompt = "(wavinfo) "
def do_bye(self, _):
'Exit the interactive browser: BYE'
return True
def main(): def main():
version = importlib.metadata.version('wavinfo') version = importlib.metadata.version('wavinfo')
manpath = os.path.dirname(__file__) + "/man" manpath = os.path.dirname(__file__) + "/man"
@@ -51,8 +133,15 @@ def main():
default=False, default=False,
action='store_true') action='store_true')
parser.add_option('-i',
help='Read metadata with an interactive prompt',
default=False,
action='store_true')
(options, args) = parser.parse_args(sys.argv) (options, args) = parser.parse_args(sys.argv)
interactive_dict = []
# if options.install_manpages: # if options.install_manpages:
# print("Installing manpages...") # print("Installing manpages...")
# print(f"Docfiles at {__file__}") # print(f"Docfiles at {__file__}")
@@ -98,7 +187,12 @@ def main():
ret_dict['scopes'][scope][name] = value ret_dict['scopes'][scope][name] = value
json.dump(ret_dict, cls=MyJSONEncoder, fp=sys.stdout, indent=2) if options.i:
interactive_dict.append(ret_dict)
else:
json.dump(ret_dict, cls=MyJSONEncoder, fp=sys.stdout,
indent=2)
except MissingDataError as e: except MissingDataError as e:
print("MissingDataError: Missing metadata (%s) in file %s" % print("MissingDataError: Missing metadata (%s) in file %s" %
(e, arg), file=sys.stderr) (e, arg), file=sys.stderr)
@@ -106,6 +200,11 @@ def main():
except Exception as e: except Exception as e:
raise e raise e
if len(interactive_dict) > 0:
cli = MetaBrowser()
cli.metadata = interactive_dict
cli.cmdloop()
if __name__ == "__main__": if __name__ == "__main__":
main() main()
@@ -3,6 +3,7 @@
wavinfo \- probe wave files for metadata wavinfo \- probe wave files for metadata
.SH SYNOPSIS .SH SYNOPSIS
.SY wavinfo .SY wavinfo
.I "[\-i]"
.I "[\-\-adm]" .I "[\-\-adm]"
.I "[\-\-ixml]" .I "[\-\-ixml]"
.I FILE ... .I FILE ...
@@ -24,6 +25,10 @@ Output any iXML metdata in
.BR FILE . .BR FILE .
.IP "\-h, \-\-help" .IP "\-h, \-\-help"
Print brief help. Print brief help.
.IP "\-i"
Enter
.I "interactive mode"
and browse metadata in FILE with an interactive command prompt.
.SH DETAILED DESCRIPTION .SH DETAILED DESCRIPTION
.B wavinfo .B wavinfo
collects metadata according to different collects metadata according to different
@@ -89,7 +89,7 @@ class WavBextReader:
# umid_str = umid_parsed.basic_umid_to_str() # umid_str = umid_parsed.basic_umid_to_str()
# else: # else:
umid_str = None # umid_str = None
return {'description': self.description, return {'description': self.description,
'originator': self.originator, 'originator': self.originator,
@@ -98,7 +98,7 @@ class WavBextReader:
'originator_time': self.originator_time, 'originator_time': self.originator_time,
'time_reference': self.time_reference, 'time_reference': self.time_reference,
'version': self.version, 'version': self.version,
'umid': umid_str, 'umid': self.umid,
'coding_history': self.coding_history, 'coding_history': self.coding_history,
'loudness_value': self.loudness_value, 'loudness_value': self.loudness_value,
'loudness_range': self.loudness_range, 'loudness_range': self.loudness_range,