Trying to monitor my speaker/headphone usage on my laptop.
Table of content
Step 1 Gather data to perform analytics.
Step 2 Perform analytics on the time-series data obtained.
Step 3 Create a summary and visualize it.
Linux machines using ALSA/Pulseaudio play sound using a client-server architecture. A C program based on pactl subscribes to events on output devices and applications playing sound, and logs them to a file in CSV-format.
See the diff to know the changes made
Sample dumps are available in examples.
This Go program reads the log file provided and dumps a summary on the console. Additionally, it can start a web server and let you pictorially view in your web browser. HTML is awesome 😎
A text summary is simple to print on terminal screen, but a pictorial view would have been more appealing. HTML/CSS/JS was the go-to choice here. I tried playing with gg, but gave up after trying hard to center align text. If you can invest that time, please let me know.
Build
git clone https://github.com/himanshub16/music-habits
cd music-habits
./setup.sh
start collecting data
cd pulseaudio/src
make pactl
./pactl
view data collected
cd pulseaudio/src
tail -f sink*
generate summary
# to print summary (notice the file path)
# duration can be today/yesterday/month/all
go run generate_report.go -logfile pulseaudio/src/sink_input-firefox.log -duration today
# to visualize in browser
go run generate_report.go -logfile pulseaudio/src/sink_input-firefox.log -interactive -port 5000
Pulseaudio provides a great API on Linux which provides
- list of sound sinks (output devices),
- list of sink-inputs (applications/services producing sound),
- properties as volume, corked (is paused), mute, etc. and also
- subscribe to events.
pulseaudio Python drivers are a great choice to use the library. However, I couldn't find one which provides corked status
for any sink-input. This is required to know that a sink-input (browser/music player) has paused playing, and there is nothing coming out of the speakers.
This is where C came to rescue. However, due to very tiring nature of C, and after dealing with many naive mistakes (coming back from Python/JavaScript/Golang), I went up to tweaking pactl.c
to my use-case, and it works well.
Currently, I couldn't compile pactl.c
directly because of incorrect compilation flags and missing shared libraries.
In case you can help out with the right flags, or an awesome makefile to compile this without having to clone entire pulseaudio
codebase from git, feel free to help me out.
That also helps in fixing the filename from pactl.c
to something more appropriate.
It is just simple loops with some grouping and calculations. Python/NodeJS would be have been easier, but I just wanted to spend more time getting comfortable with Golang.
Additionally, it has a decent web server built in, and has everything you need (I miss you map and filter 😭).
Using an entirely Go based tool is something I would prefer. I gave a lot of try with gg, but after lot of hardwork required to fix and align the text, I gave up and moved to a simpler solution of using HTML and passing data from Golang via a web server.
If you are enthusiastic about giving this a try, feel free to let me know on this issue.