// 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 { homedir } from 'os';
import * as path from 'path';

// Functions for processing arguments before assignment
const listArg = (item, prev) => [ ...(prev || []), item ];
const listArgs = (items, prev) => (prev || []).concat((typeof items === 'string' ? JSON.parse(items) : items));
const processStreamTypes = (list) => (typeof list === 'string' ? JSON.parse(list) : list).map(e => {
    if      (e === "flac") { return ["audio/flac",  "flac"] }
    else if (e === "oga")  { return ["audio/ogg",   "oga"] }
    else if (e === "ogg")  { return ["audio/ogg",   "ogg"] }
    else if (e === "mp3")  { return ["audio/mpeg",  "mp3"] }
    else { throw "Unknown audio stream type: "+e }
});
const backgroundStyle = (img) => img ? "background-size: 100%;background-image: url('img?file="+img+"');" : "";

const defaultTrackRE = "([0-9]+)\\.(.+)\\.[a-zA-Z][a-zA-Z0-9]*";
const defaultStreamTypeList = ["flac", "ogg", "mp3"];
const defaultClassPath = [["$lib", "kliptrack.jar"], ["$lib", "json.jar"]];

const argumentSpec = [
    ["-etc", "<path>             directory for configuration files",, path.join(homedir(), ".klipspringer")],
    ["-lib", "<path>             directory for library files",, process.cwd()],
    ["-hist", "<path>            directory for history files (default: ~/.klipspringer)",, path.join(homedir(), ".klipspringer")],
    ["-sockdir", "<path>         directory for unix domain sockets (default: ~/.klipspringer)",, path.join(homedir(), ".klipspringer")],
    ["-recdir", "<path>          directory for audio recordings (default: ~/.klipspringer/rec)",, path.join(homedir(), ".klipspringer", "rec")],
    ["-track-re", "<regexp>      groups track no and title of audio file name (default: "+defaultTrackRE+")", 'trackRE', defaultTrackRE],
    ["-joutput", "<device | URL> track player -output argument",,],
    ["-jtrackopts", "<list>      extra arguments passed to track player",, [], listArgs],
    ["-port", "<number>          port for http server (default: 44100)",, "44100"],
    ["-download", "<extension>   default recording download format (default: raw)", 'default_download_format', "raw"],
    ["-streamtypes", "<list>     available streaming formats (default: "+JSON.stringify(defaultStreamTypeList)+")",, processStreamTypes(defaultStreamTypeList), processStreamTypes],
    ["-serverimage", "<path>     web page background for server players", 'serverbackground', "", backgroundStyle],
    ["-streamimage", "<path>     web page background for stream players", 'streambackground', "", backgroundStyle],
    ["-numpad", "<path>          device for numeric keypad (e.g. /dev/input/event1)",,],
    ["-remote", "<path>          device for remote control (e.g. /dev/input/event3)",,],
    ["-java", "<command>         Command to run JVM (default: java)",, "java"],
    ["-cp", "<path>              class path when invoking java (default: "+JSON.stringify(defaultClassPath)+")", 'classpath', defaultClassPath],
    ["-vlc", "<command>          specify command for VLC sources> (default: vlc)",, "vlc"],
    ["-vlc-arg", "<argument>     extra argument for invoking VLC (can appear multiple times)", 'vlcargs', [], listArg],
    ["-vlc-args", "<list>        sequence of extra VLC arguments", 'vlcargs', [], listArgs],
    ["-debug", "                 ouput debugging messages", 'debug',, 1],
    ["-debug-full", "            ouput more debugging messages", 'debug',, 2]
];

export const defaultOptions = { };

let helpText = "Arguments:\n";
const handle = { };
for (const spec of argumentSpec) {
    const [option, help, optprop, dflt, opthval] = spec;
    const prop = optprop || option.slice(1);
    const hval = opthval === undefined ? x => x : opthval;
    handle[option] = typeof hval === 'function' ? (args, opts) => {
        const v = hval(args.shift(), opts[prop]);
        opts[prop] = typeof v === 'string' || Array.isArray(v) ? v : JSON.stringify(v);
    } : (args, opts) => {
        opts[prop] = typeof hval === 'string' || Array.isArray(hval) ? hval : JSON.stringify(hval);
    }
    defaultOptions[prop] = dflt;
    helpText += option+" "+help+"\n";
}
helpText += "-help or --help         print this message";

export const parseOptions = (args) => {
    const opts = { };
    while (true) {
        const a = args[0];
        if (a === undefined || a[0] !== '-') { break }
        if (a === "--") {
            args.shift();
            break
        }
        if (a === "-help" || a === "--help") {
            console.log(helpText);
            process.exit(0);
        }
        args.shift();
        const f = handle[a];
        if (!f) { throw "unrecognized option: "+a }
        f(args, opts);
    }
    return opts;
}

export const processOptions = (optsObj) => {
    const opts = { };
    for (const [a, v] of Object.entries(optsObj)) {
        const f = handle[a];
        if (!f) { throw "unrecognized option: "+a }
        f([v], opts);
    }
    return opts;
}

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