Commit b36bc011 authored by Christopher Degawa's avatar Christopher Degawa Committed by Jean-Baptiste Kempf
Browse files

mingw-w64: Add basic mingw-w64 support



Copied the compat stuff from libmicrodns
a 6th grader could probably do better, this is some copying from stack overflow quality code.
Signed-off-by: Christopher Degawa's avatarChristopher Degawa <ccom@randomderp.com>
parent 8e5ea1eb
/**
* Copyright © 2014-2015 VideoLabs SAS
*
* Author: Jonathan Calmels <jbjcalmels@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <assert.h>
#include <errno.h>
#include <string.h>
#ifndef HAVE_POLL
#include <winsock2.h>
static int poll(struct pollfd *fds, unsigned nfds, int timeout) {
DWORD to = (timeout >= 0) ? (DWORD)timeout : INFINITE;
if (nfds == 0) { /* WSAWaitForMultipleEvents() does not allow zero events */
if (SleepEx(to, TRUE)) {
errno = EINTR;
return -1;
}
return 0;
}
WSAEVENT *evts = malloc(nfds * sizeof(WSAEVENT));
if (evts == NULL) return -1; /* ENOMEM */
DWORD ret = WSA_WAIT_FAILED;
for (unsigned i = 0; i < nfds; i++) {
SOCKET fd = fds[i].fd;
long mask = FD_CLOSE;
fd_set rdset, wrset, exset;
FD_ZERO(&rdset);
FD_ZERO(&wrset);
FD_ZERO(&exset);
FD_SET(fd, &exset);
if (fds[i].events & POLLRDNORM) {
mask |= FD_READ | FD_ACCEPT;
FD_SET(fd, &rdset);
}
if (fds[i].events & POLLWRNORM) {
mask |= FD_WRITE | FD_CONNECT;
FD_SET(fd, &wrset);
}
if (fds[i].events & POLLPRI) mask |= FD_OOB;
fds[i].revents = 0;
evts[i] = WSACreateEvent();
if (evts[i] == WSA_INVALID_EVENT) {
while (i > 0) WSACloseEvent(evts[--i]);
free(evts);
errno = ENOMEM;
return -1;
}
if (WSAEventSelect(fds[i].fd, evts[i], mask) &&
WSAGetLastError() == WSAENOTSOCK)
fds[i].revents |= POLLNVAL;
struct timeval tv = {0, 0};
/* By its horrible design, WSAEnumNetworkEvents() only enumerates
* events that were not already signaled (i.e. it is edge-triggered).
* WSAPoll() would be better in this respect, but worse in others.
* So use WSAEnumNetworkEvents() after manually checking for pending
* events. */
if (select(0, &rdset, &wrset, &exset, &tv) > 0) {
if (FD_ISSET(fd, &rdset))
fds[i].revents |= fds[i].events & POLLRDNORM;
if (FD_ISSET(fd, &wrset))
fds[i].revents |= fds[i].events & POLLWRNORM;
if (FD_ISSET(fd, &exset))
/* To add pain to injury, POLLERR and POLLPRI cannot be
* distinguished here. */
fds[i].revents |= POLLERR | (fds[i].events & POLLPRI);
}
if (fds[i].revents != 0 && ret == WSA_WAIT_FAILED)
ret = WSA_WAIT_EVENT_0 + i;
}
if (ret == WSA_WAIT_FAILED)
ret = WSAWaitForMultipleEvents(nfds, evts, FALSE, to, TRUE);
unsigned count = 0;
for (unsigned i = 0; i < nfds; i++) {
WSANETWORKEVENTS ne;
if (WSAEnumNetworkEvents(fds[i].fd, evts[i], &ne))
memset(&ne, 0, sizeof(ne));
WSAEventSelect(fds[i].fd, evts[i], 0);
WSACloseEvent(evts[i]);
if (ne.lNetworkEvents & FD_CONNECT) {
fds[i].revents |= POLLWRNORM;
if (ne.iErrorCode[FD_CONNECT_BIT] != 0) fds[i].revents |= POLLERR;
}
if (ne.lNetworkEvents & FD_CLOSE) {
fds[i].revents |= (fds[i].events & POLLRDNORM) | POLLHUP;
if (ne.iErrorCode[FD_CLOSE_BIT] != 0) fds[i].revents |= POLLERR;
}
if (ne.lNetworkEvents & FD_ACCEPT) {
fds[i].revents |= POLLRDNORM;
if (ne.iErrorCode[FD_ACCEPT_BIT] != 0) fds[i].revents |= POLLERR;
}
if (ne.lNetworkEvents & FD_OOB) {
fds[i].revents |= POLLPRI;
if (ne.iErrorCode[FD_OOB_BIT] != 0) fds[i].revents |= POLLERR;
}
if (ne.lNetworkEvents & FD_READ) {
fds[i].revents |= POLLRDNORM;
if (ne.iErrorCode[FD_READ_BIT] != 0) fds[i].revents |= POLLERR;
}
if (ne.lNetworkEvents & FD_WRITE) {
fds[i].revents |= POLLWRNORM;
if (ne.iErrorCode[FD_WRITE_BIT] != 0) fds[i].revents |= POLLERR;
}
count += fds[i].revents != 0;
}
free(evts);
if (count == 0 && ret == WSA_WAIT_IO_COMPLETION) {
errno = EINTR;
return -1;
}
return count;
}
#endif
......@@ -25,9 +25,19 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include <time.h>
#include <sys/types.h>
#ifdef _WIN32
#include <ws2tcpip.h>
#include <winsock2.h>
#else
#include <sys/socket.h>
#include <netdb.h>
#endif
#ifdef HAVE_POLL
#include <poll.h>
#else
#include "compat/poll.c"
#endif
#include <libavutil/common.h>
#include <libavutil/frame.h>
......@@ -392,7 +402,7 @@ static int receive_ndi_packet(ndi_ctx *ndi_ctx)
uint8_t tmp[5000];
/* TODO: Zero copy */
int len = recv(ndi_ctx->socket_fd, tmp, 5000, 0);
int len = recv(ndi_ctx->socket_fd, (void *)tmp, 5000, 0);
if(len < 0)
printf("bad \n");
......@@ -417,7 +427,7 @@ static int request_ndi_data(ndi_ctx *ndi_ctx)
for(int i = 0; i < 4; i++) {
ndi_message *ndi_request = &ndi_ctx->ndi_request[i];
// XXX: Check failure
send(ndi_ctx->socket_fd, ndi_request->buf, ndi_request->len, 0);
send(ndi_ctx->socket_fd, (void *)ndi_request->buf, ndi_request->len, 0);
free(ndi_request->buf);
ndi_request->buf = NULL;
ndi_ctx->pending_requests--;
......@@ -500,6 +510,26 @@ int libndi_setup(ndi_ctx *ndi_ctx, ndi_opts *ndi_opts)
return 0;
}
#ifdef _WIN32
static int system_InitWSA(int hi, int lo) {
WSADATA data;
if (WSAStartup(MAKEWORD(hi, lo), &data) == 0) {
if (LOBYTE(data.wVersion) == 2 && HIBYTE(data.wVersion) == 2) return 0;
/* Winsock DLL is not usable */
WSACleanup();
}
return -1;
}
static void system_Init(void) {
if (system_InitWSA(2, 2) && system_InitWSA(1, 1))
fputs("Error: cannot initialize Winsocks\n", stderr);
}
#else
static void system_Init(void) { return; }
#endif
void libndi_receive_data(ndi_ctx *ndi_ctx, ndi_data_callback callback)
{
ndi_ctx->callback = callback;
......@@ -511,6 +541,8 @@ void libndi_receive_data(ndi_ctx *ndi_ctx, ndi_data_callback callback)
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
system_Init();
if ((ret = getaddrinfo(ndi_ctx->ip, ndi_ctx->port, &hints, &res)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(ret));
goto end;
......
......@@ -6,6 +6,8 @@ project('libndi', 'c',
'b_ndebug=if-release'],
meson_version: '>= 0.47.0')
cc = meson.get_compiler('c')
# API/ABI version (soversion) for the library
ndi_soname_version = '0.0.1'
......@@ -17,6 +19,30 @@ add_project_arguments('-D_POSIX_C_SOURCE=200809L', language : 'c')
libavutil_dep = dependency('libavutil', required: true)
poll_src = '''
#include <stddef.h>
#ifdef _WIN32
#include <winsock2.h>
#include <windows.h>
# if _WIN32_WINNT < 0x600
# error Needs vista+
# endif
# if defined(_MSC_VER)
# error
# endif
#else
#include <poll.h>
#endif
int main() {
poll(NULL, 0, 0);
}
'''
if cc.links(poll_src)
add_project_arguments('-DHAVE_POLL=1', language: 'c')
endif
# mDNS discovery specifics
ndi_discovery_sources = []
ndi_discovery_deps = []
......
......@@ -25,9 +25,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include <unistd.h>
#include <sys/types.h>
#ifdef _WIN32
#include <wspiapi.h>
#define sleep(x) Sleep((x) * 1000)
#else
#include <poll.h>
#include <sys/socket.h>
#include <netdb.h>
#include <poll.h>
#endif
#include <libavutil/common.h>
#include <libavutil/frame.h>
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment