Problem disconnecting an OSCReceiver on Android

Hi

EDIT - made the example much simpler, see next reply

I’m trying to write a simple iOS and Android app which sends and receives OSC messages. I’m storing the address and ports for the OSCSender and OSCReceiver objects in the ApplicationProperties file and loading them and connecting when the app starts. This all seems to work fine for the moment.

I’ve also got a settings component which I set as visible from a button on the main screen. In this component I have some text fields into which the user can enter a new address and ports to send to and receive from. A button in the settings component sends a change message to the mainScreen component, which then takes the text fields’ text and saves it to the properties file and hides the settings component.

Then it disconnects the currently connected OSCSender and OSCReveiver objects and tries to connect using the new details, reloaded from the app properties.

I know this probably isn’t the most elegant solution but I’ve gone through a few methods to try and get this to work and this is the latest. The problem is that the reconnection seems to make the Android version freeze when reconnecting (I think) the OSCReceiver. It seems to work fine on the iOS version and on Windows.

Is there a problem disconnecting and reconnecting an OSCReceiver in Android or, more likely, am I doing something wrong in my code? Please see github link below – it’s just a test and doesn’t actually send or receive anything yet, just tries to connect and reconnect.

Any help appreciated!
Thanks,
Matt

https://github.com/mu01mw/OSCTest

OK - I’ve made the example much, much simpler now

The main screen’s buttonlistener callback simply tries to connect an OSCSender and OSCReceiver to a port 1 up from the previous connection (ie 8000 for the sender, 9000 for the receiver, then 8001 for the sender, 9001 for the receiver).

I’ve removed all the app properties and settings component business.

Again, the app freezes on Android, but not all the time. If I comment out the receiver connection it seems stable.

I’m confused!

Header:

#pragma once
#include "../JuceLibraryCode/JuceHeader.h"

class MainScreen  : public Component,
                    public ButtonListener
{
public:

    MainScreen ();
    ~MainScreen();

    void paint (Graphics& g) override;
    void resized() override;
    void buttonClicked (Button* buttonThatWasClicked) override;

private:
	OSCSender oscSender;
	OSCReceiver oscReceiver;
	int lastSendPort;
	int lastReceivePort;

    ScopedPointer<TextButton> settingsButton;

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainScreen)
};

cpp:

#include "MainScreen.h"

MainScreen::MainScreen() : lastSendPort(8000), lastReceivePort(9000)
{
    addAndMakeVisible (settingsButton = new TextButton ("Settings"));
    settingsButton->addListener (this);

    setSize (600, 400);
}

MainScreen::~MainScreen()
{
    settingsButton = nullptr;
}

void MainScreen::paint (Graphics& g)
{
    g.fillAll (Colour (0xff323e44));
}

void MainScreen::resized()
{
    settingsButton->setBounds (proportionOfWidth (0.9494f) - proportionOfWidth (0.0999f), proportionOfHeight (0.0503f), proportionOfWidth (0.0999f), proportionOfHeight (0.1006f));
}

void MainScreen::buttonClicked (Button* buttonThatWasClicked)
{
    if (buttonThatWasClicked == settingsButton)
    {
		if (oscSender.connect("127.0.0.1", lastSendPort))
			DBG("Connected sender on port " + String(lastSendPort));
        else
            DBG("Couldn't connect to port " + String(lastSendPort));

		if (oscReceiver.connect(lastReceivePort))
			DBG("Connected receiver on port " + String(lastReceivePort));
		else
		    DBG("Couldn't connect to port "  + String(lastReceivePort));

		++lastSendPort;
		++lastReceivePort;
    }
}

Do you see the same problem with the OSCReceiver example in JUCE/examples? Just tried a bunch of OSCSender/OSCReceiver sessions and it seemed to work fine.

Thanks Fabian. I’m not at my computer at the moment, but I’ll check when I get home.

I think it only crashes if the receiver needs to disconnect first (ie it has previously been connected), which I don’t think I’d the case for the Osc example. It hangs when trying to disconnect

Will check tonight though

Hi again

I’ve just build an android version of examples/OSCMonitor and it’s showing the same behaviour when disconnecting. It seems to get stuck in the OSCReceiver’s disconnect() method , maybe when it calls socket->shutdown().

bool disconnect()
{
    if (socket != nullptr)
    {
        signalThreadShouldExit();
        socket->shutdown();
        waitForThreadToExit (10000);
        socket = nullptr;
    }
    return true;
}

Interestingly, if you step through it in the debugger it works, but if you put a break point at waitForThreadToExit(10000) it often doesn’t reach it.

examples/OSCReceiver is ok I think, but it never needs to disconnect.

Thanks!
Matt

Hi @fabian

Just wondering if you’ve had a chance to look at this? I’ve tried everything I can think of to disconnect and reconnect an OSCReceiver and it always freezes on Android when disconnecting.

Thanks,
Matt

Hi

I’m still having trouble with this. For the moment I’m using InterprocessConnections to communicate between android and my desktop app but I’d rather use OSC if possible.

Am I being naive in thinking I can just call disconnect on an (already connected) OscReceiver from a button listener? As I say, it seems to disconnect fine on Windows doing it this way but gets stuck on Android.

I think it’s hanging on this line (138 in juce_socket.cpp) :
CriticalSection::ScopedLockType lock (readLock);

Thanks,
Matt

Can you try changing line juce_Socket.cpp:133 from

               #if JUCE_LINUX

to

               #if JUCE_LINUX || JUCE_ANDROID

Does this fix your problem?

Hi Fabian

Sorry, I’ve only just had a chance to look at this. Yes, that seems to have fixed it. Thanks for your help!

Matt

OK. Thanks for reporting. The above fix is now on develop with commit 64597c2.