r46643 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r46642‎ | r46643 | r46644 >
Date:14:23, 31 January 2009
Author:oggk
Status:deferred
Tags:
Comment:
Kate support back in - now in the -ovt- version rather than in a
new separate one, which avoids the reported problem of failing
to load the jKate decoder.
A few minor improvements to the rendering too.
Modified paths:
  • /trunk/cortado/HACKING (modified) (history)
  • /trunk/cortado/LICENSE.jkate (added) (history)
  • /trunk/cortado/LICENSE.jtiger (added) (history)
  • /trunk/cortado/README (modified) (history)
  • /trunk/cortado/build.xml (modified) (history)
  • /trunk/cortado/plugins.ini (modified) (history)
  • /trunk/cortado/src/com/fluendo/examples/Player.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/jkate/Bitmap.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/jkate/Bitwise.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/jkate/Color.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/jkate/Comment.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/jkate/Curve.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/jkate/Decode.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/jkate/Event.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/jkate/FontMapping.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/jkate/FontRange.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/jkate/Info.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/jkate/KateBadPacketException.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/jkate/KateBitmapType.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/jkate/KateCurveType.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/jkate/KateException.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/jkate/KateMarkupType.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/jkate/KateMotionMapping.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/jkate/KateMotionSemantics.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/jkate/KateSpaceMetric.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/jkate/KateTextDirectionality.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/jkate/KateTextEncoding.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/jkate/KateWrapMode.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/jkate/Motion.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/jkate/Palette.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/jkate/README (modified) (history)
  • /trunk/cortado/src/com/fluendo/jkate/RLE.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/jkate/Region.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/jkate/Result.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/jkate/State.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/jkate/Style.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/jkate/Tracker.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/jst/Element.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/jst/Sink.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/jtiger/Item.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/jtiger/README (modified) (history)
  • /trunk/cortado/src/com/fluendo/jtiger/Renderer.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/jtiger/TigerBitmap.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/player/Cortado.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/player/CortadoPipeline.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/plugin/KateDec.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/plugin/KateOverlay.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/plugin/OggDemux.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/plugin/OggPayload.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/plugin/Overlay.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/plugin/Selector.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/plugin/TextOverlay.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/plugin/TheoraDec.java (modified) (history)
  • /trunk/cortado/src/com/fluendo/plugin/VorbisDec.java (modified) (history)

Diff [purge]

Index: trunk/cortado/build.xml
@@ -175,11 +175,14 @@
176176 <condition property="plugin.Vorbis.false">
177177 <contains string="${exclude}" substring="Vorbis" casesensitive="false" />
178178 </condition>
 179+ <condition property="plugin.Kate.false">
 180+ <contains string="${exclude}" substring="Kate" casesensitive="false" />
 181+ </condition>
179182 </target>
180183
181184 <!-- generate includes and plugins.ini based on contents of exclude -->
182185 <target name="includes"
183 - depends="plugins,includes-delete,include-JPEG,include-Mulaw,include-Multipart,include-Ogg,include-Smoke,include-Theora,include-Vorbis">
 186+ depends="plugins,includes-delete,include-JPEG,include-Mulaw,include-Multipart,include-Ogg,include-Smoke,include-Theora,include-Vorbis,include-Kate">
184187 <echo>Generating ${out.buildtyped}/includes</echo>
185188 </target>
186189
@@ -192,8 +195,11 @@
193196 com/fluendo/jst/*
194197 com/fluendo/plugin/AudioSink*
195198 com/fluendo/plugin/VideoSink**
 199+com/fluendo/plugin/FakeSink*
 200+com/fluendo/plugin/Overlay*
196201 com/fluendo/plugin/HTTPSrc*
197202 com/fluendo/plugin/Queue*
 203+com/fluendo/plugin/Selector*
198204 plugins.ini
199205 </echo>
200206 <echo file="${out.buildtyped}/plugins.ini"
@@ -202,6 +208,9 @@
203209 com.fluendo.plugin.AudioSinkJ2
204210 com.fluendo.plugin.AudioSinkSA
205211 com.fluendo.plugin.Queue
 212+com.fluendo.plugin.FakeSink
 213+com.fluendo.plugin.Overlay
 214+com.fluendo.plugin.Selector
206215 </echo>
207216
208217 </target>
@@ -280,6 +289,19 @@
281290 </echo>
282291 </target>
283292
 293+ <target name="include-Kate" unless="plugin.Kate.false">
 294+ <echo>Including Kate</echo>
 295+ <echo file="${out.buildtyped}/includes" append="true"
 296+>com/fluendo/jkate/*
 297+com/fluendo/jtiger/*
 298+com/fluendo/plugin/Kate*
 299+</echo>
 300+ <echo file="${out.buildtyped}/plugins.ini" append="true"
 301+>com.fluendo.plugin.KateDec
 302+com.fluendo.plugin.KateOverlay
 303+</echo>
 304+ </target>
 305+
284306 <!-- COMPILATION -->
285307
286308 <!-- FIXME: not used currently -->
@@ -358,6 +380,36 @@
359381 </javac>
360382 </target>
361383
 384+ <target name="compile-jkate"
 385+ description="compile com.fluendo.jkate source"
 386+ depends="init,compile-utils,compile-jcraft"
 387+ >
 388+ <javac
 389+ srcdir="${src}"
 390+ destdir="${out.buildtyped}"
 391+ target="1.1" source="1.3"
 392+ debug="${build.isdebug}" debuglevel="${build.debuglevel}"
 393+ >
 394+ <include name="com/fluendo/jkate/**" />
 395+ <compilerarg line="${build.flags}" />
 396+ </javac>
 397+ </target>
 398+
 399+ <target name="compile-jtiger"
 400+ description="compile com.fluendo.jtiger source"
 401+ depends="init,compile-utils,compile-jkate"
 402+ >
 403+ <javac
 404+ srcdir="${src}"
 405+ destdir="${out.buildtyped}"
 406+ target="1.1" source="1.3"
 407+ debug="${build.isdebug}" debuglevel="${build.debuglevel}"
 408+ >
 409+ <include name="com/fluendo/jtiger/**" />
 410+ <compilerarg line="${build.flags}" />
 411+ </javac>
 412+ </target>
 413+
362414 <target name="compile-codecs"
363415 description="compile com.fluendo.codecs source"
364416 depends="init,compile-utils"
@@ -439,7 +491,7 @@
440492
441493 <target name="compile"
442494 description="compile the source"
443 - depends="init,compile-stubs,compile-jcraft,compile-jst,compile-jheora,compile-codecs,compile-plugin,compile-player,compile-examples" />
 495+ depends="init,compile-stubs,compile-jcraft,compile-jst,compile-jheora,compile-jkate,compile-jtiger,compile-codecs,compile-plugin,compile-player,compile-examples" />
444496
445497 <!-- only here for reference -->
446498 <target name="oldcompile">
@@ -494,6 +546,16 @@
495547 includes="com/fluendo/jheora/*" />
496548 </target>
497549
 550+ <target name="jar-jkate" depends="compile-jkate">
 551+ <jar jarfile="${out.dist}/${build.type}/jkate.jar" basedir="${out.buildtyped}"
 552+ includes="com/fluendo/jkate/*" />
 553+ </target>
 554+
 555+ <target name="jar-jtiger" depends="compile-jtiger">
 556+ <jar jarfile="${out.dist}/${build.type}/jtiger.jar" basedir="${out.buildtyped}"
 557+ includes="com/fluendo/jtiger/*" />
 558+ </target>
 559+
498560 <target name="jar-jst" depends="compile-jst">
499561 <jar jarfile="${out.dist}/${build.type}/jst.jar" basedir="${out.buildtyped}"
500562 includes="com/fluendo/jst/*" />
@@ -526,7 +588,7 @@
527589 <target name="applet-ov" depends="compile"
528590 description="generate the Ogg/Vorbis applet">
529591 <antcall target="includes">
530 - <param name="exclude" value="Smoke,Jpeg,Multipart,Mulaw,Theora" />
 592+ <param name="exclude" value="Smoke,Jpeg,Multipart,Mulaw,Theora,Kate" />
531593 </antcall>
532594 <jar jarfile="${out.dist}/applet/cortado-ov-${build.type}-${real_version}.jar"
533595 includesfile="${out.buildtyped}/includes"
@@ -537,7 +599,7 @@
538600 <target name="applet-mmjs" depends="compile"
539601 description="generate the Multipart/Mulaw+Smoke+Jpeg applet">
540602 <antcall target="includes">
541 - <param name="exclude" value="Ogg,Vorbis,Theora" />
 603+ <param name="exclude" value="Ogg,Vorbis,Theora,Kate" />
542604 </antcall>
543605 <jar jarfile="${out.dist}/applet/cortado-mmjs-${build.type}-${real_version}.jar"
544606 includesfile="${out.buildtyped}/includes"
@@ -549,7 +611,7 @@
550612 <target name="applet" depends="applet-ovt,applet-ov,applet-mmjs"
551613 description="generate all applets" />
552614
553 - <target name="jar" depends="jar-jcraft,jar-utils,jar-jheora,jar-jst,jar-codecs,jar-plugin,jar-player"
 615+ <target name="jar" depends="jar-jcraft,jar-utils,jar-jheora,jar-jkate,jar-jtiger,jar-jst,jar-codecs,jar-plugin,jar-player"
554616 description="generate all jar files" />
555617
556618 <!-- instead of using depends, which doesn't necessarily preserve order,
@@ -641,6 +703,8 @@
642704 <include name="src/com/jcraft/jogg/*.java" />
643705 <include name="src/com/jcraft/jorbis/*.java" />
644706 <include name="src/com/fluendo/jheora/*.java" />
 707+ <include name="src/com/fluendo/jkate/*.java" />
 708+ <include name="src/com/fluendo/jtiger/*.java" />
645709 <include name="src/com/fluendo/player/*.java" />
646710 <include name="src/com/fluendo/utils/*.java" />
647711 <include name="src/com/fluendo/codecs/*.java" />
Index: trunk/cortado/plugins.ini
@@ -3,9 +3,14 @@
44 com.fluendo.plugin.VideoSink
55 com.fluendo.plugin.AudioSinkJ2
66 com.fluendo.plugin.AudioSinkSA
 7+com.fluendo.plugin.Overlay
 8+com.fluendo.plugin.TextOverlay
 9+com.fluendo.plugin.KateOverlay
 10+com.fluendo.plugin.Selector
711 com.fluendo.plugin.OggDemux
812 com.fluendo.plugin.TheoraDec
913 com.fluendo.plugin.VorbisDec
 14+com.fluendo.plugin.KateDec
1015 com.fluendo.plugin.Queue
1116 com.fluendo.plugin.MultipartDemux
1217 com.fluendo.plugin.JPEGDec
Index: trunk/cortado/HACKING
@@ -9,6 +9,8 @@
1010 - utils: utitity classes used by jst, jheora, examples
1111 - jst: a java port of the GStreamer 0.10 design
1212 - jheora: a java implementation of the Theora video codec
 13+ - jkate: a basic java implementation of the Kate codec
 14+ - jtiger: a basic Kate stream renderer (simple text/images only for now)
1315 - codecs: additional codecs; currently contains the Smoke codec
1416 - plugin: plugins implementing/wrapping sources/decoders/sinks
1517 - examples: example programs
Index: trunk/cortado/LICENSE.jtiger
@@ -0,0 +1,20 @@
 2+/* JTiger
 3+ * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 4+ *
 5+ * Parts of JTiger are based on code by Wim Taymans <wim@fluendo.com>
 6+ *
 7+ * This program is free software; you can redistribute it and/or
 8+ * modify it under the terms of the GNU Library General Public License
 9+ * as published by the Free Software Foundation; either version 2 of
 10+ * the License, or (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU Library General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU Library General Public
 18+ * License along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20+ */
 21+
Property changes on: trunk/cortado/LICENSE.jtiger
___________________________________________________________________
Added: svn:executable
122 + *
Index: trunk/cortado/LICENSE.jkate
@@ -0,0 +1,20 @@
 2+/* JKate
 3+ * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 4+ *
 5+ * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com>
 6+ *
 7+ * This program is free software; you can redistribute it and/or
 8+ * modify it under the terms of the GNU Library General Public License
 9+ * as published by the Free Software Foundation; either version 2 of
 10+ * the License, or (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU Library General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU Library General Public
 18+ * License along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20+ */
 21+
Property changes on: trunk/cortado/LICENSE.jkate
___________________________________________________________________
Added: svn:executable
122 + *
Index: trunk/cortado/src/com/fluendo/examples/Player.java
@@ -38,6 +38,7 @@
3939 applet.setParam ("keepaspect", "true");
4040 applet.setParam ("video", "true");
4141 applet.setParam ("audio", "true");
 42+ applet.setParam ("kateIndex", "0");
4243 //applet.setParam ("audio", "false");
4344 applet.setParam ("bufferSize", "200");
4445 applet.setParam ("userId", "wim");
Index: trunk/cortado/src/com/fluendo/jkate/KateException.java
@@ -0,0 +1,26 @@
 2+/* JKate
 3+ * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 4+ *
 5+ * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com>
 6+ *
 7+ * This program is free software; you can redistribute it and/or
 8+ * modify it under the terms of the GNU Library General Public License
 9+ * as published by the Free Software Foundation; either version 2 of
 10+ * the License, or (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU Library General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU Library General Public
 18+ * License along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20+ */
 21+
 22+package com.fluendo.jkate;
 23+
 24+class KateException extends java.lang.Exception {
 25+ public KateException(String s) { super(); }
 26+}
 27+
Index: trunk/cortado/src/com/fluendo/jkate/KateSpaceMetric.java
@@ -0,0 +1,45 @@
 2+/* JKate
 3+ * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 4+ *
 5+ * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com>
 6+ *
 7+ * This program is free software; you can redistribute it and/or
 8+ * modify it under the terms of the GNU Library General Public License
 9+ * as published by the Free Software Foundation; either version 2 of
 10+ * the License, or (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU Library General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU Library General Public
 18+ * License along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20+ */
 21+
 22+package com.fluendo.jkate;
 23+
 24+public class KateSpaceMetric {
 25+ public static final KateSpaceMetric kate_metric_pixels = new KateSpaceMetric ();
 26+ public static final KateSpaceMetric kate_metric_percentage = new KateSpaceMetric ();
 27+ public static final KateSpaceMetric kate_metric_millionths = new KateSpaceMetric ();
 28+
 29+ private static final KateSpaceMetric[] list = {
 30+ kate_metric_pixels,
 31+ kate_metric_percentage,
 32+ kate_metric_millionths,
 33+ };
 34+
 35+ private KateSpaceMetric() {
 36+ }
 37+
 38+ /**
 39+ * Create a KateSpaceMetric object from an integer.
 40+ */
 41+ public static KateSpaceMetric CreateSpaceMetric(int idx) throws KateException {
 42+ if (idx < 0 || idx >= list.length)
 43+ throw new KateException("Space metrics "+idx+" out of bounds");
 44+ return list[idx];
 45+ }
 46+}
Index: trunk/cortado/src/com/fluendo/jkate/Motion.java
@@ -0,0 +1,35 @@
 2+/* JKate
 3+ * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 4+ *
 5+ * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com>
 6+ *
 7+ * This program is free software; you can redistribute it and/or
 8+ * modify it under the terms of the GNU Library General Public License
 9+ * as published by the Free Software Foundation; either version 2 of
 10+ * the License, or (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU Library General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU Library General Public
 18+ * License along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20+ */
 21+
 22+package com.fluendo.jkate;
 23+
 24+/**
 25+ * A motion definition, composed of a series of curves
 26+ */
 27+public class Motion
 28+{
 29+ public Curve curves[];
 30+ public double durations[];
 31+ KateMotionMapping x_mapping;
 32+ KateMotionMapping y_mapping;
 33+ KateMotionSemantics semantics;
 34+ boolean periodic;
 35+}
 36+
Index: trunk/cortado/src/com/fluendo/jkate/Bitwise.java
@@ -0,0 +1,154 @@
 2+/* JKate
 3+ * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 4+ *
 5+ * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com>
 6+ *
 7+ * This program is free software; you can redistribute it and/or
 8+ * modify it under the terms of the GNU Library General Public License
 9+ * as published by the Free Software Foundation; either version 2 of
 10+ * the License, or (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU Library General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU Library General Public
 18+ * License along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20+ */
 21+
 22+package com.fluendo.jkate;
 23+
 24+import com.jcraft.jogg.*;
 25+
 26+/**
 27+ * Various methods to read data from a bitstream.
 28+ */
 29+public class Bitwise {
 30+
 31+ /**
 32+ * Read a number of bytes into a buffer.
 33+ */
 34+ static void readbuf(Buffer opb, byte[] buf, int len)
 35+ {
 36+ for (int i=0; i<len; i++) {
 37+ buf[i] = (byte)opb.read(8);
 38+ }
 39+ }
 40+
 41+ /**
 42+ * Read a little endian 32 bit integer.
 43+ */
 44+ static int read32(Buffer opb)
 45+ {
 46+ int value;
 47+
 48+ value = opb.read(8);
 49+ value |= opb.read(8) << 8;
 50+ value |= opb.read(8) << 16;
 51+ value |= opb.read(8) << 24;
 52+
 53+ return value;
 54+ }
 55+
 56+ /**
 57+ * Read a variable size integer.
 58+ * Format defined in the Kate specification.
 59+ */
 60+ static int read32v(Buffer opb)
 61+ {
 62+ int value;
 63+
 64+ value = opb.read(4);
 65+ if (value == 15) {
 66+ int sign = opb.read(1);
 67+ int bits = opb.read(5)+1;
 68+ value = opb.read(bits);
 69+ if (sign != 0) value = -value;
 70+ }
 71+
 72+ return value;
 73+ }
 74+
 75+ /**
 76+ * Read a little endian 64 bit integer.
 77+ */
 78+ static long read64(Buffer opb)
 79+ {
 80+ long vl, vh;
 81+ vl = (long)read32(opb);
 82+ vh = (long)read32(opb);
 83+ return vl | (vh<<32);
 84+ }
 85+
 86+ /**
 87+ * Read a (possibly multiple) warp.
 88+ * Used to skip over unhandled data from newer (bit still compatible)
 89+ * bitstream versions.
 90+ */
 91+ static int skipWarp(Buffer opb)
 92+ {
 93+ while (true) {
 94+ int bits = read32v(opb);
 95+ if (bits == 0)
 96+ break;
 97+ if (bits < 0)
 98+ return Result.KATE_E_BAD_PACKET;
 99+ opb.adv(bits);
 100+ }
 101+
 102+ return 0;
 103+ }
 104+
 105+ static private final int fp_bits = (4*8);
 106+ static private final int fp_cuts_bits = fp_bits/2-1;
 107+ static private final int fp_cuts_bits_bits = 4;
 108+ static private final int fp_sign_bit = 0x80000000;
 109+ private static int[] readFixed(Buffer opb, int count) {
 110+ int head = opb.read(fp_cuts_bits_bits);
 111+ int tail = opb.read(fp_cuts_bits_bits);
 112+ int bits = fp_bits - head - tail;
 113+ int values[] = new int[count];
 114+ int n = 0;
 115+ while (count-- > 0) {
 116+ int sign = 0;
 117+ if (head > 0)
 118+ sign = opb.read1();
 119+ int v = opb.read(bits);
 120+ v <<= tail;
 121+ if (sign != 0)
 122+ v = -v;
 123+ values[n++] = v;
 124+ }
 125+ return values;
 126+ }
 127+ static private double fixedToFloat(int v) {
 128+ return ((double)v) / (1<<16);
 129+ }
 130+
 131+ /**
 132+ * Read an array of float channels.
 133+ * Float format defined in the Kate specification.
 134+ */
 135+ static double[][] readFloats(Buffer opb, int count, int streams) {
 136+ if (count*streams == 0)
 137+ return null;
 138+ if (streams > 1) {
 139+ if (opb.read1() != 0) {
 140+ count *= streams;
 141+ streams = 1;
 142+ }
 143+ }
 144+
 145+ double values[][] = new double[streams][];
 146+ for (int s=0; s<streams; ++s) {
 147+ int ints[] = readFixed(opb, count);
 148+ values[s] = new double[count];
 149+ for (int c=0; c<count; ++c) {
 150+ values[s][c] = fixedToFloat(ints[c]);
 151+ }
 152+ }
 153+ return values;
 154+ }
 155+}
Index: trunk/cortado/src/com/fluendo/jkate/KateMarkupType.java
@@ -0,0 +1,43 @@
 2+/* JKate
 3+ * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 4+ *
 5+ * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com>
 6+ *
 7+ * This program is free software; you can redistribute it and/or
 8+ * modify it under the terms of the GNU Library General Public License
 9+ * as published by the Free Software Foundation; either version 2 of
 10+ * the License, or (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU Library General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU Library General Public
 18+ * License along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20+ */
 21+
 22+package com.fluendo.jkate;
 23+
 24+public class KateMarkupType {
 25+ public static final KateMarkupType kate_markup_none = new KateMarkupType ();
 26+ public static final KateMarkupType kate_markup_simple = new KateMarkupType ();
 27+
 28+ private static final KateMarkupType[] list = {
 29+ kate_markup_none,
 30+ kate_markup_simple,
 31+ };
 32+
 33+ private KateMarkupType() {
 34+ }
 35+
 36+ /**
 37+ * Create a KateMarkupType object from an integer.
 38+ */
 39+ public static KateMarkupType CreateMarkupType(int idx) throws KateException {
 40+ if (idx < 0 || idx >= list.length)
 41+ throw new KateException("Markup type "+idx+" out of bounds");
 42+ return list[idx];
 43+ }
 44+}
Index: trunk/cortado/src/com/fluendo/jkate/Bitmap.java
@@ -0,0 +1,37 @@
 2+/* JKate
 3+ * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 4+ *
 5+ * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com>
 6+ *
 7+ * This program is free software; you can redistribute it and/or
 8+ * modify it under the terms of the GNU Library General Public License
 9+ * as published by the Free Software Foundation; either version 2 of
 10+ * the License, or (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU Library General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU Library General Public
 18+ * License along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20+ */
 21+
 22+package com.fluendo.jkate;
 23+
 24+/**
 25+ * A Bitmap definition.
 26+ */
 27+public class Bitmap
 28+{
 29+ public int width;
 30+ public int height;
 31+ public int bpp;
 32+ public KateBitmapType type;
 33+ public int palette;
 34+ public byte[] pixels;
 35+ public int size;
 36+ public int x_offset;
 37+ public int y_offset;
 38+}
Index: trunk/cortado/src/com/fluendo/jkate/README
@@ -0,0 +1,4 @@
 2+JKate is a simple Kate stream decoder.
 3+
 4+At the moment, only text is supported.
 5+
Index: trunk/cortado/src/com/fluendo/jkate/Result.java
@@ -0,0 +1,35 @@
 2+/* JKate
 3+ * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 4+ *
 5+ * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com>
 6+ *
 7+ * This program is free software; you can redistribute it and/or
 8+ * modify it under the terms of the GNU Library General Public License
 9+ * as published by the Free Software Foundation; either version 2 of
 10+ * the License, or (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU Library General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU Library General Public
 18+ * License along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20+ */
 21+
 22+package com.fluendo.jkate;
 23+
 24+public final class Result {
 25+ public static final int KATE_E_NOT_FOUND = -1;
 26+ public static final int KATE_E_INVALID_PARAMETER = -2;
 27+ public static final int KATE_E_OUT_OF_MEMORY = -3;
 28+ public static final int KATE_E_BAD_GRANULE = -4;
 29+ public static final int KATE_E_INIT = -5;
 30+ public static final int KATE_E_BAD_PACKET = -6;
 31+ public static final int KATE_E_TEXT = -7;
 32+ public static final int KATE_E_LIMIT = -8;
 33+ public static final int KATE_E_VERSION = -9;
 34+ public static final int KATE_E_NOT_KATE = -10;
 35+ public static final int KATE_E_BAD_TAG = -11;
 36+}
Index: trunk/cortado/src/com/fluendo/jkate/Color.java
@@ -0,0 +1,29 @@
 2+/* JKate
 3+ * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 4+ *
 5+ * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com>
 6+ *
 7+ * This program is free software; you can redistribute it and/or
 8+ * modify it under the terms of the GNU Library General Public License
 9+ * as published by the Free Software Foundation; either version 2 of
 10+ * the License, or (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU Library General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU Library General Public
 18+ * License along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20+ */
 21+
 22+package com.fluendo.jkate;
 23+
 24+public class Color
 25+{
 26+ public byte r;
 27+ public byte g;
 28+ public byte b;
 29+ public byte a;
 30+}
Index: trunk/cortado/src/com/fluendo/jkate/State.java
@@ -0,0 +1,127 @@
 2+/* JKate
 3+ * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 4+ *
 5+ * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com>
 6+ *
 7+ * This program is free software; you can redistribute it and/or
 8+ * modify it under the terms of the GNU Library General Public License
 9+ * as published by the Free Software Foundation; either version 2 of
 10+ * the License, or (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU Library General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU Library General Public
 18+ * License along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20+ */
 21+
 22+package com.fluendo.jkate;
 23+
 24+import com.jcraft.jogg.*;
 25+import com.fluendo.utils.*;
 26+
 27+public class State
 28+{
 29+ long granulepos;
 30+
 31+ private Decode dec;
 32+ private Event ev = null;
 33+
 34+ public void clear()
 35+ {
 36+ }
 37+
 38+ /**
 39+ * Initialize for decoding.
 40+ */
 41+ public int decodeInit(Info ki)
 42+ {
 43+ dec = new Decode(ki);
 44+ granulepos=-1;
 45+
 46+ return(0);
 47+ }
 48+
 49+ /**
 50+ * Decode a Kate data packet.
 51+ * Headers are supposed to have been parsed already.
 52+ * An event may be generated, and will then be available from decodeEventOut.
 53+ */
 54+ public int decodePacketin (Packet op)
 55+ {
 56+ long ret;
 57+ byte type;
 58+
 59+ ev = null;
 60+
 61+ dec.opb.readinit(op.packet_base, op.packet, op.bytes);
 62+
 63+ /* get packet type */
 64+ type = (byte)dec.opb.read(8);
 65+
 66+ /* ignore headers */
 67+ if ((type & 0x80) != 0)
 68+ return 0;
 69+
 70+ switch (type) {
 71+ case 0x00:
 72+ ev = new Event(dec.info);
 73+ ret = dec.decodeTextPacket(ev);
 74+
 75+ if(ret < 0) {
 76+ ev = null;
 77+ return (int) ret;
 78+ }
 79+
 80+ if(op.granulepos>-1)
 81+ granulepos=op.granulepos;
 82+ else{
 83+ if(granulepos==-1){
 84+ granulepos=0;
 85+ }
 86+ }
 87+
 88+ return 0;
 89+
 90+ case 0x01:
 91+ /* keepalive */
 92+ return 0;
 93+
 94+ case 0x7f:
 95+ /* eos */
 96+ return 1;
 97+
 98+ default:
 99+ Debug.debug("Kate packet type "+type+" ignored");
 100+ return 0;
 101+ }
 102+ }
 103+
 104+ /**
 105+ * Returns the event (if any) generated from the last decoded packet.
 106+ */
 107+ public Event decodeEventOut ()
 108+ {
 109+ return ev;
 110+ }
 111+
 112+ /**
 113+ * Returns, in seconds, absolute time of current packet in given
 114+ * logical stream
 115+ */
 116+ public double granuleTime(long granulepos)
 117+ {
 118+ return dec.granuleTime(granulepos);
 119+ }
 120+
 121+ /**
 122+ * Returns, in seconds, duration in granule units
 123+ */
 124+ public double granuleDuration(long granulepos)
 125+ {
 126+ return dec.granuleDuration(granulepos);
 127+ }
 128+}
Index: trunk/cortado/src/com/fluendo/jkate/KateMotionSemantics.java
@@ -0,0 +1,119 @@
 2+/* JKate
 3+ * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 4+ *
 5+ * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com>
 6+ *
 7+ * This program is free software; you can redistribute it and/or
 8+ * modify it under the terms of the GNU Library General Public License
 9+ * as published by the Free Software Foundation; either version 2 of
 10+ * the License, or (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU Library General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU Library General Public
 18+ * License along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20+ */
 21+
 22+package com.fluendo.jkate;
 23+
 24+public class KateMotionSemantics {
 25+ public static final KateMotionSemantics kms_time = new KateMotionSemantics ();
 26+ public static final KateMotionSemantics kms_z = new KateMotionSemantics ();
 27+ public static final KateMotionSemantics kms_region_position = new KateMotionSemantics ();
 28+ public static final KateMotionSemantics kms_region_size = new KateMotionSemantics ();
 29+ public static final KateMotionSemantics kms_text_alignment_int = new KateMotionSemantics ();
 30+ public static final KateMotionSemantics kms_text_alignment_ext = new KateMotionSemantics ();
 31+ public static final KateMotionSemantics kms_text_position = new KateMotionSemantics ();
 32+ public static final KateMotionSemantics kms_text_size = new KateMotionSemantics ();
 33+ public static final KateMotionSemantics kms_marker1_position = new KateMotionSemantics ();
 34+ public static final KateMotionSemantics kms_marker2_position = new KateMotionSemantics ();
 35+ public static final KateMotionSemantics kms_marker3_position = new KateMotionSemantics ();
 36+ public static final KateMotionSemantics kms_marker4_position = new KateMotionSemantics ();
 37+ public static final KateMotionSemantics kms_glyph_pointer_1 = new KateMotionSemantics ();
 38+ public static final KateMotionSemantics kms_glyph_pointer_2 = new KateMotionSemantics ();
 39+ public static final KateMotionSemantics kms_glyph_pointer_3 = new KateMotionSemantics ();
 40+ public static final KateMotionSemantics kms_glyph_pointer_4 = new KateMotionSemantics ();
 41+ public static final KateMotionSemantics kms_text_color_rg = new KateMotionSemantics ();
 42+ public static final KateMotionSemantics kms_text_color_ba = new KateMotionSemantics ();
 43+ public static final KateMotionSemantics kms_background_color_rg = new KateMotionSemantics ();
 44+ public static final KateMotionSemantics kms_background_color_ba = new KateMotionSemantics ();
 45+ public static final KateMotionSemantics kms_draw_color_rg = new KateMotionSemantics ();
 46+ public static final KateMotionSemantics kms_draw_color_ba = new KateMotionSemantics ();
 47+ public static final KateMotionSemantics kms_style_morph = new KateMotionSemantics ();
 48+ public static final KateMotionSemantics kms_text_path = new KateMotionSemantics ();
 49+ public static final KateMotionSemantics kms_text_path_section = new KateMotionSemantics ();
 50+ public static final KateMotionSemantics kms_draw = new KateMotionSemantics ();
 51+ public static final KateMotionSemantics kms_text_visible_section = new KateMotionSemantics ();
 52+ public static final KateMotionSemantics kms_horizontal_margins = new KateMotionSemantics ();
 53+ public static final KateMotionSemantics kms_vertical_margins = new KateMotionSemantics ();
 54+ public static final KateMotionSemantics kms_bitmap_position = new KateMotionSemantics ();
 55+ public static final KateMotionSemantics kms_bitmap_size = new KateMotionSemantics ();
 56+ public static final KateMotionSemantics kms_marker1_bitmap = new KateMotionSemantics ();
 57+ public static final KateMotionSemantics kms_marker2_bitmap = new KateMotionSemantics ();
 58+ public static final KateMotionSemantics kms_marker3_bitmap = new KateMotionSemantics ();
 59+ public static final KateMotionSemantics kms_marker4_bitmap = new KateMotionSemantics ();
 60+ public static final KateMotionSemantics kms_glyph_pointer_1_bitmap = new KateMotionSemantics ();
 61+ public static final KateMotionSemantics kms_glyph_pointer_2_bitmap = new KateMotionSemantics ();
 62+ public static final KateMotionSemantics kms_glyph_pointer_3_bitmap = new KateMotionSemantics ();
 63+ public static final KateMotionSemantics kms_glyph_pointer_4_bitmap = new KateMotionSemantics ();
 64+ public static final KateMotionSemantics kms_draw_width = new KateMotionSemantics ();
 65+
 66+ private static final KateMotionSemantics[] list = {
 67+ kms_time,
 68+ kms_z,
 69+ kms_region_position,
 70+ kms_region_size,
 71+ kms_text_alignment_int,
 72+ kms_text_alignment_ext,
 73+ kms_text_position,
 74+ kms_text_size,
 75+ kms_marker1_position,
 76+ kms_marker2_position,
 77+ kms_marker3_position,
 78+ kms_marker4_position,
 79+ kms_glyph_pointer_1,
 80+ kms_glyph_pointer_2,
 81+ kms_glyph_pointer_3,
 82+ kms_glyph_pointer_4,
 83+ kms_text_color_rg,
 84+ kms_text_color_ba,
 85+ kms_background_color_rg,
 86+ kms_background_color_ba,
 87+ kms_draw_color_rg,
 88+ kms_draw_color_ba,
 89+ kms_style_morph,
 90+ kms_text_path,
 91+ kms_text_path_section,
 92+ kms_draw,
 93+ kms_text_visible_section,
 94+ kms_horizontal_margins,
 95+ kms_vertical_margins,
 96+ kms_bitmap_position,
 97+ kms_bitmap_size,
 98+ kms_marker1_bitmap,
 99+ kms_marker2_bitmap,
 100+ kms_marker3_bitmap,
 101+ kms_marker4_bitmap,
 102+ kms_glyph_pointer_1_bitmap,
 103+ kms_glyph_pointer_2_bitmap,
 104+ kms_glyph_pointer_3_bitmap,
 105+ kms_glyph_pointer_4_bitmap,
 106+ kms_draw_width,
 107+ };
 108+
 109+ private KateMotionSemantics() {
 110+ }
 111+
 112+ /**
 113+ * Create a KateMotionSemantics object from an integer.
 114+ */
 115+ public static KateMotionSemantics CreateMotionSemantics(int idx) throws KateException {
 116+ if (idx < 0 || idx >= list.length)
 117+ throw new KateException("Motion semantics "+idx+" out of bounds");
 118+ return list[idx];
 119+ }
 120+}
Index: trunk/cortado/src/com/fluendo/jkate/Event.java
@@ -0,0 +1,69 @@
 2+/* JKate
 3+ * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 4+ *
 5+ * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com>
 6+ *
 7+ * This program is free software; you can redistribute it and/or
 8+ * modify it under the terms of the GNU Library General Public License
 9+ * as published by the Free Software Foundation; either version 2 of
 10+ * the License, or (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU Library General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU Library General Public
 18+ * License along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20+ */
 21+
 22+package com.fluendo.jkate;
 23+
 24+public class Event
 25+{
 26+ public Info ki = null;
 27+
 28+ public long start;
 29+ public long duration;
 30+ public long backlink;
 31+ public double start_time;
 32+ public double end_time;
 33+
 34+ public int id = -1;
 35+
 36+ public KateTextEncoding text_encoding;
 37+ public KateTextDirectionality text_directionality;
 38+ public KateMarkupType markup_type;
 39+ public byte[] language;
 40+
 41+ public Region kr = null;
 42+ public Style ks = null;
 43+ public Style ks2 = null;
 44+ public Motion motions[] = null;
 45+ public Palette palette = null;
 46+ public Bitmap bitmap = null;
 47+ public FontMapping font_mapping = null;
 48+
 49+ public byte text[];
 50+
 51+ /**
 52+ * Initialize an event to safe defaults.
 53+ */
 54+ public Event(Info ki) {
 55+ this.ki = ki;
 56+ id = -1;
 57+ kr = null;
 58+ ks = null;
 59+ ks2 = null;
 60+ motions = null;
 61+ palette = null;
 62+ bitmap = null;
 63+ text = null;
 64+ font_mapping = null;
 65+ text_encoding = ki.text_encoding;
 66+ text_directionality = ki.text_directionality;
 67+ markup_type = ki.markup_type;
 68+ language = null;
 69+ }
 70+}
Index: trunk/cortado/src/com/fluendo/jkate/RLE.java
@@ -0,0 +1,296 @@
 2+/* JKate
 3+ * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 4+ *
 5+ * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com>
 6+ *
 7+ * This program is free software; you can redistribute it and/or
 8+ * modify it under the terms of the GNU Library General Public License
 9+ * as published by the Free Software Foundation; either version 2 of
 10+ * the License, or (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU Library General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU Library General Public
 18+ * License along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20+ */
 21+
 22+package com.fluendo.jkate;
 23+
 24+import com.jcraft.jogg.*;
 25+
 26+/**
 27+ * RLE decoding routines.
 28+ */
 29+public class RLE
 30+{
 31+ private static final int KATE_RLE_RUN_LENGTH_BITS_BASIC = 4;
 32+ private static final int KATE_RLE_RUN_LENGTH_BITS_BASIC_IN_DELTA = 3;
 33+ private static final int KATE_RLE_RUN_LENGTH_BITS_BASIC_STARTEND = 3;
 34+ private static final int KATE_RLE_RUN_LENGTH_BITS_BASIC_STOP = 6;
 35+ private static final int KATE_RLE_RUN_LENGTH_BITS_DELTA = 6;
 36+ private static final int KATE_RLE_RUN_LENGTH_BITS_BASIC_STARTEND_START = 9;
 37+ private static final int KATE_RLE_RUN_LENGTH_BITS_BASIC_STARTEND_END = 8;
 38+ private static final int KATE_RLE_RUN_LENGTH_BITS_BASIC_STOP_START = 8;
 39+ private static final int KATE_RLE_RUN_LENGTH_BITS_BASIC_IN_DELTA_STOP = 3;
 40+ private static final int KATE_RLE_RUN_LENGTH_BITS_DELTA_STOP = 5;
 41+ private static final int KATE_RLE_RUN_LENGTH_BITS_BASIC_ZERO = 8;
 42+ private static final int KATE_RLE_RUN_LENGTH_BITS_BASIC_NON_ZERO = 3;
 43+
 44+ private static final int KATE_RLE_TYPE_EMPTY = 0;
 45+ private static final int KATE_RLE_TYPE_BASIC = 1;
 46+ private static final int KATE_RLE_TYPE_DELTA = 2;
 47+ private static final int KATE_RLE_TYPE_BASIC_STOP = 3;
 48+ private static final int KATE_RLE_TYPE_BASIC_STARTEND = 4;
 49+ private static final int KATE_RLE_TYPE_DELTA_STOP = 5;
 50+ private static final int KATE_RLE_TYPE_BASIC_ZERO = 6;
 51+
 52+ private static final int KATE_RLE_TYPE_BITS = 3;
 53+
 54+ private static int decodeLineEmpty(Buffer opb, int width, byte pixels[], int offset, int bits, byte zero)
 55+ {
 56+ for (int n=0; n<width; ++n)
 57+ pixels[offset+n] = zero;
 58+ return 0;
 59+ }
 60+
 61+ private static int decodeLineBasic(Buffer opb, int width, byte pixels[], int offset, int bits, byte zero)
 62+ {
 63+ final int run_length_bits = KATE_RLE_RUN_LENGTH_BITS_BASIC;
 64+ int p = 0;
 65+ int count = width;
 66+ while (count > 0) {
 67+ int run_length = 1+opb.read(run_length_bits);
 68+ if (run_length == 0 || run_length > count)
 69+ return -1;
 70+ byte value = (byte)opb.read(bits);
 71+ for (int n=0; n<run_length; ++n)
 72+ pixels[offset+p++] = value;
 73+ count -= run_length;
 74+ }
 75+ return 0;
 76+ }
 77+
 78+ private static int decodeLineDelta(Buffer opb, int width, byte pixels[], int offset, int bits, byte zero)
 79+ {
 80+ final int run_length_delta_bits = KATE_RLE_RUN_LENGTH_BITS_DELTA;
 81+ final int run_length_basic_bits = KATE_RLE_RUN_LENGTH_BITS_BASIC_IN_DELTA;
 82+ int p = 0;
 83+ int count = width;
 84+ while (count > 0) {
 85+ int type = opb.read1();
 86+ if (type != 0) {
 87+ int run_length = 1+opb.read(run_length_delta_bits);
 88+ if (run_length == 0 || run_length > count)
 89+ return -1;
 90+ if (offset > 0) {
 91+ for (int n=0; n<run_length; ++n) {
 92+ pixels[offset+p] = pixels[offset+p-width];
 93+ ++p;
 94+ }
 95+ }
 96+ else {
 97+ for (int n=0; n<run_length; ++n)
 98+ pixels[offset+p++] = zero;
 99+ }
 100+ count -= run_length;
 101+ }
 102+ else {
 103+ int run_length = 1 + opb.read(run_length_basic_bits);
 104+ if (run_length == 0 || run_length > count)
 105+ return -1;
 106+ byte value = (byte)opb.read(bits);
 107+ for (int n=0; n<run_length; ++n)
 108+ pixels[offset+p++] = value;
 109+ count -= run_length;
 110+ }
 111+ }
 112+ return 0;
 113+ }
 114+
 115+ private static int decodeLineBasicStartEnd(Buffer opb, int width, byte pixels[], int offset, int bits, byte zero)
 116+ {
 117+ final int run_length_bits = KATE_RLE_RUN_LENGTH_BITS_BASIC_STARTEND;
 118+ int run_length;
 119+ int count = width;
 120+ int p = 0;
 121+
 122+ run_length = opb.read(KATE_RLE_RUN_LENGTH_BITS_BASIC_STARTEND_START);
 123+ if (run_length > 0) {
 124+ if (run_length > count)
 125+ return -1;
 126+ for (int n=0; n<run_length; ++n)
 127+ pixels[offset+p++] = zero;
 128+ count -= run_length;
 129+ }
 130+
 131+ run_length = opb.read(KATE_RLE_RUN_LENGTH_BITS_BASIC_STARTEND_END);
 132+ if (run_length > 0) {
 133+ if (run_length > count)
 134+ return -1;
 135+ for (int n=0; n<run_length; ++n)
 136+ pixels[offset+width-1-n] = zero;
 137+ count -= run_length;
 138+ }
 139+
 140+ while (count > 0) {
 141+ run_length = 1 + opb.read(run_length_bits);
 142+ if (run_length == 0 || run_length > count)
 143+ return -1;
 144+ byte value = (byte)opb.read(bits);
 145+ for (int n=0; n<run_length; ++n)
 146+ pixels[offset+p++] = value;
 147+ count -= run_length;
 148+ }
 149+
 150+ return 0;
 151+ }
 152+
 153+ private static int decodeLineBasicStop(Buffer opb, int width, byte pixels[], int offset, int bits, byte zero)
 154+ {
 155+ final int run_length_bits = KATE_RLE_RUN_LENGTH_BITS_BASIC_STOP;
 156+ int run_length;
 157+ int count = width;
 158+ int p = 0;
 159+
 160+ run_length = opb.read(KATE_RLE_RUN_LENGTH_BITS_BASIC_STOP_START);
 161+ if (run_length > 0) {
 162+ if (run_length > count)
 163+ return -1;
 164+ for (int n=0; n<run_length; ++n)
 165+ pixels[offset+p++] = zero;
 166+ count -= run_length;
 167+ }
 168+
 169+ while (count > 0) {
 170+ run_length = opb.read(run_length_bits);
 171+ if (run_length > count)
 172+ return -1;
 173+ if (run_length == 0) {
 174+ for (int n=0; n<run_length; ++n)
 175+ pixels[offset+p++] = zero;
 176+ break;
 177+ }
 178+ byte value = (byte)opb.read(bits);
 179+ for (int n=0; n<run_length; ++n)
 180+ pixels[offset+p++] = value;
 181+ count -= run_length;
 182+ }
 183+
 184+ return 0;
 185+ }
 186+
 187+ private static int decodeLineDeltaStop(Buffer opb, int width, byte pixels[], int offset, int bits, byte zero)
 188+ {
 189+ final int run_length_delta_bits = KATE_RLE_RUN_LENGTH_BITS_DELTA_STOP;
 190+ final int run_length_basic_bits = KATE_RLE_RUN_LENGTH_BITS_BASIC_IN_DELTA_STOP;
 191+ int run_length;
 192+ int count = width;
 193+ int p = 0;
 194+
 195+ while (count > 0) {
 196+ int type = opb.read1();
 197+ if (type != 0) {
 198+ run_length = 1 + opb.read(run_length_delta_bits);
 199+ if (run_length == 0 || run_length > count)
 200+ return -1;
 201+ if (offset > 0) {
 202+ for (int n=0; n<run_length; ++n) {
 203+ pixels[offset+p] = pixels[offset+p-width];
 204+ ++p;
 205+ }
 206+ }
 207+ else {
 208+ for (int n=0; n<run_length; ++n)
 209+ pixels[offset+p++] = zero;
 210+ }
 211+ }
 212+ else {
 213+ run_length = opb.read(run_length_basic_bits);
 214+ if (run_length == 0) {
 215+ for (int n=0; n<run_length; ++n)
 216+ pixels[offset+p++] = zero;
 217+ break;
 218+ }
 219+ if (run_length > count)
 220+ return -1;
 221+ byte value = (byte)opb.read(bits);
 222+ for (int n=0; n<run_length; ++n)
 223+ pixels[offset+p++] = value;
 224+ }
 225+ count -= run_length;
 226+ }
 227+
 228+ return 0;
 229+ }
 230+
 231+ private static int decodeLineBasicZero(Buffer opb, int width, byte pixels[], int offset, int bits, byte zero)
 232+ {
 233+ final int run_length_bits_zero = KATE_RLE_RUN_LENGTH_BITS_BASIC_ZERO;
 234+ final int run_length_bits_non_zero = KATE_RLE_RUN_LENGTH_BITS_BASIC_NON_ZERO;
 235+ int run_length;
 236+ int count = width;
 237+ int p = 0;
 238+
 239+ while (count > 0) {
 240+ byte value = (byte)opb.read(bits);
 241+ if (value == zero) {
 242+ run_length = 1 + opb.read(run_length_bits_zero);
 243+ }
 244+ else {
 245+ run_length = 1 + opb.read(run_length_bits_non_zero);
 246+ }
 247+ if (run_length == 0 || run_length > count)
 248+ return -1;
 249+ for (int n=0; n<run_length; ++n)
 250+ pixels[offset+p++] = value;
 251+ count -= run_length;
 252+ }
 253+
 254+ return 0;
 255+ }
 256+
 257+ public static byte[] decodeRLE(Buffer opb, int width, int height, int bpp)
 258+ {
 259+ byte[] pixels = new byte[width*height];
 260+ int offset = 0;
 261+ int ret;
 262+ byte zero = (byte)opb.read(bpp);
 263+ while (height > 0) {
 264+ int type = opb.read(KATE_RLE_TYPE_BITS);
 265+ switch (type) {
 266+ case KATE_RLE_TYPE_EMPTY:
 267+ ret = decodeLineEmpty(opb, width, pixels, offset, bpp, zero);
 268+ break;
 269+ case KATE_RLE_TYPE_DELTA:
 270+ ret = decodeLineDelta(opb, width, pixels, offset, bpp, zero);
 271+ break;
 272+ case KATE_RLE_TYPE_BASIC:
 273+ ret = decodeLineBasic(opb, width, pixels, offset, bpp, zero);
 274+ break;
 275+ case KATE_RLE_TYPE_BASIC_STARTEND:
 276+ ret = decodeLineBasicStartEnd(opb, width, pixels, offset, bpp, zero);
 277+ break;
 278+ case KATE_RLE_TYPE_BASIC_STOP:
 279+ ret = decodeLineBasicStop(opb, width, pixels, offset, bpp, zero);
 280+ break;
 281+ case KATE_RLE_TYPE_DELTA_STOP:
 282+ ret = decodeLineDeltaStop(opb, width, pixels, offset, bpp, zero);
 283+ break;
 284+ case KATE_RLE_TYPE_BASIC_ZERO:
 285+ ret = decodeLineBasicZero(opb, width, pixels, offset, bpp, zero);
 286+ break;
 287+ default:
 288+ return null;
 289+ }
 290+ if (ret != 0)
 291+ return null;
 292+ offset += width;
 293+ --height;
 294+ }
 295+ return pixels;
 296+ }
 297+}
Index: trunk/cortado/src/com/fluendo/jkate/FontMapping.java
@@ -0,0 +1,29 @@
 2+/* JKate
 3+ * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 4+ *
 5+ * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com>
 6+ *
 7+ * This program is free software; you can redistribute it and/or
 8+ * modify it under the terms of the GNU Library General Public License
 9+ * as published by the Free Software Foundation; either version 2 of
 10+ * the License, or (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU Library General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU Library General Public
 18+ * License along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20+ */
 21+
 22+package com.fluendo.jkate;
 23+
 24+/**
 25+ * A set of ranges defining a mapping from code points to bitmaps.
 26+ */
 27+class FontMapping
 28+{
 29+ FontRange ranges[];
 30+}
Index: trunk/cortado/src/com/fluendo/jkate/Region.java
@@ -0,0 +1,35 @@
 2+/* JKate
 3+ * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 4+ *
 5+ * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com>
 6+ *
 7+ * This program is free software; you can redistribute it and/or
 8+ * modify it under the terms of the GNU Library General Public License
 9+ * as published by the Free Software Foundation; either version 2 of
 10+ * the License, or (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU Library General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU Library General Public
 18+ * License along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20+ */
 21+
 22+package com.fluendo.jkate;
 23+
 24+/**
 25+ * A region definition, for placement of text/images.
 26+ */
 27+public class Region
 28+{
 29+ public KateSpaceMetric metric;
 30+ public int x;
 31+ public int y;
 32+ public int w;
 33+ public int h;
 34+ public int style;
 35+ public boolean clip;
 36+}
Index: trunk/cortado/src/com/fluendo/jkate/KateWrapMode.java
@@ -0,0 +1,43 @@
 2+/* JKate
 3+ * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 4+ *
 5+ * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com>
 6+ *
 7+ * This program is free software; you can redistribute it and/or
 8+ * modify it under the terms of the GNU Library General Public License
 9+ * as published by the Free Software Foundation; either version 2 of
 10+ * the License, or (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU Library General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU Library General Public
 18+ * License along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20+ */
 21+
 22+package com.fluendo.jkate;
 23+
 24+public class KateWrapMode {
 25+ public static final KateWrapMode kate_wrap_word = new KateWrapMode ();
 26+ public static final KateWrapMode kate_wrap_none = new KateWrapMode ();
 27+
 28+ private static final KateWrapMode[] list = {
 29+ kate_wrap_word,
 30+ kate_wrap_none,
 31+ };
 32+
 33+ private KateWrapMode() {
 34+ }
 35+
 36+ /**
 37+ * Create a KateWrapMode object from an integer.
 38+ */
 39+ public static KateWrapMode CreateWrapMode(int idx) throws KateException {
 40+ if (idx < 0 || idx >= list.length)
 41+ throw new KateException("Wrap mode "+idx+" out of bounds");
 42+ return list[idx];
 43+ }
 44+}
Index: trunk/cortado/src/com/fluendo/jkate/Decode.java
@@ -0,0 +1,238 @@
 2+/* JKate
 3+ * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 4+ *
 5+ * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com>
 6+ *
 7+ * This program is free software; you can redistribute it and/or
 8+ * modify it under the terms of the GNU Library General Public License
 9+ * as published by the Free Software Foundation; either version 2 of
 10+ * the License, or (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU Library General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU Library General Public
 18+ * License along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20+ */
 21+
 22+package com.fluendo.jkate;
 23+
 24+import com.jcraft.jogg.*;
 25+import com.fluendo.utils.*;
 26+
 27+public final class Decode {
 28+
 29+ Buffer opb = new Buffer();
 30+ Info info;
 31+
 32+ public Decode (Info i) {
 33+ info = i;
 34+ }
 35+
 36+ /**
 37+ * Decode a text data packet (packet type 0x00), and fills the passed event
 38+ * from the decoded data.
 39+ */
 40+ int decodeTextPacket(Event ev)
 41+ {
 42+ ev.ki = info;
 43+
 44+ ev.start = Bitwise.read64(opb);
 45+ ev.duration = Bitwise.read64(opb);
 46+ ev.backlink = Bitwise.read64(opb);
 47+
 48+ ev.start_time = granuleDuration(ev.start);
 49+ ev.end_time = ev.start_time+granuleDuration(ev.duration);
 50+
 51+ /* text */
 52+ int len = Bitwise.read32(opb);
 53+ ev.text = new byte[len];
 54+ Bitwise.readbuf(opb, ev.text, len);
 55+
 56+ /* event ID */
 57+ ev.id = -1;
 58+ if (opb.read1() != 0) {
 59+ ev.id = Bitwise.read32v(opb);
 60+ }
 61+
 62+ /* motions */
 63+ ev.motions = null;
 64+ if (opb.read1() != 0) {
 65+ int nmotions = Bitwise.read32v(opb);
 66+ if (nmotions < 0)
 67+ return -1;
 68+ ev.motions = new Motion[nmotions];
 69+ for (int n=0; n<nmotions; ++n) {
 70+ if (opb.read1() != 0) {
 71+ int idx = Bitwise.read32v(opb);
 72+ if (idx < 0 || idx >= info.motions.length)
 73+ return -1;
 74+ ev.motions[n] = info.motions[idx];
 75+ }
 76+ else {
 77+ try {
 78+ ev.motions[n] = info.unpackMotion(opb);
 79+ }
 80+ catch (KateException ke) {
 81+ return Result.KATE_E_BAD_PACKET;
 82+ }
 83+ }
 84+ }
 85+ }
 86+
 87+ /* overrides */
 88+ if (opb.read1() != 0) {
 89+ try {
 90+ if (opb.read1() != 0)
 91+ ev.text_encoding = KateTextEncoding.CreateTextEncoding(opb.read(8));
 92+ if (opb.read1() != 0)
 93+ ev.text_directionality = KateTextDirectionality.CreateTextDirectionality(opb.read(8));
 94+ }
 95+ catch (KateException ke) {
 96+ return Result.KATE_E_BAD_PACKET;
 97+ }
 98+
 99+ /* language override */
 100+ if (opb.read1() != 0) {
 101+ int nbytes = Bitwise.read32v(opb);
 102+ if (nbytes < 0)
 103+ return Result.KATE_E_BAD_PACKET;
 104+ if (nbytes > 0) {
 105+ ev.language=new byte[nbytes];
 106+ Bitwise.readbuf(opb, ev.language, nbytes);
 107+ }
 108+ }
 109+
 110+ /* region override */
 111+ if (opb.read1() != 0) {
 112+ int idx = Bitwise.read32v(opb);
 113+ if (idx < 0 || idx >= info.regions.length)
 114+ return Result.KATE_E_BAD_PACKET;
 115+ ev.kr = info.regions[idx];
 116+ }
 117+ if (opb.read1() != 0) {
 118+ try {
 119+ ev.kr = info.unpackRegion(opb);
 120+ }
 121+ catch (KateException ke) {
 122+ return Result.KATE_E_BAD_PACKET;
 123+ }
 124+ }
 125+
 126+ /* style override */
 127+ if (opb.read1() != 0) {
 128+ int idx = Bitwise.read32v(opb);
 129+ if (idx < 0 || idx >= info.styles.length)
 130+ return Result.KATE_E_BAD_PACKET;
 131+ ev.ks = info.styles[idx];
 132+ }
 133+ if (opb.read1() != 0) {
 134+ try {
 135+ ev.ks = info.unpackStyle(opb);
 136+ }
 137+ catch (KateException ke) {
 138+ return Result.KATE_E_BAD_PACKET;
 139+ }
 140+ }
 141+ if (opb.read1() != 0) {
 142+ int idx = Bitwise.read32v(opb);
 143+ if (idx < 0 || idx >= info.styles.length)
 144+ return Result.KATE_E_BAD_PACKET;
 145+ ev.ks2 = info.styles[idx];
 146+ }
 147+ if (opb.read1() != 0) {
 148+ try {
 149+ ev.ks2 = info.unpackStyle(opb);
 150+ }
 151+ catch (KateException ke) {
 152+ return Result.KATE_E_BAD_PACKET;
 153+ }
 154+ }
 155+
 156+ /* font mapping */
 157+ if (opb.read1() != 0) {
 158+ int idx = Bitwise.read32v(opb);
 159+ if (idx < 0 || idx >= info.font_mappings.length)
 160+ return Result.KATE_E_BAD_PACKET;
 161+ ev.font_mapping = info.font_mappings[idx];
 162+ }
 163+ }
 164+
 165+ /* new in 0.2: palettes/bitmaps/markup type */
 166+ if (((info.bitstream_version_major<<8) | info.bitstream_version_minor) >= 0x0002) {
 167+ Bitwise.read32v(opb);
 168+ if (opb.read1() != 0) {
 169+ if (opb.read1() != 0) {
 170+ int idx = Bitwise.read32v(opb);
 171+ if (idx < 0 || idx >= info.palettes.length)
 172+ return Result.KATE_E_BAD_PACKET;
 173+ ev.palette = info.palettes[idx];
 174+ }
 175+ if (opb.read1() != 0) {
 176+ try {
 177+ ev.palette = info.unpackPalette(opb);
 178+ }
 179+ catch (KateException e) {
 180+ return Result.KATE_E_BAD_PACKET;
 181+ }
 182+ }
 183+ if (opb.read1() != 0) {
 184+ int idx = Bitwise.read32v(opb);
 185+ if (idx < 0 || idx >= info.bitmaps.length)
 186+ return Result.KATE_E_BAD_PACKET;
 187+ ev.bitmap = info.bitmaps[idx];
 188+ }
 189+ if (opb.read1() != 0) {
 190+ try {
 191+ ev.bitmap = info.unpackBitmap(opb);
 192+ }
 193+ catch (KateException e) {
 194+ return Result.KATE_E_BAD_PACKET;
 195+ }
 196+ }
 197+ if (opb.read1() != 0) {
 198+ try {
 199+ ev.markup_type = KateMarkupType.CreateMarkupType(opb.read(8));
 200+ }
 201+ catch (KateException e) {
 202+ return Result.KATE_E_BAD_PACKET;
 203+ }
 204+ }
 205+ }
 206+ }
 207+
 208+// TODO: remainder
 209+ return 0;
 210+ }
 211+
 212+ /**
 213+ * Convert a granule to a time.
 214+ */
 215+ public double granuleTime(long granulepos)
 216+ {
 217+ if(granulepos>=0){
 218+ long base=granulepos>>info.granule_shift;
 219+ long offset=granulepos-(base<<info.granule_shift);
 220+
 221+ return (base+offset)*
 222+ ((double)info.gps_denominator/info.gps_numerator);
 223+ }
 224+ return(-1);
 225+ }
 226+
 227+ /**
 228+ * Convert a time in granule units to a duration.
 229+ */
 230+ public double granuleDuration(long granule)
 231+ {
 232+ if(granule>=0){
 233+ return (granule)*
 234+ ((double)info.gps_denominator/info.gps_numerator);
 235+ }
 236+ return(-1);
 237+ }
 238+
 239+}
Index: trunk/cortado/src/com/fluendo/jkate/FontRange.java
@@ -0,0 +1,32 @@
 2+/* JKate
 3+ * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 4+ *
 5+ * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com>
 6+ *
 7+ * This program is free software; you can redistribute it and/or
 8+ * modify it under the terms of the GNU Library General Public License
 9+ * as published by the Free Software Foundation; either version 2 of
 10+ * the License, or (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU Library General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU Library General Public
 18+ * License along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20+ */
 21+
 22+package com.fluendo.jkate;
 23+
 24+/**
 25+ * A code point range mapping to a set of bitmaps.
 26+ */
 27+public class FontRange
 28+{
 29+ int first_code_point;
 30+ int last_code_point;
 31+ int first_bitmap;
 32+}
 33+
Index: trunk/cortado/src/com/fluendo/jkate/KateBitmapType.java
@@ -0,0 +1,43 @@
 2+/* JKate
 3+ * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 4+ *
 5+ * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com>
 6+ *
 7+ * This program is free software; you can redistribute it and/or
 8+ * modify it under the terms of the GNU Library General Public License
 9+ * as published by the Free Software Foundation; either version 2 of
 10+ * the License, or (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU Library General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU Library General Public
 18+ * License along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20+ */
 21+
 22+package com.fluendo.jkate;
 23+
 24+public class KateBitmapType {
 25+ public static final KateBitmapType kate_bitmap_type_paletted = new KateBitmapType ();
 26+ public static final KateBitmapType kate_bitmap_type_png = new KateBitmapType ();
 27+
 28+ private static final KateBitmapType[] list = {
 29+ kate_bitmap_type_paletted,
 30+ kate_bitmap_type_png,
 31+ };
 32+
 33+ private KateBitmapType() {
 34+ }
 35+
 36+ /**
 37+ * Create a KateBitmapType object from an integer.
 38+ */
 39+ public static KateBitmapType CreateBitmapType(int idx) throws KateException {
 40+ if (idx < 0 || idx >= list.length)
 41+ throw new KateException("Bitmap type "+idx+" out of bounds");
 42+ return list[idx];
 43+ }
 44+}
Index: trunk/cortado/src/com/fluendo/jkate/Curve.java
@@ -0,0 +1,31 @@
 2+/* JKate
 3+ * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 4+ *
 5+ * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com>
 6+ *
 7+ * This program is free software; you can redistribute it and/or
 8+ * modify it under the terms of the GNU Library General Public License
 9+ * as published by the Free Software Foundation; either version 2 of
 10+ * the License, or (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU Library General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU Library General Public
 18+ * License along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20+ */
 21+
 22+package com.fluendo.jkate;
 23+
 24+/**
 25+ * A curve definition, splines, segments, etc.
 26+ */
 27+public class Curve
 28+{
 29+ public KateCurveType type;
 30+ public int npts;
 31+ public double pts[][];
 32+}
Index: trunk/cortado/src/com/fluendo/jkate/KateMotionMapping.java
@@ -0,0 +1,51 @@
 2+/* JKate
 3+ * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 4+ *
 5+ * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com>
 6+ *
 7+ * This program is free software; you can redistribute it and/or
 8+ * modify it under the terms of the GNU Library General Public License
 9+ * as published by the Free Software Foundation; either version 2 of
 10+ * the License, or (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU Library General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU Library General Public
 18+ * License along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20+ */
 21+
 22+package com.fluendo.jkate;
 23+
 24+public class KateMotionMapping {
 25+ public static final KateMotionMapping kmm_none = new KateMotionMapping ();
 26+ public static final KateMotionMapping kmm_frame = new KateMotionMapping ();
 27+ public static final KateMotionMapping kmm_window = new KateMotionMapping ();
 28+ public static final KateMotionMapping kmm_region = new KateMotionMapping ();
 29+ public static final KateMotionMapping kmm_event_duration = new KateMotionMapping ();
 30+ public static final KateMotionMapping kmm_bitmap_size = new KateMotionMapping ();
 31+
 32+ private static final KateMotionMapping[] list = {
 33+ kmm_none,
 34+ kmm_frame,
 35+ kmm_window,
 36+ kmm_region,
 37+ kmm_event_duration,
 38+ kmm_bitmap_size,
 39+ };
 40+
 41+ private KateMotionMapping() {
 42+ }
 43+
 44+ /**
 45+ * Create a KateMotionMapping object from an integer.
 46+ */
 47+ public static KateMotionMapping CreateMotionMapping(int idx) throws KateException {
 48+ if (idx < 0 || idx >= list.length)
 49+ throw new KateException("Motion mapping "+idx+" out of bounds");
 50+ return list[idx];
 51+ }
 52+}
Index: trunk/cortado/src/com/fluendo/jkate/KateCurveType.java
@@ -0,0 +1,51 @@
 2+/* JKate
 3+ * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 4+ *
 5+ * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com>
 6+ *
 7+ * This program is free software; you can redistribute it and/or
 8+ * modify it under the terms of the GNU Library General Public License
 9+ * as published by the Free Software Foundation; either version 2 of
 10+ * the License, or (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU Library General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU Library General Public
 18+ * License along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20+ */
 21+
 22+package com.fluendo.jkate;
 23+
 24+public class KateCurveType {
 25+ public static final KateCurveType kate_curve_none = new KateCurveType ();
 26+ public static final KateCurveType kate_curve_static = new KateCurveType ();
 27+ public static final KateCurveType kate_curve_linear = new KateCurveType ();
 28+ public static final KateCurveType kate_curve_catmull_rom_spline = new KateCurveType ();
 29+ public static final KateCurveType kate_curve_bezier_cubic_spline = new KateCurveType ();
 30+ public static final KateCurveType kate_curve_bspline = new KateCurveType ();
 31+
 32+ private static final KateCurveType[] list = {
 33+ kate_curve_none,
 34+ kate_curve_static,
 35+ kate_curve_linear,
 36+ kate_curve_catmull_rom_spline,
 37+ kate_curve_bezier_cubic_spline,
 38+ kate_curve_bspline,
 39+ };
 40+
 41+ private KateCurveType() {
 42+ }
 43+
 44+ /**
 45+ * Create a KateCurveType object from an integer.
 46+ */
 47+ public static KateCurveType CreateCurveType(int idx) throws KateException {
 48+ if (idx < 0 || idx >= list.length)
 49+ throw new KateException("Curve type "+idx+" out of bounds");
 50+ return list[idx];
 51+ }
 52+}
Index: trunk/cortado/src/com/fluendo/jkate/Info.java
@@ -0,0 +1,742 @@
 2+/* JKate
 3+ * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 4+ *
 5+ * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com>
 6+ *
 7+ * This program is free software; you can redistribute it and/or
 8+ * modify it under the terms of the GNU Library General Public License
 9+ * as published by the Free Software Foundation; either version 2 of
 10+ * the License, or (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU Library General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU Library General Public
 18+ * License along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20+ */
 21+
 22+package com.fluendo.jkate;
 23+
 24+import com.jcraft.jogg.*;
 25+import com.fluendo.utils.*;
 26+
 27+public class Info {
 28+ public int bitstream_version_major = -1;
 29+ public int bitstream_version_minor = -1;
 30+ public KateTextEncoding text_encoding;
 31+ public KateTextDirectionality text_directionality;
 32+ public int num_headers = 0;
 33+ public int granule_shift;
 34+ public int gps_numerator;
 35+ public int gps_denominator;
 36+ public byte language[];
 37+ public byte category[];
 38+ public Region regions[];
 39+ public Style styles[];
 40+ public Curve curves[];
 41+ public Motion motions[];
 42+ public Palette palettes[];
 43+ public Bitmap bitmaps[];
 44+ public FontRange font_ranges[];
 45+ public FontMapping font_mappings[];
 46+
 47+ public KateMarkupType markup_type;
 48+ public int original_canvas_width;
 49+ public int original_canvas_height;
 50+
 51+ /* used to track which header we need to decode next */
 52+ private int probe = 0;
 53+
 54+ /**
 55+ * Read a packet canvas size (width or height).
 56+ * Format defined in the Kate specification.
 57+ */
 58+ private static int read_canvas_size(Buffer opb)
 59+ {
 60+ int value, base, shift;
 61+
 62+ value = opb.read(8) | (opb.read(8)<<8);
 63+ base = value>>4;
 64+ shift = value&15;
 65+ return base<<shift;
 66+ }
 67+
 68+ /**
 69+ * Decodes a Kate info header packet and fills the class data with
 70+ * what was found in it.
 71+ */
 72+ private int unpackInfo(Buffer opb){
 73+ int reserved, tmp;
 74+
 75+ bitstream_version_major = (byte)opb.read(8);
 76+ bitstream_version_minor = (byte)opb.read(8);
 77+ Debug.info("Kate bitstream v"+bitstream_version_major+"."+bitstream_version_minor);
 78+
 79+ if (bitstream_version_major > 0)
 80+ return Result.KATE_E_VERSION;
 81+
 82+ num_headers = (int)opb.read(8);
 83+ if (num_headers < 1)
 84+ return Result.KATE_E_BAD_PACKET;
 85+ tmp = opb.read(8);
 86+ if (tmp != 0)
 87+ return Result.KATE_E_BAD_PACKET;
 88+ try {
 89+ text_encoding = KateTextEncoding.CreateTextEncoding(tmp);
 90+ text_directionality = KateTextDirectionality.CreateTextDirectionality(opb.read(8));
 91+ }
 92+ catch (KateException e) {
 93+ return Result.KATE_E_BAD_PACKET;
 94+ }
 95+ reserved = opb.read(8);
 96+ if (bitstream_version_major==0 && bitstream_version_minor<3) {
 97+ if (reserved != 0)
 98+ return Result.KATE_E_BAD_PACKET;
 99+ }
 100+ granule_shift = opb.read(8);
 101+
 102+ original_canvas_width = read_canvas_size(opb);
 103+ original_canvas_height = read_canvas_size(opb);
 104+
 105+ reserved = Bitwise.read32(opb);
 106+ if (bitstream_version_major==0 && bitstream_version_minor<3) {
 107+ if (reserved != 0)
 108+ return Result.KATE_E_BAD_PACKET;
 109+ }
 110+
 111+ gps_numerator = Bitwise.read32(opb);
 112+ gps_denominator = Bitwise.read32(opb);
 113+
 114+ if (granule_shift >= 64)
 115+ return Result.KATE_E_BAD_PACKET;
 116+ if (gps_numerator == 0 || gps_denominator == 0)
 117+ return Result.KATE_E_BAD_PACKET;
 118+
 119+ language=new byte[16];
 120+ Bitwise.readbuf(opb, language, 16);
 121+ if (language[15] != 0)
 122+ return Result.KATE_E_BAD_PACKET;
 123+
 124+ category=new byte[16];
 125+ Bitwise.readbuf(opb, category, 16);
 126+ if (category[15] != 0)
 127+ return Result.KATE_E_BAD_PACKET;
 128+
 129+ /* end of packet */
 130+ if (opb.read(1) != -1)
 131+ return (Result.KATE_E_BAD_PACKET);
 132+
 133+ return(0);
 134+ }
 135+
 136+ /**
 137+ * Checks that we have reached the end of the packet.
 138+ */
 139+ static int checkEOP(Buffer opb) {
 140+ int bits = 7 & (8 - (opb.bits()&7));
 141+ if (bits > 0) {
 142+ if (opb.read(bits) != 0)
 143+ return Result.KATE_E_BAD_PACKET;
 144+ }
 145+ if (opb.look1() != -1)
 146+ return (Result.KATE_E_BAD_PACKET);
 147+ return 0;
 148+ }
 149+
 150+ /**
 151+ * Decodes a Vorbis comment packet.
 152+ * straight copy of the jheora one
 153+ */
 154+ private int unpackComment (Comment kc, Buffer opb)
 155+ {
 156+ int i;
 157+ int len;
 158+ byte[] tmp;
 159+ int comments;
 160+
 161+ len = Bitwise.read32(opb);
 162+ if(len<0)
 163+ return(Result.KATE_E_BAD_PACKET);
 164+
 165+ tmp=new byte[len];
 166+ Bitwise.readbuf(opb, tmp, len);
 167+ kc.vendor=new String(tmp);
 168+
 169+ comments = Bitwise.read32(opb);
 170+ if(comments<0) {
 171+ kc.clear();
 172+ return Result.KATE_E_BAD_PACKET;
 173+ }
 174+ kc.user_comments=new String[comments];
 175+ for(i=0;i<comments;i++){
 176+ len = Bitwise.read32(opb);
 177+ if(len<0) {
 178+ kc.clear();
 179+ return Result.KATE_E_BAD_PACKET;
 180+ }
 181+
 182+ tmp=new byte[len];
 183+ Bitwise.readbuf(opb,tmp,len);
 184+ kc.user_comments[i]=new String(tmp);
 185+ }
 186+ return 0;
 187+ }
 188+
 189+ /**
 190+ * Decode a single region.
 191+ */
 192+ public Region unpackRegion (Buffer opb) throws KateException
 193+ {
 194+ Region kr = new Region();
 195+
 196+ kr.metric = KateSpaceMetric.CreateSpaceMetric(opb.read(8));
 197+ kr.x = Bitwise.read32v(opb);
 198+ kr.y = Bitwise.read32v(opb);
 199+ kr.w = Bitwise.read32v(opb);
 200+ kr.h = Bitwise.read32v(opb);
 201+ kr.style = Bitwise.read32v(opb);
 202+
 203+ if (((bitstream_version_major<<8) | bitstream_version_minor) >= 0x0002) {
 204+ Bitwise.read32v(opb);
 205+ kr.clip = (opb.read1() != 0);
 206+ }
 207+ else {
 208+ kr.clip = false;
 209+ }
 210+
 211+ Bitwise.skipWarp(opb);
 212+
 213+ return kr;
 214+ }
 215+
 216+ /**
 217+ * Decode the regions header packet.
 218+ */
 219+ private int unpackRegions (Buffer opb)
 220+ {
 221+ int nregions = Bitwise.read32v(opb);
 222+ if (nregions < 0) return Result.KATE_E_BAD_PACKET;
 223+ regions = new Region[nregions];
 224+ for (int n=0; n<nregions; ++n) {
 225+ try {
 226+ regions[n] = unpackRegion(opb);
 227+ }
 228+ catch (KateException ke) {
 229+ regions = null;
 230+ return Result.KATE_E_BAD_PACKET;
 231+ }
 232+ }
 233+
 234+ Bitwise.skipWarp(opb);
 235+
 236+ /* end of packet */
 237+ return checkEOP(opb);
 238+ }
 239+
 240+ /**
 241+ * Decode a color.
 242+ */
 243+ private Color unpackColor (Buffer opb)
 244+ {
 245+ Color color = new Color();
 246+ color.r = (byte)opb.read(8);
 247+ color.g = (byte)opb.read(8);
 248+ color.b = (byte)opb.read(8);
 249+ color.a = (byte)opb.read(8);
 250+ return color;
 251+ }
 252+
 253+ /**
 254+ * Decode a single style.
 255+ */
 256+ public Style unpackStyle (Buffer opb) throws KateException
 257+ {
 258+ Style ks = new Style();
 259+
 260+ double floats[][] = Bitwise.readFloats(opb, 8, 1);
 261+ int idx = 0;
 262+ ks.halign = floats[0][idx++];
 263+ ks.valign = floats[0][idx++];
 264+ ks.font_width = floats[0][idx++];
 265+ ks.font_height = floats[0][idx++];
 266+ ks.left_margin = floats[0][idx++];
 267+ ks.top_margin = floats[0][idx++];
 268+ ks.right_margin = floats[0][idx++];
 269+ ks.bottom_margin = floats[0][idx++];
 270+ ks.text_color = unpackColor(opb);
 271+ ks.background_color = unpackColor(opb);
 272+ ks.draw_color = unpackColor(opb);
 273+ ks.font_metric = KateSpaceMetric.CreateSpaceMetric(opb.read(8));
 274+ ks.margin_metric = KateSpaceMetric.CreateSpaceMetric(opb.read(8));
 275+ ks.bold = opb.read1() != 0;
 276+ ks.italics = opb.read1() != 0;
 277+ ks.underline = opb.read1() != 0;
 278+ ks.strike = opb.read1() != 0;
 279+
 280+ if (((bitstream_version_major<<8) | bitstream_version_minor) >= 0x0002) {
 281+ Bitwise.read32v(opb);
 282+ ks.justify = opb.read1() != 0;
 283+ int len = Bitwise.read32v(opb);
 284+ if (len < 0)
 285+ throw new KateBadPacketException();
 286+ byte s[] = new byte[len];
 287+ Bitwise.readbuf(opb, s, len);
 288+ ks.font = new String(s);
 289+ }
 290+ else {
 291+ ks.justify = false;
 292+ ks.font = null;
 293+ }
 294+
 295+ if (((bitstream_version_major<<8) | bitstream_version_minor) >= 0x0004) {
 296+ Bitwise.read32v(opb);
 297+ ks.wrap_mode = KateWrapMode.CreateWrapMode(Bitwise.read32v(opb));
 298+ }
 299+ else {
 300+ ks.wrap_mode = KateWrapMode.kate_wrap_word;
 301+ }
 302+
 303+ Bitwise.skipWarp(opb);
 304+
 305+ return ks;
 306+ }
 307+
 308+ /**
 309+ * Decode the styles header packet.
 310+ */
 311+ private int unpackStyles (Buffer opb)
 312+ {
 313+ int nstyles = Bitwise.read32v(opb);
 314+ if (nstyles < 0) return Result.KATE_E_BAD_PACKET;
 315+ styles = new Style[nstyles];
 316+ for (int n=0; n<nstyles; ++n) {
 317+ try {
 318+ styles[n] = unpackStyle(opb);
 319+ }
 320+ catch (KateException ke) {
 321+ styles = null;
 322+ return Result.KATE_E_BAD_PACKET;
 323+ }
 324+ }
 325+
 326+ Bitwise.skipWarp(opb);
 327+
 328+ /* end of packet */
 329+ return checkEOP(opb);
 330+ }
 331+
 332+ /**
 333+ * Decode a single curve.
 334+ */
 335+ private Curve unpackCurve (Buffer opb) throws KateException
 336+ {
 337+ Curve kc = new Curve();
 338+
 339+ kc.type = KateCurveType.CreateCurveType(opb.read(8));
 340+ kc.npts = Bitwise.read32v(opb);
 341+ if (kc.npts < 0)
 342+ throw new KateBadPacketException();
 343+ Bitwise.skipWarp(opb);
 344+
 345+ kc.pts = Bitwise.readFloats(opb, kc.npts, 2);
 346+
 347+ return kc;
 348+ }
 349+
 350+ /**
 351+ * Decode the curves header packet.
 352+ */
 353+ private int unpackCurves (Buffer opb)
 354+ {
 355+ int ncurves = Bitwise.read32v(opb);
 356+ if (ncurves < 0) return Result.KATE_E_BAD_PACKET;
 357+ curves = new Curve[ncurves];
 358+ for (int n=0; n<ncurves; ++n) {
 359+ try {
 360+ curves[n] = unpackCurve(opb);
 361+ }
 362+ catch (KateException ke) {
 363+ curves = null;
 364+ return Result.KATE_E_BAD_PACKET;
 365+ }
 366+ }
 367+
 368+ Bitwise.skipWarp(opb);
 369+
 370+ /* end of packet */
 371+ return checkEOP(opb);
 372+ }
 373+
 374+ /**
 375+ * Decode a single motion.
 376+ */
 377+ public Motion unpackMotion (Buffer opb) throws KateException
 378+ {
 379+ Motion km = new Motion();
 380+
 381+ int ncurves = Bitwise.read32v(opb);
 382+ if (ncurves < 0)
 383+ throw new KateBadPacketException();
 384+ km.curves = new Curve[ncurves];
 385+ for (int n=0; n<ncurves; ++n) {
 386+ if (opb.read1() != 0) {
 387+ int idx = Bitwise.read32v(opb);
 388+ if (idx < 0 || idx >= this.curves.length)
 389+ throw new KateBadPacketException();
 390+ km.curves[n] = this.curves[idx];
 391+ }
 392+ else {
 393+ km.curves[n] = unpackCurve(opb);
 394+ }
 395+ }
 396+
 397+ double floats[][] = Bitwise.readFloats(opb, ncurves, 1);
 398+ km.durations = new double[ncurves];
 399+ for (int n=0; n<ncurves; ++n) {
 400+ km.durations[n] = floats[0][n];
 401+ }
 402+
 403+ km.x_mapping = KateMotionMapping.CreateMotionMapping(opb.read(8));
 404+ km.y_mapping = KateMotionMapping.CreateMotionMapping(opb.read(8));
 405+ km.semantics = KateMotionSemantics.CreateMotionSemantics(opb.read(8));
 406+ km.periodic = (opb.read1() != 0);
 407+
 408+ Bitwise.skipWarp(opb);
 409+
 410+ return km;
 411+ }
 412+
 413+ /**
 414+ * Decode the motions header packet.
 415+ */
 416+ private int unpackMotions (Buffer opb)
 417+ {
 418+ int nmotions = Bitwise.read32v(opb);
 419+ if (nmotions < 0) return Result.KATE_E_BAD_PACKET;
 420+ motions = new Motion[nmotions];
 421+ for (int n=0; n<nmotions; ++n) {
 422+ try {
 423+ motions[n] = unpackMotion(opb);
 424+ }
 425+ catch (KateException ke) {
 426+ motions = null;
 427+ return Result.KATE_E_BAD_PACKET;
 428+ }
 429+ }
 430+
 431+ Bitwise.skipWarp(opb);
 432+
 433+ /* end of packet */
 434+ return checkEOP(opb);
 435+ }
 436+
 437+ /**
 438+ * Decode a single palette.
 439+ */
 440+ public Palette unpackPalette (Buffer opb) throws KateException
 441+ {
 442+ Palette kp = new Palette();
 443+
 444+ int ncolors = opb.read(8)+1;
 445+ kp.colors = new Color[ncolors];
 446+ for (int n=0; n<ncolors; ++n) {
 447+ kp.colors[n] = unpackColor(opb);
 448+ }
 449+
 450+ Bitwise.skipWarp(opb);
 451+
 452+ return kp;
 453+ }
 454+
 455+ /**
 456+ * Decodes the palettes packet.
 457+ */
 458+ private int unpackPalettes (Buffer opb)
 459+ {
 460+ int npalettes = Bitwise.read32v(opb);
 461+ if (npalettes < 0) return Result.KATE_E_BAD_PACKET;
 462+ palettes = new Palette[npalettes];
 463+ for (int n=0; n<npalettes; ++n) {
 464+ try {
 465+ palettes[n] = unpackPalette(opb);
 466+ }
 467+ catch (KateException ke) {
 468+ palettes = null;
 469+ return Result.KATE_E_BAD_PACKET;
 470+ }
 471+ }
 472+
 473+ Bitwise.skipWarp(opb);
 474+
 475+ /* end of packet */
 476+ return checkEOP(opb);
 477+ }
 478+
 479+ /**
 480+ * Decode a single bitmap.
 481+ */
 482+ public Bitmap unpackBitmap (Buffer opb) throws KateException
 483+ {
 484+ Bitmap kb = new Bitmap();
 485+
 486+ kb.width = Bitwise.read32v(opb);
 487+ kb.height = Bitwise.read32v(opb);
 488+ kb.bpp = opb.read(8);
 489+ if (kb.width < 0 || kb.height < 0 || kb.bpp < 0 || kb.bpp > 8)
 490+ throw new KateBadPacketException();
 491+
 492+ if (kb.bpp == 0) {
 493+ kb.type = KateBitmapType.CreateBitmapType(opb.read(8));
 494+ kb.palette = -1;
 495+ if (kb.type == KateBitmapType.kate_bitmap_type_paletted) {
 496+ int encoding = opb.read(8);
 497+ switch (encoding) {
 498+ case 1: /* RLE */
 499+ kb.bpp = Bitwise.read32v(opb);
 500+ kb.palette = Bitwise.read32v(opb);
 501+ kb.pixels = RLE.decodeRLE(opb, kb.width, kb.height, kb.bpp);
 502+ break;
 503+ default:
 504+ Debug.warning("Unsupported bitmap type");
 505+ throw new KateBadPacketException();
 506+ }
 507+ }
 508+ else if (kb.type == KateBitmapType.kate_bitmap_type_png) {
 509+ kb.size = Bitwise.read32(opb);
 510+ kb.pixels = new byte[kb.size];
 511+ Bitwise.readbuf(opb, kb.pixels, kb.size);
 512+ }
 513+ else {
 514+ Debug.warning("Unsupported bitmap type");
 515+ throw new KateBadPacketException();
 516+ }
 517+ }
 518+ else {
 519+ kb.type = KateBitmapType.kate_bitmap_type_paletted;
 520+ kb.palette = Bitwise.read32v(opb);
 521+ int npixels = kb.width * kb.height;
 522+ kb.pixels = new byte[npixels];
 523+ for (int n=0; n<npixels; ++n)
 524+ kb.pixels[n] = (byte)opb.read(kb.bpp);
 525+ }
 526+
 527+ if (((bitstream_version_major<<8) | bitstream_version_minor) >= 0x0004) {
 528+ Bitwise.read32v(opb);
 529+ kb.x_offset = Bitwise.read32v(opb);
 530+ kb.y_offset = Bitwise.read32v(opb);
 531+ }
 532+ else {
 533+ kb.x_offset = 0;
 534+ kb.y_offset = 0;
 535+ }
 536+
 537+ Bitwise.skipWarp(opb);
 538+
 539+ return kb;
 540+ }
 541+
 542+ /**
 543+ * Decodes the bitmaps packet.
 544+ */
 545+ private int unpackBitmaps (Buffer opb)
 546+ {
 547+ int nbitmaps = Bitwise.read32v(opb);
 548+ if (nbitmaps < 0) return Result.KATE_E_BAD_PACKET;
 549+ bitmaps = new Bitmap[nbitmaps];
 550+ for (int n=0; n<nbitmaps; ++n) {
 551+ try {
 552+ bitmaps[n] = unpackBitmap(opb);
 553+ }
 554+ catch (KateException ke) {
 555+ bitmaps = null;
 556+ return Result.KATE_E_BAD_PACKET;
 557+ }
 558+ }
 559+
 560+ Bitwise.skipWarp(opb);
 561+
 562+ /* end of packet */
 563+ return checkEOP(opb);
 564+ }
 565+
 566+ /**
 567+ * Decodes a single font range.
 568+ */
 569+ private FontRange unpackFontRange (Buffer opb)
 570+ {
 571+ FontRange fr = new FontRange();
 572+ fr.first_code_point = Bitwise.read32v(opb);
 573+ fr.last_code_point = Bitwise.read32v(opb);
 574+ fr.first_bitmap = Bitwise.read32v(opb);
 575+ Bitwise.skipWarp(opb);
 576+ return fr;
 577+ }
 578+
 579+ /**
 580+ * Decodes the font ranges/mappings packet.
 581+ */
 582+ private int unpackFontMappings (Buffer opb)
 583+ {
 584+ int nranges = Bitwise.read32v(opb);
 585+ if (nranges < 0)
 586+ return Result.KATE_E_BAD_PACKET;
 587+ if (nranges > 0) {
 588+ font_ranges = new FontRange[nranges];
 589+ for (int n=0; n<nranges; ++n) {
 590+ font_ranges[n] = unpackFontRange(opb);
 591+ }
 592+ }
 593+
 594+ int nmappings = Bitwise.read32v(opb);
 595+ if (nmappings < 0)
 596+ return Result.KATE_E_BAD_PACKET;
 597+ if (nmappings > 0) {
 598+ font_mappings = new FontMapping[nmappings];
 599+ for (int n=0; n<nmappings; ++n) {
 600+ nranges = Bitwise.read32v(opb);
 601+ if (nranges < 0)
 602+ return Result.KATE_E_BAD_PACKET;
 603+ if (nranges > 0) {
 604+ FontRange fr[] = new FontRange[nranges];
 605+ for (int l=0; l<nranges; ++l) {
 606+ if (opb.read1() != 0) {
 607+ int idx = Bitwise.read32v(opb);
 608+ if (idx < 0 || idx >= this.font_ranges.length)
 609+ return Result.KATE_E_BAD_PACKET;
 610+ fr[l] = this.font_ranges[idx];
 611+ }
 612+ else {
 613+ fr[l] = unpackFontRange(opb);
 614+ }
 615+ }
 616+ font_mappings[n].ranges = fr;
 617+ }
 618+ else {
 619+ font_mappings[n] = null;
 620+ }
 621+ }
 622+ }
 623+
 624+ Bitwise.skipWarp(opb);
 625+
 626+ /* end of packet */
 627+ return checkEOP(opb);
 628+ }
 629+
 630+ /**
 631+ * Resets the header decoder to the start, so a new stream may be decoded.
 632+ */
 633+ public void clear() {
 634+ num_headers = 0;
 635+ regions = null;
 636+ styles = null;
 637+ curves = null;
 638+ motions = null;
 639+ probe = 0;
 640+ }
 641+
 642+ /**
 643+ * Decodes a Kate header, updating the info with the data decoded from the header.
 644+ * If the next expected header is decoded properly, the next header will be expected.
 645+ * Headers beyond the ones we know about are ignored.
 646+ */
 647+ public int decodeHeader (Comment kc, Packet op)
 648+ {
 649+ long ret;
 650+ Buffer opb = new Buffer();
 651+
 652+ opb.readinit (op.packet_base, op.packet, op.bytes);
 653+
 654+ {
 655+ byte[] id = new byte[7];
 656+ int typeflag;
 657+
 658+ typeflag = opb.read(8);
 659+
 660+ /* header types have the MSB set */
 661+ if((typeflag & 0x80) == 0) {
 662+ return Result.KATE_E_BAD_PACKET;
 663+ }
 664+
 665+ /* Kate header magic */
 666+ Bitwise.readbuf(opb,id,7);
 667+ if (!"kate\0\0\0".equals(new String(id))) {
 668+ return Result.KATE_E_NOT_KATE;
 669+ }
 670+
 671+ if (op.packetno < num_headers) {
 672+ if (probe != op.packetno) return Result.KATE_E_BAD_PACKET;
 673+ }
 674+
 675+ /* reserved 0 byte */
 676+ if (opb.read(8) != 0)
 677+ return Result.KATE_E_BAD_PACKET;
 678+
 679+ Debug.debug("decodeHeader: packet type "+typeflag+", probe "+probe);
 680+
 681+ /* ensure packets are received in order */
 682+ switch(probe){
 683+ case 0:
 684+ if(op.b_o_s == 0){
 685+ /* Not the initial packet */
 686+ return Result.KATE_E_BAD_PACKET;
 687+ }
 688+ ret = unpackInfo(opb);
 689+ break;
 690+
 691+ case 1:
 692+ ret = unpackComment(kc,opb);
 693+ break;
 694+
 695+ case 2:
 696+ ret = unpackRegions(opb);
 697+ break;
 698+
 699+ case 3:
 700+ ret = unpackStyles(opb);
 701+ break;
 702+
 703+ case 4:
 704+ ret = unpackCurves(opb);
 705+ break;
 706+
 707+ case 5:
 708+ ret = unpackMotions(opb);
 709+ break;
 710+
 711+ case 6:
 712+ ret = unpackPalettes(opb);
 713+ break;
 714+
 715+ case 7:
 716+ ret = unpackBitmaps(opb);
 717+ break;
 718+
 719+ case 8:
 720+ ret = unpackFontMappings(opb);
 721+ /* last known header, we can init for decode */
 722+ if (ret == 0) {
 723+ Debug.debug("Found last known header, returning 1");
 724+ ret = 1;
 725+ }
 726+ break;
 727+
 728+ default:
 729+ /* ignore any trailing header packets for forward compatibility */
 730+ ret = 0;
 731+ break;
 732+ }
 733+ }
 734+
 735+ /* decode was successful, we're now expecting the next packet in sequence */
 736+ if (ret >= 0) {
 737+ ++probe;
 738+ }
 739+
 740+ return (int)ret;
 741+ }
 742+}
 743+
Index: trunk/cortado/src/com/fluendo/jkate/Tracker.java
@@ -0,0 +1,96 @@
 2+/* JKate
 3+ * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 4+ *
 5+ * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com>
 6+ *
 7+ * This program is free software; you can redistribute it and/or
 8+ * modify it under the terms of the GNU Library General Public License
 9+ * as published by the Free Software Foundation; either version 2 of
 10+ * the License, or (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU Library General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU Library General Public
 18+ * License along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20+ */
 21+
 22+package com.fluendo.jkate;
 23+
 24+import java.util.*;
 25+import java.awt.*;
 26+import com.fluendo.utils.*;
 27+
 28+public final class Tracker {
 29+
 30+ private Dimension window;
 31+ private Dimension frame;
 32+
 33+ public com.fluendo.jkate.Event ev = null;
 34+
 35+ public boolean has[] = new boolean[64];
 36+ public static final int has_region = 0;
 37+ public static final int has_text_alignment_int = 1;
 38+ public static final int has_text_alignment_ext = 2;
 39+
 40+ public float region_x;
 41+ public float region_y;
 42+ public float region_w;
 43+ public float region_h;
 44+
 45+ public Tracker (com.fluendo.jkate.Event ev) {
 46+ this.ev = ev;
 47+ }
 48+
 49+ /**
 50+ * Update the tracker at the given time for the given image's dimensions.
 51+ */
 52+ public boolean update(double t, Dimension window, Dimension frame)
 53+ {
 54+ this.window = window;
 55+ this.frame = frame;
 56+
 57+ /* find current region and style, if any */
 58+ Region kr = ev.kr;
 59+ Style ks = ev.ks;
 60+ if (ks == null && kr != null && kr.style >= 0) {
 61+ ks = ev.ki.styles[kr.style];
 62+ }
 63+
 64+ /* start with nothing */
 65+ for (int n=0; n<has.length; ++n) has[n] = false;
 66+
 67+ /* define region */
 68+ if (kr != null) {
 69+ if (kr.metric == KateSpaceMetric.kate_metric_percentage) {
 70+ region_x = kr.x * frame.width / 100.0f;
 71+ region_y = kr.y * frame.height / 100.0f;
 72+ region_w = kr.w * frame.width / 100.0f;
 73+ region_h = kr.h * frame.height / 100.0f;
 74+ }
 75+ else if (kr.metric == KateSpaceMetric.kate_metric_millionths) {
 76+ region_x = kr.x * frame.width / 1000000.0f;
 77+ region_y = kr.y * frame.height / 1000000.0f;
 78+ region_w = kr.w * frame.width / 1000000.0f;
 79+ region_h = kr.h * frame.height / 1000000.0f;
 80+ }
 81+ else if (kr.metric == KateSpaceMetric.kate_metric_pixels) {
 82+ region_x = kr.x;
 83+ region_y = kr.y;
 84+ region_w = kr.w;
 85+ region_h = kr.h;
 86+ }
 87+ else {
 88+ Debug.debug("Invalid metrics");
 89+ return false;
 90+ }
 91+ has[has_region] = true;
 92+ }
 93+
 94+ return true;
 95+ }
 96+
 97+}
Index: trunk/cortado/src/com/fluendo/jkate/KateTextDirectionality.java
@@ -0,0 +1,47 @@
 2+/* JKate
 3+ * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 4+ *
 5+ * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com>
 6+ *
 7+ * This program is free software; you can redistribute it and/or
 8+ * modify it under the terms of the GNU Library General Public License
 9+ * as published by the Free Software Foundation; either version 2 of
 10+ * the License, or (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU Library General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU Library General Public
 18+ * License along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20+ */
 21+
 22+package com.fluendo.jkate;
 23+
 24+public class KateTextDirectionality {
 25+ public static final KateTextDirectionality kate_l2r_t2b = new KateTextDirectionality ();
 26+ public static final KateTextDirectionality kate_r2l_t2b = new KateTextDirectionality ();
 27+ public static final KateTextDirectionality kate_t2b_r2l = new KateTextDirectionality ();
 28+ public static final KateTextDirectionality kate_t2b_l2r = new KateTextDirectionality ();
 29+
 30+ private static final KateTextDirectionality[] list = {
 31+ kate_l2r_t2b,
 32+ kate_r2l_t2b,
 33+ kate_t2b_r2l,
 34+ kate_t2b_l2r
 35+ };
 36+
 37+ private KateTextDirectionality() {
 38+ }
 39+
 40+ /**
 41+ * Create a KateTextDirectionality object from an integer.
 42+ */
 43+ public static KateTextDirectionality CreateTextDirectionality(int idx) throws KateException {
 44+ if (idx < 0 || idx >= list.length)
 45+ throw new KateException("Text directionality "+idx+" out of bounds");
 46+ return list[idx];
 47+ }
 48+}
Index: trunk/cortado/src/com/fluendo/jkate/Palette.java
@@ -0,0 +1,29 @@
 2+/* JKate
 3+ * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 4+ *
 5+ * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com>
 6+ *
 7+ * This program is free software; you can redistribute it and/or
 8+ * modify it under the terms of the GNU Library General Public License
 9+ * as published by the Free Software Foundation; either version 2 of
 10+ * the License, or (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU Library General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU Library General Public
 18+ * License along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20+ */
 21+
 22+package com.fluendo.jkate;
 23+
 24+/**
 25+ * A Palette definition, containing between 0 and 256 colors.
 26+ */
 27+public class Palette
 28+{
 29+ public Color colors[] = null;
 30+}
Index: trunk/cortado/src/com/fluendo/jkate/KateTextEncoding.java
@@ -0,0 +1,41 @@
 2+/* JKate
 3+ * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 4+ *
 5+ * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com>
 6+ *
 7+ * This program is free software; you can redistribute it and/or
 8+ * modify it under the terms of the GNU Library General Public License
 9+ * as published by the Free Software Foundation; either version 2 of
 10+ * the License, or (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU Library General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU Library General Public
 18+ * License along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20+ */
 21+
 22+package com.fluendo.jkate;
 23+
 24+public class KateTextEncoding {
 25+ public static final KateTextEncoding kate_utf8 = new KateTextEncoding ();
 26+
 27+ private static final KateTextEncoding[] list = {
 28+ kate_utf8,
 29+ };
 30+
 31+ private KateTextEncoding() {
 32+ }
 33+
 34+ /**
 35+ * Create a KateTextEncoding object from an integer.
 36+ */
 37+ public static KateTextEncoding CreateTextEncoding(int idx) throws KateException {
 38+ if (idx < 0 || idx >= list.length)
 39+ throw new KateException("Text encoding "+idx+" out of bounds");
 40+ return list[idx];
 41+ }
 42+}
Index: trunk/cortado/src/com/fluendo/jkate/Style.java
@@ -0,0 +1,54 @@
 2+/* JKate
 3+ * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 4+ *
 5+ * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com>
 6+ *
 7+ * This program is free software; you can redistribute it and/or
 8+ * modify it under the terms of the GNU Library General Public License
 9+ * as published by the Free Software Foundation; either version 2 of
 10+ * the License, or (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU Library General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU Library General Public
 18+ * License along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20+ */
 21+
 22+package com.fluendo.jkate;
 23+
 24+/**
 25+ * A style definition.
 26+ */
 27+
 28+public class Style
 29+{
 30+ public double halign;
 31+ public double valign;
 32+
 33+ public Color text_color;
 34+ public Color background_color;
 35+ public Color draw_color;
 36+
 37+ public KateSpaceMetric font_metric;
 38+ public double font_width;
 39+ public double font_height;
 40+
 41+ public KateSpaceMetric margin_metric;
 42+ public double left_margin;
 43+ public double top_margin;
 44+ public double right_margin;
 45+ public double bottom_margin;
 46+
 47+ public boolean bold;
 48+ public boolean italics;
 49+ public boolean underline;
 50+ public boolean strike;
 51+ public boolean justify;
 52+ public KateWrapMode wrap_mode;
 53+
 54+ public String font;
 55+}
Index: trunk/cortado/src/com/fluendo/jkate/KateBadPacketException.java
@@ -0,0 +1,26 @@
 2+/* JKate
 3+ * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 4+ *
 5+ * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com>
 6+ *
 7+ * This program is free software; you can redistribute it and/or
 8+ * modify it under the terms of the GNU Library General Public License
 9+ * as published by the Free Software Foundation; either version 2 of
 10+ * the License, or (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU Library General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU Library General Public
 18+ * License along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20+ */
 21+
 22+package com.fluendo.jkate;
 23+
 24+class KateBadPacketException extends KateException {
 25+ public KateBadPacketException() { super("Bad packet"); }
 26+}
 27+
Index: trunk/cortado/src/com/fluendo/jkate/Comment.java
@@ -0,0 +1,35 @@
 2+/* JKate
 3+ * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 4+ *
 5+ * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com>
 6+ *
 7+ * This program is free software; you can redistribute it and/or
 8+ * modify it under the terms of the GNU Library General Public License
 9+ * as published by the Free Software Foundation; either version 2 of
 10+ * the License, or (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU Library General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU Library General Public
 18+ * License along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20+ */
 21+
 22+package com.fluendo.jkate;
 23+
 24+/**
 25+ * Vorbis comments are used in Kate streams too.
 26+ */
 27+public class Comment {
 28+ String[] user_comments;
 29+ String vendor;
 30+
 31+
 32+ public void clear() {
 33+ user_comments = null;
 34+ vendor = null;
 35+ }
 36+}
Index: trunk/cortado/src/com/fluendo/plugin/TheoraDec.java
@@ -66,6 +66,10 @@
6767 {
6868 return ts.isKeyframe(op);
6969 }
 70+ public boolean isDiscontinuous ()
 71+ {
 72+ return false;
 73+ }
7074 public long getFirstTs (Vector packets)
7175 {
7276 int len = packets.size();
Index: trunk/cortado/src/com/fluendo/plugin/KateDec.java
@@ -0,0 +1,334 @@
 2+/* Copyright (C) <2008> ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 3+ * based on code Copyright (C) <2004> Wim Taymans <wim@fluendo.com>
 4+ *
 5+ * This library is free software; you can redistribute it and/or
 6+ * modify it under the terms of the GNU Library General Public
 7+ * License as published by the Free Software Foundation; either
 8+ * version 2 of the License, or (at your option) any later version.
 9+ *
 10+ * This library is distributed in the hope that it will be useful,
 11+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 13+ * Library General Public License for more details.
 14+ *
 15+ * You should have received a copy of the GNU Library General Public
 16+ * License along with this library; if not, write to the
 17+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 18+ * Boston, MA 02111-1307, USA.
 19+ */
 20+
 21+package com.fluendo.plugin;
 22+
 23+import java.util.*;
 24+import com.jcraft.jogg.*;
 25+import com.fluendo.jkate.*;
 26+import com.fluendo.jst.*;
 27+import com.fluendo.utils.*;
 28+
 29+/**
 30+ * Katedec is a decoder element for the Kate stream format.
 31+ * See http://wiki.xiph.org/index.php/OggKate for more information.
 32+ * Kate streams may be multiplexed in Ogg.
 33+ * The Katedec element accepts Kate packets (presumably demultiplexed by an
 34+ * Ogg demuxer element) on its sink, and generates Kate events on its source.
 35+ * Kate events are Kate specific structures, which may then be interpreted
 36+ * by a renderer.
 37+*/
 38+public class KateDec extends Element implements OggPayload
 39+{
 40+ /* Kate magic: 0x80 (BOS header) followed by "kate\0\0\0" */
 41+ private static final byte[] signature = { -128, 0x6b, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00 };
 42+
 43+ private Info ki;
 44+ private Comment kc;
 45+ private State k;
 46+ private Packet op;
 47+ private int packetno;
 48+
 49+ private long basetime = 0;
 50+ private long lastTs;
 51+ private boolean haveDecoder = false;
 52+
 53+ /*
 54+ * OggPayload interface
 55+ */
 56+ public boolean isType (Packet op)
 57+ {
 58+ return typeFind (op.packet_base, op.packet, op.bytes) > 0;
 59+ }
 60+ public boolean isKeyFrame (Packet op)
 61+ {
 62+ return true;
 63+ }
 64+
 65+ /**
 66+ * A discontinuous codec will not cause the pipeline to wait for data if starving
 67+ */
 68+ public boolean isDiscontinuous ()
 69+ {
 70+ return true;
 71+ }
 72+ public int takeHeader (Packet op)
 73+ {
 74+ int ret = ki.decodeHeader(kc, op);
 75+ if (ret > 0) {
 76+ k.decodeInit(ki);
 77+ Debug.debug("Kate decoder ready");
 78+ haveDecoder = true;
 79+ }
 80+ return ret;
 81+ }
 82+ public boolean isHeader (Packet op)
 83+ {
 84+ return (op.packet_base[op.packet] & 0x80) == 0x80;
 85+ }
 86+ public long getFirstTs (Vector packets)
 87+ {
 88+ int len = packets.size();
 89+ int i;
 90+ long time;
 91+ com.fluendo.jst.Buffer data = null;
 92+
 93+ /* first find buffer with valid offset */
 94+ for (i=0; i<len; i++) {
 95+ data = (com.fluendo.jst.Buffer) packets.elementAt(i);
 96+
 97+ if (data.time_offset != -1)
 98+ break;
 99+ }
 100+ if (i == packets.size())
 101+ return -1;
 102+
 103+ time = granuleToTime (data.time_offset);
 104+
 105+ data = (com.fluendo.jst.Buffer) packets.elementAt(0);
 106+ data.timestamp = time - (long) ((i+1) * (Clock.SECOND * ki.gps_denominator / ki.gps_numerator));
 107+
 108+ return time;
 109+ }
 110+
 111+ /**
 112+ * Converts a granule position to its time equivalent
 113+ */
 114+ public long granuleToTime (long gp)
 115+ {
 116+ long res;
 117+
 118+ if (gp < 0 || !haveDecoder)
 119+ return -1;
 120+
 121+ res = (long) (k.granuleTime(gp) * Clock.SECOND);
 122+
 123+ return res;
 124+ }
 125+
 126+ /**
 127+ * Converts a granule position to its duration equivalent
 128+ */
 129+ public long granuleToDuration (long gp)
 130+ {
 131+ long res;
 132+
 133+ if (gp < 0 || !haveDecoder)
 134+ return -1;
 135+
 136+ res = (long) (k.granuleDuration(gp) * Clock.SECOND);
 137+
 138+ return res;
 139+ }
 140+
 141+ private Pad srcPad = new Pad(Pad.SRC, "src") {
 142+ protected boolean eventFunc (com.fluendo.jst.Event event) {
 143+ return sinkPad.pushEvent(event);
 144+ }
 145+ };
 146+
 147+ private Pad sinkPad = new Pad(Pad.SINK, "sink") {
 148+ protected boolean eventFunc (com.fluendo.jst.Event event) {
 149+ boolean result;
 150+
 151+ switch (event.getType()) {
 152+ case com.fluendo.jst.Event.FLUSH_START:
 153+ result = srcPad.pushEvent (event);
 154+ synchronized (streamLock) {
 155+ Debug.log(Debug.DEBUG, "synced "+this);
 156+ }
 157+ break;
 158+ case com.fluendo.jst.Event.FLUSH_STOP:
 159+ result = srcPad.pushEvent(event);
 160+ break;
 161+ case com.fluendo.jst.Event.EOS:
 162+ Debug.log(Debug.INFO, "got EOS "+this);
 163+ result = srcPad.pushEvent(event);
 164+ break;
 165+ case com.fluendo.jst.Event.NEWSEGMENT:
 166+ basetime = event.parseNewsegmentStart();
 167+ Debug.info("new segment: base time "+basetime);
 168+ result = srcPad.pushEvent(event);
 169+ break;
 170+ default:
 171+ result = srcPad.pushEvent(event);
 172+ break;
 173+ }
 174+ return result;
 175+ }
 176+
 177+ /**
 178+ * receives Kate packets, and generates Kate events
 179+ */
 180+ protected int chainFunc (com.fluendo.jst.Buffer buf) {
 181+ int result;
 182+ long timestamp;
 183+
 184+ Debug.log( Debug.DEBUG, parent.getName() + " <<< " + buf );
 185+
 186+ op.packet_base = buf.data;
 187+ op.packet = buf.offset;
 188+ op.bytes = buf.length;
 189+ op.b_o_s = (packetno == 0 ? 1 : 0);
 190+ op.e_o_s = 0;
 191+ op.packetno = packetno;
 192+ timestamp = buf.timestamp;
 193+
 194+ Debug.log(Debug.DEBUG, "Kate chainFunc with packetno "+packetno+", haveDecoder "+haveDecoder);
 195+
 196+// if (buf.isFlagSet (com.fluendo.jst.Buffer.FLAG_DISCONT)) {
 197+// Debug.log(Debug.INFO, "kate: got discont");
 198+// /* should flush, if we keep events to handle repeats in the future */
 199+// lastTs = -1;
 200+// }
 201+
 202+ if (!haveDecoder) {
 203+ //System.out.println ("decoding header");
 204+ result = takeHeader(op);
 205+ if (result < 0){
 206+ buf.free();
 207+ // error case; not a kate header
 208+ Debug.log(Debug.ERROR, "does not contain Kate data.");
 209+ return ERROR;
 210+ }
 211+ else if (result > 0) {
 212+ // we've decoded all headers
 213+ Debug.log(Debug.DEBUG, "Kate initialized for decoding");
 214+
 215+ /* we're sending raw kate_event structures */
 216+ caps = new Caps ("application/x-kate-event");
 217+ }
 218+ buf.free();
 219+ packetno++;
 220+
 221+ return OK;
 222+ }
 223+ else {
 224+ if ((op.packet_base[op.packet] & 0x80) == 0x80) {
 225+ Debug.log(Debug.DEBUG, "ignoring header");
 226+ buf.free();
 227+ return OK;
 228+ }
 229+
 230+ if (timestamp != -1) {
 231+ lastTs = timestamp;
 232+ }
 233+
 234+ if (true) {
 235+ try{
 236+ result = k.decodePacketin(op);
 237+ if (result < 0) {
 238+ buf.free();
 239+ Debug.log(Debug.ERROR, "Error Decoding Kate.");
 240+ postMessage (Message.newError (this, "Error decoding Kate"));
 241+ return ERROR;
 242+ }
 243+ com.fluendo.jkate.Event ev = k.decodeEventOut();
 244+ if (ev != null) {
 245+ buf.object = ev;
 246+ buf.caps = caps;
 247+ buf.timestamp = granuleToDuration(ev.start);
 248+ buf.timestampEnd = buf.timestamp + granuleToDuration(ev.duration);
 249+ Debug.log( Debug.DEBUG, parent.getName() + " >>> " + buf );
 250+ Debug.debug("Got Kate text: "+new String(ev.text)+" from "+buf.timestamp+" to "+buf.timestampEnd+", basetime "+basetime);
 251+ result = srcPad.push(buf);
 252+ Debug.log(Debug.DEBUG, "push returned "+result);
 253+ }
 254+ else {
 255+ Debug.debug("Got no event");
 256+ buf.free();
 257+ result = OK;
 258+ }
 259+ }
 260+ catch (Exception e) {
 261+ e.printStackTrace();
 262+ postMessage (Message.newError (this, e.getMessage()));
 263+ result = ERROR;
 264+ }
 265+ }
 266+ else {
 267+ result = OK;
 268+ buf.free();
 269+ }
 270+ }
 271+ packetno++;
 272+
 273+ return result;
 274+ }
 275+
 276+ protected boolean activateFunc (int mode)
 277+ {
 278+ return true;
 279+ }
 280+ };
 281+
 282+ public KateDec() {
 283+ super();
 284+
 285+ ki = new Info();
 286+ kc = new Comment();
 287+ k = new State();
 288+ op = new Packet();
 289+
 290+ addPad (srcPad);
 291+ addPad (sinkPad);
 292+ }
 293+
 294+ protected int changeState (int transition) {
 295+ int res;
 296+
 297+ switch (transition) {
 298+ case STOP_PAUSE:
 299+ lastTs = -1;
 300+ packetno = 0;
 301+ break;
 302+ default:
 303+ break;
 304+ }
 305+
 306+ res = super.changeState (transition);
 307+
 308+ switch (transition) {
 309+ case PAUSE_STOP:
 310+ ki.clear();
 311+ kc.clear();
 312+ k.clear();
 313+ break;
 314+ default:
 315+ break;
 316+ }
 317+
 318+ return res;
 319+ }
 320+
 321+ public String getFactoryName ()
 322+ {
 323+ return "katedec";
 324+ }
 325+ public String getMime ()
 326+ {
 327+ return "application/x-kate";
 328+ }
 329+ public int typeFind (byte[] data, int offset, int length)
 330+ {
 331+ if (MemUtils.startsWith (data, offset, length, signature))
 332+ return 10;
 333+ return -1;
 334+ }
 335+}
Index: trunk/cortado/src/com/fluendo/plugin/OggDemux.java
@@ -41,7 +41,8 @@
4242
4343 private OggPayload payloads[] = {
4444 new TheoraDec(),
45 - new VorbisDec()
 45+ new VorbisDec(),
 46+ new KateDec()
4647 };
4748
4849 class OggStream extends Pad {
@@ -222,15 +223,20 @@
223224 complete = true;
224225 return Pad.OK;
225226 }
 227+
226228 /* first read all the headers */
227229 if (!haveHeaders) {
228230 if (payload.isHeader(op)) {
229 - if (payload.takeHeader (op) < 0) {
 231+ int result = payload.takeHeader (op);
 232+ if (result < 0) {
230233 postMessage (Message.newError (this, "cannot read header"));
231234 return Pad.ERROR;
232235 }
233236 com.fluendo.jst.Buffer data = bufferFromPacket (op);
234237 headers.addElement(data);
 238+ if (result > 0) {
 239+ haveHeaders = true;
 240+ }
235241 }
236242 else {
237243 haveHeaders = true;
@@ -238,6 +244,10 @@
239245 }
240246 /* if we have all the headers we can stream */
241247 if (haveHeaders) {
 248+ /* discontinuous codecs do not need to wait for data to allow playback */
 249+ if (!complete && payload.isDiscontinuous()) {
 250+ complete = true;
 251+ }
242252 if (complete && started) {
243253 int ret;
244254 com.fluendo.jst.Buffer data = bufferFromPacket (op);
Index: trunk/cortado/src/com/fluendo/plugin/VorbisDec.java
@@ -56,6 +56,10 @@
5757 {
5858 return true;
5959 }
 60+ public boolean isDiscontinuous ()
 61+ {
 62+ return false;
 63+ }
6064 public long getFirstTs (Vector packets)
6165 {
6266 int len = packets.size();
Index: trunk/cortado/src/com/fluendo/plugin/Selector.java
@@ -0,0 +1,137 @@
 2+/* Copyright (C) <2008> ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 3+ *
 4+ * This library is free software; you can redistribute it and/or
 5+ * modify it under the terms of the GNU Library General Public
 6+ * License as published by the Free Software Foundation; either
 7+ * version 2 of the License, or (at your option) any later version.
 8+ *
 9+ * This library is distributed in the hope that it will be useful,
 10+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 12+ * Library General Public License for more details.
 13+ *
 14+ * You should have received a copy of the GNU Library General Public
 15+ * License along with this library; if not, write to the
 16+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 17+ * Boston, MA 02111-1307, USA.
 18+ */
 19+
 20+package com.fluendo.plugin;
 21+
 22+import java.util.*;
 23+import java.awt.*;
 24+import com.fluendo.jst.*;
 25+import com.fluendo.utils.*;
 26+
 27+/**
 28+ * This element receives data from N sinks, and selects one of them
 29+ * to send from its source.
 30+ */
 31+public class Selector extends Element
 32+{
 33+ private Vector sinks = new Vector();
 34+ int selected = -1;
 35+ Pad selectedPad = null;
 36+
 37+ private Pad srcPad = new Pad(Pad.SRC, "src") {
 38+ /**
 39+ * Pushes the event to every sink.
 40+ */
 41+ protected boolean eventFunc (com.fluendo.jst.Event event) {
 42+ boolean ret = true;
 43+ for (int n=0; n<sinks.size(); ++n) {
 44+ ret &= ((Pad)sinks.get(n)).pushEvent(event);
 45+ }
 46+ return ret;
 47+ }
 48+ };
 49+
 50+ private int findPad (Pad pad) {
 51+ for (int n=0; n<sinks.size(); ++n) {
 52+ if (sinks.get(n) == pad)
 53+ return n;
 54+ }
 55+ return -1;
 56+ }
 57+
 58+ /**
 59+ * Requests a new sink pad to be created for the given peer.
 60+ * The caps do not matter, as Selector is a caps agnostic element.
 61+ */
 62+ public Pad requestSinkPad(Pad peer) {
 63+ Pad pad = new Pad(Pad.SINK, "sink"+sinks.size()) {
 64+ protected boolean eventFunc (com.fluendo.jst.Event event) {
 65+ if (selectedPad == this) {
 66+ return srcPad.pushEvent (event);
 67+ }
 68+ return true;
 69+ }
 70+
 71+ protected int chainFunc (com.fluendo.jst.Buffer buf) {
 72+ int result = Pad.OK;
 73+
 74+ //Debug.log( Debug.DEBUG, parent.getName() + " <<< " + buf );
 75+ Debug.debug("Selector got "+buf.caps+" buffer on "+this.toString());
 76+
 77+ if (selectedPad == this) {
 78+ Debug.debug("what a coincidence, we're selected - pushing");
 79+ result = srcPad.push(buf);
 80+ }
 81+
 82+ return result;
 83+ }
 84+
 85+ protected boolean activateFunc (int mode)
 86+ {
 87+ return true;
 88+ }
 89+ };
 90+
 91+ sinks.addElement(pad);
 92+ addPad(pad);
 93+ return pad;
 94+ }
 95+
 96+ public Selector() {
 97+ super();
 98+
 99+ addPad (srcPad);
 100+ }
 101+
 102+ /**
 103+ * The selected sink may be selected via the "selected" property - negative to select nothing
 104+ */
 105+ public boolean setProperty (String name, java.lang.Object value) {
 106+ if (name.equals("selected")) {
 107+ int new_selected = Integer.valueOf(value.toString()).intValue();
 108+ Debug.info("Selector: request to select "+new_selected+" (from "+selected+"), within 0-"+(sinks.size()-1));
 109+ if (new_selected < 0 || new_selected >= sinks.size()) {
 110+ selected = -1;
 111+ selectedPad = null;
 112+ }
 113+ else {
 114+ selected = new_selected;
 115+ selectedPad = (Pad)sinks.get(selected);
 116+ }
 117+ }
 118+ else {
 119+ return super.setProperty(name, value);
 120+ }
 121+
 122+ return true;
 123+ }
 124+
 125+ public java.lang.Object getProperty (String name) {
 126+ if (name.equals("selected")) {
 127+ return new Integer(selected);
 128+ }
 129+ else {
 130+ return super.getProperty(name);
 131+ }
 132+ }
 133+
 134+ public String getFactoryName ()
 135+ {
 136+ return "selector";
 137+ }
 138+}
Index: trunk/cortado/src/com/fluendo/plugin/Overlay.java
@@ -0,0 +1,122 @@
 2+/* Copyright (C) <2008> ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 3+ *
 4+ * This library is free software; you can redistribute it and/or
 5+ * modify it under the terms of the GNU Library General Public
 6+ * License as published by the Free Software Foundation; either
 7+ * version 2 of the License, or (at your option) any later version.
 8+ *
 9+ * This library is distributed in the hope that it will be useful,
 10+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 12+ * Library General Public License for more details.
 13+ *
 14+ * You should have received a copy of the GNU Library General Public
 15+ * License along with this library; if not, write to the
 16+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 17+ * Boston, MA 02111-1307, USA.
 18+ */
 19+
 20+package com.fluendo.plugin;
 21+
 22+import java.util.*;
 23+import java.awt.*;
 24+import com.fluendo.jst.*;
 25+import com.fluendo.utils.*;
 26+
 27+/**
 28+ * This is a base overlay element, just passes images from sink to source.
 29+ * Extend this and override the overlay function to draw something onto
 30+ * images as they go from sink to source.
 31+ */
 32+public class Overlay extends Element
 33+{
 34+ protected Component component;
 35+
 36+ private Pad videoSrcPad = new Pad(Pad.SRC, "videosrc") {
 37+ protected boolean eventFunc (com.fluendo.jst.Event event) {
 38+ return videoSinkPad.pushEvent(event);
 39+ }
 40+ };
 41+
 42+ private Pad videoSinkPad = new Pad(Pad.SINK, "videosink") {
 43+ protected boolean eventFunc (com.fluendo.jst.Event event) {
 44+ return videoSrcPad.pushEvent (event);
 45+ }
 46+
 47+ /**
 48+ * Receives an image, allows a derived class to overlay whatever it wants on it,
 49+ * and sends it to the video source pad.
 50+ */
 51+ protected int chainFunc (com.fluendo.jst.Buffer buf) {
 52+ int result;
 53+
 54+ Debug.log( Debug.DEBUG, parent.getName() + " <<< " + buf );
 55+
 56+ overlay(buf);
 57+
 58+ result = videoSrcPad.push(buf);
 59+ if (result != Pad.OK) {
 60+ Debug.log( Debug.WARNING, parent.getName() + ": failed to push buffer to video source pad: "+result);
 61+ }
 62+
 63+ return result;
 64+ }
 65+
 66+ protected boolean activateFunc (int mode)
 67+ {
 68+ return true;
 69+ }
 70+ };
 71+
 72+ public Overlay() {
 73+ super();
 74+
 75+ addPad (videoSinkPad);
 76+ addPad (videoSrcPad);
 77+ }
 78+
 79+ /**
 80+ * this function may be overridden to draw whatever the derived
 81+ * class wants onto the incoming image.
 82+ * By default, the image is passed without alteration.
 83+ */
 84+ protected void overlay(com.fluendo.jst.Buffer buf) {
 85+ /* straight pass through by default */
 86+ }
 87+
 88+ public boolean setProperty (String name, java.lang.Object value) {
 89+ if (name.equals("component")) {
 90+ component = (Component) value;
 91+ }
 92+ else {
 93+ return super.setProperty(name, value);
 94+ }
 95+
 96+ return true;
 97+ }
 98+
 99+ public java.lang.Object getProperty (String name) {
 100+ if (name.equals("component")) {
 101+ return component;
 102+ }
 103+ else {
 104+ return super.getProperty(name);
 105+ }
 106+ }
 107+
 108+ /* from the video sink code, I do not understand what this does semantically,
 109+ the frame would be 0x0 sized. Maybe just to avoid possible null dereference,
 110+ but I suspect there might be something more clever, so it goes in for safety */
 111+ protected int changeState (int transition) {
 112+ if (currentState == STOP && pendingState == PAUSE && component == null) {
 113+ Frame frame = new Frame();
 114+ component = (Component) frame;
 115+ }
 116+ return super.changeState(transition);
 117+ }
 118+
 119+ public String getFactoryName ()
 120+ {
 121+ return "overlay";
 122+ }
 123+}
Index: trunk/cortado/src/com/fluendo/plugin/TextOverlay.java
@@ -0,0 +1,114 @@
 2+/* Copyright (C) <2008> ogg.k.ogg.k <ogg.k.ogg.k@googlecode.com>
 3+ *
 4+ * This library is free software; you can redistribute it and/or
 5+ * modify it under the terms of the GNU Library General Public
 6+ * License as published by the Free Software Foundation; either
 7+ * version 2 of the License, or (at your option) any later version.
 8+ *
 9+ * This library is distributed in the hope that it will be useful,
 10+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 12+ * Library General Public License for more details.
 13+ *
 14+ * You should have received a copy of the GNU Library General Public
 15+ * License along with this library; if not, write to the
 16+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 17+ * Boston, MA 02111-1307, USA.
 18+ */
 19+
 20+package com.fluendo.plugin;
 21+
 22+import java.util.*;
 23+import java.awt.*;
 24+import java.awt.image.*;
 25+import com.fluendo.jst.*;
 26+import com.fluendo.utils.*;
 27+
 28+/**
 29+ * This class displays a simple text string on top of incoming video.
 30+ */
 31+public class TextOverlay extends Overlay
 32+{
 33+ private BufferedImage bimg = null;
 34+ private Font font = null;
 35+ private String text = null;
 36+
 37+ public TextOverlay() {
 38+ super();
 39+ }
 40+
 41+ /**
 42+ * Display a text string (from a property) onto the image.
 43+ */
 44+ protected void overlay(com.fluendo.jst.Buffer buf) {
 45+ Image img;
 46+
 47+ /* img retrieval from VideoSink.java */
 48+ if (buf.object instanceof ImageProducer) {
 49+ img = component.createImage((ImageProducer)buf.object);
 50+ }
 51+ else if (buf.object instanceof Image) {
 52+ img = (Image)buf.object;
 53+ }
 54+ else {
 55+ System.out.println(this+": unknown buffer received "+buf);
 56+ return;
 57+ }
 58+
 59+ Dimension d = component.getSize();
 60+ int x = 0;
 61+ int y = 0;
 62+ int w = d.width;
 63+ int h = d.height;
 64+
 65+ /* based on a java SDK example */
 66+ if (bimg == null || bimg.getWidth() != w || bimg.getHeight() != h) {
 67+ bimg = component.getGraphicsConfiguration().createCompatibleImage(w, h);
 68+ int font_size = w / 32;
 69+ if (font_size < 12) font_size = 12;
 70+ font = new Font("sans", Font.BOLD, font_size); // TODO: should be selectable ?
 71+ }
 72+
 73+ Graphics2D g2 = bimg.createGraphics();
 74+ g2.drawImage(img, x, y, w, h, null);
 75+
 76+ /* render text on top */
 77+ if (text != null) {
 78+ double tw;
 79+ g2.setFont(font);
 80+ g2.setColor(Color.white);
 81+ FontMetrics fm = g2.getFontMetrics();
 82+ tw = fm.stringWidth(text);
 83+ g2.drawString(text, x+(int)((w-tw)/2), y+(int)(h*0.85));
 84+ }
 85+
 86+ g2.dispose();
 87+
 88+ buf.object = bimg;
 89+ }
 90+
 91+ public boolean setProperty (String name, java.lang.Object value) {
 92+ if (name.equals("text")) {
 93+ text = value.toString();
 94+ }
 95+ else {
 96+ return super.setProperty(name, value);
 97+ }
 98+
 99+ return true;
 100+ }
 101+
 102+ public java.lang.Object getProperty (String name) {
 103+ if (name.equals("text")) {
 104+ return text;
 105+ }
 106+ else {
 107+ return super.getProperty(name);
 108+ }
 109+ }
 110+
 111+ public String getFactoryName ()
 112+ {
 113+ return "textoverlay";
 114+ }
 115+}
Index: trunk/cortado/src/com/fluendo/plugin/KateOverlay.java
@@ -0,0 +1,121 @@
 2+/* Copyright (C) <2008> ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 3+ *
 4+ * This library is free software; you can redistribute it and/or
 5+ * modify it under the terms of the GNU Library General Public
 6+ * License as published by the Free Software Foundation; either
 7+ * version 2 of the License, or (at your option) any later version.
 8+ *
 9+ * This library is distributed in the hope that it will be useful,
 10+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 12+ * Library General Public License for more details.
 13+ *
 14+ * You should have received a copy of the GNU Library General Public
 15+ * License along with this library; if not, write to the
 16+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 17+ * Boston, MA 02111-1307, USA.
 18+ */
 19+
 20+package com.fluendo.plugin;
 21+
 22+import java.util.*;
 23+import java.awt.*;
 24+import java.awt.image.*;
 25+import com.fluendo.jst.*;
 26+import com.fluendo.jkate.Event;
 27+import com.fluendo.jtiger.Renderer;
 28+import com.fluendo.utils.*;
 29+
 30+/* This element renders a Kate stream on incoming video */
 31+public class KateOverlay extends Overlay
 32+{
 33+ private BufferedImage bimg = null;
 34+ private Font font = null;
 35+ private String text = null;
 36+ private Renderer tr = new Renderer();
 37+
 38+ private Pad kateSinkPad = new Pad(Pad.SINK, "katesink") {
 39+ protected boolean eventFunc (com.fluendo.jst.Event event) {
 40+ /* don't propagate, the video sink is the master */
 41+ return true;
 42+ }
 43+
 44+ /**
 45+ * This pad receives Kate events, and add them to the renderer.
 46+ * They will be removed from it as they become inactive.
 47+ */
 48+ protected synchronized int chainFunc (com.fluendo.jst.Buffer buf) {
 49+ addKateEvent((com.fluendo.jkate.Event)buf.object);
 50+ return Pad.OK;
 51+ }
 52+ };
 53+
 54+ /**
 55+ * Create a new Kate overlay
 56+ */
 57+ public KateOverlay() {
 58+ super();
 59+ addPad(kateSinkPad);
 60+ }
 61+
 62+
 63+ /**
 64+ * Add a new Kate event to the renderer.
 65+ * This needs locking so the Kate events are not changed while the
 66+ * overlay is rendering them to an image.
 67+ */
 68+ protected synchronized void addKateEvent(com.fluendo.jkate.Event ev) {
 69+ tr.add(ev);
 70+ Debug.log(Debug.DEBUG, "Kate overlay got Kate event: "+new String(ev.text));
 71+ }
 72+
 73+ /**
 74+ * Overlay the Kate renderer onto the given image.
 75+ */
 76+ protected synchronized void overlay(com.fluendo.jst.Buffer buf) {
 77+ Image img;
 78+
 79+ if (buf.object instanceof ImageProducer) {
 80+ img = component.createImage((ImageProducer)buf.object);
 81+ }
 82+ else if (buf.object instanceof Image) {
 83+ img = (Image)buf.object;
 84+ }
 85+ else {
 86+ System.out.println(this+": unknown buffer received "+buf);
 87+ return;
 88+ }
 89+
 90+ /* before rendering, we update the state of the events; for now this
 91+ just weeds out old ones, but at some point motions could be tracked. */
 92+ int ret = tr.update(component, buf.timestamp/(double)Clock.SECOND);
 93+ /* if there are no Kate events active, just return the buffer as is */
 94+ if (ret == 1)
 95+ return;
 96+
 97+ Dimension d = component.getSize();
 98+ int x = 0;
 99+ int y = 0;
 100+ int w = d.width;
 101+ int h = d.height;
 102+
 103+ if (bimg == null || bimg.getWidth() != w || bimg.getHeight() != h) {
 104+ bimg = component.getGraphicsConfiguration().createCompatibleImage(w, h);
 105+ }
 106+
 107+ Graphics2D g2 = bimg.createGraphics();
 108+ g2.drawImage(img, x, y, w, h, null);
 109+
 110+ /* render Kate stream on top */
 111+ tr.render(component, bimg);
 112+
 113+ g2.dispose();
 114+
 115+ buf.object = bimg;
 116+ }
 117+
 118+ public String getFactoryName ()
 119+ {
 120+ return "kateoverlay";
 121+ }
 122+}
Index: trunk/cortado/src/com/fluendo/plugin/OggPayload.java
@@ -30,6 +30,7 @@
3131 public boolean isType (Packet op);
3232 /**
3333 * Initialize the payload with a header packet.
 34+ * Returns < 0 for error, 0 if OK, 1 if OK and ready for decoding data.
3435 */
3536 public int takeHeader (Packet op);
3637 /**
@@ -52,5 +53,10 @@
5354 * Get mime type
5455 */
5556 public String getMime ();
 57+ /**
 58+ * Check if the stream is discontinuous (eg, no need to wait
 59+ * for data on this stream before playing)
 60+ */
 61+ public boolean isDiscontinuous ();
5662 }
5763
Index: trunk/cortado/src/com/fluendo/jst/Sink.java
@@ -29,7 +29,7 @@
3030 private boolean needPreroll;
3131 private Clock.ClockID clockID;
3232 protected boolean discont;
33 - protected long segStart;
 33+ protected long segStart = 0;
3434 protected long segStop;
3535 protected long segPosition;
3636 protected long pauseTime;
@@ -352,11 +352,11 @@
353353 synchronized (this) {
354354 if (currentState == PLAY) {
355355 if (clock != null) {
356 - position = clock.getTime() - baseTime + segPosition;
 356+ position = clock.getTime() - baseTime + segPosition + segStart;
357357 }
358358 }
359359 else {
360 - position = pauseTime + segPosition;
 360+ position = pauseTime + segPosition + segStart;
361361 }
362362 }
363363 query.setPosition(Format.TIME, position);
Index: trunk/cortado/src/com/fluendo/jst/Element.java
@@ -464,4 +464,8 @@
465465 public boolean query (Query query) {
466466 return false;
467467 }
 468+
 469+ public Pad requestSinkPad(Pad peer) {
 470+ return null;
 471+ }
468472 }
Index: trunk/cortado/src/com/fluendo/jtiger/Renderer.java
@@ -0,0 +1,62 @@
 2+/* JTiger
 3+ * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 4+ *
 5+ * Parts of JTiger are based on code by Wim Taymans <wim@fluendo.com>
 6+ *
 7+ * This program is free software; you can redistribute it and/or
 8+ * modify it under the terms of the GNU Library General Public License
 9+ * as published by the Free Software Foundation; either version 2 of
 10+ * the License, or (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU Library General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU Library General Public
 18+ * License along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20+ */
 21+
 22+package com.fluendo.jtiger;
 23+
 24+import java.util.*;
 25+import java.awt.*;
 26+import java.awt.image.*;
 27+
 28+public class Renderer {
 29+ private Vector items = new Vector();
 30+
 31+ /**
 32+ * Add a new event to the renderer.
 33+ */
 34+ public void add(com.fluendo.jkate.Event ev) {
 35+ items.addElement(new Item(ev));
 36+ }
 37+
 38+ /**
 39+ * Update the renderer, and all the events it tracks.
 40+ * Returns 1 if there is nothing to draw, as an optimization
 41+ */
 42+ public int update(Component c, double t) {
 43+ for (int n=0; n<items.size(); ++n) {
 44+ boolean ret = ((Item)items.get(n)).update(c, t);
 45+ if (!ret) {
 46+ items.removeElementAt(n);
 47+ --n;
 48+ }
 49+ }
 50+ if (items.size() == 0)
 51+ return 1;
 52+ return 0;
 53+ }
 54+
 55+ /**
 56+ * Renders onto the given image.
 57+ */
 58+ public void render(Component c, BufferedImage bimg) {
 59+ for (int n=0; n<items.size(); ++n) {
 60+ ((Item)items.get(n)).render(c, bimg);
 61+ }
 62+ }
 63+}
Index: trunk/cortado/src/com/fluendo/jtiger/TigerBitmap.java
@@ -0,0 +1,93 @@
 2+/* JTiger
 3+ * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 4+ *
 5+ * Parts of JTiger are based on code by Wim Taymans <wim@fluendo.com>
 6+ *
 7+ * This program is free software; you can redistribute it and/or
 8+ * modify it under the terms of the GNU Library General Public License
 9+ * as published by the Free Software Foundation; either version 2 of
 10+ * the License, or (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU Library General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU Library General Public
 18+ * License along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20+ */
 21+
 22+package com.fluendo.jtiger;
 23+
 24+import java.util.*;
 25+import java.awt.*;
 26+import java.awt.image.*;
 27+import com.fluendo.jkate.*;
 28+import com.fluendo.utils.*;
 29+
 30+public class TigerBitmap {
 31+ private Image image;
 32+ private Image scaled_image;
 33+
 34+ /**
 35+ * Create a new TigerBitmap from a Kate bitmap and optional palette.
 36+ */
 37+ public TigerBitmap(Bitmap kb, Palette kp)
 38+ {
 39+ if (kb == null) {
 40+ image = null;
 41+ }
 42+ else if (kb.bpp == 0) {
 43+ /* PNG */
 44+ image = createPNGBitmap(kb, kp);
 45+ }
 46+ else {
 47+ if (kp == null) {
 48+ image = null;
 49+ }
 50+ else {
 51+ image = createPalettedBitmap(kb, kp);
 52+ }
 53+ }
 54+ }
 55+
 56+ /**
 57+ * Returns a scaled version of the image.
 58+ */
 59+ public Image getScaled(int width, int height)
 60+ {
 61+ if (scaled_image == null || width != scaled_image.getWidth(null) || height != scaled_image.getHeight(null)) {
 62+ scaled_image = image.getScaledInstance(width, height, BufferedImage.SCALE_SMOOTH); // TODO: quality setting
 63+ }
 64+ return scaled_image;
 65+ }
 66+
 67+ /**
 68+ * Create an image from bits representing a PNG image.
 69+ */
 70+ private Image createPNGBitmap(Bitmap kb, Palette kp)
 71+ {
 72+ Debug.warning("PNG bitmaps not supported yet");
 73+ return null;
 74+ }
 75+
 76+ /**
 77+ * Create a paletted image.
 78+ */
 79+ private Image createPalettedBitmap(Bitmap kb, Palette kp)
 80+ {
 81+ byte[] cmap = new byte[4*kp.colors.length];
 82+ for (int n=0; n<kp.colors.length; ++n) {
 83+ cmap[n*4+0] = kp.colors[n].r;
 84+ cmap[n*4+1] = kp.colors[n].g;
 85+ cmap[n*4+2] = kp.colors[n].b;
 86+ cmap[n*4+3] = kp.colors[n].a;
 87+ }
 88+ IndexColorModel icm = new IndexColorModel(kb.bpp, kp.colors.length, cmap, 0, true);
 89+ BufferedImage img = new BufferedImage(kb.width, kb.height, BufferedImage.TYPE_BYTE_INDEXED, icm);
 90+ WritableRaster r = img.getRaster();
 91+ r.setDataElements(0, 0, kb.width, kb.height, kb.pixels);
 92+ return img;
 93+ }
 94+}
Index: trunk/cortado/src/com/fluendo/jtiger/README
@@ -0,0 +1,3 @@
 2+JTiger is a very basic renderer for Kate streams.
 3+
 4+At the moment, only raw text is supported.
Index: trunk/cortado/src/com/fluendo/jtiger/Item.java
@@ -0,0 +1,201 @@
 2+/* JTiger
 3+ * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
 4+ *
 5+ * Parts of JTiger are based on code by Wim Taymans <wim@fluendo.com>
 6+ *
 7+ * This program is free software; you can redistribute it and/or
 8+ * modify it under the terms of the GNU Library General Public License
 9+ * as published by the Free Software Foundation; either version 2 of
 10+ * the License, or (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU Library General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU Library General Public
 18+ * License along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20+ */
 21+
 22+package com.fluendo.jtiger;
 23+
 24+import java.util.*;
 25+import java.awt.*;
 26+import java.awt.image.*;
 27+import java.awt.font.*;
 28+import java.text.*;
 29+import com.fluendo.jkate.Event;
 30+import com.fluendo.jkate.Tracker;
 31+import com.fluendo.utils.*;
 32+
 33+public class Item {
 34+ private Tracker kin = null;
 35+ private boolean alive = false;
 36+ private Font font = null;
 37+ private int font_size = 0;
 38+ private String text = null;
 39+ private TigerBitmap background_image = null;
 40+
 41+ private int width = -1;
 42+ private int height = -1;
 43+
 44+ private float region_x;
 45+ private float region_y;
 46+ private float region_w;
 47+ private float region_h;
 48+
 49+
 50+ /**
 51+ * Create a new item from a Kate event.
 52+ */
 53+ public Item(com.fluendo.jkate.Event ev) {
 54+ this.kin = new Tracker(ev);
 55+ text = null;
 56+ if (ev.text != null && ev.text.length > 0) {
 57+ try {
 58+ text = new String(ev.text, "UTF8");
 59+ }
 60+ catch (Exception e) {
 61+ Debug.warning("Failed to convert text from UTF-8 - text will not display");
 62+ text = null;
 63+ }
 64+ }
 65+ }
 66+
 67+ /**
 68+ * Create a font suitable for displaying on the given component
 69+ */
 70+ protected void createFont(Component c) {
 71+ Dimension d = c.getSize();
 72+ font_size = d.width / 32;
 73+ if (font_size < 12) font_size = 12;
 74+ font = new Font("sansserif", Font.BOLD, font_size); // TODO: should be selectable ?
 75+ }
 76+
 77+ /**
 78+ * Regenerate any cached data to match any relevant changes in the
 79+ * given component
 80+ */
 81+ protected void updateCachedData(Component c) {
 82+ Dimension d = c.getSize();
 83+ if (d.width == width && d.height == height)
 84+ return;
 85+
 86+ createFont(c);
 87+
 88+ width = d.width;
 89+ height = d.height;
 90+ }
 91+
 92+ /**
 93+ * Updates the item at the given time.
 94+ * returns true for alive, false for dead
 95+ */
 96+ public boolean update(Component c, double t) {
 97+ com.fluendo.jkate.Event ev = kin.ev;
 98+ if (ev == null) return false;
 99+ if (t >= ev.end_time) return false;
 100+
 101+ if (t < ev.start_time) {
 102+ alive = false;
 103+ }
 104+ else {
 105+ alive = true;
 106+ }
 107+
 108+ Dimension d = c.getSize();
 109+ return kin.update(t-ev.start_time, d, d);
 110+ }
 111+
 112+ /**
 113+ * Set up the region.
 114+ */
 115+ public void setupRegion(Component c) {
 116+ if (kin.has[Tracker.has_region]) {
 117+ region_x = kin.region_x;
 118+ region_y = kin.region_y;
 119+ region_w = kin.region_w;
 120+ region_h = kin.region_h;
 121+ }
 122+ else {
 123+ Dimension d = c.getSize();
 124+ region_x = d.width * 0.1f;
 125+ region_y = d.height * 0.8f;
 126+ region_w = d.width * 0.8f;
 127+ region_h = d.height * 0.1f;
 128+ }
 129+ }
 130+
 131+ /**
 132+ * Renders the item on the given image.
 133+ */
 134+ public void render(Component c, BufferedImage bimg) {
 135+ com.fluendo.jkate.Event ev = kin.ev;
 136+
 137+ if (!alive)
 138+ return;
 139+
 140+ updateCachedData(c);
 141+
 142+ setupRegion(c);
 143+ renderBackground(bimg);
 144+ renderText(bimg);
 145+ }
 146+
 147+ /**
 148+ * Render a background for the item, if approrpiate.
 149+ * The background may be a color, or an image.
 150+ */
 151+ public void renderBackground(BufferedImage bimg)
 152+ {
 153+ if (kin.ev.bitmap != null) {
 154+ if (background_image == null) {
 155+ background_image = new TigerBitmap(kin.ev.bitmap, kin.ev.palette);
 156+ }
 157+
 158+ Graphics2D g = bimg.createGraphics();
 159+ int rx = (int)(region_x+0.5), ry = (int)(region_y+0.5);
 160+ int rw = (int)(region_w+0.5), rh = (int)(region_h+0.5);
 161+ g.drawImage(background_image.getScaled(rw, rh), rx, ry, null);
 162+ g.dispose();
 163+ }
 164+ }
 165+
 166+ /**
 167+ * Render text text for the item, if approrpiate.
 168+ */
 169+ public void renderText(BufferedImage bimg)
 170+ {
 171+ if (text == null)
 172+ return;
 173+
 174+ Graphics2D g = bimg.createGraphics();
 175+
 176+ AttributedString atext = new AttributedString(text, font.getAttributes());
 177+ AttributedCharacterIterator text_it = atext.getIterator();
 178+ int text_end = text_it.getEndIndex();
 179+
 180+ FontRenderContext frc = g.getFontRenderContext();
 181+ LineBreakMeasurer lbm = new LineBreakMeasurer(text_it, frc);
 182+ float dy = 0.0f;
 183+ float shadow_dx = font_size * 0.05f, shadow_dy = font_size * 0.05f;
 184+ while (lbm.getPosition() < text_end) {
 185+ TextLayout layout = lbm.nextLayout(region_w);
 186+ dy += layout.getAscent();
 187+ float tw = layout.getAdvance();
 188+
 189+ g.setColor(Color.black);
 190+ layout.draw(g, region_x+((region_w-tw)/2)+shadow_dx, region_y+dy+shadow_dy);
 191+ layout.draw(g, region_x+((region_w-tw)/2)-shadow_dx, region_y+dy-shadow_dy);
 192+ layout.draw(g, region_x+((region_w-tw)/2)+shadow_dx, region_y+dy-shadow_dy);
 193+ layout.draw(g, region_x+((region_w-tw)/2)-shadow_dx, region_y+dy+shadow_dy);
 194+ g.setColor(Color.white);
 195+ layout.draw(g, region_x+((region_w-tw)/2), region_y+dy);
 196+
 197+ dy += layout.getDescent() + layout.getLeading();
 198+ }
 199+
 200+ g.dispose();
 201+ }
 202+}
Index: trunk/cortado/src/com/fluendo/player/CortadoPipeline.java
@@ -18,6 +18,7 @@
1919
2020 package com.fluendo.player;
2121
 22+import java.util.*;
2223 import java.awt.*;
2324 import java.net.URL;
2425
@@ -31,6 +32,7 @@
3233 private String password;
3334 private boolean enableAudio;
3435 private boolean enableVideo;
 36+ private int enableKate;
3537 private Component component;
3638 private int bufferSize = -1;
3739 private int bufferLow = -1;
@@ -46,8 +48,12 @@
4749 private Element videosink;
4850 private Element audiosink;
4951 private Element v_queue, a_queue;
50 - private Pad asinkpad, vsinkpad;
 52+ private Element overlay;
 53+ private Pad asinkpad, ovsinkpad, oksinkpad;
5154 private Pad apad, vpad;
 55+ private Vector katedec = new Vector();
 56+ private Vector k_queue = new Vector();
 57+ private Element kselector = null;
5258
5359 public boolean usingJavaX = false;
5460
@@ -115,7 +121,7 @@
116122
117123 pad.link(v_queue.getPad("sink"));
118124 v_queue.getPad("src").link(videodec.getPad("sink"));
119 - if (!videodec.getPad("src").link(vsinkpad)) {
 125+ if (!videodec.getPad("src").link(ovsinkpad)) {
120126 postMessage (Message.newError (this, "videosink already linked"));
121127 return;
122128 }
@@ -132,7 +138,7 @@
133139 videodec.setProperty ("component", component);
134140
135141 pad.link(videodec.getPad("sink"));
136 - if (!videodec.getPad("src").link(vsinkpad)) {
 142+ if (!videodec.getPad("src").link(ovsinkpad)) {
137143 postMessage (Message.newError (this, "videosink already linked"));
138144 return;
139145 }
@@ -146,7 +152,7 @@
147153 videodec.setProperty ("component", component);
148154
149155 pad.link(videodec.getPad("sink"));
150 - if (!videodec.getPad("src").link(vsinkpad)) {
 156+ if (!videodec.getPad("src").link(ovsinkpad)) {
151157 postMessage (Message.newError (this, "videosink already linked"));
152158 return;
153159 }
@@ -154,13 +160,104 @@
155161
156162 videodec.setState (PAUSE);
157163 }
 164+ else if (enableVideo && mime.equals("application/x-kate")) {
 165+ Element tmp_k_queue, tmp_katedec, tmp_katesink;
 166+ Pad tmp_kpad, tmp_ksinkpad;
 167+ int kate_index = katedec.size();
 168+
 169+ Debug.debug("Found Kate stream, setting up pipeline branch");
 170+
 171+ /* dynamically create a queue/decoder/overlay pipeline */
 172+ tmp_k_queue = ElementFactory.makeByName("queue", "k_queue"+kate_index);
 173+ if (tmp_k_queue == null) {
 174+ noSuchElement ("queue");
 175+ return;
 176+ }
 177+
 178+ tmp_katedec = ElementFactory.makeByName("katedec", "katedec"+kate_index);
 179+ if (tmp_katedec == null) {
 180+ noSuchElement ("katedec");
 181+ return;
 182+ }
 183+
 184+ /* The selector is created when the first Kate stream is encountered */
 185+ if (kselector == null) {
 186+ Debug.debug("No Kate selector yet, creating one");
 187+
 188+ /* insert an overlay before the video sink */
 189+ ovsinkpad.unlink();
 190+ videodec.getPad("src").unlink();
 191+ overlay = ElementFactory.makeByName("kateoverlay", "overlay");
 192+ if (overlay == null) {
 193+ noSuchElement ("overlay");
 194+ return;
 195+ }
 196+ ovsinkpad = overlay.getPad("videosink");
 197+ oksinkpad = overlay.getPad("katesink");
 198+ if (!videodec.getPad("src").link(ovsinkpad)) {
 199+ postMessage (Message.newError (this, "Failed linking video decoder to overlay"));
 200+ return;
 201+ }
 202+ add(overlay);
 203+ overlay.setProperty ("component", component);
 204+ overlay.getPad("videosrc").link(videosink.getPad("sink"));
 205+
 206+ kselector = ElementFactory.makeByName("selector", "selector");
 207+ if (kselector == null) {
 208+ noSuchElement ("selector");
 209+ return;
 210+ }
 211+ add(kselector);
 212+ if (!kselector.getPad("src").link(oksinkpad)) {
 213+ postMessage (Message.newError (this, "Failed linking Kate selector to overlay"));
 214+ return;
 215+ }
 216+ kselector.setState (PAUSE);
 217+ }
 218+ tmp_katesink = kselector;
 219+
 220+ add(tmp_k_queue);
 221+ add(tmp_katedec);
 222+
 223+ tmp_kpad = pad;
 224+ tmp_ksinkpad = tmp_katesink.getPad("sink");
 225+
 226+ /* link new elements together */
 227+ if (!pad.link(tmp_k_queue.getPad("sink"))) {
 228+ postMessage (Message.newError (this, "Failed to link new Kate stream to queue"));
 229+ return;
 230+ }
 231+ if (!tmp_k_queue.getPad("src").link(tmp_katedec.getPad("sink"))) {
 232+ postMessage (Message.newError (this, "Failed to link new Kate queue to decoder"));
 233+ return;
 234+ }
 235+
 236+ Pad new_selector_pad = kselector.requestSinkPad(tmp_katedec.getPad("src"));
 237+ if (!tmp_katedec.getPad("src").link(new_selector_pad)) {
 238+ postMessage (Message.newError (this, "kate sink already linked"));
 239+ return;
 240+ }
 241+
 242+ tmp_katedec.setState (PAUSE);
 243+ tmp_k_queue.setState (PAUSE);
 244+
 245+ /* add to the lists */
 246+ katedec.addElement(tmp_katedec);
 247+ k_queue.addElement(tmp_k_queue);
 248+
 249+ /* if we have just added the one that was selected, link it now */
 250+ if (enableKate == katedec.size()-1) {
 251+ doEnableKateIndex(enableKate);
 252+ }
 253+ }
158254 }
159255
160256 public void padRemoved(Pad pad) {
161257 pad.unlink();
162258 if (pad == vpad) {
163259 Debug.log(Debug.INFO, "video pad removed "+pad);
164 - vsinkpad.unlink();
 260+ ovsinkpad.unlink();
 261+ //oksinkpad.unlink(); // needed ????
165262 vpad = null;
166263 }
167264 else if (pad == apad) {
@@ -172,6 +269,7 @@
173270
174271 public void noMorePads() {
175272 boolean changed = false;
 273+ Element el;
176274
177275 Debug.log(Debug.INFO, "all streams detected");
178276
@@ -185,8 +283,28 @@
186284 if (vpad == null && enableVideo) {
187285 Debug.log(Debug.INFO, "file has no video, remove videosink");
188286 videosink.setState(STOP);
 287+ if (overlay != null) {
 288+ overlay.setState(STOP);
 289+ }
 290+ for (int n=0; n<katedec.size(); ++n) {
 291+ el = (Element)katedec.get(n);
 292+ el.setState(STOP);
 293+ remove(el);
 294+ el = (Element)k_queue.get(n);
 295+ el.setState(STOP);
 296+ remove(el);
 297+ }
 298+ if (kselector != null) {
 299+ kselector.setState(STOP);
 300+ remove(kselector);
 301+ kselector = null;
 302+ }
189303 remove (videosink);
 304+ remove (overlay);
 305+ katedec.clear();
 306+ k_queue.clear();
190307 videosink = null;
 308+ overlay = null;
191309 changed = true;
192310 }
193311 if (changed)
@@ -199,6 +317,7 @@
200318 enableAudio = true;
201319 enableVideo = true;
202320 application = cortado;
 321+ enableKate = -1; /* none by default */
203322 }
204323
205324 public void setUrl(String anUrl) {
@@ -228,6 +347,40 @@
229348 return enableVideo;
230349 }
231350
 351+ /**
 352+ * Selects the Kate stream index (if any) to enable.
 353+ * The first Kate stream has index 0, the second has index 1, etc.
 354+ * A negative index will enable none.
 355+ */
 356+ public void enableKateIndex(int idx) {
 357+ if (idx == enableKate) return;
 358+ doEnableKateIndex(idx);
 359+ }
 360+
 361+ /**
 362+ * Enables the given Kate stream, by index.
 363+ * A negative index will enable none.
 364+ */
 365+ private void doEnableKateIndex(int idx)
 366+ {
 367+ if (kselector != null) {
 368+ Debug.info("Switching Kate streams from "+enableKate+" to "+idx);
 369+ kselector.setProperty("selected", new Integer(idx));
 370+ }
 371+ else {
 372+ Debug.warning("Switching Kate stream request, but no Kate selector exists");
 373+ }
 374+
 375+ enableKate = idx;
 376+ }
 377+
 378+ /**
 379+ * Returns the index of the currently enabled Kate stream (negative if none)
 380+ */
 381+ public int getEnabledKateIndex() {
 382+ return enableKate;
 383+ }
 384+
232385 public void setComponent(Component c) {
233386 component = c;
234387 }
@@ -410,8 +563,9 @@
411564 resize(component.getSize());
412565
413566 videosink.setProperty ("max-lateness", Long.toString(Clock.MSECOND * 20));
414 - vsinkpad = videosink.getPad("sink");
415567 add(videosink);
 568+
 569+ ovsinkpad = videosink.getPad("sink");
416570 }
417571 if (audiosink == null && videosink == null) {
418572 postMessage(Message.newError(this, "Both audio and video are disabled, can't play anything"));
@@ -445,6 +599,7 @@
446600 }
447601
448602 private boolean cleanup() {
 603+ int n;
449604 Debug.log(Debug.INFO, "cleanup");
450605 if (httpsrc != null) {
451606 remove (httpsrc);
@@ -458,8 +613,13 @@
459614 if (videosink != null) {
460615 remove (videosink);
461616 videosink = null;
462 - vsinkpad = null;
463617 }
 618+ if (overlay != null) {
 619+ remove (overlay);
 620+ overlay = null;
 621+ ovsinkpad = null;
 622+ oksinkpad = null;
 623+ }
464624 if (buffer != null) {
465625 remove (buffer);
466626 buffer = null;
@@ -485,6 +645,23 @@
486646 remove(audiodec);
487647 audiodec = null;
488648 }
 649+
 650+ for (n=0; n<katedec.size(); ++n) {
 651+ if (k_queue.get(n) != null) {
 652+ remove ((Element)k_queue.get(n));
 653+ }
 654+ if (katedec.get(n) != null) {
 655+ remove((Element)katedec.get(n));
 656+ }
 657+ }
 658+ k_queue.clear();
 659+ katedec.clear();
 660+
 661+ if (kselector != null) {
 662+ remove(kselector);
 663+ kselector = null;
 664+ }
 665+
489666 return true;
490667 }
491668
Index: trunk/cortado/src/com/fluendo/player/Cortado.java
@@ -34,6 +34,7 @@
3535 private String urlString;
3636 private boolean audio;
3737 private boolean video;
 38+ private int kateIndex;
3839 private boolean showSpeaker;
3940 private boolean keepAspect;
4041 private boolean autoPlay;
@@ -100,6 +101,7 @@
101102 "Total duration of the file in seconds (default unknown)"},
102103 {"audio", "boolean", "Enable audio playback (default true)"},
103104 {"video", "boolean", "Enable video playback (default true)"},
 105+ {"kateIndex", "boolean", "Enable playback of a particular Kate stream (default -1 (none))"},
104106 {"statusHeight", "int", "The height of the status area (default 12)"},
105107 {"autoPlay", "boolean", "Automatically start playback (default true)"},
106108 {"showStatus", "enum", "Show status area (auto|show|hide) (default auto)"},
@@ -223,6 +225,7 @@
224226 durationParam = getDoubleParam("duration", -1.0);
225227 audio = getBoolParam("audio", true);
226228 video = getBoolParam("video", true);
 229+ kateIndex = getIntParam("kateIndex", -1);
227230 statusHeight = getIntParam("statusHeight", 12);
228231 autoPlay = getBoolParam("autoPlay", true);
229232 showStatus = getEnumParam("showStatus", showStatusVals, "auto");
@@ -257,6 +260,7 @@
258261 pipeline.setPassword(password);
259262 pipeline.enableAudio(audio);
260263 pipeline.enableVideo(video);
 264+ pipeline.enableKateIndex(kateIndex);
261265 pipeline.setBufferSize(bufferSize);
262266 pipeline.setBufferLow(bufferLow);
263267 pipeline.setBufferHigh(bufferHigh);
@@ -409,6 +413,12 @@
410414 setStatusVisible(false, false);
411415 }
412416 }
 417+
 418+ // we want to be able to change subtitles at runtime without having
 419+ // to restart the player, and selecting a stream which is already selected
 420+ // is very cheap, so we update the stream to play periodically.
 421+ pipeline.enableKateIndex(Integer.valueOf(getParam("kateIndex", "" + -1)).intValue());
 422+
413423 } catch (Exception e) {
414424 if (statusRunning) {
415425 Debug.log(Debug.ERROR, "Exception in status thread:");
Index: trunk/cortado/README
@@ -7,6 +7,8 @@
88 - JST, a port of the GStreamer 0.10 design to Java
99 - jcraft, a copy of the JCraft JOgg/Jorbis code
1010 - jheora, an implementation of Theora in Java
 11+- jkate, an implementation of a basic Kate decoder in Java
 12+- jtiger, a basic Kate renderer (simple text/images only for now)
1113 - codecs (currently only containing the Smoke codec, a variant on Jpeg)
1214 - JST plugins for:
1315 - HTTP source element
@@ -15,6 +17,9 @@
1618 - Vorbis and MuLaw audio decoders
1719 - Java 1.1 sun.audio API audio sink
1820 - Java 1.4 javax.sound.sampled API audio sink
 21+ - Overlay element
 22+ - Kate text decoder and overlay
 23+ - Selector element
1924 - examples
2025 - applets
2126
@@ -152,6 +157,13 @@
153158 resources to play an audio stream. true or false.
154159 Defaults to true
155160
 161+ kateIndex: int
 162+ Use text from the given Kate stream (indexed from zero).
 163+ The first Kate stream found will have index 0, the second will
 164+ have index 1, etc.
 165+ At most one Kate stream may be enabled at a time.
 166+ Defaults to -1 (none)
 167+
156168 statusHeight: int
157169 The height of the status area (default 12)
158170

Status & tagging log