traverso-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Traverso-devel] Sample OSC Implementation [patch included]


From: Remon
Subject: Re: [Traverso-devel] Sample OSC Implementation [patch included]
Date: Wed, 5 Dec 2007 22:23:45 +0100
User-agent: KMail/1.9.6 (enterprise 0.20070907.709405)

Hi !

> Howdy Folks:

From Texas ? :D


> Appended is a patch against current CVS that implements OSC support for
> Traverso.  It uses Steve Harris's and Nicholas Humfrey's 'liblo' library,
> available at:
>
>       http://liblo.sourceforge.net/

Nice!

> At present, the namespace is extremely simple, consisting of just a single
> leaf:  '/traverso/transport/insert_track', which expects a single string
> argument: a fully qualified name for an audio file.  When executed (by
> sending the appropriate OSC message to UDP port 7770), traverso will create
> a new track and then attempt to import the referenced file into it.  The
> implementation uses two new classes in 'common/': 'OscEvent' (a container
> class for OSC message bundles) and 'OscHandler' (a C++ encapsulation of
> liblo that allows OSC events to by processed by means of the standard Qt
> signal/slot mechanism).  To date, I have tested this only on Linux (i386
> architecture).
>
> This patch is intended to demonstrate a basic 'proof of concept', not a
> finished implementation.  Specifically, I'd appreciate it if some of the
> senior folks here could take a glance at it and give a shout if they find
> any obvious showstoppers (organization, coding style, cross-platform
> pitfalls, etc).  If it passes muster, I'll go ahead and start putting
> together a draft namespace layout for a full implementation.


I'm a bit short on time today and tomorrow, but a first quick impression, some 
comments:

* Traverso uses an event based approach (like all GUI programs?) to reflect 
changes in core data (structures). 
As such, the GUI is not controlled, but the core. The GUI just reflects the 
changes, and visualizes the core data.
* For that reason I wouldn't use Interface.cpp to init and handle OSC, but 
rather see OSC as another way of an 'input event', but I could of course 
misunderstand the purpose of OSC.
* Since OSC doesn't operate in a 'context which is dependend on the mouse 
position', but rather gives programmatic control of the application, the 
question arises if a) existing infrastructure for dispacting events can still 
be used. b) if there is need for a 'ProgramaticInterface' which operates in a 
similar way as the current SongCanvas, but without the GUI.
This PI retrieves pointers to core Objects after a Project load, and connects 
to the important signals of the core.
Benefit is that the PI has it's own set of pointers to core Objects (like 
Song, Project, Track etc) and doesn't need to query the core lib (which could 
be unsafe when an event is being processed by Tsar !!).
* What about moving it into either it's own subdir, or see it as an extension 
to InputEngine, and thus add the SCO logic (at the least) to the core lib 
(instead of common, which is no lib at all)
* could you make a list of at least a minimal set of options you want to 
implement ? Like loading a track, creating a clip is one, but 
starting/stopping a song another etc.
Depending on that list, it might be valuable to research if e.g. the 
InputEngine can be used for most of it.
* I try to depend 'only' to Qt if possible, so std::vector/list/etc isn't 
used, unless you think it's better then those of Qt. Probably a matter of 
habit, preference... Not that important.
* qmake is compilation is becoming deprecated (at least that's true for > 
Traverso 0.42.0), we're using cmake now....     

Well, these are just some thoughts, also inspired by your off-list email (that 
you like to control the GUI, which is exactly what we don't do in 
Traverso :) )

More later, and thanks for working on this!

Regards,

Remon.

P.S.
Short is relative .... :P


>
> Patch follows:
>
> *** snip snip ***
> diff --unified --recursive --new-file traverso/src/commands/Import.cpp
> traverso-fredg01/src/commands/Import.cpp
> --- traverso/src/commands/Import.cpp  2007-11-19 06:18:52.000000000 -0500
> +++ traverso-fredg01/src/commands/Import.cpp  2007-12-03 08:45:35.000000000
> -0500
> @@ -98,22 +98,22 @@
>                               tr("Import audio source"),
>                               pm().get_project()->get_import_dir(),
>                               tr("All files (*);;Audio files (*.wav 
> *.flac)"));
> +     }
>
> -             int splitpoint = m_fileName.lastIndexOf("/") + 1;
> -             QString dir = m_fileName.left(splitpoint - 1);
> +             int splitpoint = m_fileName.lastIndexOf("/") + 1;
> +             QString dir = m_fileName.left(splitpoint - 1);
>
> -             if (m_fileName.isEmpty()) {
> -                     PWARN("Import:: FileName is empty!");
> -                     return -1;
> -             }
> +             if (m_fileName.isEmpty()) {
> +                     PWARN("Import:: FileName is empty!");
> +                     return -1;
> +             }
>
> -             pm().get_project()->set_import_dir(dir);
> +             pm().get_project()->set_import_dir(dir);
>
> -             if (create_readsource() == -1) {
> -                     return -1;
> -             }
> -             create_audioclip();
> -     }
> +             if (create_readsource() == -1) {
> +                     return -1;
> +             }
> +             create_audioclip();
>
>       return 1;
>  }
> @@ -131,7 +131,6 @@
>               PERROR("Can't import audiofile %s", QS_C(m_fileName));
>               return -1;
>       }
> -
>       return 1;
>  }
>
> diff --unified --recursive --new-file traverso/src/common/OscEvent.cpp
> traverso-fredg01/src/common/OscEvent.cpp
> --- traverso/src/common/OscEvent.cpp  1969-12-31 19:00:00.000000000 -0500
> +++ traverso-fredg01/src/common/OscEvent.cpp  2007-12-03 13:47:01.000000000
> -0500
> @@ -0,0 +1,59 @@
> +// OscEvent.cpp
> +//
> +// Copyright (C) 2007 Fred Gleason <address@hidden>
> +//
> +//  This file is part of Traverso
> +//
> +//  Traverso 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 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 General Public License for more details.
> +//
> +//  You should have received a copy of the GNU General Public License
> +//  along with this program; if not, write to the Free Software
> +//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
> USA.
> +
> +
> +#include "OscEvent.h"
> +
> +
> +OscEvent::OscEvent(const QString &path)
> +{
> +        m_path=path;
> +}
> +
> +
> +QString OscEvent::path() const
> +{
> +        return m_path;
> +}
> +
> +
> +unsigned OscEvent::args() const
> +{
> +        return m_args.size();
> +}
> +
> +
> +OscEvent::OscType OscEvent::type(unsigned n) const
> +{
> +        return m_types[n];
> +}
> +
> +
> +QVariant OscEvent::arg(unsigned n) const
> +{
> +        return m_args[n];
> +}
> +
> +
> +void OscEvent::addArg(OscType type,QVariant arg)
> +{
> +        m_types.push_back(type);
> +        m_args.push_back(arg);
> +}
> diff --unified --recursive --new-file traverso/src/common/OscEvent.h
> traverso-fredg01/src/common/OscEvent.h
> --- traverso/src/common/OscEvent.h    1969-12-31 19:00:00.000000000 -0500
> +++ traverso-fredg01/src/common/OscEvent.h    2007-12-03 14:38:55.000000000
> -0500 @@ -0,0 +1,56 @@
> +// OscEvent.h
> +//
> +// Copyright (C) 2007 Fred Gleason <address@hidden>
> +//
> +//  This file is part of Traverso
> +//
> +//  Traverso 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 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 General Public License for more details.
> +//
> +//  You should have received a copy of the GNU General Public License
> +//  along with this program; if not, write to the Free Software
> +//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
> USA.
> +//
> +//
> +//  This abstracts an OSC message, as defined in v1.0 of the Open Sound
> Control
> +//  Protocol [http://opensoundcontrol.org/spec-1_0].
> +//
> +
> +#ifndef OSCEVENT_H
> +#define OSCEVENT_H
> +
> +#include <vector>
> +
> +#include <qstring.h>
> +#include <qvariant.h>
> +
> +
> +class OscEvent
> +{
> + public :
> +        enum OscType
> {TypeInt32='i',TypeFloat32='f',TypeString='s',TypeBlob='b'};
> +     OscEvent(const QString &path);
> +     QString path() const;
> +     unsigned args() const;
> +     OscEvent::OscType type(unsigned n) const;
> +     QVariant arg(unsigned n) const;
> +     void addArg(OscType type,QVariant arg);
> +
> + private:
> +     QString m_path;
> +     OscEvent::OscType m_type;
> +     QVariant m_arg;
> +     std::vector<OscEvent::OscType> m_types;
> +     std::vector<QVariant> m_args;
> +};
> +
> +
> +
> +#endif
> diff --unified --recursive --new-file traverso/src/common/OscHandler.cpp
> traverso-fredg01/src/common/OscHandler.cpp
> --- traverso/src/common/OscHandler.cpp        1969-12-31 19:00:00.000000000 
> -0500
> +++ traverso-fredg01/src/common/OscHandler.cpp        2007-12-03
> 14:35:27.000000000 -0500
> @@ -0,0 +1,87 @@
> +// OscHandler.cpp
> +//
> +// Copyright (C) 2007 Fred Gleason <address@hidden>
> +//
> +//  This file is part of Traverso
> +//
> +//  Traverso 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 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 General Public License for more details.
> +//
> +//  You should have received a copy of the GNU General Public License
> +//  along with this program; if not, write to the Free Software
> +//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
> USA.
> +
> +
> +#include <qtimer.h>
> +#include <qbytearray.h>
> +
> +#include "OscEvent.h"
> +#include "OscHandler.h"
> +
> +int OscCallback(const char *path, const char *types, lo_arg **argv,
> +             int argc, void *data, void *user_data)
> +{
> +        int size=0;
> +        OscEvent *e=new OscEvent(path);
> +     for (int i=0; i<argc; i++) {
> +             switch((OscEvent::OscType)types[i]) {
> +                     case OscEvent::TypeInt32:
> +                             e->addArg(OscEvent::TypeInt32,argv[i]->i);
> +                             break;
> +
> +                     case OscEvent::TypeFloat32:
> +                             e->addArg(OscEvent::TypeFloat32,argv[i]->f);
> +                             break;
> +
> +                     case OscEvent::TypeString:
> +                             e->addArg(OscEvent::TypeString,QString((const 
> char *)argv[i]));
> +                             break;
> +
> +                     case OscEvent::TypeBlob:
> +                             size=argv[i]->i;
> +                             e->addArg(OscEvent::TypeBlob,QByteArray(((const 
> char
> *)argv[i])+4,size)); +                                break;
> +
> +                     default:  // Ignore unknown types as per the OSC spec
> (http://opensoundcontrol.org/spec-1_0)
> +                             return -1;
> +             }
> +     }
> +     ((OscHandler *)user_data)->handlerData(e);
> +     delete e;
> +     return 1;
> +}
> +
> +
> +OscHandler::OscHandler(uint16_t port)
> +{
> +        m_server=lo_server_new_with_proto((const char
> *)QString().sprintf("%d",port).toAscii(),LO_UDP,NULL);
> +     lo_server_add_method(m_server, NULL, NULL, OscCallback, this);
> +     QTimer *timer=new QTimer(this);
> +     connect(timer,SIGNAL(timeout()),this,SLOT(pollData()));
> +     timer->start(OSC_POLL_INTERVAL);
> +}
> +
> +
> +OscHandler::~OscHandler()
> +{
> +        free(m_server);
> +}
> +
> +
> +void OscHandler::handlerData(OscEvent *e)
> +{
> +        emit messageReceived(e);
> +}
> +
> +
> +void OscHandler::pollData()
> +{
> +     while(lo_server_recv_noblock(m_server,0)>0);
> +}
> diff --unified --recursive --new-file traverso/src/common/OscHandler.h
> traverso-fredg01/src/common/OscHandler.h
> --- traverso/src/common/OscHandler.h  1969-12-31 19:00:00.000000000 -0500
> +++ traverso-fredg01/src/common/OscHandler.h  2007-12-03 14:41:37.000000000
> -0500
> @@ -0,0 +1,58 @@
> +// OscHandler.h
> +//
> +// Copyright (C) 2007 Fred Gleason <address@hidden>
> +//
> +//  This file is part of Traverso
> +//
> +//  Traverso 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 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 General Public License for more details.
> +//
> +//  You should have received a copy of the GNU General Public License
> +//  along with this program; if not, write to the Free Software
> +//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
> USA.
> +//
> +//
> +//  This class is designed to make a thin wrapper around the 'liblo'
> library +//  for formatting and handling OSC (Open Sound Control) messages,
> allowing +//  such messages to be handled via Qt's standard signal/slot
> mechanism. +//
> +
> +#ifndef OSCHANDLER_H
> +#define OSCHANDLER_H
> +
> +#include <lo/lo.h>
> +
> +#include "OscEvent.h"
> +#include "defines.h"
> +
> +#define DEFAULT_OSC_PORT 7770
> +#define OSC_POLL_INTERVAL 100
> +
> +class OscHandler : public QObject
> +{
> + Q_OBJECT;
> + public :
> +     OscHandler(uint16_t port);
> +     ~OscHandler();
> +     void handlerData(OscEvent *e);
> +
> + signals:
> +     void messageReceived(OscEvent *e);
> +
> + private slots:
> +        void pollData();
> +
> + private:
> +     lo_server m_server;
> +};
> +
> +
> +
> +#endif
> diff --unified --recursive --new-file traverso/src/core/core.pro
> traverso-fredg01/src/core/core.pro
> --- traverso/src/core/core.pro        2007-11-19 06:18:53.000000000 -0500
> +++ traverso-fredg01/src/core/core.pro        2007-12-03 10:45:24.000000000 
> -0500
> @@ -27,6 +27,8 @@
>       ../common/Mixer.cpp \
>       ../common/RingBuffer.cpp \
>       ../common/Resampler.cpp \
> +        ../common/OscEvent.cpp \
> +        ../common/OscHandler.cpp \
>       AudioClip.cpp \
>       AudioClipManager.cpp \
>       AudioSource.cpp \
> @@ -66,6 +68,8 @@
>       ../common/RingBuffer.h \
>       ../common/RingBufferNPT.h \
>       ../common/Resampler.h \
> +        ../common/OscEvent.h \
> +        ../common/OscHandler.h \
>       AudioClip.h \
>       AudioClipManager.h \
>       AudioSource.h \
> diff --unified --recursive --new-file traverso/src/traverso/Interface.cpp
> traverso-fredg01/src/traverso/Interface.cpp
> --- traverso/src/traverso/Interface.cpp       2007-12-03 09:05:25.000000000 
> -0500
> +++ traverso-fredg01/src/traverso/Interface.cpp       2007-12-03
> 15:10:28.000000000 -0500
> @@ -46,6 +46,7 @@
>  #include "SpectralMeterWidget.h"
>
>  #include "Import.h"
> +#include "CommandGroup.h"
>
>  #include "songcanvas/SongWidget.h"
>
> @@ -200,6 +201,8 @@
>       cpointer().add_contextitem(this);
>
>       connect(&config(), SIGNAL(configChanged()), this,
> SLOT(config_changed())); +
> +     init_osc();
>  }
>
>  Interface::~Interface()
> @@ -279,7 +282,7 @@
>  {
>       PENTER;
>
> -     SongWidget* songWidget;
> +     SongWidget* songWidget = 0;
>
>       if (!song) {
>               Project* project = pm().get_project();
> @@ -1248,3 +1251,55 @@
>       config().save();
>  }
>
> +
> +void Interface::init_osc()
> +{
> +        m_oscHandler=new OscHandler(DEFAULT_OSC_PORT);
> +     connect(m_oscHandler,SIGNAL(messageReceived(OscEvent
> *)),this,SLOT(handle_osc_messages(OscEvent *)));
> +}
> +
> +
> +void Interface::handle_osc_messages(OscEvent* e)
> +{
> +        if(e->path()!="/traverso/transport/insert_track") {
> +             return;
> +     }
> +     if((e->args()==1)&&(e->type(0)==OscEvent::TypeString)) {
> +             insert_audio(e->arg(0).toString());
> +     }
> +}
> +
> +
> +void Interface::insert_audio(const QString &filename)
> +{
> +        //
> +        // Create a new track
> +        //
> +        Project *project=pm().get_project();
> +     if (! project) {
> +             info().information(tr("I can't create a new Track if there is 
> no Project
> loaded!!"));
> +             return;
> +     }
> +
> +     Song* song = project->get_current_song();
> +     if ( ! song ) {
> +             return ;
> +     }
> +
> +     CommandGroup* group = new CommandGroup(song, "");
> +
> +     Track* track = new Track(song, "Unnamed", Track::INITIAL_HEIGHT);
> +     track->set_name("Unnamed");
> +     group->add_command(song->add_track(track));
> +
> +     group->setText(tr("Added 1 Track(s)", ""));
> +     Command::process_command(group);
> +
> +     //
> +     // Import Audio
> +     //
> +             Import* cmd = new Import(track, filename, TimeRef());
> +     Command::process_command(cmd);
> +}
> +
> +
> diff --unified --recursive --new-file traverso/src/traverso/Interface.h
> traverso-fredg01/src/traverso/Interface.h
> --- traverso/src/traverso/Interface.h 2007-11-29 14:52:18.000000000 -0500
> +++ traverso-fredg01/src/traverso/Interface.h 2007-12-03 15:09:36.000000000
> -0500
> @@ -23,6 +23,7 @@
>  #ifndef INTERFACE_H
>  #define INTERFACE_H
>
> +#include <OscHandler.h>
>  #include <QMainWindow>
>  #include <QHash>
>
> @@ -87,6 +88,7 @@
>       void select_fade_out_shape();
>       void show_busselector(Track* track);
>       void set_insertsilence_track(Track* track);
> +     void init_osc();
>
>  protected:
>       void keyPressEvent ( QKeyEvent* e);
> @@ -125,7 +127,7 @@
>       NewProjectDialog*       m_newProjectDialog;
>       QDialog*                m_quickStart;
>       RestoreProjectBackupDialog* m_restoreProjectBackupDialog;
> -
> +     OscHandler*             m_oscHandler;
>
>       BusMonitor*             busMonitor;
>       QToolBar*               mainToolBar;
> @@ -149,6 +151,7 @@
>       QMenu* create_context_menu(QObject* item, QList<MenuData >* list = 0);
>       QMenu* create_fade_selector_menu(const QString& fadeTypeName);
>
> +
>  public slots :
>       void set_project(Project* project);
>       void show_song(Song* song);
> @@ -167,6 +170,8 @@
>       void change_resample_quality_to_high();
>       void change_resample_quality_to_medium();
>       void change_resample_quality_to_fast();
> +     void handle_osc_messages(OscEvent* e);
> +     void insert_audio(const QString &filename);
>
>       Command* full_screen();
>       Command* about_traverso();
> diff --unified --recursive --new-file traverso/src/traverso/Traverso.cpp
> traverso-fredg01/src/traverso/Traverso.cpp
> --- traverso/src/traverso/Traverso.cpp        2007-12-03 11:27:31.000000000 
> -0500
> +++ traverso-fredg01/src/traverso/Traverso.cpp        2007-12-03
> 14:50:13.000000000 -0500
> @@ -34,6 +34,7 @@
>  #include <AudioDevice.h>
>  #include <ContextPointer.h>
>  #include <Information.h>
> +#include <OscHandler.h>
>  #include "defines.h"
>  #include "fpu.h"
>  #ifdef __SSE__
> @@ -106,7 +107,7 @@
>       srand ( time(NULL) );
>
>       init_sse();
> -
> +
>       QMetaObject::invokeMethod(this, "create_interface",
> Qt::QueuedConnection); //     create_interface();
>
> diff --unified --recursive --new-file traverso/src/traverso/traverso.pro
> traverso-fredg01/src/traverso/traverso.pro
> --- traverso/src/traverso/traverso.pro        2007-11-07 17:02:48.000000000 
> -0500
> +++ traverso-fredg01/src/traverso/traverso.pro        2007-12-03
> 10:25:42.000000000 -0500
> @@ -140,6 +140,10 @@
>      LIBS += -lslv2 -lrdf -lrasqal -lraptor
>      INCLUDEPATH +=   ../3rdparty/slv2 ../plugins/LV2
>  }
> +contains(DEFINES, OSC_SUPPORT) {
> +    LIBS += -llo
> +    INCLUDEPATH += lo/lo.h
> +}
>
>  contains(DEFINES, QT_OPENGL_SUPPORT){
>      QT += opengl
> *** snip snip ***
>
> Cheers!
>
> |-------------------------------------------------------------------------|
> | Frederick F. Gleason, Jr. |               Chief Developer               |
> |
> |                           |               Paravel Systems               |
> |
> |-------------------------------------------------------------------------|
> |               Machines should work.  People should think.               |
> |                                           -- IBM Pollyanna Principle    |
> |-------------------------------------------------------------------------|
>
> _______________________________________________
> Traverso-devel mailing list
> address@hidden
> http://lists.nongnu.org/mailman/listinfo/traverso-devel






reply via email to

[Prev in Thread] Current Thread [Next in Thread]