[SCM] calf/master: + OSC client/server: started implementing (very primitive, incomplete implementation, just enough to be able to implement DSSI GUI) + DSSI GUI: started implementing; seems to receive messages already, the actual GUI code is not even started + Added .svnignore containing autogenerated files (configure stuff and tarballs)

js at users.alioth.debian.org js at users.alioth.debian.org
Tue May 7 15:36:54 UTC 2013


The following commit has been merged in the master branch:
commit abafcd81478d4953498c2e10aeb7c114a744f417
Author: kfoltman <kfoltman at 78b06b96-2940-0410-b7fc-879d825d01d8>
Date:   Thu Jan 3 22:17:08 2008 +0000

    + OSC client/server: started implementing (very primitive, incomplete implementation, just enough to be able to implement DSSI GUI)
    + DSSI GUI: started implementing; seems to receive messages already, the actual GUI code is not even started
    + Added .svnignore containing autogenerated files (configure stuff and tarballs)
    
    
    
    git-svn-id: https://calf.svn.sourceforge.net/svnroot/calf/trunk@71 78b06b96-2940-0410-b7fc-879d825d01d8

diff --git a/.svnignore b/.svnignore
new file mode 100644
index 0000000..168a7a0
--- /dev/null
+++ b/.svnignore
@@ -0,0 +1,10 @@
+config.h
+config.log
+config.guess
+configure
+calf-*.tar.gz
+autom4te.cache
+stamp-h1
+libtool
+aclocal.m4
+Makefile.in
diff --git a/src/Makefile.am b/src/Makefile.am
index 2161dd0..5604426 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -8,7 +8,7 @@ ladspadir = $(with_ladspa_dir)
 
 bin_PROGRAMS = 
 
-noinst_PROGRAMS = calfbenchmark
+noinst_PROGRAMS = calfbenchmark calfdssigui
 noinst_LTLIBRARIES = calf.la libcalfstatic.la
 
 AM_CXXFLAGS = -ffast-math -march=i686 -finline-limit=80 -DPKGLIBDIR=\"$(pkglibdir)\"
@@ -42,7 +42,10 @@ AM_CXXFLAGS += -DUSE_DSSI=1
 endif
 
 calfbenchmark_SOURCES = benchmark.cpp
-calfbenchmark_LDADD = 
+calfbenchmark_LDADD =  -lglib-2.0 libcalfgui.la
+
+calfdssigui_SOURCES = dssigui.cpp
+calfdssigui_LDADD =  -lglib-2.0 libcalfgui.la
 
 calf_la_SOURCES = modules.cpp giface.cpp monosynth.cpp organ.cpp preset.cpp synth.cpp 
 calf_la_LDFLAGS = -rpath $(ladspadir) -avoid-version -module -lexpat
@@ -50,7 +53,7 @@ calf_la_LDFLAGS = -rpath $(ladspadir) -avoid-version -module -lexpat
 libcalfstatic_la_SOURCES = modules.cpp giface.cpp monosynth.cpp organ.cpp preset.cpp synth.cpp
 libcalfstatic_la_LDFLAGS = -static -lexpat
 
-libcalfgui_la_SOURCES = gui.cpp preset_gui.cpp custom_ctl.cpp
+libcalfgui_la_SOURCES = gui.cpp preset_gui.cpp custom_ctl.cpp osctl.cpp
 libcalfgui_la_LDFLAGS = -static
 
 clean-local:
@@ -71,7 +74,9 @@ if USE_LADSPA
 endif
 if USE_DSSI
 	install -d -m 755 $(DESTDIR)$(with_dssi_dir)
+	install -d -m 755 $(DESTDIR)$(with_dssi_dir)/calf
 	install -c -m 755 $(top_builddir)/src/.libs/calf.so $(DESTDIR)$(with_dssi_dir)/calf.so
+	install -c -m 755 $(top_builddir)/src/calfdssigui $(DESTDIR)$(with_dssi_dir)/calf/calf_gtk
 endif
 
 #remove calf.so, calf.rdf and - if empty - ladspa dir in usr/share
@@ -89,6 +94,8 @@ if USE_LADSPA
 endif
 if USE_DSSI
 	$(RM) -f $(DESTDIR)$(with_dssi_dir)/calf.so
+	$(RM) -f $(DESTDIR)$(with_dssi_dir)/calf/calf_gtk
+	$(RMDIR) -f $(DESTDIR)$(with_dssi_dir)/calf
 endif
 
 #install:
diff --git a/src/benchmark.cpp b/src/benchmark.cpp
index 2128586..3e86b4c 100644
--- a/src/benchmark.cpp
+++ b/src/benchmark.cpp
@@ -26,9 +26,16 @@
 #include <calf/modules_dev.h>
 #include <calf/benchmark.h>
 
+// #define TEST_OSC
+
 using namespace std;
 using namespace dsp;
 
+#ifdef TEST_OSC
+#include <calf/osctl.h>
+using namespace osctl;
+#endif
+
 bool benchmark_globals::warned = false;
 
 template<int BUF_SIZE>
@@ -320,6 +327,39 @@ void reverbir_calc()
     }
 }
 
+#ifdef TEST_OSC
+void osctl_test()
+{
+    string sdata = string("\000\000\000\003123\000test\000\000\000\000\000\000\000\001\000\000\000\002", 24);
+    osc_stream is(sdata);
+    vector<osc_data> data;
+    is.read("bsii", data);
+    assert(is.pos == sdata.length());
+    assert(data.size() == 4);
+    assert(data[0].type == osc_blob);
+    assert(data[1].type == osc_string);
+    assert(data[2].type == osc_i32);
+    assert(data[3].type == osc_i32);
+    assert(data[0].strval == "123");
+    assert(data[1].strval == "test");
+    assert(data[2].i32val == 1);
+    assert(data[3].i32val == 2);
+    osc_stream os("");
+    os.write(data);
+    assert(os.buffer == sdata);
+    osc_server srv;
+    srv.bind("0.0.0.0", 4541);
+    
+    osc_client cli;
+    cli.bind("0.0.0.0", 0);
+    cli.set_addr("0.0.0.0", 4541);
+    if (!cli.send("/blah", data))
+        g_error("Could not send the OSC message");
+    
+    g_main_loop_run(g_main_loop_new(NULL, FALSE));
+}
+#endif
+
 int main(int argc, char *argv[])
 {
     while(1) {
@@ -341,6 +381,11 @@ int main(int argc, char *argv[])
         }
     }
     
+#ifdef TEST_OSC
+    if (!strcmp(unit, "osc"))
+        osctl_test();
+#endif
+    
     if (!unit || !strcmp(unit, "biquad"))
         biquad_test();
     
diff --git a/src/calf/osctl.h b/src/calf/osctl.h
new file mode 100644
index 0000000..73b6430
--- /dev/null
+++ b/src/calf/osctl.h
@@ -0,0 +1,209 @@
+/* Calf DSP Library
+ * Open Sound Control primitives
+ *
+ * Copyright (C) 2007 Krzysztof Foltman
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string>
+#include <vector>
+#include <glib.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+namespace osctl
+{
+    
+enum osc_type
+{
+    osc_i32 = 'i',
+    osc_f32 = 'f',
+    osc_string = 's',
+    osc_blob = 'b',
+    
+    // unsupported
+    osc_i64 = 'h',
+    osc_ts = 't',
+    osc_f64 = 'd',
+    osc_string_alt = 'S',
+    osc_char = 'c',
+    osc_rgba = 'r',
+    osc_midi = 'm',
+    osc_true = 'T',
+    osc_false = 'F',
+    osc_nil = 'N',
+    osc_inf = 'I',
+    osc_start_array = '[',
+    osc_end_array = ']'
+};
+
+extern const char *osc_type_name(osc_type type);
+
+// perhaps a little inefficient, but this is OSC anyway, so efficiency
+// goes out of the window right from start :)
+struct osc_data
+{
+    osc_type type;
+    union {
+        int32_t i32val;
+        uint64_t tsval;
+        float f32val;
+        double f64val;
+    };
+    std::string strval;
+    osc_data()
+    {
+        type = osc_nil;
+    }
+    osc_data(std::string _sval, osc_type _type = osc_string)
+    : type(_type)
+    , strval(_sval)
+    {
+    }
+    osc_data(int ival)
+    : type(osc_i32)
+    , i32val(ival)
+    {
+    }
+    osc_data(float fval)
+    : type(osc_f32)
+    , f32val(fval)
+    {
+    }
+    std::string to_string() const;
+    ~osc_data()
+    {
+    }
+};
+
+struct osc_exception: public std::exception
+{
+    virtual const char *what() const throw() { return "OSC parsing error"; }
+};
+    
+struct osc_stream
+{
+    std::string buffer;
+    unsigned int pos;
+    
+    osc_stream() : pos(0) {}
+    osc_stream(const std::string &_buffer, unsigned int _pos = 0)
+    : buffer(_buffer), pos(_pos) {}
+    
+    inline void copy_from(void *dest, int bytes)
+    {
+        if (pos + bytes > buffer.length())
+            throw osc_exception();
+        memcpy(dest, &buffer[pos], bytes);
+        pos += bytes;
+    }
+    
+    void read(osc_type type, osc_data &od);
+    void write(const osc_data &od);
+    
+    void read(const char *tags, std::vector<osc_data> &data);
+    void write(const std::vector<osc_data> &data);
+};
+
+struct osc_net_bad_address: public std::exception
+{
+    std::string addr, error_msg;
+    osc_net_bad_address(const char *_addr)
+    {
+        addr = _addr;
+        error_msg = "Incorrect OSC URI: " + addr;
+    }
+    virtual const char *what() const throw() { return error_msg.c_str(); }
+    virtual ~osc_net_bad_address() throw () {}
+};
+
+struct osc_net_exception: public std::exception
+{
+    int net_errno;
+    std::string command, error_msg;
+    osc_net_exception(const char *cmd, int _errno = errno)
+    {
+        command = cmd;
+        net_errno = _errno;
+        error_msg = "OSC error in "+command+": "+strerror(_errno);
+    }
+    virtual const char *what() const throw() { return error_msg.c_str(); }
+    virtual ~osc_net_exception() throw () {}
+};
+    
+struct osc_net_dns_exception: public std::exception
+{
+    int net_errno;
+    std::string command, error_msg;
+    osc_net_dns_exception(const char *cmd, int _errno = h_errno)
+    {
+        command = cmd;
+        net_errno = _errno;
+        error_msg = "OSC error in "+command+": "+hstrerror(_errno);
+    }
+    virtual const char *what() const throw() { return error_msg.c_str(); }
+    virtual ~osc_net_dns_exception() throw () {}
+};
+    
+struct osc_message_sink
+{
+    virtual void receive_osc_message(std::string address, std::string type_tag, const std::vector<osc_data> &args)=0;
+    virtual ~osc_message_sink() {}
+};
+
+struct osc_message_dump: public osc_message_sink
+{
+    virtual void receive_osc_message(std::string address, std::string type_tag, const std::vector<osc_data> &args);
+};
+
+struct osc_socket
+{
+    GIOChannel *ioch;
+    int socket, srcid;
+    std::string prefix;
+
+    osc_socket() : ioch(NULL), socket(-1), srcid(0) {}
+    void bind(const char *hostaddr = "0.0.0.0", int port = 0);
+    std::string get_uri() const;
+    virtual void on_bind() {}
+    virtual ~osc_socket();
+};
+
+struct osc_server: public osc_socket
+{
+    static osc_message_dump dump;
+    osc_message_sink *sink;
+    
+    osc_server() : sink(&dump) {}
+    
+    virtual void on_bind();
+    
+    static gboolean on_data(GIOChannel *channel, GIOCondition cond, void *obj);
+    void parse_message(const char *buffer, int len);    
+};
+
+struct osc_client: public osc_socket
+{
+    sockaddr_in addr;
+    
+    void set_addr(const char *hostaddr, int port);
+    void set_url(const char *url);
+    bool send(const std::string &address, const std::vector<osc_data> &args);
+};
+
+};
diff --git a/src/osctl.cpp b/src/osctl.cpp
new file mode 100644
index 0000000..e7a4cd7
--- /dev/null
+++ b/src/osctl.cpp
@@ -0,0 +1,305 @@
+#include <calf/osctl.h>
+#include <assert.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <sstream>
+
+using namespace osctl;
+using namespace std;
+
+std::string osc_data::to_string() const
+{
+    std::stringstream ss;
+    switch(type)
+    {
+    case osc_i32: ss << i32val; break;
+    case osc_i64: ss << (int64_t)tsval; break;
+    case osc_f32: ss << f32val; break;
+    case osc_ts: ss << tsval; break;
+    case osc_string: return strval;
+    case osc_string_alt: return strval;
+    case osc_blob: return strval;
+    case osc_true: return "TRUE";
+    case osc_false: return "FALSE";
+    case osc_nil: return "NIL";
+    case osc_inf: return "INF";
+    case osc_start_array: return "[";
+    case osc_end_array: return "]";
+    default:
+        return "?";
+    }
+    return ss.str();
+}
+
+const char *osctl::osc_type_name(osc_type type)
+{
+    switch(type)
+    {
+    case osc_i32: return "i32";
+    case osc_i64: return "i64";
+    case osc_f32: return "f32";
+    case osc_ts: return "ts";
+    case osc_string: return "str";
+    case osc_string_alt: return "stralt";
+    case osc_blob: return "blob";
+    case osc_char: return "char";
+    case osc_rgba: return "rgba";
+    case osc_midi: return "midi";
+    case osc_true: return "TRUE";
+    case osc_false: return "FALSE";
+    case osc_nil: return "NIL";
+    case osc_inf: return "INF";
+    case osc_start_array: return "[";
+    case osc_end_array: return "]";
+    default:
+        return "unknown";
+    }
+}
+
+void osc_stream::read(osc_type type, osc_data &od)
+{
+    od.type = type;
+    switch(type)
+    {
+    case osc_i32:
+    case osc_f32:
+        copy_from(&od.i32val, 4);
+        od.i32val = ntohl(od.i32val);
+        break;
+    case osc_ts:
+        copy_from(&od.tsval, 8);
+        if (ntohl(1) != 1) {
+            uint32_t a = ntohl(od.tsval), b = ntohl(od.tsval >> 32);
+            od.tsval = (((uint64_t)a) << 32) | b;
+        }
+        break;
+    case osc_string:
+    case osc_string_alt:
+    {
+        int len = 0, maxlen = 0;
+        maxlen = buffer.length() - pos;
+        while(len < maxlen && buffer[pos + len])
+            len++;
+        od.strval = buffer.substr(pos, len);
+        pos += (len + 4) &~ 3;
+        break;
+    }
+    case osc_blob: {
+        copy_from(&od.i32val, 4);
+        od.i32val = ntohl(od.i32val);
+        od.strval = buffer.substr(pos, od.i32val);
+        pos += (od.i32val + 3) &~ 3;
+        break;
+    }
+    case osc_true:
+    case osc_false:
+    case osc_nil:
+        return;
+    default:
+        assert(0);
+    }
+}
+
+void osc_stream::write(const osc_data &od)
+{
+    uint32_t val;
+    switch(od.type)
+    {
+    case osc_i32:
+    case osc_f32:
+    {
+        val = ntohl(od.i32val);
+        buffer += string((const char *)&val, 4);
+        break;
+    }
+    case osc_ts: {
+        uint64_t ts = od.tsval;
+        if (ntohl(1) != 1) {
+            uint32_t a = ntohl(od.tsval), b = ntohl(od.tsval >> 32);
+            ts = (((uint64_t)a) << 32) | b;
+        }
+        buffer += string((const char *)&ts, 8);        
+        break;
+    }
+    case osc_string:
+    case osc_string_alt:
+    {
+        buffer += od.strval;
+        val = 0;
+        buffer += string((const char *)&val, 4 - (od.strval.length() & 3));
+        break;
+    }
+    case osc_blob:
+    {
+        val = ntohl(od.strval.length());
+        buffer += string((const char *)&val, 4);
+        buffer += od.strval;
+        val = 0;
+        buffer += string((const char *)&val, 4 - (od.strval.length() & 3));
+        break;
+    }
+    case osc_true:
+    case osc_false:
+    case osc_nil:
+        return;
+    default:
+        assert(0);
+    }
+}
+    
+void osc_stream::read(const char *tags, vector<osc_data> &data)
+{
+    while(*tags)
+    {
+        data.push_back(osc_data());
+        read((osc_type)*tags++, *data.rbegin());
+    }
+}
+
+void osc_stream::write(const vector<osc_data> &data)
+{
+    unsigned int pos = 0;
+    
+    while(pos < data.size())
+        write(data[pos++]);
+}
+
+osc_message_dump osc_server::dump;
+
+void osc_message_dump::receive_osc_message(std::string address, std::string type_tag, const std::vector<osc_data> &args)
+{
+    printf("address: %s, type tag: %s\n", address.c_str(), type_tag.c_str());
+    for (unsigned int i = 0; i < args.size(); i++)
+    {
+        printf("argument %d is %s\n", i, args[i].to_string().c_str());
+    }
+}
+
+void osc_server::parse_message(const char *buffer, int len)
+{
+    vector<osc_data> data;
+    osc_stream str(string(buffer, len));
+    str.read("ss", data);
+    if (!data[0].strval.empty() && data[0].strval[0] == '/'
+      &&!data[1].strval.empty() && data[1].strval[0] == ',')
+    {
+        vector<osc_data> data2;
+        str.read(data[1].strval.substr(1).c_str(), data2);
+        sink->receive_osc_message(data[0].strval, data[1].strval, data2);
+    }
+}
+
+void osc_socket::bind(const char *hostaddr, int port)
+{
+    socket = ::socket(PF_INET, SOCK_DGRAM, 0);
+    if (socket < 0)
+        throw osc_net_exception("socket");
+    
+    sockaddr_in sadr;
+    sadr.sin_family = AF_INET;
+    sadr.sin_port = htons(port);
+    inet_aton(hostaddr, &sadr.sin_addr);
+    if (::bind(socket, (sockaddr *)&sadr, sizeof(sadr)) < 0)
+        throw osc_net_exception("bind");
+    on_bind();
+}
+
+std::string osc_socket::get_uri() const
+{
+    sockaddr_in sadr;
+    socklen_t len = sizeof(sadr);
+    if (getsockname(socket, (sockaddr *)&sadr, &len) < 0)
+        throw osc_net_exception("getsockname");
+    
+    char name[INET_ADDRSTRLEN], buf[32];
+    
+    inet_ntop(AF_INET, &sadr.sin_addr, name, INET_ADDRSTRLEN);
+    sprintf(buf, "%d", ntohs(sadr.sin_port));
+    
+    return string("osc.udp://") + name + ":" + buf + prefix;
+}
+
+osc_socket::~osc_socket()
+{
+    if (ioch)
+        g_source_remove(srcid);
+    close(socket);
+}
+
+void osc_server::on_bind()
+{    
+    ioch = g_io_channel_unix_new(socket);
+    srcid = g_io_add_watch(ioch, G_IO_IN, on_data, this);
+}
+
+gboolean osc_server::on_data(GIOChannel *channel, GIOCondition cond, void *obj)
+{
+    osc_server *self = (osc_server *)obj;
+    char buf[16384];
+    int len = recv(self->socket, buf, 16384, 0);
+    if (len > 0)
+    {
+        if (buf[0] == '/')
+        {
+            self->parse_message(buf, len);
+        }
+        if (buf[0] == '#')
+        {
+            // XXXKF bundles are not supported yet
+        }
+    }
+    return TRUE;
+}
+
+void osc_client::set_addr(const char *hostaddr, int port)
+{
+    addr.sin_family = AF_INET;
+    addr.sin_port = htons(port);
+    inet_aton(hostaddr, &addr.sin_addr);
+}
+
+void osc_client::set_url(const char *url)
+{
+    if (strncmp(url, "osc.udp://", 10))
+        throw osc_net_bad_address(url);
+    url += 10;
+    
+    const char *pos = strchr(url, ':');
+    const char *pos2 = strchr(url, '/');
+    if (!pos || !pos2)
+        throw osc_net_bad_address(url);
+    
+    // XXXKF perhaps there is a default port for osc.udp?
+    if (pos2 - pos < 0)
+        throw osc_net_bad_address(url);
+    
+    string hostname = string(url, pos - url);
+    int port = atoi(pos + 1);
+    prefix = string(pos2);
+    printf("hostname %s port %d\n", hostname.c_str(), port);
+
+    addr.sin_family = AF_INET;
+    addr.sin_port = htons(port);
+
+    hostent *he = gethostbyname(hostname.c_str());
+    if (!he)
+        throw osc_net_dns_exception("gethostbyname");
+    
+    addr.sin_addr = *(struct in_addr *)he->h_addr;
+}
+
+bool osc_client::send(const std::string &address, const std::vector<osc_data> &args)
+{
+    vector<osc_data> data;
+    std::string type_tag = ",";
+    osc_stream str;
+    str.write(prefix + address);
+    for (unsigned int i = 0; i < args.size(); i++)
+        type_tag += char(args[i].type);
+    str.write(type_tag);
+    
+    for (unsigned int i = 0; i < args.size(); i++)
+        str.write(args[i]);    
+
+    return ::sendto(socket, str.buffer.data(), str.buffer.length(), 0, (sockaddr *)&addr, sizeof(addr)) == (int)str.buffer.length();
+}

-- 
calf audio plugins packaging



More information about the pkg-multimedia-commits mailing list