Electrical-Forenics Home ray@RayFranco.com                       601.529.7473

   Updated 4/17/2025

   © Dr. Ray Franco, PhD, PE  :  2006-2025

Jukebox

  1. Official Raspberry Pi HAT DAC [1]
  2. HAT - Hifiberry DAC [1]
  3. HAT - JustBoom [2]
  4. HAT - Hi Berry DAC [3 for Zero ]
  5. D57YFLYCP1EFLTMK

References

  1. Raspberry Pi Documentation - Raspberry Pi Audio
  2. Raspberry Pi DAC Pro
  3. Reviving a console stereo with a Raspberry Pi and PiMusicBox
  4. raspberry pi official magazine - build a home music system with raspberry pi
  5. raspberry pi official magazine - Build a multi-room audio system with Raspberry Pi
  6. How to Build a Raspberry Pi Jukebox Any Non-Geek Can Use
  7. Raspberry Pi Forums - Fruitbox
  8. Fruitbox V2 for Raspberry Pi4 and Pi5 rev 1.9
  9. MP3 Kit for Rowe R-86 Jukebox-Print Your Own Labels
  10. Rowe R-86 Service Manual
  11. Raspberry Pi Forum - Accessing GPIO pins from a BASH Script on a Raspberry Pi 5
  12. A history of GPIO usage on Raspberry Pi devices, and current best practices
  13. Raspberry Pi Install Guide/Raspberry Pi GPIO

Rowe (AMI) R-86 Jukebox

Replacement Glass

You can get replacmeent tempered glass at https://www.glassgenius.com/tempered-glass.

For a 39-1/16 x 21-3/4 x 1/8 inch tempered glass the cost is $139.67, which includes shipping.

Inverse RIAA Filter

In order to pack more data onto a vinyl record, the recording industry reduced low frequencies and increased the high frequencies. To corect for this, the output of record player (phono) passes through a preamp that does just the opposite. In the audio industry, this is refereed to as RIAA equalization. RIAA stands for Recording Industry Assocation of America [1-2].

Unfortunately, on many jukeboxes, the preamp stage and linear amplifier stage are in the same unit, and there is no auxiliary linear input for tape and mp3 players.

You can antenuate the output from an mp3 player to the same levels and the phono cartridge. However, the output to the speakers will not be liner. However, if you pass the output of an mp3 player through a Inverse RIAA filter and antenuator, then the output to speakers will be linear.

Thus. to send the output of an mp3 player to a phono preamp, you need to pass it through a inverse or reverse RIAA filter antenuator.

Another problem with sending an mp3 output to a jukebox is that the amplifier (including) the pre-amp is muted when a record is not playing. This is to prevent the noise from the record being mounted from being amplified.

  1. Youtube - The RIAA Equalization Curve
  2. Youtube - The Truth About Vinyl - Vinyl vs. Digital
  3. Wiring into the Amp on a AMI Rowe R-84
  4. #1656 ROWE 45rpm JUKEBOX Repair Advice-Packing Tips- Adjustments-"Todd's Tips" - TNT Amusements
  5. #68 How to Unpack and Setup a ROWE 45rpm Record Jukebox! TNT Amusements
  6. Ebay $14 -Hydraulic Piston Support for Rowe Ami Jukeboxes Set of 2 Jukebox! TNT Amusements
  7. A&B Jukebox Repair - Bruce
  8. i
  9. Jukebox Support
  10. Jeremys Jukebox Repair
  11. Tools to help you in your Rowe Jukebox Repair
  12. troubleshooting sound issues on a rowe juke box abjukebox repair
  13. Troubleshooting error codes in a Rowe record jukebox
  14. AMI Rowe R-88 blutooth
  15. Rowe R86 - Sevice & Parts Manul
  16. Rowe Juke Box Service Manuals

Inverse RIAA Filter

  1. A Precision inverse RIAA Filter for Phono Stages
  2. iRIAA2 - Inverse RIAA Filter
  3. iRIAA2 - Users Manual
  4. On Reference RIAA Networks

Line Level Audio

Large Speakers need 50 to 100 volts.

Line out is o.5 to 1 volt

Micophone 0.1 volts 1 mv to 100 mv.

  1. Phono vs Line: What’s the Difference? – Vinyl 101
  2. Wikipedia - Audio Line Level
  3. What Is a Line Level Signal and Why Does It Matter?
  4. Understanding Audio Levels
  5. Phono vs Line: What’s the Difference? – Vinyl 101
  6. Moving Magnet vs Moving Coil Cartridges
  7. Shop for Rowe jukebox Needles - Shure 44 - Rowe/AMI

Detect Connected Bluetooth Device

References

The following code can be used to detect if a a bluetooth device is connected:

    sudo bluetoothctl devices Connected | {
    if read ; then
        echo -e "a device is connected\n"
    else
        echo -e "No Devices Connected\n"
    fi
        }
                
  1. bluetoothctl: list connected devices?
  2. Read values into a shell variable from a pipe

Music List

  1. Neil Young - Old Man
  2. Christopher Cross - Sailing
  3. Christopher Cross - Ride Like the Wind
  4. Christopher Cross - The Best you can do
  5. Gerry Rafferty - Get it Right Next Time
  6. Gerry Rafferty - Baker Street
  7. Boz Scagss - Liddo Shuffle
  8. Boz Scaggs - Look What You've Done to Me
  9. Bob Seger - Night Moves
  10. Billy Winters - Lean on Me
  11. Randy Vanwarmer - Just When I Need You the Most
  12. Paul Simon - 50 Ways to Leave Your Lover
  13. Paul Simon - Homeward Bound
  14. Paul Simon - Late in teh Evening
  15. Paul Simon - Slip Sliding Away
  16. Linda Ronstadt - You are no good
  17. Elvin Bishop - Fooled around and fell in Love
  18. Emerson, Lake & Palmaer - From the Begining
  19. Who - Behind Blue Eyes
  20. Firefall - You are the Woman
  21. Firefall - Just Remember I Love You
  22. Kansas - Dust in the Wind

Raspberry Pi as a Bluetooth Speaker using Pipewire

To set this up, I followed references [1-3]

However, his installation of pipewire is out of date.Just use the following:

sudo apt install pipewire pipewire-audio

This will install pipewire, wireplumber and libspa-0.2-bluetooth

Next install python3-dbus for his python script:

sudo apt install python3-dbus

Place the following python script into ~speaker-agent.py:

#!/usr/bin/python3
# SPDX-License-Identifier: LGPL-2.1-or-later

import argparse
import dbus
import dbus.service
import dbus.mainloop.glib
from gi.repository import GLib

BUS_NAME = 'org.bluez'
AGENT_INTERFACE = 'org.bluez.Agent1'
AGENT_PATH = "/speaker/agent"

A2DP = '0000110d-0000-1000-8000-00805f9b34fb'
AVRCP = '0000110e-0000-1000-8000-00805f9b34fb'

bus = None


class Rejected(dbus.DBusException):
    _dbus_error_name = "org.bluez.Error.Rejected"


class Agent(dbus.service.Object):

    def __init__(self, bus, path, single_connection):
        self.exit_on_release = True
        self.remote_device = None

        dbus.service.Object.__init__(self, bus, path)

        if single_connection:
            bus.add_signal_receiver(self.signal_handler,
                                    bus_name='org.bluez',
                                    interface_keyword='org.freedesktop.DBus.Properties',
                                    member_keyword='PropertiesChanged',
                                    arg0='org.bluez.Device1',
                                    path_keyword='path'
                                    )

    def signal_handler(self, *args, **kwargs):
        path = kwargs['path']
        connected = None
        for i, arg in enumerate(args):
            if type(arg) == dbus.Dictionary and "Connected" in arg:
                connected = arg["Connected"]

        if connected == None:
            return

        if not self.remote_device and connected == True:
            self.remote_device = path
            print("{} connected".format(path))
        elif path == self.remote_device and connected == False:
            self.remote_device = None
            print("{} disconnected".format(path))

    def set_exit_on_release(self, exit_on_release):
        self.exit_on_release = exit_on_release

    @dbus.service.method(AGENT_INTERFACE,
                         in_signature="", out_signature="")
    def Release(self):
        print("Release")
        if self.exit_on_release:
            mainloop.quit()

    @dbus.service.method(AGENT_INTERFACE,
                         in_signature="os", out_signature="")
    def AuthorizeService(self, device, uuid):
        if self.remote_device and self.remote_device != device:
            print("%s try to connect while %s already connected" % (device, self.remote_device))
            raise Rejected("Connection rejected by user")

        # Always authorize A2DP and AVRCP connection
        if uuid in [A2DP, AVRCP]:
            print("AuthorizeService (%s, %s)" % (device, uuid))
            return
        else:
            print("Service rejected (%s, %s)" % (device, uuid))
        raise Rejected("Connection rejected by user")

    @dbus.service.method(AGENT_INTERFACE,
                         in_signature="", out_signature="")
    def Cancel(self):
        print("Cancel")


def start_speaker_agent():
    # By default Bluetooth adapter is not discoverable and there's
    # a 3 min timeout
    # Set it as always discoverable
    adapter = dbus.Interface(bus.get_object(BUS_NAME, "/org/bluez/hci0"),
                             "org.freedesktop.DBus.Properties")
    adapter.Set("org.bluez.Adapter1", "DiscoverableTimeout", dbus.UInt32(0))
    adapter.Set("org.bluez.Adapter1", "Discoverable", True)

    print("RPi speaker discoverable")

    # As the RPi speaker will not have any interface, create a pairing
    # agent with NoInputNoOutput capability
    obj = bus.get_object(BUS_NAME, "/org/bluez")
    manager = dbus.Interface(obj, "org.bluez.AgentManager1")
    manager.RegisterAgent(AGENT_PATH, "NoInputNoOutput")

    print("Agent registered")

    manager.RequestDefaultAgent(AGENT_PATH)


def nameownerchanged_handler(*args, **kwargs):
    if not args[1]:
        print('org.bluez appeared')
        start_speaker_agent()


if __name__ == '__main__':
    options = argparse.ArgumentParser(description="BlueZ Speaker Agent")
    options.add_argument("--single-connection", action='store_true', help="Allow only one connection at a time")
    args = options.parse_args()

    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)

    bus = dbus.SystemBus()

    agent = Agent(bus, AGENT_PATH, args.single_connection)
    agent.set_exit_on_release(False)

    bus.add_signal_receiver(nameownerchanged_handler,
                            signal_name='NameOwnerChanged',
                            dbus_interface='org.freedesktop.DBus',
                            path='/org/freedesktop/DBus',
                            interface_keyword='dbus_interface',
                            arg0='org.bluez')

    dbus_service = bus.get_object('org.freedesktop.DBus',
                                  '/org/freedesktop/DBus')
    dbus_dbus = dbus.Interface(dbus_service, 'org.freedesktop.DBus')
    if (dbus_dbus.NameHasOwner('org.bluez')):
        print('org.bluez already started')
        start_speaker_agent()

    mainloop = GLib.MainLoop()
    mainloop.run()
             

What was not obvious was that the Unix name of the computer will show up when you pair or connect it as a bluetooth speaker

The next step was not obvious from the references [1-3]

sudo mkdir ~.config/systemd/user

Inside this directory create the file:

touch speaker-agent.service

Place the following inside speaker-agent.service:

[Unit]
Description=Bluetooth speaker agent

[Service]
ExecStart=python speaker-agent.py --single-connection

[Install]
WantedBy=default.target
             

Enable it manually using:

systemctl --user enable speaker-agent.service

Configure the BlueZ daemon to allow re-pairing without user interaction:

sudo sed -i 's/#JustWorksRepairing.*/JustWorksRepairing = always/' /etc/bluetooth/main.conf

To change the pipewire's volume:

If the volume is too low, use:

wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.8

References

  1. GitHub - Using a Raspberry Pi as a Bluetooth® speaker with PipeWire
  2. Collabora - Using a Raspberry Pi as a Bluetooth speaker with PipeWire
  3. PiShop Blog - Using a Raspberry Pi as a Bluetooth speaker with PipeWire