Documentation | Desktop App | Server | Controller
Client and server for Tomato Radio Automation software. Tomato is easy to use, and hard to screw up playout software written for the specific use case of Burning Man Information Radio.
The backend server is written in Python's Django web framework, heavily leveraging its automatic admin interface.
The desktop app is a native, cross-platform Svelte + Electron app. It communicates with the backend via a websocket and supports intermittent connectivity loss.
Detailed instructions on how to install the server in both development and production environments can be found here in the docs.
Download a development preview build here or run the client's code locally following the instruction here
To run the documentation locally, install Python 3.9 or higher. Then in your terminal,
# Install Poetry (for Python dependencies) if you don't already have it.
curl -sSL https://install.python-poetry.org | python3 -
# Clone the repo
git clone https://github.com/dtcooper/tomato.git
# Enter the docs code
cd tomato/docs
# Install dependencies and run
poetry install
poetry run mkdocs serve
Head over to http://localhost:8888/ in your web browser.
- Client — JavaScript (Node.js)
- Electron, Svelte, Tailwind CSS, daisyUI, and esbuild.
- Server — Python
- Libraries: Django, huey, Constance, and Starlette
- Tools, Databases, and Containers: PostgreSQL, docker-nginx-certbot, and Dozzle.
- Button Box (Controller) —
Raspberry Pi Pico
(or similar) and CircuitPython
- See
controller/README.md
for firmware/setup instructions
- See
- Documentation
Tomato's UX and UI was designed in part by Miranda Kay. Testing and feedback was provided by the entire Burning Man Information Radio (BMIR) team.
- Supress power save mode
- Trim silence on uploaded assets
- Reject files based on pre-processed file hash
- CSV export to client log entries
- Idiot mode, easy mode, advanced mode
-
Timeout on fetch?(websockets makes this unneeded, except for downloading files) - Attempt to prevent duplicate assets from playing within a certain time period
- Start/end time for assets in client are based on "is likely to play at" time
- Empty rotators are warned on (based on feature flag)
- Deal with non-playable assets (error state ones)
- Compression and selecting output device using a bridge to the web audio API.
- Any custom django admin pages can follow this guide
- Flash whole screen after configurable time with some messaging ("play the promos, station management has been notified")
- Button to get out of fullscreen (useful on Linux)
Changes for 2024 based on real world usage in 2023 and feedback
- Make rotators able to disabled (UI for assets / stopsets needs to show that too)
-
Implement soft delete for assets-- keep the file, but delete the DB entity- Behind the scenes track deleted files.
- Easier way to toggle, simple / standard / advanced view settings in client. Not in settings.
(Change advanced mode to "admin" mode)
- Build out "switch back to simple mode" timer feature a little better, ie
comma separated times?
- Build out "switch back to simple mode" timer feature a little better, ie
- Better datetime picker in admin
- Skip track in stopset when we get to it
-
Mark a bad asset? Interesting. Not sure how it would work.– too difficult to implement, too many opinions, person wishing to flag talks to manager-of-the-moment - Refresh playlist from backend. Connected client status from backend? Communicate what's in the playlist?
-
Status updates, ie news and traffic? Fullscreen thing?/Custom UI labels unused labels that play every N times (ie for telling the DJ to do something)-- Probably not - Round-robin (or "cycle evenly") rotator scheduling, ignoring weight as an option for a rotator
- Check / validate randomization algorithm
- Validated! Review of algorithm provided by Andy
- Mini-player column in asset list view
- Asset alternates (single asset has 4-5 underlying audio files that are cycled through)
- Backend done
- A large clock in the UI
- Make weights for previous 24 hours... AND reflect that in front-end (day-of
pill) and back-end (sortable)... will require change to
END_DATE_PRIORITY_WEIGHT_MULTIPLIER
- Stop playing at end of current asset. (Stop playing in 3s with fadeout as well?)
Other things
- Ability to do speech synthesis / pull asset from API? / weather
- Best cross-platform way to do this might be to use text2wav.node.js to generate WAV files with a timeout
- KLOS color scheme:
#D91E75
,#4B89BF
,#8CBF3F
,#F2D750
, and#D95525
- "Island Mode" with an embedded standalone Python distribution
- Login interstitial to populate with demo data
- Integrated Twilio call board
- Single app client lock (ie only ONE client per username/password)'
- Way to parse filename into rotator, start/end date
- Submit form built into Tomato?
- Silence detection REJECTs audio assets in backend (if there's more than 2 seconds?) (behind FEATURE flag)
- Export all audio assets as zip
- Import as well (have to be careful with different
protocol.json:protocol_version
)
- Import as well (have to be careful with different
- Add configurable silence between ads. Crossfade, with fade points? Fancy!
- Client "Demo mode", requiring no backend with demo assets.
- Button to play an asset from a specific rotator
- Backend done as
SINGLE_PLAY_ROTATORS
- Backend done as
- Cursor can be a fun thing?
This project is licensed under the MIT License — see the LICENSE file for details.