X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fmidi%2B%2B2%2Fipmidi_port.cc;h=4fb54a90bf540d04255719c0a58155eae95fdc43;hb=62ff9d9276f7047ecbff824a3291281d35d655a9;hp=c90a3dbe6fd133a2200c21cf4ce38fd9e92ed2e6;hpb=0d31fc76d52dd1c6bec65886bac0f9cd3b4a60cd;p=ardour.git diff --git a/libs/midi++2/ipmidi_port.cc b/libs/midi++2/ipmidi_port.cc index c90a3dbe6f..4fb54a90bf 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 @@ -25,10 +25,18 @@ #include #include #include +#ifdef COMPILER_MSVC +#undef O_NONBLOCK +#define O_NONBLOCK 0 +#endif +#if defined(PLATFORM_WINDOWS) +#include +#include +#else #include +#endif -#if defined(WIN32) -static WSADATA g_wsaData; +#if defined(PLATFORM_WINDOWS) typedef int socklen_t; #else #include @@ -36,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" @@ -77,8 +82,8 @@ IPMIDIPort::~IPMIDIPort () int IPMIDIPort::selectable () const -{ - return sockin; +{ + return sockin; } XMLNode& @@ -100,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(WIN32) struct ifreq ifr; ::strncpy(ifr.ifr_name, ifname.c_str(), sizeof(ifr.ifr_name)); @@ -136,13 +141,8 @@ 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 // !WIN32 } +#endif bool IPMIDIPort::open_sockets (int base_port, const string& ifname) @@ -165,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; @@ -188,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)"); @@ -206,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)) { @@ -219,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, (char *) &loop, &size)) { + ::perror ("getsockopt(IP_MULTICAST_LOOP)"); + } else { + cout << "********* 1. multicast loopback: " << loop << " size was " << size << endl; + } + // Turn off loopback... - int loop = 0; + loop = 0; if (::setsockopt(sockout, IPPROTO_IP, IP_MULTICAST_LOOP, (char *) &loop, sizeof (loop)) < 0) { ::perror("setsockopt(IP_MULTICAST_LOOP)"); return false; } + if (::getsockopt (sockin, IPPROTO_IP, IP_MULTICAST_LOOP, (char *) &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; @@ -241,12 +269,26 @@ 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; } - + +#else + // 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 -IPMIDIPort::write (const byte* msg, size_t msglen, timestamp_t /* ignored */) { +IPMIDIPort::write (const MIDI::byte* msg, size_t msglen, timestamp_t /* ignored */) { if (sockout) { Glib::Threads::Mutex::Lock lm (write_lock); @@ -260,7 +302,7 @@ IPMIDIPort::write (const byte* msg, size_t msglen, timestamp_t /* ignored */) { } int -IPMIDIPort::read (byte* /*buf*/, size_t /*bufsize*/) +IPMIDIPort::read (MIDI::byte* /*buf*/, size_t /*bufsize*/) { /* nothing to do here - all handled by parse() */ return 0; @@ -273,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]); } @@ -290,4 +336,3 @@ IPMIDIPort::parse (framecnt_t timestamp) ::perror ("failed to recv from socket"); } } -