What is the "JUCE-way" of handling text input for a command line application?


#1

The title says it all. For the first time ever I needed to create a GUI-less audio application running as as command line application. The application inherits from JUCEApplicationBase.

Now I want to be able to end the application by something like typing in quit to the command line window and maybe allow even more input at runtime for future . I’m not sure if I just overlooked it, but I think there is no such thing as reacting to command line input with the help of the MessageManager that gets started by JUCEApplicationBase instance? Should I create my own thread just waiting for std::cin to return all the time? Altough this should work it does not “feel” like the JUCE-way of doing this :smiley:


#2

Maybe you shouldn’t be using JUCEApplicationBase at all? What’s the reason for using that?


#3

I need the message manager for networking tasks, my application basically does some dsp processing and measurements on a real time audio stream and continously outputs measurement results via Network. I found the JUCEApplicationBase to be the best fitting base class for such a kind of application. Would you recommend another base class?


#4

The JUCE MessageManager is a singleton that can be used without an application object.

static MessageManager* MessageManager::getInstance	()

I don’t know though, if calling that allows async network operations to run as intended…It has worked for me when doing audio playback and hosting plugins in a command line program.


#5

Nice to know, thank you for that information.

However using JUCEApplicationBase does not really seem to be a problem so I see no need to change my existing design to try not using it. And even with your approach, the message manager is still involved.

So the question stays the same, is there any trick I’m not aware of to let the MessageManager handle command line input at runtime?
In the meantime I’ve indeed solved it with a separate thread that calls std::getline, and gains a MessageManagerLock to process the input string as soon as the call to std::getline returns. This was not to hard to implement, it seems to work fine so far, but it seems a bit like a unneeded hack to me, as I’m used to rely on the MessageManager for all user input handling from GUI apps :smiley:


#6

Something to try instead of dealing with locking the MessageManager is to use the ActionBroadcaster/ActionListener classes? In your console processing thread (in a class also derived from ActionBroadcaster), something like (not tested, obvs):

   std::string input; 
   std::getline(std::cin, input); 
   sendActionMessage(String(input));

…and elsewhere have an object of a class derived from ActionListener that’s listening to that console object and handle the input in its actionListenerCallback


#7

Okay, now as all solutions until now rely on a thread just waiting for std::getline I’m facing a problem that didn’t come to my mind in the first place:

I can’t find any way of shutting the app down by other means than typing the shutdown keyword to the console, as any attempt to end the thread waiting for std::getline to end obviously waits for ever, as it is blocking for ever if no console input will appear, which leads in always killing the listening thread by force.

Seems like I needed to set up some platform specific asynchronous console input solution for each OS as there is no version of std::getline that works with a timeout or completely non-blocking. While this should be possible to achieve somehow (have to dig through some system APIs…), I really wonder if I’m the first one here facing this problem or if anyone has already solved this problem? Don’t want to reinvent the wheel…


#8

gnu readline any use?


#9

In the end I came up with a quite simple solution:
I poll stdin on a Timer (which obviously is run on the MessageThread) for available chars and call std::getline in case the returned number of chars available is greater than 0 and then process the returned string from the timer callback. This works smooth and removes the need for a thread that waits on the blocking call.

Find it here


(Windows implementation has not been tested yet but I expect it to work)