// Copyright 2014-2025 Jesper Larsson
//
// This file is part of Klipspringer, <https://klipspringer.avadeaux.net/>
//
// Klipspringer is free software: you can redistribute it and/or modify it under the terms of the
// GNU General Public License as published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// Klipspringer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
// even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with Klipspringer. If
// not, see <https://www.gnu.org/licenses/>.

import * as net from 'net';
import { createPlayerCommon } from './player_common.js';
import { log } from './log.js';

export const createDevicePlayer = (opts, controlPath, inDevice, format) => {
    const options = [...opts.java_opts];
    options.push('net.avadeaux.klipspringer.DevicePlayer');
    options.push('-recdir', opts.recdir);
    options.push('-controlsock', controlPath);
    if (inDevice) { options.push('-device', inDevice); }
    if (format) {
        let f = "", delim = "";
        if (format.rate) { f += delim+"-r "+format.rate; delim = " " }
        if (format.bits) { f += delim+"-b "+format.bits; delim = " " }
        if (format.channels) { f += delim+"-c "+format.channels; delim = " " }
        if (format.encoding) { f += delim+"-e "+format.encoding; delim = " " }
        if (format.bigendian !== undefined) { f += delim+(format.bigendian ? "-B" : "-L") }
        options.push("-format", f);
    }

    // Get superintf by createPlayerCommon.
    const intf = createPlayerCommon("Device player", opts.java, options);

    // Override pattern to check stdout for before ready.
    intf.readyPattern = /^Ready control socket.*\n?/m;

    // Sends command to player, returning a promise that resolves with answer
    // object when it is done.
    intf.command = (qstring) => intf.ready().then(() => new Promise((resolve, reject) => {
        let ansString = '';
        const sock = net.connect(controlPath, () => { sock.write(qstring+'\n') });
        sock.on('data', msg => {
            ansString += msg.toString();
        }).on('end', () => {
            ansString = ansString.trim();
            try {
                resolve(ansString.length ? JSON.parse(ansString) : { ok: "empty" });
            } catch (jsonErr) {
                resolve({ ok: ansString })
            }
        }).on('error', err => {
            log.debug("Socket error: "+err);
            reject(err);
        });
    })).catch(ans => ans && (ans.defunct || ans.err) ? { ...ans, defunct: true } : { defunct: true, err: ans.toString ? ans.toString() : ans });

    // Commands passed on to Java process.
    for (const cmd of ['start_record', 'stop_record', 'set_format', 'set_reclimit']) { intf.httpCallable[cmd] = intf.command }

    // Quit only ends the stream, not the process.
    intf.httpCallable.quit = (qstring, query) => intf.command(Object.entries({
        ...query,
        cmd: 'end',
    }).map(([p, v]) => p+'='+encodeURIComponent(v.toString())).join('&')+'\n');

    return intf;
}

Version: v4.3.2.2 (2026-05-16T17:03:34+02:00)
Raw file
Source code overview
Klipspringer home