Joystick in Juce plugin


#1

Hello,

I am new to C++ and Juce, but managed to build a plugin relatively easy, thanks to Juce and its community!
I am currently struggling to make my plugin receive joystick events. (I am on OSX 10.10, Juce 5, Xcode 7.2.1)

I am using SDL for joystick event handling, and I can successfully run a basic application outside my plugin, but once I started integrating SDL code with the plugin, the compiler complains about:

“_SDL_Init”, referenced from:

ld: symbol(s) not found for architecture x86_64

I have tried initializing SDL ‘SDL_Init(SDL_INIT_JOYSTICK)’ in different places/constructors (Processor, Editor…) with no luck.

My plan was to initiate SDL in a constructor, then have the SDL event loop (while(SDL_PollEvent(&event) != 0)) inside a juce timerCallback.

I have the following doubt: to my info SDL uses a macro to rename main() at compile time!!, and since with plugins, main() actually runs inside the plugin host, this might be leading to the issue.

I would appreciate any pointer on how to get joystick control with a Juce plugin, or if any alternative approach can be suggested

Cheers
Fahed


#2

Hi,

The error you pasted doesn’t come from the compiler (which is named clang), but from the linker (which is named ld). Once the compiler is done converting C++ source files (usually with the extension .cpp), into object files (with the extension .o), the linker takes care of assembling the object files into a binary (with the extension .dylib for shared libraries, or without extension for executables and plugins).

Here the linker is complaining that it cannot find the symbols that the compiler has generated when compiling the definition of the function SDL_Init. There are two solutions to solve that issue:

  1. compile the definition of SDL_Init as part of compiling your plugin. This requires that you have the source file that defines SDL_Init.
  2. point the linker to a pre-built library that contains the symbols. It can be a static library (with the extension .a) or a dynamic library (with the extension .dylib). In Projucer, you can use the fields External libraries to link and Extra library search paths to help the linker find that library.

I hope this helps.
Alain


#3

Thank you very much Alain, also for taking the time to clarify some basics for me, it really helped, and put me for useful extra reading :slight_smile:

I’ve followed solution 2, It worked!

I compiled the libraries (in my case to /usr/local/) and pointed Projucer accordingly:
Header search paths: /usr/local/include/SDL2
Extra library search paths: /usr/local/lib
External libraries to link: SDL2 (i.e without .a extension)

In case somebody is interested in the working solution:

In my Component, I inherit from Juce Timer & add SDL member SDL_Event event;
In the constructor:

  • Start the timer: startTimer(50);

  • Initiate SDL subsystem: SDL_Init(SDL_INIT_JOYSTICK);

  • Create joystick (I am using only one joystick: DUALSHOCK4)

    if(SDL_NumJoysticks() > 0){
       SDL_Joystick * joystick;
       SDL_JoystickEventState(SDL_ENABLE);
       joystick = SDL_JoystickOpen(0); 
    }
    
  • In timer callback:

    void PlotComponent::timerCallback(){
              while(SDL_PollEvent(&event) != 0){
                  if(event.type == SDL_JOYAXISMOTION) // on any axis movement
                  {
                      if(event.jaxis.which == 0) // of joystick 0
                      {           
                          std::cout << "Axis:" << (int) event.jaxis.axis << ", Value: " << event.jaxis.value << std::endl; 
                         // and do something useful   
                      }
                  }
              }
          }