X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fmidi%2B%2B2%2Fipmidi_port.cc;h=440374eadea1630c12b31fd9ca1644456ad00d48;hb=efca4413b927d2e728a4cc3e7b892aa9bfd1fdff;hp=4c0282f1f757a40e32cca91106a43c3d11108e26;hpb=300b484cf6ac14c15e365c4062345d64a61c4b18;p=ardour.git diff --git a/libs/midi++2/ipmidi_port.cc b/libs/midi++2/ipmidi_port.cc index 4c0282f1f7..440374eade 100644 --- a/libs/midi++2/ipmidi_port.cc +++ b/libs/midi++2/ipmidi_port.cc @@ -2,7 +2,7 @@ Copyright (C) 2012 Paul Davis Using code from Rui Nuno Capela's qmidinet as inspiration. - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or @@ -31,12 +31,12 @@ #endif #if defined(PLATFORM_WINDOWS) #include +#include #else #include #endif #if defined(PLATFORM_WINDOWS) -static WSADATA g_wsaData; typedef int socklen_t; #else #include @@ -44,9 +44,6 @@ typedef int socklen_t; inline void closesocket(int s) { ::close(s); } #endif -#include -#include - #include "pbd/xml++.h" #include "pbd/error.h" #include "pbd/failed_constructor.h" @@ -85,8 +82,8 @@ IPMIDIPort::~IPMIDIPort () int IPMIDIPort::selectable () const -{ - return sockin; +{ + return sockin; } XMLNode& @@ -108,19 +105,19 @@ IPMIDIPort::close_sockets () ::closesocket (sockin); sockin = -1; } - + if (sockout >= 0) { ::closesocket (sockout); sockout = -1; } } -static bool +#ifndef PLATFORM_WINDOWS +static bool get_address (int sock, struct in_addr *inaddr, const string& ifname ) { // Get interface address from supplied name. -#if !defined(PLATFORM_WINDOWS) struct ifreq ifr; ::strncpy(ifr.ifr_name, ifname.c_str(), sizeof(ifr.ifr_name)); @@ -144,18 +141,12 @@ get_address (int sock, struct in_addr *inaddr, const string& ifname ) inaddr->s_addr = sa.sin_addr.s_addr; return true; - -#else - - return false; - -#endif // !PLATFORM_WINDOWS' } +#endif bool IPMIDIPort::open_sockets (int base_port, const string& ifname) { -#if !defined(PLATFORM_WINDOWS) int protonum = 0; struct protoent *proto = ::getprotobyname("IP"); @@ -174,16 +165,17 @@ IPMIDIPort::open_sockets (int base_port, const string& ifname) addrin.sin_family = AF_INET; addrin.sin_addr.s_addr = htonl(INADDR_ANY); addrin.sin_port = htons(base_port); - + if (::bind(sockin, (struct sockaddr *) (&addrin), sizeof(addrin)) < 0) { ::perror("bind"); return false; } - + // Will Hall, 2007 // INADDR_ANY will bind to default interface, // specify alternate interface nameon which to bind... struct in_addr if_addr_in; +#ifndef PLATFORM_WINDOWS if (!ifname.empty()) { if (!get_address(sockin, &if_addr_in, ifname)) { error << string_compose ("socket(in): could not find interface address for %1", ifname) << endmsg; @@ -197,9 +189,12 @@ IPMIDIPort::open_sockets (int base_port, const string& ifname) } else { if_addr_in.s_addr = htonl (INADDR_ANY); } - +#else + if_addr_in.s_addr = htonl (INADDR_ANY); +#endif + struct ip_mreq mreq; - mreq.imr_multiaddr.s_addr = ::inet_addr("225.0.0.37"); + mreq.imr_multiaddr.s_addr = ::inet_addr("225.0.0.37"); /* ipMIDI group multicast address */ mreq.imr_interface.s_addr = if_addr_in.s_addr; if(::setsockopt (sockin, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof(mreq)) < 0) { ::perror("setsockopt(IP_ADD_MEMBERSHIP)"); @@ -215,8 +210,9 @@ IPMIDIPort::open_sockets (int base_port, const string& ifname) ::perror("socket(out)"); return false; } - + // Will Hall, Oct 2007 +#ifndef PLATFORM_WINDOWS if (!ifname.empty()) { struct in_addr if_addr_out; if (!get_address(sockout, &if_addr_out, ifname)) { @@ -228,19 +224,42 @@ IPMIDIPort::open_sockets (int base_port, const string& ifname) return false; } } - +#endif + ::memset(&addrout, 0, sizeof(struct sockaddr_in)); addrout.sin_family = AF_INET; addrout.sin_addr.s_addr = ::inet_addr("225.0.0.37"); addrout.sin_port = htons (base_port); - + +#ifndef PLATFORM_WINDOWS + int loop; + socklen_t size; +#else + u_char loop; + int size; +#endif + + if (::getsockopt (sockin, IPPROTO_IP, IP_MULTICAST_LOOP, (void *) &loop, &size)) { + ::perror ("getsockopt(IP_MULTICAST_LOOP)"); + } else { + cout << "********* 1. multicast loopback: " << loop << " size was " << size << endl; + } + // Turn off loopback... - int loop = 0; - if (::setsockopt(sockout, IPPROTO_IP, IP_MULTICAST_LOOP, (char *) &loop, sizeof (loop)) < 0) { + loop = 0; + if (::setsockopt(sockout, IPPROTO_IP, IP_MULTICAST_LOOP, (void *) &loop, sizeof (loop)) < 0) { ::perror("setsockopt(IP_MULTICAST_LOOP)"); return false; } + if (::getsockopt (sockin, IPPROTO_IP, IP_MULTICAST_LOOP, (void *) &loop, &size)) { + ::perror ("getsockopt(IP_MULTICAST_LOOP)"); + } else { + cout << "********* 2. multicast loopback: " << loop << " size was " << size << endl; + } + +#ifndef PLATFORM_WINDOWS + if (fcntl (sockin, F_SETFL, O_NONBLOCK)) { error << "cannot set non-blocking mode for IP MIDI input socket (" << ::strerror (errno) << ')' << endmsg; return false; @@ -250,11 +269,22 @@ IPMIDIPort::open_sockets (int base_port, const string& ifname) error << "cannot set non-blocking mode for IP MIDI output socket (" << ::strerror (errno) << ')' << endmsg; return false; } - - return true; + #else - return false; -#endif // !PLATFORM_WINDOWS' + // If imode !=0, non-blocking mode is enabled. + u_long mode=1; + if (ioctlsocket(sockin,FIONBIO,&mode)) { + error << "cannot set non-blocking mode for IP MIDI input socket (" << ::strerror (errno) << ')' << endmsg; + return false; + } + mode = 1; /* just in case it was modified in the previous call */ + if (ioctlsocket(sockout,FIONBIO,&mode)) { + error << "cannot set non-blocking mode for IP MIDI output socket (" << ::strerror (errno) << ')' << endmsg; + return false; + } +#endif + + return true; } int @@ -285,16 +315,20 @@ IPMIDIPort::parse (framecnt_t timestamp) * parser. This will emit appropriate signals that will be handled * by anyone who cares. */ - + unsigned char buf[1024]; struct sockaddr_in sender; socklen_t slen = sizeof(sender); int r = ::recvfrom (sockin, (char *) buf, sizeof(buf), 0, (struct sockaddr *) &sender, &slen); + if (r != 18) { + cout << "IPMIDI: received from socket: " << r << endl; + } + if (r >= 0) { _parser->set_timestamp (timestamp); - + for (int i = 0; i < r; ++i) { _parser->scanner (buf[i]); } @@ -302,4 +336,3 @@ IPMIDIPort::parse (framecnt_t timestamp) ::perror ("failed to recv from socket"); } } -