[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