Starting to write the command-line/server version of FreeDV. So far, I've just done...
authorbruceperens <bruceperens@01035d8c-6547-0410-b346-abe4f91aad63>
Wed, 11 Dec 2013 23:07:39 +0000 (23:07 +0000)
committerbruceperens <bruceperens@01035d8c-6547-0410-b346-abe4f91aad63>
Wed, 11 Dec 2013 23:07:39 +0000 (23:07 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@1334 01035d8c-6547-0410-b346-abe4f91aad63

freedv-server/.gitignore [deleted file]
freedv-server/CMakeLists.txt [new file with mode: 0644]
freedv-server/source/main.cpp [new file with mode: 0644]

diff --git a/freedv-server/.gitignore b/freedv-server/.gitignore
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/freedv-server/CMakeLists.txt b/freedv-server/CMakeLists.txt
new file mode 100644 (file)
index 0000000..6b72678
--- /dev/null
@@ -0,0 +1,100 @@
+#
+# 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)
diff --git a/freedv-server/source/main.cpp b/freedv-server/source/main.cpp
new file mode 100644 (file)
index 0000000..042cc06
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * 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;
+}