Skip to content
This repository has been archived by the owner on Jan 13, 2023. It is now read-only.

Socket back-end and VU Scale functionality #15

Open
wants to merge 26 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
9b3c813
Experimental vu_scale option
Gadgetoid Apr 5, 2017
ee6c579
Added experimental Socket client mode
Gadgetoid Apr 6, 2017
f645c51
Added POC Python socket server
Gadgetoid Apr 6, 2017
88b364d
Merge branch 'devel' of github.com:pimoroni/pivumeter into devel
Gadgetoid Apr 25, 2017
c82488e
Update to socket client and server
Gadgetoid Apr 25, 2017
2a1cbda
Started adding FFT support to socket mode
Gadgetoid Apr 25, 2017
193eea2
Added FFT and SPHD example
Gadgetoid Apr 25, 2017
472bcf8
Advanced example to display text overriding EQ
Gadgetoid Apr 25, 2017
34d123f
Chmod socket file
Gadgetoid Apr 26, 2017
6a635ad
Unicorn HAT example
Gadgetoid Apr 26, 2017
899358b
Refactor server into library
Gadgetoid May 11, 2017
ee997f6
Fixed library, speakerphat server example
Gadgetoid May 11, 2017
0579dc8
Tweaked 0777 to 0o777
Gadgetoid May 11, 2017
d266cd2
Create README.md
Gadgetoid May 11, 2017
b5ca7e2
Very beta example of Shairport Metadata on SPHD
Gadgetoid May 12, 2017
0023f79
Merge branch 'devel' of github.com:pimoroni/pivumeter into devel
Gadgetoid May 12, 2017
23606d5
Mopidy example
Gadgetoid May 15, 2017
cf95c8b
Relaxed timeout for Zero
Gadgetoid May 15, 2017
1752d23
Update README.md
roblan Oct 9, 2017
367c7b1
Update README.md
roblan Oct 29, 2017
4ec8c68
Update README.md
roblan Oct 29, 2017
e92b53b
Merge pull request #19 from roblan/patch-1
Gadgetoid Nov 17, 2017
4685277
Added close handler, improved level calcs
Gadgetoid Feb 1, 2018
45eb18f
Added check for close before calling
Gadgetoid Feb 1, 2018
2fd7c1b
add 3D Xmas Tree for Raspberry Pi example
roblan Oct 6, 2018
f0e3332
Merge pull request #29 from roblan/devel
Gadgetoid Oct 17, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ ACLOCAL_AMFLAGS = -I m4

lib_LTLIBRARIES = libpivumeter.la

libpivumeter_la_SOURCES = src/pivumeter.c src/devices/scroll-phat.c src/devices/scroll-phat-hd.c src/devices/blinkt.c src/devices/speaker-phat.c src/devices/phat-beat.c
libpivumeter_la_SOURCES = src/pivumeter.c src/devices/socket.c src/devices/scroll-phat.c src/devices/scroll-phat-hd.c src/devices/blinkt.c src/devices/speaker-phat.c src/devices/phat-beat.c
22 changes: 22 additions & 0 deletions python_server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Pi VU Meter: Python Front-end

The `pivumeter` Python library creates a socket-based server to which the Pi VU Meter ALSA plugin can
connect and stream left/right VU amplitude and FFT transform frequency bins.

## Installing

Currently to run this code you will need to clone the `devel` branch of Pi VU Meter and compile it from source.

You may use our automated setup to do so, specifying the output device to `socket`
```
setup.sh socket
```
You can also compile and set up thing yourself - just follow [this guide](../README.md#installing) but change the `output-device` to `socket`.

After that you need to install python pivumeter library.
Just go to the `pivumeter/python_server/library` folder and run
```
sudo python setup.py install
```

Finally, run the desired example from the Python Server examples folder and play some audio!
58 changes: 58 additions & 0 deletions python_server/examples/3d-xmas-tree.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#!/usr/bin/env python
import pivumeter
from signal import pause
from gpiozero import LEDBoard
from time import sleep
from random import shuffle

MAX = 65535.0

class Xmas(pivumeter.OutputDevice):
def setup(self):
self.busy = False
self.tree = LEDBoard(*(2, 19,16,25,27,11, 17,4,8,5,26,13,9, 18,20,24,22,15,6,12, 23,10,14,7,21), pwm = True)
self.leds = [0] * 5
self.blink()

def normalize(self, number):
return max(float(format(number/MAX, '.1f')), 0.05)

def display(self):
self.busy = True
values = [self.leds[0]] + [self.leds[1]] * 5 + [self.leds[2]] * 7 + [self.leds[3]] * 7 + [self.leds[4]] * 5
self.tree.value = values
sleep(0.025)
self.busy = False

def display_fft(self, bins):
if self.busy: return
bins = bins[:(len(self.leds) - 1)];
self.leds = [self.leds[0]] + map(lambda x: self.normalize(x), bins);

def display_vu(self, left, right):
if self.busy: return
vu = left + right
self.leds[0] = self.normalize(vu)
if vu == 0:
if self.blinking != True:
self.blink()
else:
self.blinking = False
self.display()

def cleanup(self):
for led in reversed(self.tree.leds):
led.off()
sleep(0.1)

def blink(self):
self.blinking = True
leds = list(self.tree.leds[1:])
shuffle(leds)
self.tree[0].on()
for led in leds:
led.pulse()
sleep(0.05)

pivumeter.run(Xmas)
pause()
63 changes: 63 additions & 0 deletions python_server/examples/blinkt-server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#!/usr/bin/env python
"""
A basic implementaton of a Pi VU Meter python server, for use with the "socket" mode.

To create a server for a specific HAT or pHAT you must derive from the pivumeter.OutputDevice class.

This class includes three methods you should override:

setup(self): Perform any initial setup for your output device here
display_vu(self, left, right): Receives the left/right VU meter data unscaled
cleanup(self): Perform any cleanup for your output device here

The left and right channel values passed into `display_vu` are unscaled. It is your responsibility to
scale them to a sensible range for display on your HAT or pHAT.
"""
import pivumeter
import signal
import blinkt
#import speakerphat

BRIGHTNESS = 255

class OutputBlinkt(pivumeter.OutputDevice):
def setup(self):
self.base_colours = [(0,0,0) for x in range(blinkt.NUM_PIXELS)]
self.generate_base_colours(BRIGHTNESS)

def generate_base_colours(self, brightness = 255.0):
for x in range(blinkt.NUM_PIXELS):
self.base_colours[x] = (float(brightness)/blinkt.NUM_PIXELS-1) * x, float(brightness) - ((255/blinkt.NUM_PIXELS-1) * x), 0

def display_fft(self, bins):
pass

def display_vu(self, left, right):
left /= 2000.0
right /= 2000.0

level = max(left, right)
level = max(min(level, 8), 0)

for x in range(blinkt.NUM_PIXELS):
val = 0

if level > 1:
val = 1
elif level > 0:
val = level

r, g, b = [int(c * val) for c in self.base_colours[x]]

blinkt.set_pixel(x, r, g, b)
#speakerphat.set_led(x, int(val * 255.0))
level -= 1

blinkt.show()
#speakerphat.show()

def cleanup(self):
self.display_vu(0, 0)

pivumeter.run(OutputBlinkt)
signal.pause()
60 changes: 60 additions & 0 deletions python_server/examples/phatbeat-server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/usr/bin/env python
"""
A basic implementaton of a Pi VU Meter python server, for use with the "socket" mode.

To create a server for a specific HAT or pHAT you must derive from the pivumeter.OutputDevice class.

This class includes three methods you should override:

setup(self): Perform any initial setup for your output device here
display_vu(self, left, right): Receives the left/right VU meter data unscaled
cleanup(self): Perform any cleanup for your output device here

The left and right channel values passed into `display_vu` are unscaled. It is your responsibility to
scale them to a sensible range for display on your HAT or pHAT.
"""
import pivumeter
import signal
import phatbeat

BRIGHTNESS = 255

class OutputBlinkt(pivumeter.OutputDevice):
def setup(self):
self.base_colours = [(0,0,0) for x in range(phatbeat.CHANNEL_PIXELS)]
self.generate_base_colours(BRIGHTNESS)

def generate_base_colours(self, brightness = 255.0):
for x in range(phatbeat.CHANNEL_PIXELS):
self.base_colours[x] = (float(brightness)/phatbeat.CHANNEL_PIXELS-1) * x, float(brightness) - ((255/phatbeat.CHANNEL_PIXELS-1) * x), 0

def display_fft(self, bins):
pass

def display_vu(self, left, right):
left /= 2000.0
right /= 2000.0

left = max(min(left, 8), 0)
right = max(min(right, 8), 0)

self.set_level(0, left)
self.set_level(1, right)

phatbeat.show()

def set_level(self, channel, level):
for x in range(phatbeat.CHANNEL_PIXELS):
val = max(min(level, 1), 0)

r, g, b = [int(c * val) for c in self.base_colours[x]]

phatbeat.set_pixel(x, r, g, b, channel=channel)

level -= 1

def cleanup(self):
self.display_vu(0, 0)

pivumeter.run(OutputBlinkt)
signal.pause()
58 changes: 58 additions & 0 deletions python_server/examples/speakerphat-server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#!/usr/bin/env python

import pivumeter
import signal

BRIGHTNESS = 255

try:
import sn3218
except ImportError:
exit("This library requires the sn3218 module\nInstall with: sudo pip install sn3218")

class OutputSpeakerpHAT(pivumeter.OutputDevice):
NUM_PIXELS = 10

def set_led(self, index, value):
self.led_values[self.stupid_led_mappings[index]] = value

def show(self):
sn3218.output(self.led_values)

def setup(self):
self.stupid_led_mappings = [0, 1, 2, 4, 6, 8, 10, 12, 14, 16]

self.led_values = [0 for x in range(18)]

enable_leds = 0

for x in self.stupid_led_mappings:
enable_leds |= 1 << x

sn3218.enable_leds(enable_leds)
sn3218.enable()

def display_fft(self, bins):
pass

def display_vu(self, left, right):
left /= 2000.0
right /= 2000.0

level = max(left, right)
level = max(min(level, 8), 0)

for x in range(self.NUM_PIXELS):
val = max(min(level, 1), 0)

self.set_led(x, int(val * BRIGHTNESS))

level -= 1

self.show()

def cleanup(self):
self.display_vu(0, 0)

pivumeter.run(OutputSpeakerpHAT)
signal.pause()
88 changes: 88 additions & 0 deletions python_server/examples/sphd-advanced.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#!/usr/bin/env python

import pivumeter
import signal
import scrollphathd
import threading
import time

try:
import queue
except ImportError:
import Queue as queue

class OutputScrollPhatHD(pivumeter.OutputDevice):
def __init__(self):
super(OutputScrollPhatHD, self).__init__()

self.running = False
self.busy = False
scrollphathd.set_brightness(0.1)
self.messages = queue.Queue()

self._thread = threading.Thread(target=self.run_messages)
self._thread.daemon = True
self._thread.start()

def run_messages(self):
self.running = True
while self.running:
try:
message = self.messages.get(False)
self.busy = True
scrollphathd.clear()
length = scrollphathd.write_string(message)
scrollphathd.set_pixel(length + 17, 0, 0)
scrollphathd.show()
time.sleep(1)
for x in range(length):
if not self.running: break
scrollphathd.scroll(1)
scrollphathd.show()
time.sleep(0.05)

scrollphathd.clear()
self.messages.task_done()
self.busy = False
except queue.Empty:
pass
time.sleep(1)

def setup(self):
pass

def display_fft(self, bins):
if self.busy: return
self.busy = True
scrollphathd.set_graph(bins, low=0, high=65535, brightness=0.5, x=0, y=0)
scrollphathd.show()
self.busy = False

def display_vu(self, left, right):
pass

def cleanup(self):
self.running = False
self._thread.join()

print("""
This advanced proof of concept will let you type messages into the console.

They will display in place of the VU meter.

Type a message and hit enter for it to scroll across the display.

Press Ctrl+C then hit Enter to exit.
""")

output_device = OutputScrollPhatHD()

pivumeter.run(output_device)

try:
while pivumeter.running:
output_device.messages.put(raw_input("\n\nYour message: "))
time.sleep(1)
except KeyboardInterrupt:
pass

Loading