mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-09 08:14:58 +01:00
add basic support for the griffin powermate (a control surface) (from ben loftis)
git-svn-id: svn://localhost/ardour2/trunk@2078 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
39f5c0ad56
commit
f95aa76f4a
15 changed files with 438 additions and 16 deletions
|
|
@ -989,7 +989,12 @@ else:
|
||||||
# its included in the tarball
|
# its included in the tarball
|
||||||
#
|
#
|
||||||
|
|
||||||
surface_subdirs = [ 'libs/surfaces/control_protocol', 'libs/surfaces/generic_midi', 'libs/surfaces/tranzport', 'libs/surfaces/mackie' ]
|
surface_subdirs = [ 'libs/surfaces/control_protocol',
|
||||||
|
'libs/surfaces/generic_midi',
|
||||||
|
'libs/surfaces/tranzport',
|
||||||
|
'libs/surfaces/mackie',
|
||||||
|
'libs/surfaces/powermate'
|
||||||
|
]
|
||||||
|
|
||||||
if env['SURFACES']:
|
if env['SURFACES']:
|
||||||
if have_libusb:
|
if have_libusb:
|
||||||
|
|
|
||||||
|
|
@ -56,8 +56,8 @@ using namespace Gtkmm2ext;
|
||||||
using namespace Gtk;
|
using namespace Gtk;
|
||||||
using namespace sigc;
|
using namespace sigc;
|
||||||
|
|
||||||
LadspaPluginUI::LadspaPluginUI (boost::shared_ptr<PluginInsert> pi, bool scrollable)
|
LadspaPluginUI::LadspaPluginUI (boost::shared_ptr<PluginInsert> pi, nframes64_t sample_rate, nframes64_t period_size, bool scrollable)
|
||||||
: PlugUIBase (pi),
|
: PlugUIBase (pi, sample_rate, period_size),
|
||||||
button_table (initial_button_rows, initial_button_cols),
|
button_table (initial_button_rows, initial_button_cols),
|
||||||
output_table (initial_output_rows, initial_output_cols),
|
output_table (initial_output_rows, initial_output_cols),
|
||||||
hAdjustment(0.0, 0.0, 0.0),
|
hAdjustment(0.0, 0.0, 0.0),
|
||||||
|
|
@ -77,7 +77,11 @@ LadspaPluginUI::LadspaPluginUI (boost::shared_ptr<PluginInsert> pi, bool scrolla
|
||||||
Label* combo_label = manage (new Label (_("<span size=\"large\">Presets</span>")));
|
Label* combo_label = manage (new Label (_("<span size=\"large\">Presets</span>")));
|
||||||
combo_label->set_use_markup (true);
|
combo_label->set_use_markup (true);
|
||||||
|
|
||||||
smaller_hbox->pack_start (*combo_label, false, false, 10);
|
Label* latency_label = manage (new Label (_("<span size=\"large\">Latency</span>")));
|
||||||
|
latency_label->set_use_markup (true);
|
||||||
|
|
||||||
|
smaller_hbox->pack_start (*latency_label, false, false, 10);
|
||||||
|
smaller_hbox->pack_start (latency_gui, false, false, 10);
|
||||||
smaller_hbox->pack_start (combo, false, false);
|
smaller_hbox->pack_start (combo, false, false);
|
||||||
smaller_hbox->pack_start (save_button, false, false);
|
smaller_hbox->pack_start (save_button, false, false);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef __gtk2_ardour_latency_gui_h__
|
||||||
|
#define __gtk2_ardour_latency_gui_h__
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
@ -59,3 +62,5 @@ class LatencyDialog : public ArdourDialog
|
||||||
private:
|
private:
|
||||||
LatencyGUI lwidget;
|
LatencyGUI lwidget;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif /* __gtk2_ardour_latency_gui_h__ */
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ using namespace Gtkmm2ext;
|
||||||
using namespace Gtk;
|
using namespace Gtk;
|
||||||
using namespace sigc;
|
using namespace sigc;
|
||||||
|
|
||||||
PluginUIWindow::PluginUIWindow (boost::shared_ptr<PluginInsert> insert, bool scrollable)
|
PluginUIWindow::PluginUIWindow (boost::shared_ptr<PluginInsert> insert, nframes64_t sr, nframes64_t period, bool scrollable)
|
||||||
: ArdourDialog ("plugin ui")
|
: ArdourDialog ("plugin ui")
|
||||||
{
|
{
|
||||||
if (insert->plugin()->has_editor()) {
|
if (insert->plugin()->has_editor()) {
|
||||||
|
|
@ -73,7 +73,7 @@ PluginUIWindow::PluginUIWindow (boost::shared_ptr<PluginInsert> insert, bool scr
|
||||||
if ((vp = boost::dynamic_pointer_cast<VSTPlugin> (insert->plugin())) != 0) {
|
if ((vp = boost::dynamic_pointer_cast<VSTPlugin> (insert->plugin())) != 0) {
|
||||||
|
|
||||||
|
|
||||||
VSTPluginUI* vpu = new VSTPluginUI (insert, vp);
|
VSTPluginUI* vpu = new VSTPluginUI (insert, vp, session.frame_rate(), session.engine().frames_per_cycle());
|
||||||
|
|
||||||
_pluginui = vpu;
|
_pluginui = vpu;
|
||||||
get_vbox()->add (*vpu);
|
get_vbox()->add (*vpu);
|
||||||
|
|
@ -90,7 +90,7 @@ PluginUIWindow::PluginUIWindow (boost::shared_ptr<PluginInsert> insert, bool scr
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
LadspaPluginUI* pu = new LadspaPluginUI (insert, scrollable);
|
LadspaPluginUI* pu = new LadspaPluginUI (insert, sr, period, scrollable);
|
||||||
|
|
||||||
_pluginui = pu;
|
_pluginui = pu;
|
||||||
get_vbox()->add (*pu);
|
get_vbox()->add (*pu);
|
||||||
|
|
@ -145,11 +145,12 @@ PluginUIWindow::plugin_going_away ()
|
||||||
delete_when_idle (this);
|
delete_when_idle (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
PlugUIBase::PlugUIBase (boost::shared_ptr<PluginInsert> pi)
|
PlugUIBase::PlugUIBase (boost::shared_ptr<PluginInsert> pi, nframes64_t sr, nframes64_t period)
|
||||||
: insert (pi),
|
: insert (pi),
|
||||||
plugin (insert->plugin()),
|
plugin (insert->plugin()),
|
||||||
save_button(_("Add")),
|
save_button(_("Add")),
|
||||||
bypass_button (_("Bypass"))
|
bypass_button (_("Bypass")),
|
||||||
|
latency_gui (*pi, sr, period)
|
||||||
{
|
{
|
||||||
//combo.set_use_arrows_always(true);
|
//combo.set_use_arrows_always(true);
|
||||||
set_popdown_strings (combo, plugin->get_presets());
|
set_popdown_strings (combo, plugin->get_presets());
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,8 @@
|
||||||
#include <ardour_dialog.h>
|
#include <ardour_dialog.h>
|
||||||
#include <ardour/types.h>
|
#include <ardour/types.h>
|
||||||
|
|
||||||
|
#include "latency_gui.h"
|
||||||
|
|
||||||
namespace ARDOUR {
|
namespace ARDOUR {
|
||||||
class PluginInsert;
|
class PluginInsert;
|
||||||
class Plugin;
|
class Plugin;
|
||||||
|
|
@ -66,7 +68,7 @@ namespace Gtkmm2ext {
|
||||||
class PlugUIBase : public virtual sigc::trackable
|
class PlugUIBase : public virtual sigc::trackable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PlugUIBase (boost::shared_ptr<ARDOUR::PluginInsert>);
|
PlugUIBase (boost::shared_ptr<ARDOUR::PluginInsert>, nframes64_t sample_rate, nframes64_t period_size);
|
||||||
virtual ~PlugUIBase() {}
|
virtual ~PlugUIBase() {}
|
||||||
|
|
||||||
virtual gint get_preferred_height () = 0;
|
virtual gint get_preferred_height () = 0;
|
||||||
|
|
@ -79,6 +81,7 @@ class PlugUIBase : public virtual sigc::trackable
|
||||||
Gtk::ComboBoxText combo;
|
Gtk::ComboBoxText combo;
|
||||||
Gtk::Button save_button;
|
Gtk::Button save_button;
|
||||||
Gtk::ToggleButton bypass_button;
|
Gtk::ToggleButton bypass_button;
|
||||||
|
LatencyGUI latency_gui;
|
||||||
|
|
||||||
void setting_selected();
|
void setting_selected();
|
||||||
void save_plugin_setting (void);
|
void save_plugin_setting (void);
|
||||||
|
|
@ -88,7 +91,7 @@ class PlugUIBase : public virtual sigc::trackable
|
||||||
class LadspaPluginUI : public PlugUIBase, public Gtk::VBox
|
class LadspaPluginUI : public PlugUIBase, public Gtk::VBox
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LadspaPluginUI (boost::shared_ptr<ARDOUR::PluginInsert> plug, bool scrollable=false);
|
LadspaPluginUI (boost::shared_ptr<ARDOUR::PluginInsert> plug, nframes64_t sample_rate, nframes64_t period_size, bool scrollable = false);
|
||||||
~LadspaPluginUI ();
|
~LadspaPluginUI ();
|
||||||
|
|
||||||
gint get_preferred_height () { return prefheight; }
|
gint get_preferred_height () { return prefheight; }
|
||||||
|
|
@ -198,7 +201,7 @@ class LadspaPluginUI : public PlugUIBase, public Gtk::VBox
|
||||||
class PluginUIWindow : public ArdourDialog
|
class PluginUIWindow : public ArdourDialog
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PluginUIWindow (boost::shared_ptr<ARDOUR::PluginInsert> insert, bool scrollable=false);
|
PluginUIWindow (boost::shared_ptr<ARDOUR::PluginInsert> insert, nframes64_t sample_rate, nframes64_t period_size, bool scrollable = false);
|
||||||
~PluginUIWindow ();
|
~PluginUIWindow ();
|
||||||
|
|
||||||
PlugUIBase& pluginui() { return *_pluginui; }
|
PlugUIBase& pluginui() { return *_pluginui; }
|
||||||
|
|
@ -217,7 +220,7 @@ class PluginUIWindow : public ArdourDialog
|
||||||
class VSTPluginUI : public PlugUIBase, public Gtk::VBox
|
class VSTPluginUI : public PlugUIBase, public Gtk::VBox
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
VSTPluginUI (boost::shared_ptr<ARDOUR::PluginInsert>, boost::shared_ptr<ARDOUR::VSTPlugin>);
|
VSTPluginUI (boost::shared_ptr<ARDOUR::PluginInsert>, boost::shared_ptr<ARDOUR::VSTPlugin>, nframes64_t sample_rate, nframes64_t period_size);
|
||||||
~VSTPluginUI ();
|
~VSTPluginUI ();
|
||||||
|
|
||||||
gint get_preferred_height ();
|
gint get_preferred_height ();
|
||||||
|
|
|
||||||
|
|
@ -1088,7 +1088,7 @@ ProcessorBox::edit_processor (boost::shared_ptr<Processor> processor)
|
||||||
|
|
||||||
if (plugin_processor->get_gui() == 0) {
|
if (plugin_processor->get_gui() == 0) {
|
||||||
|
|
||||||
plugin_ui = new PluginUIWindow (plugin_processor);
|
plugin_ui = new PluginUIWindow (plugin_processor, _session.frame_rate(), _session.engine().frames_per_cycle());
|
||||||
|
|
||||||
if (_owner_is_mixer) {
|
if (_owner_is_mixer) {
|
||||||
ARDOUR_UI::instance()->the_mixer()->ensure_float (*plugin_ui);
|
ARDOUR_UI::instance()->the_mixer()->ensure_float (*plugin_ui);
|
||||||
|
|
@ -1190,7 +1190,7 @@ ProcessorBox::register_actions ()
|
||||||
/* new stuff */
|
/* new stuff */
|
||||||
ActionManager::register_action (popup_act_grp, X_("newplugin"), _("New Plugin ..."), sigc::ptr_fun (ProcessorBox::rb_choose_plugin));
|
ActionManager::register_action (popup_act_grp, X_("newplugin"), _("New Plugin ..."), sigc::ptr_fun (ProcessorBox::rb_choose_plugin));
|
||||||
|
|
||||||
act = ActionManager::register_action (popup_act_grp, X_("newprocessor"), _("New Insert"), sigc::ptr_fun (ProcessorBox::rb_choose_processor));
|
act = ActionManager::register_action (popup_act_grp, X_("newinsert"), _("New Insert"), sigc::ptr_fun (ProcessorBox::rb_choose_processor));
|
||||||
ActionManager::jack_sensitive_actions.push_back (act);
|
ActionManager::jack_sensitive_actions.push_back (act);
|
||||||
act = ActionManager::register_action (popup_act_grp, X_("newsend"), _("New Send ..."), sigc::ptr_fun (ProcessorBox::rb_choose_send));
|
act = ActionManager::register_action (popup_act_grp, X_("newsend"), _("New Send ..."), sigc::ptr_fun (ProcessorBox::rb_choose_send));
|
||||||
ActionManager::jack_sensitive_actions.push_back (act);
|
ActionManager::jack_sensitive_actions.push_back (act);
|
||||||
|
|
|
||||||
|
|
@ -581,7 +581,7 @@ RouteParams_UI::redirect_selected (boost::shared_ptr<ARDOUR::Processor> insert,
|
||||||
}
|
}
|
||||||
} else if ((plugin_insert = boost::dynamic_pointer_cast<PluginInsert> (insert)) != 0) {
|
} else if ((plugin_insert = boost::dynamic_pointer_cast<PluginInsert> (insert)) != 0) {
|
||||||
|
|
||||||
LadspaPluginUI *plugin_ui = new LadspaPluginUI (plugin_insert, true);
|
LadspaPluginUI *plugin_ui = new LadspaPluginUI (plugin_insert, session->frame_rate(), session->engine().frames_per_cycle(), true);
|
||||||
|
|
||||||
if (place == PreFader) {
|
if (place == PreFader) {
|
||||||
cleanup_pre_view();
|
cleanup_pre_view();
|
||||||
|
|
|
||||||
21
libs/surfaces/powermate/README
Normal file
21
libs/surfaces/powermate/README
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
|
||||||
|
This module works with the Griffin Powermate and allows some basic transport control.
|
||||||
|
|
||||||
|
It autodetects the Powermate on any input device of the form "/dev/input/event*". This means you must have the powermate module in your kernel. It works out-of-the-box with 64Studio and presumably lots of other modern distributions.
|
||||||
|
|
||||||
|
Turning the wheel left and right will act as a "Shuttle" wheel, adjusting playback speed up and down
|
||||||
|
Pushing the knob will switch between play and stop
|
||||||
|
Pushing the knob while turning will jump to the next or previous markers
|
||||||
|
|
||||||
|
|
||||||
|
In order for the powermate to work, you have to have permission to open the input device for reading.
|
||||||
|
In debian, I changed /etc/udev/rules.d/0_permissions.rules to have the line:
|
||||||
|
KERNEL=="event[0-9]*", MODE="0666"
|
||||||
|
but there are other ways to achieve this
|
||||||
|
|
||||||
|
|
||||||
|
Feedback, tweaks, bug fixes and feature ideas are encouraged
|
||||||
|
|
||||||
|
-Ben Loftis, ben@benloftis.com
|
||||||
|
|
||||||
|
|
||||||
57
libs/surfaces/powermate/SConscript
Normal file
57
libs/surfaces/powermate/SConscript
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
# -*- python -*-
|
||||||
|
|
||||||
|
import os
|
||||||
|
import os.path
|
||||||
|
import glob
|
||||||
|
|
||||||
|
Import('env final_prefix install_prefix final_config_prefix libraries i18n')
|
||||||
|
|
||||||
|
powermate = env.Copy()
|
||||||
|
|
||||||
|
#
|
||||||
|
# this defines the version number of powermate
|
||||||
|
#
|
||||||
|
|
||||||
|
domain = 'ardour_powermate'
|
||||||
|
|
||||||
|
powermate.Append(DOMAIN = domain, MAJOR = 1, MINOR = 0, MICRO = 0)
|
||||||
|
powermate.Append(CXXFLAGS = "-DPACKAGE=\\\"" + domain + "\\\"")
|
||||||
|
powermate.Append(CXXFLAGS="-DLIBSIGC_DISABLE_DEPRECATED")
|
||||||
|
powermate.Append(PACKAGE = domain)
|
||||||
|
powermate.Append(POTFILE = domain + '.pot')
|
||||||
|
|
||||||
|
powermate_files=Split("""
|
||||||
|
interface.cc
|
||||||
|
powermate.cc
|
||||||
|
""")
|
||||||
|
|
||||||
|
powermate.Append(CCFLAGS="-D_REENTRANT -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE")
|
||||||
|
powermate.Append(CXXFLAGS="-DDATA_DIR=\\\""+final_prefix+"/share\\\"")
|
||||||
|
powermate.Append(CXXFLAGS="-DCONFIG_DIR=\\\""+final_config_prefix+"\\\"")
|
||||||
|
powermate.Append(CXXFLAGS="-DLOCALEDIR=\\\""+final_prefix+"/share/locale\\\"")
|
||||||
|
|
||||||
|
powermate.Merge ([
|
||||||
|
libraries['ardour'],
|
||||||
|
libraries['ardour_cp'],
|
||||||
|
libraries['sigc2'],
|
||||||
|
libraries['pbd'],
|
||||||
|
libraries['midi++2'],
|
||||||
|
libraries['xml'],
|
||||||
|
libraries['usb'],
|
||||||
|
libraries['glib2'],
|
||||||
|
libraries['glibmm2']
|
||||||
|
])
|
||||||
|
|
||||||
|
libardour_powermate = powermate.SharedLibrary('ardour_powermate', powermate_files)
|
||||||
|
|
||||||
|
Default(libardour_powermate)
|
||||||
|
|
||||||
|
if env['NLS']:
|
||||||
|
i18n (powermate, powermate_files, env)
|
||||||
|
|
||||||
|
env.Alias('install', env.Install(os.path.join(install_prefix, 'lib/ardour2/surfaces'), libardour_powermate))
|
||||||
|
|
||||||
|
env.Alias('tarball', env.Distribute (env['DISTTREE'],
|
||||||
|
[ 'SConscript' ] +
|
||||||
|
powermate_files +
|
||||||
|
glob.glob('po/*.po') + glob.glob('*.h')))
|
||||||
57
libs/surfaces/powermate/interface.cc
Normal file
57
libs/surfaces/powermate/interface.cc
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
Ardour9pin interface file
|
||||||
|
Ben Loftis
|
||||||
|
Created: 05/18/06 11:07:56
|
||||||
|
Copyright Harrison Audio, LLC, 2007
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "powermate.h"
|
||||||
|
|
||||||
|
using namespace ARDOUR;
|
||||||
|
|
||||||
|
ControlProtocol*
|
||||||
|
new_powermate_protocol (ControlProtocolDescriptor* descriptor, Session* s)
|
||||||
|
{
|
||||||
|
PowermateControlProtocol* pcp = new PowermateControlProtocol (*s);
|
||||||
|
|
||||||
|
if (pcp->set_active (true)) {
|
||||||
|
delete pcp;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pcp;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
delete_powermate_protocol (ControlProtocolDescriptor* descriptor, ControlProtocol* cp)
|
||||||
|
{
|
||||||
|
delete cp;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
probe_powermate_protocol (ControlProtocolDescriptor* descriptor)
|
||||||
|
{
|
||||||
|
return PowermateControlProtocol::probe ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static ControlProtocolDescriptor powermate_descriptor = {
|
||||||
|
name : "powermate",
|
||||||
|
id : "uri://ardour.org/ardour/powermate:0",
|
||||||
|
ptr : 0,
|
||||||
|
module : 0,
|
||||||
|
mandatory : 0,
|
||||||
|
supports_feedback : false,
|
||||||
|
probe : probe_powermate_protocol,
|
||||||
|
initialize : new_powermate_protocol,
|
||||||
|
destroy : delete_powermate_protocol
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
ControlProtocolDescriptor*
|
||||||
|
protocol_descriptor () {
|
||||||
|
return &powermate_descriptor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BIN
libs/surfaces/powermate/interface.os
Normal file
BIN
libs/surfaces/powermate/interface.os
Normal file
Binary file not shown.
BIN
libs/surfaces/powermate/libardour_powermate.so
Executable file
BIN
libs/surfaces/powermate/libardour_powermate.so
Executable file
Binary file not shown.
235
libs/surfaces/powermate/powermate.cc
Normal file
235
libs/surfaces/powermate/powermate.cc
Normal file
|
|
@ -0,0 +1,235 @@
|
||||||
|
/*
|
||||||
|
powermate.cc
|
||||||
|
Ben Loftis
|
||||||
|
Created: 03/26/07 20:07:56
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <linux/input.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include <i18n.h>
|
||||||
|
#include <pbd/xml++.h>
|
||||||
|
|
||||||
|
#include "powermate.h"
|
||||||
|
|
||||||
|
using namespace ARDOUR;
|
||||||
|
using namespace std;
|
||||||
|
using namespace sigc;
|
||||||
|
|
||||||
|
#define NUM_VALID_PREFIXES 2
|
||||||
|
|
||||||
|
static const char *valid_prefix[NUM_VALID_PREFIXES] = {
|
||||||
|
"Griffin PowerMate",
|
||||||
|
"Griffin SoundKnob"
|
||||||
|
};
|
||||||
|
|
||||||
|
#define NUM_EVENT_DEVICES 16
|
||||||
|
|
||||||
|
int open_powermate(const char *dev, int mode)
|
||||||
|
{
|
||||||
|
int fd = open(dev, mode);
|
||||||
|
int i;
|
||||||
|
char name[255];
|
||||||
|
|
||||||
|
if(fd < 0){
|
||||||
|
fprintf(stderr, "Unable to open \"%s\": %s\n", dev, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ioctl(fd, EVIOCGNAME(sizeof(name)), name) < 0){
|
||||||
|
fprintf(stderr, "\"%s\": EVIOCGNAME failed: %s\n", dev, strerror(errno));
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// it's the correct device if the prefix matches what we expect it to be:
|
||||||
|
for(i=0; i<NUM_VALID_PREFIXES; i++)
|
||||||
|
if(!strncasecmp(name, valid_prefix[i], strlen(valid_prefix[i])))
|
||||||
|
return fd;
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int find_powermate(int mode)
|
||||||
|
{
|
||||||
|
char devname[256];
|
||||||
|
int i, r;
|
||||||
|
|
||||||
|
for(i=0; i<NUM_EVENT_DEVICES; i++){
|
||||||
|
sprintf(devname, "/dev/input/event%d", i);
|
||||||
|
r = open_powermate(devname, mode);
|
||||||
|
if(r >= 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PowermateControlProtocol::PowermateControlProtocol (Session& s)
|
||||||
|
: ControlProtocol (s, "powermate")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PowermateControlProtocol::~PowermateControlProtocol ()
|
||||||
|
{
|
||||||
|
set_active (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PowermateControlProtocol::probe ()
|
||||||
|
{
|
||||||
|
int port = find_powermate( O_RDONLY );
|
||||||
|
|
||||||
|
if (port < 0) {
|
||||||
|
printf ("powermate: Opening of powermate failed - %s\n", strerror(errno));
|
||||||
|
close (port);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
close (port);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
PowermateControlProtocol::set_active (bool inActivate)
|
||||||
|
{
|
||||||
|
if (inActivate != _active) {
|
||||||
|
|
||||||
|
if (inActivate) {
|
||||||
|
|
||||||
|
mPort = find_powermate(O_RDONLY);
|
||||||
|
|
||||||
|
if ( mPort < 0 ) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pthread_create (&mThread, 0, SerialThreadEntry, this) == 0) {
|
||||||
|
_active = true;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Powermate Control Protocol activated\n");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
pthread_cancel (mThread);
|
||||||
|
close (mPort);
|
||||||
|
_active = false;
|
||||||
|
printf("Powermate Control Protocol deactivated\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
XMLNode&
|
||||||
|
PowermateControlProtocol::get_state ()
|
||||||
|
{
|
||||||
|
XMLNode* node = new XMLNode (X_("Protocol"));
|
||||||
|
node->add_property (X_("name"), _name);
|
||||||
|
return *node;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
PowermateControlProtocol::set_state (const XMLNode& node)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void*
|
||||||
|
PowermateControlProtocol::SerialThreadEntry (void* arg)
|
||||||
|
{
|
||||||
|
return static_cast<PowermateControlProtocol*>(arg)->SerialThread ();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BUFFER_SIZE 32
|
||||||
|
|
||||||
|
bool held = false;
|
||||||
|
bool skippingMarkers = false;
|
||||||
|
|
||||||
|
void
|
||||||
|
PowermateControlProtocol::ProcessEvent(struct input_event *ev)
|
||||||
|
{
|
||||||
|
#ifdef VERBOSE
|
||||||
|
fprintf(stderr, "type=0x%04x, code=0x%04x, value=%d\n",
|
||||||
|
ev->type, ev->code, (int)ev->value);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch(ev->type){
|
||||||
|
case EV_MSC:
|
||||||
|
printf("The LED pulse settings were changed; code=0x%04x, value=0x%08x\n", ev->code, ev->value);
|
||||||
|
break;
|
||||||
|
case EV_REL:
|
||||||
|
if(ev->code != REL_DIAL)
|
||||||
|
fprintf(stderr, "Warning: unexpected rotation event; ev->code = 0x%04x\n", ev->code);
|
||||||
|
else{
|
||||||
|
if (held) {
|
||||||
|
//click and hold to skip forward and back by markers
|
||||||
|
skippingMarkers = true;;
|
||||||
|
if (ev->value > 0)
|
||||||
|
next_marker();
|
||||||
|
else
|
||||||
|
prev_marker();
|
||||||
|
} else {
|
||||||
|
//scale the range so that we can go from +/-8x within 180 degrees, with less precision at the higher speeds
|
||||||
|
float speed = get_transport_speed();
|
||||||
|
speed += (float)ev->value * 0.05;
|
||||||
|
if (speed > 1.5 || speed < -1.5 )
|
||||||
|
speed += ev->value;
|
||||||
|
set_transport_speed( speed );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EV_KEY:
|
||||||
|
if(ev->code != BTN_0)
|
||||||
|
fprintf(stderr, "Warning: unexpected key event; ev->code = 0x%04x\n", ev->code);
|
||||||
|
else
|
||||||
|
if (ev->value)
|
||||||
|
held = true;
|
||||||
|
else {
|
||||||
|
held = false;
|
||||||
|
if (skippingMarkers) {
|
||||||
|
skippingMarkers = false;
|
||||||
|
} else {
|
||||||
|
if (get_transport_speed() == 0.0) {
|
||||||
|
set_transport_speed(1.0);
|
||||||
|
} else {
|
||||||
|
set_transport_speed(0.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void*
|
||||||
|
PowermateControlProtocol::SerialThread ()
|
||||||
|
{
|
||||||
|
struct input_event ibuffer[BUFFER_SIZE];
|
||||||
|
int r, events, i;
|
||||||
|
|
||||||
|
while(1){
|
||||||
|
r = read(mPort, ibuffer, sizeof(struct input_event) * BUFFER_SIZE);
|
||||||
|
if( r > 0 ){
|
||||||
|
events = r / sizeof(struct input_event);
|
||||||
|
for(i=0; i<events; i++)
|
||||||
|
ProcessEvent(&ibuffer[i]);
|
||||||
|
}else{
|
||||||
|
fprintf(stderr, "read() failed: %s\n", strerror(errno));
|
||||||
|
return (void*) 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (void*) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
34
libs/surfaces/powermate/powermate.h
Normal file
34
libs/surfaces/powermate/powermate.h
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
#ifndef ardour_powermate_h
|
||||||
|
#define ardour_powermate_h
|
||||||
|
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#include "control_protocol/control_protocol.h"
|
||||||
|
|
||||||
|
class PowermateControlProtocol : public ARDOUR::ControlProtocol
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PowermateControlProtocol (ARDOUR::Session&);
|
||||||
|
virtual ~PowermateControlProtocol();
|
||||||
|
|
||||||
|
int set_active (bool yn);
|
||||||
|
static bool probe ();
|
||||||
|
|
||||||
|
XMLNode& get_state ();
|
||||||
|
int set_state (const XMLNode&);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
static void* SerialThreadEntry (void* arg);
|
||||||
|
void* SerialThread ();
|
||||||
|
|
||||||
|
void ProcessEvent(struct input_event *ev);
|
||||||
|
|
||||||
|
int mPort;
|
||||||
|
pthread_t mThread;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
BIN
libs/surfaces/powermate/powermate.os
Normal file
BIN
libs/surfaces/powermate/powermate.os
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue