First attempt at a service with python
This commit is contained in:
parent
c2e1ac3ae9
commit
8bfc406e85
3 changed files with 217 additions and 0 deletions
67
main.js
Normal file
67
main.js
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
const GPIO = require("onoff").Gpio;
|
||||||
|
const WS = require("ws");
|
||||||
|
|
||||||
|
const HEARTBEAT_INT = 400;
|
||||||
|
|
||||||
|
const button = new GPIO(4, "in", "both", {debounceTimeout: 30, activeLow: true});
|
||||||
|
const ledOnAir = new GPIO(24, "low");
|
||||||
|
const ledReady = new GPIO(23, "low");
|
||||||
|
|
||||||
|
const ws = new WS('ws://10.0.0.4:2000');
|
||||||
|
|
||||||
|
let currentID = 0;
|
||||||
|
|
||||||
|
let heartBeat;
|
||||||
|
|
||||||
|
ws.on('open', () => {
|
||||||
|
|
||||||
|
button.watch((e, value) => {
|
||||||
|
if(e) {
|
||||||
|
console.error("Error on button watch:", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(value) {
|
||||||
|
ws.send(JSON.stringify({type: 'button-press'}));
|
||||||
|
} else {
|
||||||
|
ws.send(JSON.stringify({type: 'button-release'}));
|
||||||
|
}
|
||||||
|
|
||||||
|
ledOnAir.write(value, (e) => e && console.error("Error writing to led: ", e));
|
||||||
|
});
|
||||||
|
heartBeat = setInterval(() => {
|
||||||
|
button.read((e, buttonState) => {
|
||||||
|
console.log("Button state!", buttonState);
|
||||||
|
if(e) {
|
||||||
|
return console.error("Error reading button state!", e);
|
||||||
|
}
|
||||||
|
ws.send(JSON.stringify({
|
||||||
|
type: 'button-update',
|
||||||
|
body: {buttonState}
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}, 400);
|
||||||
|
ledReady.write(1, console.error);
|
||||||
|
});
|
||||||
|
|
||||||
|
ws.on('error', (e) => {
|
||||||
|
console.error(e);
|
||||||
|
cleanup();
|
||||||
|
process.exit();
|
||||||
|
});
|
||||||
|
|
||||||
|
function cleanup() {
|
||||||
|
ledOnAir.unexport();
|
||||||
|
ledReady.unexport();
|
||||||
|
button.unexport();
|
||||||
|
ws.close();
|
||||||
|
if(heartBeat) {
|
||||||
|
cancelInterval(heartBeat);
|
||||||
|
heartBeat = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
process.on('SIGINT', () => {
|
||||||
|
cleanup();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
65
miccontrol.c
Normal file
65
miccontrol.c
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* miccontrol.c
|
||||||
|
* Copyright (C) 2018 jshaver <jshaver@je-laptop>
|
||||||
|
*
|
||||||
|
* Distributed under terms of the MIT license.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdio.h"
|
||||||
|
#include "pulse/pulseaudio.h"
|
||||||
|
|
||||||
|
const char *NAME = "miccontrol";
|
||||||
|
|
||||||
|
static pa_context *context = NULL;
|
||||||
|
static pa_mainloop_api *mainloop_api = NULL;
|
||||||
|
static pa_mainloop *mainloop = NULL;
|
||||||
|
|
||||||
|
void querySources(pa_context *c, void *userdata);
|
||||||
|
void handleSourceList(struct pa_context *c, const pa_source_info *i, int eol, void *userdata);
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int ret = 1;
|
||||||
|
mainloop = pa_mainloop_new();
|
||||||
|
mainloop_api = pa_mainloop_get_api(mainloop);
|
||||||
|
context = pa_context_new(mainloop_api, NULL);
|
||||||
|
pa_context_set_state_callback(context, querySources, NULL);
|
||||||
|
pa_context_connect(context, NULL, 0, NULL);
|
||||||
|
//pa_operation_unref(getSourceOp);
|
||||||
|
|
||||||
|
pa_mainloop_run(mainloop, &ret);
|
||||||
|
|
||||||
|
pa_context_unref(context);
|
||||||
|
pa_mainloop_free(mainloop);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void querySources(pa_context *c, void *userdata) {
|
||||||
|
if(pa_context_get_state(context) != PA_CONTEXT_READY) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pa_operation *getSourceOp = NULL;
|
||||||
|
getSourceOp = pa_context_get_source_info_list(context, handleSourceList, NULL);
|
||||||
|
if(!getSourceOp) {
|
||||||
|
} else {
|
||||||
|
pa_operation_state_t state = pa_operation_get_state(getSourceOp);
|
||||||
|
switch(state) {
|
||||||
|
case PA_OPERATION_RUNNING:
|
||||||
|
break;
|
||||||
|
case PA_OPERATION_DONE:
|
||||||
|
break;
|
||||||
|
case PA_OPERATION_CANCELLED:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleSourceList(pa_context *c, const pa_source_info *i, int eol, void *userdata) {
|
||||||
|
printf("Callback called...\n");
|
||||||
|
printf("eol is %d\n", eol);
|
||||||
|
printf(i->description);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
85
service.py
Normal file
85
service.py
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
#! /usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from pulsectl import Pulse
|
||||||
|
import SocketServer
|
||||||
|
from threading import Thread
|
||||||
|
|
||||||
|
LISTEN_ON = ("10.0.0.4", 2000)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
pulse = Pulse('mic-control')
|
||||||
|
|
||||||
|
sources = pulse.source_list()
|
||||||
|
|
||||||
|
sourceNumber = getSourceSelection(sources)
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
server = SocketServer.TCPServer(LISTEN_ON, RequestHandler)
|
||||||
|
server.serve_forever()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
server.shutdown()
|
||||||
|
server.server_close()
|
||||||
|
except:
|
||||||
|
server.shutdown()
|
||||||
|
server.server_close()
|
||||||
|
|
||||||
|
|
||||||
|
def getSourceSelection(sources):
|
||||||
|
sourceCount = len(sources) - 1
|
||||||
|
error = False
|
||||||
|
while True:
|
||||||
|
message = error if error else "Please select a source: "
|
||||||
|
print(message)
|
||||||
|
for i, source in enumerate(sources):
|
||||||
|
print "%i: %s" % (i, source.description)
|
||||||
|
selection = raw_input("Enter a number[0-%i]:" % sourceCount)
|
||||||
|
print("")
|
||||||
|
try :
|
||||||
|
return getInt(selection, sourceCount)
|
||||||
|
except InputError as e:
|
||||||
|
error = e.message
|
||||||
|
|
||||||
|
def getInt(value, sourceCount):
|
||||||
|
|
||||||
|
number = 0
|
||||||
|
try:
|
||||||
|
number = int(value)
|
||||||
|
except ValueError as e:
|
||||||
|
raise InputError("Enter only a number...")
|
||||||
|
|
||||||
|
if number not in range(0, sourceCount):
|
||||||
|
raise InputError("Not a valid option...")
|
||||||
|
|
||||||
|
return number
|
||||||
|
|
||||||
|
class RequestHandler(SocketServer.StreamRequestHandler):
|
||||||
|
def handle(self):
|
||||||
|
|
||||||
|
for line in self.rfile:
|
||||||
|
message = line.strip()
|
||||||
|
if message in messageTypes:
|
||||||
|
messageTypes[message]()
|
||||||
|
print("message: ".message)
|
||||||
|
print("Closed!")
|
||||||
|
self.request.close()
|
||||||
|
|
||||||
|
|
||||||
|
def buttonPressed():
|
||||||
|
print("down!")
|
||||||
|
|
||||||
|
def buttonReleased():
|
||||||
|
print("up!")
|
||||||
|
|
||||||
|
messageTypes = {
|
||||||
|
'button_press': buttonPressed,
|
||||||
|
'button_release': buttonReleased,
|
||||||
|
}
|
||||||
|
|
||||||
|
class InputError(Exception):
|
||||||
|
def __init__(self, message):
|
||||||
|
self.message = message
|
||||||
|
|
||||||
|
|
||||||
|
main()
|
Loading…
Reference in a new issue