diff --git a/main.js b/main.js new file mode 100644 index 0000000..ce6bfc7 --- /dev/null +++ b/main.js @@ -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(); +}); + + diff --git a/miccontrol.c b/miccontrol.c new file mode 100644 index 0000000..2ac3e9d --- /dev/null +++ b/miccontrol.c @@ -0,0 +1,65 @@ +/* + * miccontrol.c + * Copyright (C) 2018 jshaver + * + * 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; +} + diff --git a/service.py b/service.py new file mode 100644 index 0000000..5652c40 --- /dev/null +++ b/service.py @@ -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()