Commit 6b295ac4 authored by Your Name's avatar Your Name
Browse files

added preliminary init.d scripts

parent b65aa853
......@@ -86,9 +86,10 @@ $ make all
Make the firmware run upon reboot
$ sudo crontab -e
add lines like these
@reboot /home/pi/firmware/lsldert/zmq_trigger
@reboot /home/pi/firmware/lslder/lslder_1chan
@reboot /home/pi/firmware/lsldert/init.d/rc
In ~/init.d for each host a specific rc file exists that will be called from the rc script
The script uses the name returned by the 'hostname' command, prependen with 'rc.'. E.g. if your raspberry's hostname is 'myraspberry', the script should be named 'rc.myraspberry'.
```
##
......
#!/bin/bash
#
# rc -- this script is called from crontab at @reboot
# calls rc.boot and the system specific file rc.$(hostname)
# rc.* must have the executable permission bit set in order to run
#
hostname="$(hostname)"
fwdir="/home/pi/firmware"
rcdir="$fwdir/init.d"
rcboot="$rcdir/rc.boot"
rchost="$rcdir/rc.$hostname"
cd "$fwdir" || exit 1
if [ -x "$rcboot" ]; then
"$rcboot"
fi
if [ -x "$rchost" ]; then
"$rchost"
fi
#!/bin/bash
echo "Running rc.boot"
#!/bin/bash
./lsldert/msgqueue_pubsub &
#!/bin/bash
echo "Running $0"
......@@ -299,7 +299,10 @@ int main(int argc, const char *argv[]) {
zmq::socket_t ssub(context, ZMQ_SUB);
ssub.connect("tcp://lsldert00:5557");
//ssub.connect("tcp://lsldert00.local:5557");
ssub.setsockopt(ZMQ_SUBSCRIBE, "", 0);
ssub.setsockopt(ZMQ_SUBSCRIBE, "b", 0);
ssub.setsockopt(ZMQ_SUBSCRIBE, "B", 0);
ssub.setsockopt(ZMQ_SUBSCRIBE, "D", 0);
ssub.setsockopt(ZMQ_SUBSCRIBE, "M", 0);
zmq::socket_t srep(context, ZMQ_REP);
srep.bind("tcp://*:5555");
......
No preview for this file type
/** @file paex_sine.c
@ingroup examples_src
@brief Play a sine wave for several seconds.
@author Ross Bencina <rossb@audiomulch.com>
@author Phil Burk <philburk@softsynth.com>
*/
/*
* $Id$
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com/
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
//
// zmqaudio.cc -- play audio samples received over zeromq sockets
// Copyright (c) 2020 Günter Winau
// based on the example in paex_sine.c
//
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
//
// This program uses the PortAudio Portable Audio Library.
// For more information see: http://www.portaudio.com/
// Copyright (c) 1999-2000 Ross Bencina and Phil Burk
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files
// (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//
// The text above constitutes the entire PortAudio license; however,
// the PortAudio community also makes the following non-binding requests:
//
// Any person wishing to distribute modifications to the Software is
// requested to send the modifications to the original developer so that
// they can be incorporated into the canonical version. It is also
// requested that these non-binding requests be included along with the
// license above.
//
#include "zmqaudio.h"
#include "portaudio.h"
#include "zhelpers.hpp"
#include <math.h>
#include <stdio.h>
#include <iostream>
#define NUM_SECONDS (5)
#define SAMPLE_RATE (44100)
......@@ -61,6 +61,50 @@ typedef struct {
char message[20];
} paTestData;
int verbose = 0;
const int nbuf = 5;
zmq_audiobuffer *buffer[nbuf];
zmq_audiobuffer::zmq_audiobuffer(std::uint32_t _fsamp, std::uint32_t _nsamp,
std::uint32_t _nchan)
: fsamp{_fsamp}, nsamp{_nsamp}, nchan{_nchan},
data{new float[_nsamp * _nchan]}, idata{0}, frames_per_buffer{64},
playing{false}, stream{nullptr}
{
assert(sizeof(float) == 4); // need 32 bit IEEE 754 floats
PaStreamParameters outputParameters;
outputParameters.device =
Pa_GetDefaultOutputDevice(); /* default output device */
if (outputParameters.device == paNoDevice) {
fprintf(stderr, "Error: No default output device.\n");
return 1;
}
outputParameters.channelCount = nchan; /* stereo output */
outputParameters.sampleFormat =
paFloat32; /* 32 bit floating point output */
outputParameters.suggestedLatency =
Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
PaError err;
err = Pa_OpenStream(&stream, NULL, /* no input */
&outputParameters, fsamp, frames_per_buffer,
paClipOff, /* we won't output out of range samples so
don't bother clipping them */
zmq_audiobuffer::stream_callback, this);
if (err != paNoError)
return err;
}
zmq_audiobuffer::~zmq_audiobuffer()
{
delete data;
Pa_StopStream(stream);
Pa_CloseStream(stream);
}
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
......@@ -75,18 +119,20 @@ int zmq_audiobuffer::stream_callback(
float *out = (float *)outputBuffer;
unsigned long i;
int ret = paContinue;
for (i = 0; i < framesPerBuffer; i++) {
if (data->idata < data->nsamp) {
*out++ = data->data[2*(data->idata)]; // left
*out++ = data->data[2*(data->idata)+1]; // right
*out++ = data->data[2 * (data->idata)]; // left
*out++ = data->data[2 * (data->idata) + 1]; // right
data->idata++;
}
else {
*out++ = 0;
*out++ = 0;
ret = paComplete;
}
}
return paContinue;
return ret;
}
/*
......@@ -94,37 +140,13 @@ int zmq_audiobuffer::stream_callback(
*/
void zmq_audiobuffer::stream_finished(void *userData) {
zmq_audiobuffer *data = (zmq_audiobuffer *)userData;
data->playing = false;
printf("Stream Completed: %s\n", data->message);
}
int zmq_audiobuffer::play()
{
idata=0;
PaStreamParameters outputParameters;
outputParameters.device =
Pa_GetDefaultOutputDevice(); /* default output device */
if (outputParameters.device == paNoDevice) {
fprintf(stderr, "Error: No default output device.\n");
return 1;
}
outputParameters.channelCount = nchan; /* stereo output */
outputParameters.sampleFormat =
paFloat32; /* 32 bit floating point output */
outputParameters.suggestedLatency =
Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
PaStream *stream;
PaError err;
err = Pa_OpenStream(&stream, NULL, /* no input */
&outputParameters, fsamp, frames_per_buffer,
paClipOff, /* we won't output out of range samples so
don't bother clipping them */
zmq_audiobuffer::stream_callback, this);
if (err != paNoError)
return err;
int zmq_audiobuffer::play() {
idata = 0;
sprintf(message, "No Message");
err =
Pa_SetStreamFinishedCallback(stream, &zmq_audiobuffer::stream_finished);
......@@ -134,37 +156,33 @@ int zmq_audiobuffer::play()
err = Pa_StartStream(stream);
if (err != paNoError)
return err;
playing = true;
printf("Play for %d seconds.\n", NUM_SECONDS);
Pa_Sleep((unsigned int)(duration() * 1000));
err = Pa_StopStream(stream);
if (err != paNoError)
return err;
err = Pa_CloseStream(stream);
if (err != paNoError)
return err;
//printf("Play for %d seconds.\n", NUM_SECONDS);
//Pa_Sleep((unsigned int)(duration() * 1000));
}
return err;
void zmq_audiobuffer::abort() {
Pa_AbortStream(stream);
}
void zmq_audiobuffer::stop() {
Pa_StopStream(stream);
}
void zmq_audiobuffer::fill()
{
void zmq_audiobuffer::fill() {
// initialise sinusoidal wavetable
const float fl {440};
const float fr {880};
const float vol {0.1};
for (int i = 0; i < nsamp-1; i++) {
data[2*i] = vol*sin((2*M_PI*fl*i)/fsamp);
data[2*i+1] = vol*sin((2*M_PI*fr*i)/fsamp);
const float fl{440};
const float fr{880};
const float vol{0.1};
for (int i = 0; i < nsamp - 1; i++) {
data[2 * i] = vol * sin((2 * M_PI * fl * i) / fsamp);
data[2 * i + 1] = vol * sin((2 * M_PI * fr * i) / fsamp);
}
}
PaError print_error(PaError e)
{
if (e != paNoError)
PaError print_error(PaError e) {
if (e != paNoError)
Pa_Terminate();
fprintf(stderr, "An error occured while using the portaudio stream\n");
fprintf(stderr, "Error number: %d\n", e);
......@@ -172,27 +190,104 @@ PaError print_error(PaError e)
return e;
}
int zmq_recv_multi(zmq::socket_t &socket, zmq::message_t parts[], int nmax) {
int64_t more;
size_t more_size = sizeof more;
int n = 0;
try {
do {
if (n < nmax) {
socket.recv(&parts[n]);
if (verbose)
std::cout << "recv part " << n << std::endl;
n++;
}
else {
zmq::message_t discard;
socket.recv(&discard);
if (verbose)
std::cout << "recv part " << n << " (discarded)." << std::endl;
}
socket.getsockopt(ZMQ_RCVMORE, &more, &more_size);
} while (more);
}
catch (std::exception &error) {
std::cout << "zmq_rev_multi while receiving frame " << n << ": "
<< error.what() << std::endl;
}
return n;
}
/*******************************************************************/
int main(void);
int main(void) {
PaError err = Pa_Initialize();
if (err != paNoError)
return print_error(err);
zmq_audiobuffer data(44100, 5*48000, 2);
data.fill();
printf("PortAudio Test: output sine wave. SR = %d, BufSize = %d\n",
SAMPLE_RATE, data.frames_per_buffer);
// Prepare our context and socket
zmq::context_t context(1);
zmq::socket_t ssub(context, ZMQ_SUB);
ssub.connect("tcp://lsldert00:5557");
// ssub.connect("tcp://lsldert00.local:5557");
ssub.setsockopt(ZMQ_SUBSCRIBE, "A", 0);
int run = 1;
while (run) {
const int maxmsg = 3;
zmq::message_t msg[maxmsg];
int nmsg = 0;
nmsg = zmq_recv_multi(ssub, msg, maxmsg);
zmq::message_t &request = msg[0];
std::string str((char *)request.data());
if (verbose) {
std::cout << "Received: " << str << " (" << request.size()
<< " bytes)" << std::endl;
if (nmsg > 1) {
for (int i = 1; i < nmsg; i++)
std::cout << " ...one more message, " << msg[i].size()
<< " bytes" << std::endl;
}
}
// parse the command and data in the message
std::istringstream s(str);
std::string cmd;
s >> cmd;
if (verbose)
std::cout << "cmd=" << str << std::endl;
err = data.play();
if (err != paNoError)
return print_error(err);
if (cmd == "AF") { // Fill
}
else if (cmd == "AP") { // Play
}
else if (cmd == "AS") { // Stop
}
buffer[0] = new zmq_audiobuffer(44100, 5 * 48000, 2);
zmq_audiobuffer *data = buffer[0];
data->fill();
printf("PortAudio Test: output sine wave. SR = %d, BufSize = %d\n",
SAMPLE_RATE, data->frames_per_buffer);
err = data->play();
if (err != paNoError)
return print_error(err);
}
Pa_Terminate();
printf("Test finished.\n");
return err;
}
#include "portaudio.h"
#include <cassert>
#include <cstdint>
#include <zmq.hpp>
class zmq_audiobuffer {
......@@ -14,20 +15,22 @@ class zmq_audiobuffer {
int frames_per_buffer;
zmq_audiobuffer(std::uint32_t _fsamp, std::uint32_t _nsamp,
std::uint32_t _nchan)
: fsamp{_fsamp}, nsamp{_nsamp}, nchan{_nchan},
data{new float[_nsamp * _nchan]}, idata{0}, frames_per_buffer{64} {
assert(sizeof(float) == 4); // need 32 bit IEEE 754 floats
}
~zmq_audiobuffer() { delete data; }
std::uint32_t _nchan);
~zmq_audiobuffer();
void fill();
void fill(zmq::message_t&);
int play();
void stop();
void abort();
double duration() {
return double(nsamp)/fsamp;
}
protected:
bool playing;
PaStream *stream;
static int stream_callback(const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo *timeInfo,
......@@ -35,3 +38,15 @@ class zmq_audiobuffer {
void *userData);
static void stream_finished(void *userData);
};
struct zmq_audio_metadata {
std::uint32_t fsamp;
std::uint32_t nsamp;
std::uint32_t nchan;
std::uint32_t _spare5;
std::uint32_t _spare4;
std::uint32_t _spare3;
std::uint32_t _spare2;
std::uint32_t _spare1;
};
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment