[cvs-annodex] commit (mod_annodex-ap20): +trunk/.deps +trunk/.libs/
+trunk/.libs/mod_annodex.a +trunk/.libs/mod_annodex.lai
+trunk/.libs/mod_annodex.so +trunk/LICENSE +trunk/Makefile
+trunk/README +trunk/mod_annodex.c +trunk/modules.mk
conrad
nobody at lists.annodex.net
Thu May 6 13:21:06 EST 2004
Update of /annodex/mod_annodex-ap20 (new revision 4)
Added files:
trunk/.deps
trunk/.libs/
trunk/.libs/mod_annodex.a
trunk/.libs/mod_annodex.lai
trunk/.libs/mod_annodex.so
trunk/LICENSE
trunk/Makefile
trunk/README
trunk/mod_annodex.c
trunk/modules.mk
Log Message:
initial import
Added: trunk/.deps
===================================================================
Added: trunk/.libs/mod_annodex.a
===================================================================
(Binary files differ)
Property changes on: trunk/.libs/mod_annodex.a
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/.libs/mod_annodex.lai
===================================================================
--- trunk/.libs/mod_annodex.lai 2004-05-06 02:54:45 UTC (rev 3)
+++ trunk/.libs/mod_annodex.lai 2004-05-06 03:21:06 UTC (rev 4)
@@ -0,0 +1,35 @@
+# mod_annodex.la - a libtool library file
+# Generated by ltmain.sh - GNU libtool 1.5.0a (1.1220.2.35 2003/11/12 18:51:58) Debian: 159 $
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='mod_annodex.so'
+
+# Names of this library.
+library_names='mod_annodex.so mod_annodex.so mod_annodex.so'
+
+# The name of the static archive.
+old_library='mod_annodex.a'
+
+# Libraries that this one depends upon.
+dependency_libs=' -L/usr/local/lib /usr/local/lib/libannodex.la /usr/lib/libogg.la -ldl -lm /usr/local/lib/liboggz.la /usr/lib/libogg.la'
+
+# Version information for mod_annodex.
+current=0
+age=0
+revision=0
+
+# Is this an already installed library?
+installed=yes
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=yes
+
+# Files to dlopen/dlpreopen
+dlopen=''
+dlpreopen=''
+
+# Directory that this library needs to be installed in:
+libdir='/usr/lib/apache2/modules'
Added: trunk/.libs/mod_annodex.so
===================================================================
(Binary files differ)
Property changes on: trunk/.libs/mod_annodex.so
___________________________________________________________________
Name: svn:executable
+
Name: svn:mime-type
+ application/octet-stream
Added: trunk/LICENSE
===================================================================
--- trunk/LICENSE 2004-05-06 02:54:45 UTC (rev 3)
+++ trunk/LICENSE 2004-05-06 03:21:06 UTC (rev 4)
@@ -0,0 +1,58 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2000 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" must
+ * not be used to endorse or promote products derived from this
+ * software without prior written permission. For written
+ * permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * nor may "Apache" appear in their name, without prior written
+ * permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
+ * ITS 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ * Portions of this software are based upon public domain software
+ * originally written at the National Center for Supercomputing Applications,
+ * University of Illinois, Urbana-Champaign.
+ */
+
Added: trunk/Makefile
===================================================================
--- trunk/Makefile 2004-05-06 02:54:45 UTC (rev 3)
+++ trunk/Makefile 2004-05-06 03:21:06 UTC (rev 4)
@@ -0,0 +1,48 @@
+##
+## Makefile -- Build procedure for sample annodex Apache module
+## Autogenerated via ``apxs -n annodex -g''.
+##
+
+builddir=.
+top_srcdir=/usr/share/apache2
+top_builddir=/usr/share/apache2
+include /usr/share/apache2/build/special.mk
+
+# the used tools
+APXS=apxs2
+APACHECTL=apache2ctl
+
+# additional defines, includes and libraries
+#DEFS=-Dmy_define=my_value
+#INCLUDES=-Imy/include/dir
+INCLUDES=`pkg-config --cflags annodex`
+#LIBS=-Lmy/lib/dir -lmylib
+SH_LIBS=`pkg-config --libs annodex`
+
+# the default target
+all: local-shared-build
+
+# install the shared object file into Apache
+install: install-modules
+
+# cleanup
+clean:
+ -rm -f mod_annodex.o mod_annodex.lo mod_annodex.slo mod_annodex.la
+
+# simple test
+test: reload
+ lynx -mime_header http://localhost/annodex
+
+# install and activate shared object by reloading Apache to
+# force a reload of the shared object file
+reload: install restart
+
+# the general Apache start/restart/stop
+# procedures
+start:
+ $(APACHECTL) start
+restart:
+ $(APACHECTL) restart
+stop:
+ $(APACHECTL) stop
+
Added: trunk/README
===================================================================
--- trunk/README 2004-05-06 02:54:45 UTC (rev 3)
+++ trunk/README 2004-05-06 03:21:06 UTC (rev 4)
@@ -0,0 +1,69 @@
+This is mod_annodex for Apache 2.0.
+
+What does it do?
+----------------
+
+mod_annodex provides full support for Annodex.net media. For more details
+about annodex format, see http://www.annodex.net/
+
+mod_annodex is a handler for type application/x-annodex. It provides the
+following features:
+
+ * dynamic generation of Annodex media from CMML files.
+
+ * handling of timed query offsets, such as
+
+ http://media.foo.bar/annodex/fish.anx?t=npt:01:20.8
+
+ * dynamic retrieval of CMML summaries, if the Accept: header
+ prefers type text/x-cmml over application/x-annodex.
+
+Building and installing
+-----------------------
+
+This tarball was developed on Debian GNU/Linux. To build on Debian, do
+the following:
+
+ 0. ensure you have the apache2-dev package
+ 1. Type 'make' to build
+ 2. Type 'make install' to place the module into the correct
+ directory for Apache to find it.
+
+On other systems, you may need to modify the Makefile appropriately.
+A good starting point is to use apxs to generate a Makefile for you.
+'apxs -g -n fish' will generate template apache module source in a
+directory called fish; its Makefile contains the correct Apache paths
+and build options for your system.
+
+Configuration
+-------------
+
+As with any Apache module, you must modify your httpd.conf to enable
+mod_annodex. The following example sets mod_annodex to be the handler
+for the directory /annodex:
+
+# Support for Annodex media
+LoadModule annodex_module /usr/lib/apache2/modules/mod_annodex.so
+
+<IfModule mod_annodex.c>
+ <Location /annodex>
+ SetHandler annodex
+ </Location>
+</IfModule>
+
+Contact
+-------
+
+Please use the annodex-users mailing list to discuss configuration and
+usage of this module.
+
+Copyright
+---------
+
+Copyright (C) 2003, 2004 CSIRO Australia
+
+This is free software, available under the terms of the Apache Software
+License 1.1. See the file LICENSE for details.
+
+Conrad Parker, Silvia Pfeiffer
+Annodex.net
Added: trunk/mod_annodex.c
===================================================================
--- trunk/mod_annodex.c 2004-05-06 02:54:45 UTC (rev 3)
+++ trunk/mod_annodex.c 2004-05-06 03:21:06 UTC (rev 4)
@@ -0,0 +1,689 @@
+/*
+** mod_annodex.c -- Apache sample annodex module
+** [Autogenerated via ``apxs -n annodex -g'']
+**
+** To play with this sample module first compile it into a
+** DSO file and install it into Apache's modules directory
+** by running:
+**
+** $ apxs -c -i mod_annodex.c
+**
+** Then activate it in Apache's httpd.conf file for instance
+** for the URL /annodex in as follows:
+**
+** # httpd.conf
+** LoadModule annodex_module modules/mod_annodex.so
+** <Location /annodex>
+** SetHandler annodex
+** </Location>
+**
+** Then after restarting Apache via
+**
+** $ apachectl restart
+**
+** you immediately can request the URL /annodex and watch for the
+** output of this module. This can be achieved for instance via:
+**
+** $ lynx -mime_header http://localhost/annodex
+**
+** The output should be similar to the following one:
+**
+** HTTP/1.1 200 OK
+** Date: Tue, 31 Mar 1998 14:42:22 GMT
+** Server: Apache/1.3.4 (Unix)
+** Connection: close
+** Content-Type: text/html
+**
+** The sample page from mod_annodex.c
+*/
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_protocol.h"
+#include "ap_config.h"
+#include "http_core.h"
+#include "http_log.h"
+#include "apr_strings.h"
+#include "apr_uri.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <annodex/anx_core.h>
+#include <annodex/annodex.h>
+
+/* define __PROTOTYPE to enable mode= parameter */
+/* #define __PROTOTYPE */
+
+#define DEBUG
+
+#define ANX_MIME_TYPE "application/x-annodex"
+#define CMML_MIME_TYPE "text/x-cmml"
+
+#define CMML_PREAMBLE \
+"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" \
+
+#define MOD_ANNODEX_TYPE_UNKNOWN -1
+
+#define MOD_ANNODEX_TYPE_ANX 0
+#define MOD_ANNODEX_TYPE_CMML 1
+
+#ifdef __PROTOTYPE
+#define MOD_ANNODEX_TYPE_MEDIA 2
+#endif
+
+#define MAX_ANCHOR_LEN 32768
+
+/**
+ * Print a time as npt using ap_rprintf
+ * \param r the request record
+ * \param seconds the time to print
+ * \returns the ap_rprintf return value
+ */
+static int
+rprintf_time_npt (request_rec * r, double seconds)
+{
+ int hrs, min;
+ double sec;
+ char * sign;
+
+ sign = (seconds < 0.0) ? "-" : "";
+
+ if (seconds < 0.0) seconds = -seconds;
+
+ hrs = (int) (seconds/3600.0);
+ min = (int) ((seconds - ((double)hrs * 3600.0)) / 60.0);
+ sec = seconds - ((double)hrs * 3600.0)- ((double)min * 60.0);
+
+ /* XXX: %02.3f workaround */
+ if (sec < 10.0) {
+ return ap_rprintf (r, "%s%02d:%02d:0%2.3f", sign, hrs, min, sec);
+ } else {
+ return ap_rprintf (r, "%s%02d:%02d:%02.3f", sign, hrs, min, sec);
+ }
+}
+
+/**
+ * Create a table corresponding to name=value pairs in the query string
+ * @param r The resource request
+ * @param query The query string
+ * @return A newly created table with corresponding name=value keys.
+ */
+static apr_table_t *
+make_cgi_table (request_rec * r, char * query)
+{
+ apr_table_t * t;
+ char * key, * val, * end;
+
+ t = apr_table_make (r->pool, 3);
+
+ if (!query) return t;
+
+ key = query;
+
+ do {
+ val = strchr (key, '=');
+ end = strchr (key, '&');
+
+ if (end) {
+ if (val) {
+ if (val < end) {
+ *val++ = '\0';
+ } else {
+ val = NULL;
+ }
+ }
+ *end++ = '\0';
+ } else {
+ if (val) *val++ = '\0';
+ }
+
+ /*ap_rprintf (r, "%s = %s\n", key, val);*/
+ apr_table_set (t, key, val);
+
+ key = end;
+
+ } while (end != NULL);
+
+ return t;
+}
+
+/**
+ * Determine the relative quality factor of a mime type given the Accept:
+ * header of a resource request, following rules of RFC2616 Sec. 14.1
+ * @param r The resource request
+ * @param content_type The content_type to check
+ * @return The relative quality factor
+ */
+static float
+get_accept_quality (request_rec * r, char * content_type)
+{
+ char * a, * accept, *next, * last, * pnext, * plast;
+ float q = 0.0, type_q = 0.0, all_q = 0.0;
+ char type[32], subtype[64], atype[32], asubtype[64];
+ char * m_sep, * m_major;
+ apr_size_t m_major_len;
+ int n;
+
+ a = (char *)apr_table_get (r->headers_in, (const char *)"Accept");
+
+ /* If there was no Accept: header, accept all types equally */
+ if (a == NULL) return 1.0;
+
+ /* Form a 'major/*' mime type range for later comparison */
+ m_sep = strchr (content_type, '/');
+ m_major_len = (apr_size_t)(m_sep - content_type);
+ m_major = apr_pstrndup (r->pool, content_type, m_major_len + 2);
+ *(m_major+m_major_len+1) = '*';
+ *(m_major+m_major_len+2) = '\0';
+
+ /* Copy the Accept line for tokenization */
+ accept = apr_pstrdup (r->pool, a);
+
+ apr_collapse_spaces (accept, accept);
+
+ next = apr_strtok (accept, ",", &last);
+ while (next) {
+ pnext = apr_strtok (next, ";", &plast);
+
+ if (!strcmp (pnext, content_type)) {
+ while (pnext) {
+ pnext = apr_strtok (NULL, ";", &plast);
+ if (pnext && sscanf (pnext, "q=%f", &q) == 1) {
+ return q;
+ }
+ }
+ return 1.0;
+ } else if (!strcmp (pnext, "*/*")) {
+ while (pnext) {
+ pnext = apr_strtok (NULL, ";", &plast);
+ if (pnext && sscanf (pnext, "q=%f", &q) == 1) {
+ all_q = q;
+ }
+ }
+ all_q = 1.0;
+ } else if (!strcmp (pnext, m_major)) {
+ while (pnext) {
+ pnext = apr_strtok (NULL, ";", &plast);
+ if (pnext && sscanf (pnext, "q=%f", &q) == 1) {
+ type_q = q;
+ }
+ }
+ type_q = 1.0;
+ }
+ next = apr_strtok (NULL, ",", &last);
+ }
+
+ if (q > 0.0) return q;
+ else if (type_q > 0.0) return type_q;
+ else return all_q;
+}
+
+#ifdef __PROTOTYPE
+static int
+get_cgi_mode (request_rec * r, apr_table_t * cgi_table)
+{
+ char * cgi_mode;
+
+ cgi_mode = (char *)apr_table_get (cgi_table, "mode");
+
+ if (cgi_mode == NULL)
+ return MOD_ANNODEX_TYPE_UNKNOWN;
+
+#ifdef DEBUG
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
+ "cgi mode %s", cgi_mode);
+#endif
+
+ if (!strcmp (cgi_mode, "cmml"))
+ return MOD_ANNODEX_TYPE_CMML;
+ else if (!strcmp (cgi_mode, "media"))
+ return MOD_ANNODEX_TYPE_MEDIA;
+ else
+ return MOD_ANNODEX_TYPE_UNKNOWN;
+}
+#endif /* __PROTOTYPE */
+
+static int
+prefer_cmml (request_rec * r)
+{
+ float qc, qa;
+
+ qc = get_accept_quality (r, "text/x-cmml");
+ qa = get_accept_quality (r, "application/x-annodex");
+
+#ifdef DEBUG
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
+ "Accept CMML %f, Accept ANX %f\n", qc, qa);
+#endif
+
+ return (qc > qa);
+}
+
+static int
+ma_anxenc (request_rec * r, char * filename, char * content_type,
+ apr_table_t * cgi_table)
+{
+ ANNODEX * anx;
+ int ret;
+ char * val;
+ double seek_offset = 0.0, seek_end = -1.0;
+ char buf[1024];
+ long n = 1024;
+
+ anx = anx_new (ANX_WRITE);
+ anx_init_importers (ANX_MIME_TYPE);
+
+ val = (char *)apr_table_get (cgi_table, "t");
+ if (val) {
+ seek_offset = anx_parse_time (val);
+ }
+
+ ret = anx_write_import (anx, filename, NULL, content_type,
+ seek_offset, seek_end, 0);
+
+ while ((n = anx_write_output (anx, buf, 1024)) > 0) {
+ ap_rwrite (buf, n, r);
+ }
+
+ if (anx_close (anx) != NULL) {
+ }
+}
+
+/* ma_anxrip callbacks */
+
+struct ma_anxrip_data_t {
+ request_rec * r;
+ AnxClip * prev_clip;
+ double prev_start_time;
+};
+
+static int
+read_head (ANNODEX * anx, const AnxHead * head, void * user_data)
+{
+ struct ma_anxrip_data_t * mad = (struct ma_anxrip_data_t *)user_data;
+ request_rec * r = mad->r;
+ char buf[MAX_ANCHOR_LEN];
+
+ anx_head_snprint (buf, MAX_ANCHOR_LEN, (AnxHead *)head);
+ ap_rputs (buf, r);
+ ap_rputc ('\n', r);
+
+ return ANX_CONTINUE;
+}
+
+static int
+read_clip (ANNODEX * anx, const AnxClip * clip, void * user_data)
+{
+ struct ma_anxrip_data_t * mad = (struct ma_anxrip_data_t *)user_data;
+ request_rec * r = mad->r;
+ char buf[MAX_ANCHOR_LEN];
+ double t;
+
+ t = anx_tell_time (anx);
+ /* fprintf (outfile, "%.3f (%ld)\t", t, anx_tell (anx));*/
+
+ if (mad->prev_clip != NULL) {
+ anx_clip_snprint (buf, MAX_ANCHOR_LEN, mad->prev_clip,
+ mad->prev_start_time, t);
+ ap_rputs (buf, r);
+ ap_rputc ('\n', r);
+
+ anx_clip_free (mad->prev_clip);
+ }
+
+ mad->prev_clip = anx_clip_clone ((AnxClip *)clip);
+ mad->prev_start_time = t;
+
+ return ANX_CONTINUE;
+}
+
+static int
+ma_anxrip (request_rec * r, char * filename)
+{
+ ANNODEX * anx;
+ apr_file_t * af;
+ char buf[MAX_ANCHOR_LEN];
+ apr_size_t n = MAX_ANCHOR_LEN;
+ AnxHead * head;
+ AnxList * l;
+ AnxTrack * s;
+ double timebase;
+ struct ma_anxrip_data_t mad;
+
+ mad.r = r;
+ mad.prev_clip = NULL;
+
+ anx = anx_open (filename, ANX_READ);
+
+ anx_set_read_head_callback (anx, read_head, &mad);
+ anx_set_read_clip_callback (anx, read_clip, &mad);
+
+ ap_rprintf (r, CMML_PREAMBLE);
+ ap_rprintf (r, "<cmml>\n");
+
+ ap_rprintf (r, "<stream timebase=\"");
+ timebase = anx_get_timebase (anx);
+ if (timebase < 0.0) timebase = 0.0;
+ rprintf_time_npt (r, timebase);
+ ap_rprintf (r, "\">\n"); /* XXX: and UTC */
+
+#if 0
+ for (l = anx_get_track_list (anx); l; l = l->next) {
+ s = (AnxTrack *)l->data;
+
+ if (!(s->content_type && !strncmp (s->content_type, CMML_MIME_TYPE, 11))) {
+ ap_rprintf (r, "<import");
+ if (s->id) ap_rprintf (r, " id=\"%s\"", s->id);
+ if (s->content_type) ap_rprintf (r, " contenttype=\"%s\"", s->content_type);
+ /*
+ if (s->granule_rate_n != 0 && s->granule_rate_d != 0)
+ ap_rprintf (r, " granulerate=\"%ld/%ld\"",
+ (long)s->granule_rate_n, (long)s->granule_rate_d);
+ */
+ ap_rprintf (r, "/>\n");
+ }
+ }
+#endif
+ ap_rprintf (r, "</stream>\n");
+
+#if 0
+ head = anx_get_head (anx);
+
+ anx_head_snprint (buf, MAX_ANCHOR_LEN, (AnxHead *)head);
+ ap_rputs (buf, r);
+ ap_rputc ('\n', r);
+#endif
+
+ while ((n = anx_read (anx, 1024)) > 0);
+
+ if (mad.prev_clip != NULL) {
+ anx_clip_snprint (buf, MAX_ANCHOR_LEN, mad.prev_clip,
+ mad.prev_start_time, anx_tell_time (anx));
+ ap_rputs (buf, r);
+ ap_rputc ('\n', r);
+
+ anx_clip_free (mad.prev_clip);
+ }
+
+ ap_rprintf (r, "</cmml>\n");
+
+ if (anx_close (anx) != NULL) {
+ /*exit_err ("Failed close of annodex");*/
+ }
+}
+
+#ifdef __PROTOTYPE
+
+/* ma_anxrip_media callbacks */
+
+static double s_seek_offset = 0.0;
+
+static int
+read_m_stream (ANNODEX * anx, double timebase, char * utc, void * user_data)
+{
+ return ANX_CONTINUE;
+}
+
+static int
+read_m_track (ANNODEX * anx, long serialno, char * id, char * content_type,
+ anx_int64_t granule_rate_n, anx_int64_t granule_rate_d,
+ int nr_header_packets, void * user_data)
+{
+ request_rec * r = (request_rec *)user_data;
+
+ if (!(content_type && !strncmp (content_type, CMML_MIME_TYPE, 11))) {
+ r->content_type = content_type;
+#ifdef DEBUG
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
+ "Rip media: mime type %s\n", r->content_type);
+#endif
+ }
+
+ return ANX_CONTINUE;
+}
+
+
+static int
+read_media (ANNODEX * anx, unsigned char * data, long len, long serialno,
+ anx_int64_t granulepos, void * user_data)
+{
+ request_rec * r = (request_rec *)user_data;
+ apr_size_t remaining = (apr_size_t)len, n;
+
+#if 0
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
+ "%f\t%f\n", anx_tell_time (anx), s_seek_offset);
+
+ if (anx_tell_time (anx) >= s_seek_offset)
+#endif
+
+ while (remaining > 0) {
+ n = ap_rwrite (data, remaining, r);
+ remaining -= n;
+ }
+
+ return ANX_CONTINUE;
+}
+
+static int
+read_media_1 (ANNODEX * anx, unsigned char * data, long len, long serialno,
+ anx_int64_t granulepos, void * user_data)
+{
+ request_rec * r = (request_rec *)user_data;
+
+ r->content_type = anx_track_get_content_type (anx, serialno);
+ read_media (anx, data, len, serialno, granulepos, user_data);
+ anx_set_read_raw_callback (anx, read_media, user_data);
+
+ return ANX_CONTINUE;
+}
+
+static int
+ma_anxrip_media (request_rec * r, char * filename, apr_table_t * cgi_table)
+{
+ ANNODEX * anx;
+ apr_file_t * af;
+ char buf[MAX_ANCHOR_LEN];
+ apr_size_t n = MAX_ANCHOR_LEN;
+ double seek_offset = 0.0;
+ char * val;
+
+ val = (char *)apr_table_get (cgi_table, "t");
+ if (val) {
+ seek_offset = anx_parse_time (val);
+ }
+
+ anx = anx_open (filename, ANX_READ);
+
+ anx_set_read_stream_callback (anx, read_m_stream, r);
+ anx_set_read_track_callback (anx, read_m_track, r);
+ anx_set_read_raw_callback (anx, read_media_1, r);
+
+ if (seek_offset > 0.0)
+ anx_seek_time (anx, seek_offset, ANX_SEEK_SET);
+
+ /*s_seek_offset = seek_offset;*/
+
+ while ((n = anx_read (anx, 1024)) > 0);
+
+ if (anx_close (anx) != NULL) {
+ /*exit_err ("Failed close of annodex");*/
+ }
+}
+
+#endif
+
+static int
+ma_send (request_rec * r, char * filename)
+{
+ apr_file_t * af;
+ char buf[1024];
+ apr_size_t n = 1024;
+
+ apr_file_open (&af, filename, APR_READ, APR_OS_DEFAULT, r->pool);
+
+ while (apr_file_read (af, (void *)buf, &n) == APR_SUCCESS) {
+ ap_rwrite (buf, n, r);
+ }
+
+ apr_file_close (af);
+}
+
+/* The annodex content handler */
+static int annodex_handler(request_rec *r)
+{
+ apr_uri_t * uri;
+ char * val;
+ char * filename;
+ char * srcpath;
+ int input_type, output_type;
+ apr_table_t * cgi_table;
+
+ uri = &(r->parsed_uri);
+
+ /* usually filename is request filename */
+ filename = r->filename;
+
+ /* but we still need to determine the output type */
+ output_type = MOD_ANNODEX_TYPE_UNKNOWN;
+
+ if (strcmp(r->handler, "annodex")) {
+ return DECLINED;
+ }
+
+ /* check if file exists */
+ if (r->finfo.filetype == APR_NOFILE) {
+ apr_file_t * f;
+ char * extpos;
+ char * srcfile;
+ int filename_len;
+ apr_finfo_t finfo;
+
+ extpos = rindex (r->filename, '.');
+ if (extpos && !strncmp (extpos, ".anx", 4)) {
+ /* s/.anx$/.cmml/ */
+ filename_len = strlen (r->filename);
+ srcfile = apr_palloc (r->pool, filename_len+2);
+ apr_cpystrn (srcfile, r->filename, filename_len-2);
+ apr_cpystrn (srcfile+filename_len-3, "cmml", 5);
+
+ srcpath = r->path_info ?
+ apr_pstrcat(r->pool, srcfile, r->path_info, NULL) : srcfile;
+
+ if (apr_file_open (&f, srcpath, APR_READ, APR_OS_DEFAULT, r->pool) !=
+ APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
+ "Requested file does not exist, nor does CMML %s",
+ srcpath);
+ return HTTP_NOT_FOUND;
+ }
+
+ input_type = MOD_ANNODEX_TYPE_CMML;
+ output_type = MOD_ANNODEX_TYPE_ANX;
+
+ filename = srcpath;
+
+ } else if (extpos && !strncmp (extpos, ".cmml", 5)) {
+ /* s/.cmml$/.anx/ */
+ filename_len = strlen (r->filename);
+ srcfile = apr_palloc (r->pool, filename_len+1);
+ apr_cpystrn (srcfile, r->filename, filename_len-3);
+ apr_cpystrn (srcfile+filename_len-4, "anx", 4);
+
+ srcpath = r->path_info ?
+ apr_pstrcat(r->pool, srcfile, r->path_info, NULL) : srcfile;
+
+ if (apr_file_open (&f, srcpath, APR_READ, APR_OS_DEFAULT, r->pool) !=
+ APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
+ "Requested file %s does not exist, nor does ANX %s",
+ r->filename, srcpath);
+ return HTTP_NOT_FOUND;
+ }
+
+ input_type = MOD_ANNODEX_TYPE_ANX;
+ output_type = MOD_ANNODEX_TYPE_CMML;
+
+ filename = srcpath;
+
+ } else {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
+ "Requested file does not exist: %s",
+ (r->path_info
+ ? apr_pstrcat(r->pool, r->filename, r->path_info, NULL)
+ : r->filename));
+ return HTTP_NOT_FOUND;
+ }
+ } else {
+ input_type = MOD_ANNODEX_TYPE_ANX;
+ }
+
+ if (r->header_only) {
+ return OK;
+ }
+
+ cgi_table = make_cgi_table (r, uri->query);
+
+#ifdef __PROTOTYPE
+ if (output_type == MOD_ANNODEX_TYPE_UNKNOWN)
+ output_type = get_cgi_mode (r, cgi_table);
+#endif
+
+ if (output_type == MOD_ANNODEX_TYPE_UNKNOWN) {
+ if (prefer_cmml (r)) {
+ output_type = MOD_ANNODEX_TYPE_CMML;
+ } else {
+ output_type = MOD_ANNODEX_TYPE_ANX;
+ }
+ }
+
+ if (output_type == MOD_ANNODEX_TYPE_CMML) {
+ r->content_type = CMML_MIME_TYPE;
+ } else {
+ r->content_type = ANX_MIME_TYPE;
+ }
+
+ if (input_type == MOD_ANNODEX_TYPE_ANX &&
+ output_type == MOD_ANNODEX_TYPE_ANX) {
+ /* anx import anx */
+ ma_anxenc (r, r->filename, ANX_MIME_TYPE, cgi_table);
+ } else if (input_type == MOD_ANNODEX_TYPE_CMML &&
+ output_type == MOD_ANNODEX_TYPE_ANX) {
+ /* anx import cmml */
+ ma_anxenc (r, srcpath, CMML_MIME_TYPE, cgi_table);
+ } else if (input_type == MOD_ANNODEX_TYPE_ANX &&
+ output_type == MOD_ANNODEX_TYPE_CMML) {
+ /* anx rip cmml */
+ ma_anxrip (r, filename);
+ } else if (input_type == MOD_ANNODEX_TYPE_CMML &&
+ output_type == MOD_ANNODEX_TYPE_CMML) {
+ /* push out cmml */
+ ma_send (r, srcpath);
+#ifdef __PROTOTYPE
+ } else if (input_type == MOD_ANNODEX_TYPE_ANX &&
+ output_type == MOD_ANNODEX_TYPE_MEDIA) {
+ r->content_type = "video/mpeg";
+ ma_anxrip_media (r, r->filename, cgi_table);
+#endif
+ }
+
+ return OK;
+}
+
+static void annodex_register_hooks(apr_pool_t *p)
+{
+ ap_hook_handler(annodex_handler, NULL, NULL, APR_HOOK_MIDDLE);
+}
+
+/* Dispatch list for API hooks */
+module AP_MODULE_DECLARE_DATA annodex_module = {
+ STANDARD20_MODULE_STUFF,
+ NULL, /* create per-dir config structures */
+ NULL, /* merge per-dir config structures */
+ NULL, /* create per-server config structures */
+ NULL, /* merge per-server config structures */
+ NULL, /* table of config file commands */
+ annodex_register_hooks /* register hooks */
+};
+
Added: trunk/modules.mk
===================================================================
--- trunk/modules.mk 2004-05-06 02:54:45 UTC (rev 3)
+++ trunk/modules.mk 2004-05-06 03:21:06 UTC (rev 4)
@@ -0,0 +1,4 @@
+mod_annodex.la: mod_annodex.slo
+ $(SH_LINK) -rpath $(libexecdir) -module -avoid-version mod_annodex.lo
+DISTCLEAN_TARGETS = modules.mk
+shared = mod_annodex.la
--
conrad
More information about the cvs-annodex
mailing list