[xiph-commits] r3132 - liboggplay/trunk/plugin
shans at svn.annodex.net
shans at svn.annodex.net
Thu Jun 28 17:27:49 PDT 2007
Author: shans
Date: 2007-06-28 17:27:49 -0700 (Thu, 28 Jun 2007)
New Revision: 3132
Added:
liboggplay/trunk/plugin/plugin_cmml.c
liboggplay/trunk/plugin/plugin_cmml.h
Log:
Actual asynchronous recieve functionality
Added: liboggplay/trunk/plugin/plugin_cmml.c
===================================================================
--- liboggplay/trunk/plugin/plugin_cmml.c (rev 0)
+++ liboggplay/trunk/plugin/plugin_cmml.c 2007-06-29 00:27:49 UTC (rev 3132)
@@ -0,0 +1,368 @@
+/*
+ Copyright (C) 2003 Commonwealth Scientific and Industrial Research
+ Organisation (CSIRO) Australia
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ - Neither the name of CSIRO Australia nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * plugin_cmml.c
+ *
+ * Shane Stephens <shane.stephens at annodex.net>
+ *
+ * oggplay_* functions in this file dodgily copied from oggplay_tcp_reader.c
+ * because poor widdle windows can't handle even mildy complicated cases of
+ * #include dependencies. Honestly, I wonder if that child will ever grow
+ * up normal.
+ */
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <oggplay/oggplay.h>
+
+#ifdef WIN32
+#include <process.h>
+#include <io.h>
+
+#else
+#include <sys/types.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <sys/fcntl.h>
+#include <sys/errno.h>
+#include <sys/time.h>
+#include <time.h>
+#include <netdb.h>
+#include <unistd.h>
+#endif
+
+#include <assert.h>
+#include <pthread.h>
+
+#include "plugin_cmml.h"
+
+#define PRINT_BUFFER(s,m) \
+ printf("%s: in_mem: %d size: %d pos: %d stored: %d\n", \
+ s, m->amount_in_memory, m->buffer_size, \
+ m->current_position, m->stored_offset);
+
+#ifndef WIN32
+typedef int SOCKET;
+#define INVALID_SOCKET -1
+#endif
+
+#define START_TIMEOUT(ref) \
+ (ref) = oggplay_sys_time_in_ms()
+
+#ifdef WIN32
+#define CHECK_ERROR(error) \
+ (WSAGetLastError() == WSA##error)
+#else
+#define CHECK_ERROR(error) \
+ (errno == error)
+#endif
+
+#define RETURN_ON_TIMEOUT_OR_CONTINUE(ref) \
+ if (oggplay_sys_time_in_ms() - (ref) > 500) { \
+ return E_OGGPLAY_TIMEOUT; \
+ } else { \
+ oggplay_millisleep(10); \
+ continue; \
+ }
+
+static SOCKET
+oggplay_create_socket() {
+ SOCKET sock;
+
+#ifdef WIN32
+ WORD wVersionRequested;
+ WSADATA wsaData;
+#ifdef HAVE_WINSOCK2
+ wVersionRequested = MAKEWORD(2,2);
+#else
+ wVersionRequested = MAKEWORD(1,1);
+#endif
+ if (WSAStartup(wVersionRequested, &wsaData) == -1) {
+ printf("Socket open error\n");
+ return INVALID_SOCKET;
+ }
+ if (wsaData.wVersion != wVersionRequested) {
+ printf("Incorrect winsock version [%d]\n", wVersionRequested);
+ WSACleanup();
+ return INVALID_SOCKET;
+ }
+#endif
+
+ sock = socket(PF_INET, SOCK_STREAM, 0);
+ if (sock == INVALID_SOCKET) {
+ printf("Could not create socket\n");
+#ifdef WIN32
+ WSACleanup();
+#endif
+ return INVALID_SOCKET;
+ }
+
+ return sock;
+}
+
+/*
+ * this function guarantees it will return malloced versions of host and
+ * path
+ */
+static void
+oggplay_hostname_and_path(char *location, char *proxy, int proxy_port,
+ char **host, int *port, char **path) {
+
+
+ char * colon;
+ char * slash;
+ char * end_of_host;
+
+ /* if we have a proxy installed this is all dead simple */
+ if (proxy != NULL) {
+ *host = strdup(proxy);
+ *port = proxy_port;
+ *path = strdup(location);
+ return;
+ }
+
+ /* find start_pos */
+ if (strncmp(location, "http://", 7) == 0) {
+ location += 7;
+ }
+
+ colon = strchr(location, ':');
+ slash = strchr(location, '/');
+
+ /*
+ * if both are null, then just set the simple defaults and return
+ */
+ if (colon == NULL && slash == NULL) {
+ *host = strdup(location);
+ *port = 80;
+ *path = strdup("/");
+ return;
+ }
+
+ /*
+ * if there's a slash and it's before colon, there's no port. Hence, after
+ * this code, the only time that there's a port is when colon is non-NULL
+ */
+ if (slash != NULL && colon > slash) {
+ colon = NULL;
+ }
+
+ /*
+ * we might as well extract the port now. We can also work out where
+ * the end of the hostname is, as it's either the colon (if there's a port)
+ * or the slash (if there's no port)
+ */
+ if (colon != NULL) {
+ *port = (int)strtol(colon+1, NULL, 10);
+ end_of_host = colon;
+ } else {
+ *port = 80;
+ end_of_host = slash;
+ }
+
+ *host = strdup(location);
+ (*host)[end_of_host - location] = '\0';
+
+ if (slash == NULL) {
+ *path = strdup("/");
+ return;
+ }
+
+ *path = strdup(slash);
+
+}
+
+static OggPlayErrorCode
+oggplay_connect_to_host(SOCKET socket, struct sockaddr *addr) {
+
+ ogg_int64_t time_ref;
+
+ START_TIMEOUT(time_ref);
+
+ while (connect(socket, addr, sizeof(struct sockaddr_in)) < 0) {
+ if (
+ CHECK_ERROR(EINPROGRESS) || CHECK_ERROR(EALREADY)
+#ifdef WIN32
+ /* see http://msdn2.microsoft.com/en-us/library/ms737625.aspx */
+ || CHECK_ERROR(EWOULDBLOCK) || CHECK_ERROR(EINVAL)
+#endif
+ ) {
+ RETURN_ON_TIMEOUT_OR_CONTINUE(time_ref);
+ }
+ else if CHECK_ERROR(EISCONN)
+ {
+ break;
+ }
+ printf("Could not connect to host; error code is %d\n", errno);
+ return CHECK_ERROR(ETIMEDOUT) ? E_OGGPLAY_TIMEOUT :
+ E_OGGPLAY_SOCKET_ERROR;
+ }
+
+ return E_OGGPLAY_OK;
+
+}
+
+char *
+get_all_cmml(char *location, char *proxy, int proxy_port) {
+
+ char * host;
+ char * path;
+ int port;
+ char http_request_header[1024];
+ SOCKET socket = oggplay_create_socket();
+ struct sockaddr_in addr;
+ struct hostent * he;
+ int r;
+ char * buffer = NULL;
+ int n_chunks = 0;
+ int bytes_read = 0;
+
+ if (socket == INVALID_SOCKET) return NULL;
+
+ oggplay_hostname_and_path(location, proxy, proxy_port, &host, &port, &path);
+
+ snprintf(http_request_header, 1024,
+ "GET %s HTTP/1.0\n"
+ "Host: %s\n"
+ "User-Agent: AnnodexFirefoxPlugin/0.1\n"
+ "Accept: */*\n"
+ "Connection: Keep-Alive\n\n", path, host);
+
+ he = gethostbyname(host);
+
+ free(host);
+ free(path);
+
+ if (he == NULL) {
+ return NULL;
+ }
+
+ memcpy(&addr.sin_addr.s_addr, he->h_addr, he->h_length);
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port);
+
+ r = oggplay_connect_to_host(socket, (struct sockaddr *)&addr);
+ if (r != E_OGGPLAY_OK) return NULL;
+
+#ifdef WIN32
+ r = send(socket, http_request_header, strlen(http_request_header), 0);
+#else
+ r = write(socket, http_request_header, strlen(http_request_header));
+#endif
+
+ if (r < 0) return NULL;
+
+#define CHUNK_SIZE 2048
+
+ while (1) {
+
+ n_chunks ++;
+ buffer = realloc(buffer, CHUNK_SIZE * n_chunks);
+
+#ifdef WIN32
+ r = recv(socket, buffer + bytes_read, CHUNK_SIZE, 0);
+#else
+ r = read(socket, buffer + bytes_read, CHUNK_SIZE);
+#endif
+
+ if (r < 0) {
+ free(buffer);
+#ifdef WIN32
+ closesocket(socket);
+#else
+ close(socket);
+#endif
+ return NULL;
+ }
+
+ if (r == 0) {
+ buffer[bytes_read] = '\0';
+#ifdef WIN32
+ closesocket(socket);
+#else
+ close(socket);
+#endif
+ return buffer;
+ }
+
+ bytes_read += r;
+ }
+
+}
+
+typedef struct {
+ char * file;
+ char * proxy;
+ int proxyPort;
+ nsPluginInstance * plugin;
+} CmmlThreadInfo;
+
+static void *
+cmml_thread(void *handle) {
+
+ CmmlThreadInfo * info = (CmmlThreadInfo *)handle;
+ char * cmml;
+
+ cmml = get_all_cmml(info->file, info->proxy, info->proxyPort);
+ if (cmml == NULL) {
+ return NULL;
+ }
+
+ onCMMLData(info->plugin, &cmml, 1, 1);
+ return NULL;
+
+}
+
+void
+start_cmml_thread(nsPluginInstance *i, const char *movie, char *proxy,
+ int proxyPort) {
+
+ CmmlThreadInfo * info;
+ char * mdot = strrchr(movie, '.');
+ char * fname = malloc(mdot - movie + 6);
+ pthread_t thread;
+
+ strcpy(fname, movie);
+ strcpy(fname + (mdot - movie), ".cmml");
+
+ info = malloc(sizeof(CmmlThreadInfo));
+ info->file = fname;
+ info->proxy = proxy;
+ info->proxyPort = proxyPort;
+ info->plugin = i;
+
+ pthread_create(&thread, NULL, cmml_thread, (void *)info);
+
+}
Added: liboggplay/trunk/plugin/plugin_cmml.h
===================================================================
--- liboggplay/trunk/plugin/plugin_cmml.h (rev 0)
+++ liboggplay/trunk/plugin/plugin_cmml.h 2007-06-29 00:27:49 UTC (rev 3132)
@@ -0,0 +1,52 @@
+/*
+ Copyright (C) 2003 Commonwealth Scientific and Industrial Research
+ Organisation (CSIRO) Australia
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ - Neither the name of CSIRO Australia nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * plugin_cmml.c
+ *
+ * Shane Stephens <shane.stephens at annodex.net>
+ *
+ * oggplay_* functions in this file dodgily copied from oggplay_tcp_reader.c
+ * because poor widdle windows can't handle even mildy complicated cases of
+ * #include dependencies. Honestly, I wonder if that child will ever grow
+ * up normal.
+ */
+#ifndef _PLUGIN_CMML_H
+#define _PLUGIN_CMML_H
+
+#include "plugin_c.h"
+
+void
+start_cmml_thread(nsPluginInstance *i, const char *movie, char *proxy,
+ int proxyPort);
+
+#endif
More information about the commits
mailing list