Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OSC Server/Client Integration #2078

Closed
wants to merge 15 commits into from
Closed

OSC Server/Client Integration #2078

wants to merge 15 commits into from

Conversation

iffyloop
Copy link

@iffyloop iffyloop commented Apr 8, 2019

This PR adds OSC server support to Mixxx in a way that nicely coexists with Jakob Braun's OSC client implementation. It's basically a more robust implementation of #2064 where I've tried to take into consideration many of the changes requested there. Thanks to everyone for your patience and constructive feedback. Sorry this has taken so long.

Copy link
Member

@daschuer daschuer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the good first step. I have left some comments

src/mixxx.cpp Outdated
@@ -561,6 +563,8 @@ void MixxxMainWindow::initialize(QApplication* pApp, const CmdlineArgs& args) {

m_pOscClientManager = new OscClientManager(pConfig, m_pEngine);

m_pOscServer = new OscServer(pConfig);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we prefere using std::uniwue_ptr and make_unique in new code.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@daschuer That makes sense and I understand that unique_ptr is safer. However, may I ask why we would use unique_ptr since the rest of the codebase seems to use new/delete (e.g. line 181 where m_pSettingsManager = new SettingsManager)? Also, would it be preferable to just store an actual OscClientManager instance rather than a pointer to it in the class? I've always been a little confused why all of the manager members of MixxxMainWindow were stored as pointers.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, sorry I've been gone for so long

#ifndef __OSCSERVER_DEFS_H__
#define __OSCSERVER_DEFS_H__

#define OSC_SERVER_PREF_KEY "[OSCserver]"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pure camel case would be [OscServer]

return;
}

QString port = pConfig->getValueString(ConfigKey(OSC_SERVER_PREF_KEY, "Port"));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we fall back to a default port if the preferences value is empty? Or does this introduce issues with already used ports?

QString port = pConfig->getValueString(ConfigKey(OSC_SERVER_PREF_KEY, "Port"));
m_st = lo_server_thread_new(port.toLatin1().data(), OscServer::oscErrorHandler);
if (!m_st) {
return;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have any user feedback? Ab exclamation mark on the osc preferences page or such?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@daschuer Do you think a message box might be preferable to an exclamation mark? I think that might more directly capture the user's attention (e.g., if they click the "OK" button, then the preferences page closes before they see the exclamation mark).

}

lo_server_thread_add_method(m_st, nullptr, nullptr, OscServer::oscMsgHandler, nullptr);
lo_server_thread_start(m_st);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please handle the return value.

QRegularExpressionMatch pathMatch = pathRegEx.match(QString::fromLatin1(path));

if (!pathMatch.hasMatch()) {
qWarning() << "ERROR: Invalid OSC path! Proper format: /<group>/<control>";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can omit "ERROR:"
How about show the received string? This can be useful if only on if many us broken.

ConfigKey key = ConfigKey(pathMatch.captured(1), pathMatch.captured(2));

if (key.isNull() || key.isEmpty()) {
qWarning() << "ERROR: Invalid group/key pair specified in OSC path!";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same here.

(argType == LO_SYMBOL)) {
if (OscServer::m_st && (reinterpret_cast<char*>(argv[i])[0] == '?')) {
lo_address msgTo = lo_message_get_source(static_cast<lo_message>(data));
lo_send(msgTo, path, "d", ControlObject::get(key));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handle return value.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@daschuer What would you like to happen when lo_send returns a failure code? Right now I'm thinking of just printing an error message "Failed to reply to OSC get parameter message from: " followed by the URL of the target address.

private:
static void quitServer();

static void oscErrorHandler(int err, const char* msg, const char* path);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If possible move the message handler into an anonymous namspace in the cpp file.
All other functions should be non static.

</property>
<property name="openExternalLinks">
<bool>true</bool>
<string>(You must restart Mixxx for your changes here to take effect).</string>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A restart OSC Server Button would be helpful.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll hopefully redesign this so that the OSC server can automatically restart whenever the user clicks "Apply" or "OK"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is Ok for me if you keep this for a second PR.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. I'll wait then so we can get the other fixes applied sooner.

@iffyloop
Copy link
Author

iffyloop commented Apr 8, 2019 via email

@uklotzde
Copy link
Contributor

uklotzde commented Apr 8, 2019

Shouldn't OSC support be provided as an optional feature? I would recommend this.

It should it least be disabled by default without starting any threads or opening ports.

@iffyloop
Copy link
Author

iffyloop commented Apr 8, 2019 via email

@daschuer
Copy link
Member

daschuer commented Apr 8, 2019

I would prefer to use a separate "enabled" key to enable the OSC sever. Having it disabled by default sounds reasonable. It may scare user if Mixxx pops up in a firewall.

Has OSC reserved ports, I have not found anything.
TouchOSC uses 8000 and 9000. Unfortunately this is also used for ShoutCast. However it should not conflict because it is an outgoing port. So how about default to that if the saved port setting is invalid?

@iffyloop
Copy link
Author

iffyloop commented Apr 9, 2019

That sounds like a good idea @daschuer. Thanks for bringing ShoutCast to my attention. I don't believe OSC has any reserved ports, but it makes sense to default to TouchOSC port settings if the user enters an invalid port.

Corrected implementation according to @daschuer's comments: #2078 (review)
@iffyloop
Copy link
Author

iffyloop commented May 2, 2019

@daschuer Just finished making requested changes. Thanks for your suggestions and please let me know your thoughts on these revisions.

build/depends.py Outdated
if not build.platform_is_windows:
build.env.Append(CXXFLAGS='-std=c++11')
build.env.Append(CXXFLAGS='-std=c++14')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ups, sorry I should have say that we have our own implementation:
src/util/memory.h that works with c++11

However maybe it is time to enable c++14, but that should be done in a separate PR.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fine. Thanks for mentioning it! I will switch to src/util/memory.h if possible

float speed = 1 + float(rate.get()) * float(rateRange.get());
if(rev.get())
speed *= -1;
lo_send(serverAdress, "/mixxx/deck/speed" ,"if", deckNr, speed);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to consolidate the OSC adressspace somewhere maybe a wiki page:
https://www.mixxx.org/wiki/doku.php/osc-client
https://www.mixxx.org/wiki/doku.php/osc_backend

Is this two parameter call TouchOSC compatible?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have TouchOSC (I have an Android device but no Google Play) so I can't test. From what I've read in the docs about custom parameters I think it should work though. If we have a volunteer to test that would be great.

Copy link
Member

@daschuer daschuer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added some comments. Thank you for all the work.

lo_address serverAdress;
UserSettingsPointer m_pConfig;
QList<ControlProxy*> connectedControls;
ControlProxy prefUpdate;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use m_ prefix for all private member variables.

QTime time;
lo_address serverAdress;
UserSettingsPointer m_pConfig;
QList<ControlProxy*> connectedControls;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this uses somewhere? Can we remove it?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe all of these variables are in use in engineoscclient.cpp

src/mixxx.cpp Outdated
@@ -557,6 +561,10 @@ void MixxxMainWindow::initialize(QApplication* pApp, const CmdlineArgs& args) {
SIGNAL(currentPlayingDeckChanged(int)),
this, SLOT(slotChangedPlayingDeck(int)));

m_pOscClientManager = new OscClientManager(pConfig, m_pEngine);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also make_unique?

void OscClientManager::maybeSendState()
{

}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The formatting of this file is not correct. Please have a look here:
https://www.mixxx.org/wiki/doku.php/coding_guidelines

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I notice there are several formatting issues with the OSC-related source files. Do I need to fix these manually or is it appropriate to simply run clang-format on all the .cpp/.h files in this pull request?


namespace {
void oscErrorHandler(int err, const char* msg, const char* path) {
qWarning() << QString("%1. OSC path: %2. Error Code: %3.").arg(QString::fromLatin1(msg)).arg(QString::fromLatin1(path)).arg(err);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please break long lines at ~80.


if (!pathMatch.hasMatch()) {
qWarning() << "Invalid OSC path: " << QString::fromLatin1(path);
qWarning() << "Proper OSC path format: /<group>/<control>";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, we put the group into the root of the address field while we send out data with the Mixxx prefix.
Will we ever have a problem with this?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought the Mixxx prefix would make sense for outgoing data because, if we're interacting with a client that is compatible with multiple OSC apps, the prefix clarifies to the client that they are receiving data from Mixxx rather than another application that may use paths like /Channel1/play (because those are pretty generic names). Incoming data, on the other hand, was explicitly addressed to Mixxx, so the prefix is unnecessary because, e.g., /Channel1/play, can only have one possible meaning in that context. Please let me know if that makes sense or if I'm overthinking it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes the mixxx prefix for the outgoing data makes sense. I think from this point of view the incoming messages should have also a mixxx prefix.
In this case a transmitting button and a receiving LED can be on the same address.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good. I will fix that.

@iffyloop
Copy link
Author

@daschuer Requested changes have been made. Please let me know if anything else is necessary.

@stjohn909
Copy link

This is exactly the feature I need for a current experiment. Will this make it into the release soon?

@Be-ing
Copy link
Contributor

Be-ing commented Dec 16, 2019

@stjohn909: https://mixxx.zulipchat.com/#narrow/stream/109171-development/topic/OSC.20Support
No, sorry. But you're welcome to use this branch for your own use before then.

foltik added a commit to foltik/mixxx that referenced this pull request Jun 5, 2020
@github-actions
Copy link

This PR is marked as stale because it has been open 90 days with no activity.

@github-actions github-actions bot added the stale Stale issues that haven't been updated for a long time. label Oct 19, 2020
@Be-ing Be-ing changed the base branch from master to main October 23, 2020 23:27
@ronso0 ronso0 marked this pull request as draft February 14, 2021 21:55
@iffyloop iffyloop closed this by deleting the head repository Sep 12, 2022
@fwcd fwcd mentioned this pull request Nov 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stale Stale issues that haven't been updated for a long time.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants