--- /dev/null
+#
+# FreeDV - HF Digital Voice for Radio Amateurs
+#
+# CMake configuration started with the version written by Richard Shaw KF5OIM
+# for the original Qt FreeDV.
+# Hacked to bits for command-line/server version by Bruce Perens K6BP.
+#
+# Please report questions, comments, problems, or patches to the freetel
+# mailing list: https://lists.sourceforge.net/lists/listinfo/freetel-codec2
+#
+
+# Prevent in-source builds to protect automake/autoconf config.
+# If an in-source build is attempted, you will still need to clean up a few
+# files manually.
+if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
+ message(FATAL_ERROR "In-source builds in ${CMAKE_BINARY_DIR} are not "
+ "allowed, please remove ./CMakeCache.txt and ./CMakeFiles/, create a "
+ "separate build directory and run cmake from there.")
+endif("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
+
+cmake_minimum_required(VERSION 2.8)
+set(CMAKE_DISABLE_SOURCE_CHANGES ON)
+set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
+project(freedv-server)
+
+# Parameters are stored as .txt files in the parameters/ subdirectory.
+# They use semicolon to separate arguments, because this is what cmake uses
+# in its list type. Thus, parameters/version.txt looks like this:
+#
+# 0;1;2
+#
+# Those are easy to separate at each semicolon into the major, minor,
+# and patch version.
+#
+# You can override parameters on the command line, using
+# -DParam.name=value
+#
+macro(load_parameters)
+ foreach(name ${ARGN})
+ set(filename "${CMAKE_SOURCE_DIR}/parameters/${name}.txt")
+ if("${Param.${name}}" STREQUAL "" AND EXISTS ${filename})
+ file(STRINGS ${filename} string)
+ set("Param.${name}" ${string})
+ endif("${Param.${name}}" STREQUAL "" AND EXISTS ${filename})
+ endforeach(name)
+ unset(filename)
+endmacro(load_parameters)
+
+#
+# Parse FreeDV version, code-name from parameter.
+#
+load_parameters(version codename build-type)
+list(GET Param.version 0 Version.major)
+list(GET Param.version 1 Version.minor)
+list(GET Param.version 2 Version.patch)
+unset(list)
+
+#
+# Parse platform information
+#
+set(Platform.name ${CMAKE_SYSTEM_NAME})
+if(Platform.name STREQUAL Linux)
+ execute_process(
+ COMMAND lsb_release -s -i
+ OUTPUT_VARIABLE Platform.distribution
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ execute_process(
+ COMMAND lsb_release -s -r
+ OUTPUT_VARIABLE Platform.release
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+endif(Platform.name STREQUAL Linux)
+
+message(STATUS "${Param.build-type} ${Version.major}.${Version.minor}.${Version.patch}, "
+ "code name \"${Param.codename}\", "
+ "on ${Platform.name} ${Platform.distribution} ${Platform.release}.")
+
+#
+# Set cmake internal variables from parameters.
+#
+load_parameters(cxx-flags c-flags)
+set(CMAKE_CXX_FLAGS, ${Param.cxx-flags})
+set(CMAKE_C_FLAGS, ${Param.c-flags})
+
+set(Compile.sources
+ source/main.cpp
+)
+
+add_executable(freedv-server ${Compile.sources})
+
+find_path(Codec2.include codec2.h PATH_SUFFIXES codec2)
+find_library(Codec2.lib NAMES codec2)
+if( Codec2.lib AND Codec2.include )
+ message(STATUS "Getting Codec2 from ${Codec2.include} and ${Codec2.lib}")
+ include_directories(${Codec2.include})
+ target_link_libraries(freedv-server ${Codec2.lib})
+else( Codec2.lib AND Codec2.include )
+ message(FATAL_ERROR "Can't find Codec2 library.")
+endif( Codec2.lib AND Codec2.include )
+
+install(TARGETS freedv-server RUNTIME DESTINATION bin)
--- /dev/null
+/*
+ * For the sake of correctness and optimization, I have written whatever I can to be without
+ * side-effects, a style inherited from functional programming. Thus, the excessive use of
+ * "const". - Bruce
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <iostream>
+#include <getopt.h>
+#include <codec2.h>
+#include <codec2_fdmdv.h>
+
+using namespace std;
+
+static void drivers()
+{
+ cout << "To be implemented." << endl;
+}
+
+static void help(const char * name)
+{
+ static const char message[] =
+ " [options]\n"
+ "\n\tWhere options are these flags:\n\n"
+ "\t\t--drivers or -d\t\tPrint a list of the available device drivers.\n"
+ "\t\t--help or -h\t\tPrint this message.\n"
+ "\t\t--interface or -i\tSelect the user-interface (graphical or otherwise).\n"
+ "\t\t--keying or -k\t\tSelect the transmitter keying interface.\n"
+ "\t\t--loudspeaker or -l\tSelect the operator audio output interface.\n"
+ "\t\t--microphone or -m\tSelect the operator audio input interface.\n"
+ "\t\t--mode or -n\t\tSelect the codec mode and modulation.\n"
+ "\t\t--ptt or -p\t\tSelect the push-to-talk input interface.\n"
+ "\t\t--receiver or -r\tSelect the interface for audio input from the receiver.\n"
+ "\t\t--text or -x\t\tSelect the interface for text to be transmitted.\n"
+ "\t\t--transmitter or -t\tSelect the interface for audio output to the transmitter.\n"
+ "\n\tLong flags with parameters are in the form of --<flag>=<parameter>\n"
+ "\tShort flags with parameters are in the form of -<letter> <parameter>\n"
+ "\n\tFor example, both of these flags have the same effect:\n"
+ "\t\t-m 1600\n"
+ "\t\t--mode=1600\n"
+ "\n\tMode may be one of:\n"
+ "\t\t--mode=1600\t\tNormal 1600 bit-per-second in 1.275 kHz RF bandwidth.\n"
+ "\t\t--mode=1600-wide\t1600 bit-per-second in 2.125 kHz, wider guard-bands for improved\n"
+ "\t\t\t\t\tDX performance.\n"
+ "\n\tFlags used to select devices must have a \"<driver>:<parameter>\" argument\n"
+ "\twhere <driver> is the name of a device driver for the selected input/output device,\n"
+ "\tand <parameter> is the name or address of the selected device.\n"
+ "\n\tExample:\n"
+ "\t\t --loudspeaker=alsa:default\n"
+ ;
+ cerr << "\nUsage: " << name << message << endl;
+}
+
+struct parameters {
+ const char * * interface;
+ const char * * keying;
+ const char * * loudspeaker;
+ const char * * microphone;
+ const char * mode;
+ const char * * ptt;
+ const char * * receiver;
+ const char * * text;
+ const char * * transmitter;
+};
+
+static int run(struct parameters * p)
+{
+ return 0;
+}
+
+int
+main(int argc, char * * argv)
+{
+ int command;
+ struct parameters p = { 0,0,0,0,0,0,0,0,0 };
+
+ static const struct option options[] = {
+ { "drivers", no_argument, 0, 'd' },
+ { "help", no_argument, 0, 'h' },
+ { "interface", required_argument, 0, 'i' },
+ { "keying", required_argument, 0, 'k' },
+ { "loudspeaker", required_argument, 0, 'l' },
+ { "microphone", required_argument, 0, 'm' },
+ { "mode", required_argument, 0, 'n' },
+ { "ptt", required_argument, 0, 'p' },
+ { "receiver", required_argument, 0, 'r' },
+ { "text", required_argument, 0, 'x' },
+ { "transmitter", required_argument, 0, 't' },
+ { 0, 0, 0, 0 }
+ };
+
+ if ( argc > 1 ) {
+ const char * * vector(new const char *[2]);
+
+ while ((command = getopt_long(argc, argv, "dhi:k:l:m:n:p:r:t:x:", options, NULL)) != -1) {
+ switch (command) {
+ case 'i':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'p':
+ case 'r':
+ case 't':
+ case 'x':
+ char * const colon(index(optarg, ':'));
+
+ if ( colon == 0 || *colon == 0 ) {
+ cerr << argv[optind - 1] << ": Missing colon. Argument must be of the form \"<driver>:<parameter>\"" << endl;
+ exit(1);
+ }
+ }
+
+ switch (command) {
+ case 'd':
+ drivers();
+ exit(0);
+ break;
+ default:
+ case 'h':
+ help(argv[0]);
+ exit(1);
+ break;
+ case 'i':
+ p.interface = vector;
+ break;
+ case 'k':
+ p.keying = vector;
+ break;
+ case 'l':
+ p.loudspeaker = vector;
+ break;
+ case 'm':
+ p.microphone = vector;
+ break;
+ case 'n':
+ p.mode = optarg;
+ break;
+ case 'p':
+ p.ptt = vector;
+ break;
+ case 'r':
+ p.receiver = vector;
+ break;
+ case 't':
+ p.transmitter = vector;
+ break;
+ case 'x':
+ p.text = vector;
+ break;
+ case 0:
+ break;
+ }
+ }
+ }
+ else { // argc <= 1
+ help(argv[0]);
+ exit(1);
+ }
+ run(&p);
+ return 0;
+}