Commit b654a836 authored by daFischer's avatar daFischer

Seeking works(inefficient, though). Lectures can be chosen via the path...

Seeking works(inefficient, though). Lectures can be chosen via the path parameter when using the phtml file. e.g. fileplayer.hmtl?path=lecture
parent 58da01b1
......@@ -88,16 +88,17 @@ int Audio::getPosition()
if((error = alGetError())!= AL_NO_ERROR)
printf("getTime error: %d\n", error);
//printf("%f\n",(float) time);
return (int)(time*1000);
return (int)time;
}
void Audio::setPosition(int pos)
{
ALfloat time=(ALfloat)pos/1000.0;
ALfloat time=(ALfloat)pos;
alSourcef(source, AL_SEC_OFFSET, time);
if(alGetError()== AL_NO_ERROR)
printf("Audio.cpp: set Position error");
uint error;
if((error=alGetError()) != AL_NO_ERROR)
printf("Audio.cpp: set Position error: %d\n", error);
}
void Audio::changeVolume(float volume){
......@@ -125,7 +126,7 @@ int Audio::getDuration()
if(alGetError()!= AL_NO_ERROR)
printf("getDuration error\n");
return (int)(seconds*1000);
return (int)seconds;
}
bool Audio::hasFailed()
......
......@@ -13,7 +13,7 @@ AudioJS::AudioJS() {
duration = EM_ASM_INT({
return x_getDuration();
},0);
printf("Duration: %d min\n",duration/60000);
printf("Duration: %d min\n",duration/60);
}
void AudioJS::togglePlay(){
......@@ -28,7 +28,7 @@ int AudioJS::getDuration(){
void AudioJS::setPosition(int pos){
EM_ASM_INT({
x_setDuration($0);
x_setPosition($0);
return 0;
},pos);
}
......
......@@ -13,6 +13,7 @@ Controls::Controls(Video* video, AudioInterface* audio) {
this->video=video;
this->audio=audio;
duration=audio->getDuration();
ProtocolPreferences prefs;
//TODO: might make these relative to video's height
......@@ -30,9 +31,9 @@ Controls::Controls(Video* video, AudioInterface* audio) {
mouseOnFullScreenButton=false;
#ifdef EMSCRIPTEN
EM_ASM_INT({
x_setupFullScreen($0, $1);
}, 48, height);
EM_ASM(
x_setupFullScreen();
);
#endif
}
......@@ -52,6 +53,7 @@ void Controls::registerClick(Uint16 mx, Uint16 my){
else if(mx<=128 && mx>=64)
volumeClicked=true;
}
registerMovement(mx,my);
}
void Controls::registerMouseUp(){
......@@ -80,7 +82,7 @@ extern "C" bool getOnFullScreenButton(){
void Controls::update(){
if(!timeLineClicked && timeLineChange>=0)
{
skipTo(audio->getDuration()*timeLineChange/width);
skipTo(duration*timeLineChange/width);
timeLineChange=-1;
}
......@@ -121,11 +123,14 @@ void Controls::draw(){
SDL_FillRect(screen, &rect, 0xff338844);
//timeLine background
redefineRect(&rect, 0, y-timeLineHeight+2, width, timeLineHeight-2);
redefineRect(&rect, 0, y-timeLineHeight, width, timeLineHeight);
SDL_FillRect(screen, &rect, 0xff333333);
//timeLine foreground
redefineRect(&rect, 0, y-timeLineHeight, width*audio->getPosition()/audio->getDuration(), timeLineHeight);
if(timeLineChange==-1)
redefineRect(&rect, 0, y-timeLineHeight, audio->getPosition()*width/duration, timeLineHeight);
else
redefineRect(&rect, 0, y-timeLineHeight, timeLineChange, timeLineHeight);
SDL_FillRect(screen, &rect, 0xffaa0000);
SDL_UpdateRect(screen, 0,y-timeLineHeight,width,height+timeLineHeight);
......@@ -139,7 +144,8 @@ void Controls::redefineRect(SDL_Rect* rect, int x, int y, int w, int h){
}
void Controls::skipTo(int position){
audio->setPosition(position);
video->seekPosition(position);
}
void Controls::changeVolume(float volume){
......
......@@ -40,6 +40,7 @@ private:
bool volumeClicked;
float volume;
int y;
int duration;
void togglePlay();
void toggleFullscreen();
void skipTo(int position);
......
......@@ -22,3 +22,7 @@ void DeleteAllAnnotation::paint(SDL_Surface *screen, ProtocolPreferences* prefs)
{
}
bool DeleteAllAnnotation::completeScreen(int w, int h){
return false;
}
......@@ -16,6 +16,7 @@ public:
virtual ~DeleteAllAnnotation();
void paint(SDL_Surface *screen, ProtocolPreferences* prefs);
bool isEmpty();
bool completeScreen(int w, int h);
private:
......
......@@ -22,3 +22,8 @@ void EmptyMessage::paint(SDL_Surface *screen, ProtocolPreferences* prefs)
{
}
bool EmptyMessage::completeScreen(int w, int h){
return false;
}
......@@ -17,6 +17,7 @@ public:
~EmptyMessage();
void paint(SDL_Surface *screen, ProtocolPreferences* prefs);
bool isEmpty();
bool completeScreen(int w, int h);
private:
......
......@@ -27,6 +27,10 @@ HextileMessage::~HextileMessage() {
delete data;
}
bool HextileMessage::completeScreen(int w, int h){
return (this->w==w && this->h==h);
}
void HextileMessage::paint(SDL_Surface *screen, ProtocolPreferences* prefs)
{
//printf("paint Hextile\n");
......@@ -70,7 +74,7 @@ void HextileMessage::handleHextileSubrect(SDL_Surface *screen, ProtocolPreferenc
}
//printf("|");
// Read and draw the background if specified.
ColorConverter con;
//ColorConverter con;
unsigned char cbuf[prefs->bytesPerPixel];
......@@ -82,8 +86,6 @@ void HextileMessage::handleHextileSubrect(SDL_Surface *screen, ProtocolPreferenc
os.write(cbuf);*/
// store encoded background color
/*for(int i=0;i<prefs->bytesPerPixel;i++)
*((char*)(&hextile_bg)+i)=cbuf[i];*/
hextile_bg=con.decodeColor(cbuf, prefs->bytesPerPixel, prefs->format);
}
//printf("test4\n");
......@@ -100,8 +102,6 @@ void HextileMessage::handleHextileSubrect(SDL_Surface *screen, ProtocolPreferenc
os.write(cbuf);*/
// store encoded foreground color
/*for(int i=0;i<prefs->bytesPerPixel;i++)
*((char*)(&hextile_fg)+i)=cbuf[i];*/
hextile_fg=con.decodeColor(cbuf, prefs->bytesPerPixel, prefs->format);
}
......@@ -133,8 +133,6 @@ void HextileMessage::handleHextileSubrect(SDL_Surface *screen, ProtocolPreferenc
for (int j = 0; j < nSubrects; j++) {
if ((subencoding & HextileSubrectsColoured) != 0) {
// store encoded foreground color
/*for(int k=0;k<prefs->bytesPerPixel;k++)
*((char*)(&hextile_fg)+k)=buf[k+i];*/
hextile_fg=con.decodeColor(&buf[i], prefs->bytesPerPixel, prefs->format);
i += prefs->bytesPerPixel;
......@@ -154,18 +152,14 @@ void HextileMessage::handleHextileSubrect(SDL_Surface *screen, ProtocolPreferenc
void HextileMessage::handleRawRect(SDL_Surface *screen, ProtocolPreferences* prefs, int tx, int ty, int tw, int th)
{
//printf("%d(%d)",offSet,tw);
/*SDL_Rect rect = {tx,ty,tw,th};
SDL_FillRect(screen, &rect, (uint)(random()%0xffffff));*/
SDL_Rect rect = {0, 0, 1, 1};
//SDL_LockSurface(screen);
switch (prefs->bytesPerPixel) {
case 1:
{
for (int dy = y; dy < y + h; dy++) {
for (int dy = ty; dy < ty + th; dy++) {
//is.readFully(graphicsContext.pixels8, dy * graphicsContext.prefs->framebufferWidth + x, w);
read((char*)(screen->pixels)+dy * prefs->framebufferWidth + x,w);
read((char*)(screen->pixels)+dy * prefs->framebufferWidth + tx,tw);
/*// buffering TODO:?
if (os != null)
......@@ -180,7 +174,6 @@ void HextileMessage::handleRawRect(SDL_Surface *screen, ProtocolPreferences* pre
if (prefs->bigEndian)
for (int dy = ty; dy < ty + th; dy++)
{
//read((char*)screen->pixels + (dy * w + tx) * 4, tw * prefs->bytesPerPixel);
for(int dx = 0; dx < tw; dx++)
{
read((char*)rawColor, prefs->bytesPerPixel);
......@@ -193,16 +186,13 @@ void HextileMessage::handleRawRect(SDL_Surface *screen, ProtocolPreferences* pre
else
for (int dy = ty; dy < ty + th; dy++)
{
//read((char*)screen->pixels + (dy * w + tx) * 4, tw * prefs->bytesPerPixel);
for(int dx = 0; dx < tw; dx++)
{
read((char*)rawColor, prefs->bytesPerPixel);
color = con.decodeColor(rawColor,prefs->bytesPerPixel,prefs->format);
rect.x = dx + tx;
rect.y = dy;
//printf("half\n");
SDL_FillRect(screen, &rect, color);
//printf("rect filled\n");
}
}
break;
......@@ -228,8 +218,6 @@ void HextileMessage::handleRawRect(SDL_Surface *screen, ProtocolPreferences* pre
break;
}
}
//printf("try unlock\n");
//SDL_UnlockSurface(screen);
}
int HextileMessage::getCoveredArea()
......@@ -250,32 +238,3 @@ bool HextileMessage::read(char* dest, int n){
}
return true;
}
/*uint HextileMessage::decodeColor(char* colorField, ProtocolPreferences* prefs){
int color = 0;
for (int i = 0, shift = 0; i < prefs->bytesPerPixel; i++, shift += 8) {
color += (colorField[i] & 0xFF) << shift;
}
ColorConverter con;
switch (prefs->bitsPerPixel) {
case 16:
if (prefs->bigEndian)
// 16 bit big endian: swap bytes
color = (color & 0xFF) << 8 | ((color & 0xFF00) >> 8);
// use color table
//return con.decodeColor16(color);
case 8:
// use color table
return con.decodeColor8(color);
default:
// use default color
if (prefs->bigEndian) {
// 24 bit big endian: swap bytes
color = (color & 0xFF) << 24 | (color >> 8 & 0xFF) << 16 | (color >> 16 & 0xFF) << 8 | color >> 24
& 0xFF;
}
return color;
}
}
*/
......@@ -24,6 +24,7 @@ public:
~HextileMessage();
void paint(SDL_Surface *screen, ProtocolPreferences* prefs);
int getCoveredArea();
bool completeScreen(int w, int h);
private:
void handleHextileSubrect(SDL_Surface *screen, ProtocolPreferences* prefs, int tx, int ty, int tw, int th);
......
......@@ -11,6 +11,7 @@
#include "HextileMessage.h"
#include "WhiteboardMessage.h"
#include "DeleteAllAnnotation.h"
#include "RawMessage.h"
int number;
int total;
......@@ -26,6 +27,9 @@ bool Message::isEmpty(){
return false;
}
bool Message::completeScreen(int w, int h){
return false;
}
......@@ -156,6 +160,7 @@ Message* readMessage(Inflater* in, ProtocolPreferences* prefs){
break;*/
case ANNOTATIONDELETEALL:
//TODO:test
message = new DeleteAllAnnotation(timestamp);
break;
......@@ -164,6 +169,8 @@ Message* readMessage(Inflater* in, ProtocolPreferences* prefs){
break;*/
case ENCODINGWHITEBOARD:
//TODO:test
printf("ENCODINGWHITEBOARD\n");
in->readByte(&byte);
message = new WhiteboardMessage(timestamp, byte, prefs);
break;
......@@ -172,11 +179,13 @@ Message* readMessage(Inflater* in, ProtocolPreferences* prefs){
message = new HextileMessage(timestamp, in, size);
break;
/*case ENCODINGRAW:
case ENCODINGRAW:
//TODO:test
printf("Created RawMessage with timestamp %d, needs testing!\n", timestamp);
message = new RawMessage(timestamp, in, size);
break;
case ENCODINGINTERLACEDRAW:
/*case ENCODINGINTERLACEDRAW:
//TODO: InterlacedRawMessage
// message = new InterlacedRawMessage(timestamp,x,y,w,h,msg);
message = new EmptyMessage(timestamp);
......@@ -193,9 +202,6 @@ Message* readMessage(Inflater* in, ProtocolPreferences* prefs){
{
char skip[size+1];
in->readCharArray(skip, size);
/*for(int i=0;i<sizeof(skip);i++)
printf("%d,",skip[i]);
printf("\n");*/
}
size = 0;
......@@ -204,7 +210,9 @@ Message* readMessage(Inflater* in, ProtocolPreferences* prefs){
}
message->updateFlag = updateFlag;
message->encoding=encoding;
return message;
}
......@@ -21,7 +21,8 @@ class Message {
public:
virtual ~Message();
virtual void paint(SDL_Surface *screen, ProtocolPreferences* prefs);
bool isEmpty();
virtual bool isEmpty();
virtual bool completeScreen(int w, int h);
bool updateFlag;
int timestamp;
......
/*
* File: RawMessage.cpp
* Author: user
*
* Created on July 14, 2014, 11:38 AM
*/
#include "RawMessage.h"
ColorConverter RawMessage::con;
RawMessage::RawMessage(int timestamp, Inflater* in, int size) {
this->timestamp=timestamp;
in->readShort(&x);
in->readShort(&y);
in->readShort(&w);
in->readShort(&h);
data=new SizedArray(size-8);
in->readSizedArray(data);
}
RawMessage::~RawMessage() {
delete data;
}
bool RawMessage::completeScreen(int w, int h){
return (this->w==w && this->h==h);
}
void RawMessage::paint(SDL_Surface* screen, ProtocolPreferences* prefs){
handleRawRect(screen,prefs);
printf("Drawn RawMessage at {%d, %d, %d, %d}\n",x,y,w,h);
}
void RawMessage::handleRawRect(SDL_Surface *screen, ProtocolPreferences* prefs)
{
SDL_Rect rect = {0, 0, 1, 1};
switch (prefs->bytesPerPixel) {
case 1:
{
for (int dy = y; dy < y + h; dy++) {
//is.readFully(graphicsContext.pixels8, dy * graphicsContext.prefs->framebufferWidth + x, w);
read((char*)(screen->pixels)+dy * prefs->framebufferWidth + x,w);
/*// buffering TODO:?
if (os != null)
os.write(graphicsContext.pixels8, dy * graphicsContext.prefs->framebufferWidth + x, w);*/
}
break;
}
case 2:
{
unsigned char rawColor[prefs->bytesPerPixel];
uint color;
if (prefs->bigEndian)
for (int dy = y; dy < y + h; dy++)
{
for(int dx = 0; dx < w; dx++)
{
read((char*)rawColor, prefs->bytesPerPixel);
color = con.decodeColor(rawColor,prefs->bytesPerPixel,prefs->format);
rect.x = dx + x;
rect.y = dy;
SDL_FillRect(screen, &rect, color);
}
}
else
for (int dy = y; dy < y + h; dy++)
{
for(int dx = 0; dx < w; dx++)
{
read((char*)rawColor, prefs->bytesPerPixel);
color = con.decodeColor(rawColor,prefs->bytesPerPixel,prefs->format);
rect.x = dx + x;
rect.y = dy;
SDL_FillRect(screen, &rect, color);
}
}
break;
}
default:
{
/*char buf[w * 4];
for (int dy = y; dy < y + h; dy++) {
read(buf,w*4);
/*//* buffering
if (os != null)
os.write(buf);*//*
int offset = dy * prefs->framebufferWidth + x;
if (prefs->bigEndian)
for (int i = 0; i < w; i++)
(int*)(screen->pixels)[offset + i] = (buf[i * 4 + 1] & 0xFF) << 16 | (buf[i * 4 + 2] & 0xFF) << 8 | (buf[i * 4 + 3] & 0xFF);
else
for (int i = 0; i < w; i++)
(int*)(screen->pixels)[offset + i] = (buf[i * 4 + 2] & 0xFF) << 16 | (buf[i * 4 + 1] & 0xFF) << 8 | (buf[i * 4] & 0xFF);
}*/
break;
}
}
}
bool RawMessage::read(char* dest, int n){
for(int i = 0; i < n; i++)
{
if(offSet>=data->length)
{
//printf("failed\n");
return false;
}
dest[i]=data->array[offSet];
offSet++;
}
return true;
}
/*
* File: RawMessage.h
* Author: user
*
* Created on July 14, 2014, 11:38 AM
*/
#ifndef RAWMESSAGE_H
#define RAWMESSAGE_H
#include "Inflater.h"
#include "Message.h"
#include <SDL/SDL.h>
#include "SizedArray.h"
#include <string>
#include <stdio.h>
#include "ColorConverter.h"
class RawMessage : public Message{
public:
RawMessage(int timestamp, Inflater* in, int size);
~RawMessage();
void paint(SDL_Surface *screen, ProtocolPreferences* prefs);
bool completeScreen(int w, int h);
private:
void handleRawRect(SDL_Surface *screen, ProtocolPreferences* prefs);
bool read(char* dest, int n);
static ColorConverter con;
short x,y,w,h;
SizedArray* data;
int offSet;
};
#endif /* RAWMESSAGE_H */
......@@ -55,9 +55,9 @@ void Video::update(int zeit)
//printf("%d>=%d || %d>%d\n",currentMessage,numMessages,messages[currentMessage]->timestamp,timestamp);
while(currentMessage<numMessages)
{
if(messages[currentMessage]->timestamp>zeit)
if(messages[currentMessage]->timestamp > zeit*1000)
break;
printf("Stamp: %d, #Messages: %d, current Message: %d\n",messages[currentMessage]->timestamp,numMessages,currentMessage);
//printf("Stamp: %d, #Messages: %d, current Message: %d\n",messages[currentMessage]->timestamp,numMessages,currentMessage);
messages[currentMessage]->paint(screen, &prefs);
currentMessage++;
}
......@@ -75,6 +75,30 @@ void Video::toggleFullscreen(){
}
}
void Video::seekPosition(int position){
//binary search for message closest to position
int min, max;
min=0;
max= numMessages;
while(min!=max)
if(messages[(min+max)/2]->timestamp > position*1000)
max=(min+max)/2;
else
min=(min+max)/2+1;
currentMessage=min;
//search backwards for message that changes the whole screen
printf("From %d ",currentMessage);
for(;currentMessage>0;currentMessage--)
if(messages[currentMessage]->completeScreen((int)prefs.framebufferWidth, (int)prefs.framebufferHeight))
break;
printf("back to %d\n",currentMessage);
//only needed in case the video is paused
update(position);
}
bool readServerInit(Inflater* in)
{
ProtocolPreferences prefs;
......
......@@ -34,6 +34,7 @@ public:
void update(int zeit);
SDL_Surface* getScreen();
void toggleFullscreen();
void seekPosition(int position);
bool failed;
......
......@@ -21,3 +21,7 @@ void WhiteboardMessage::paint(SDL_Surface *screen, ProtocolPreferences* prefs)
SDL_Rect rect = {0,0,screen->w,screen->h};
SDL_FillRect(screen, &rect, 0xffffff);
}
bool WhiteboardMessage::completeScreen(int w, int h){
return true;
}
......@@ -18,6 +18,7 @@ public:
WhiteboardMessage(int timestamp, int pageNumber, ProtocolPreferences* prefs);
~WhiteboardMessage();
void paint(SDL_Surface *screen, ProtocolPreferences* prefs);
bool completeScreen(int w, int h);
private:
......
build/Debug/GNU-Linux-x86/Message.o: Message.cpp Message.h Inflater.h \
SizedArray.h ProtocolPreferences.h Constants.h EmptyMessage.h \
HextileMessage.h ColorConverter.h WhiteboardMessage.h \
DeleteAllAnnotation.h
DeleteAllAnnotation.h RawMessage.h
Message.h:
......@@ -22,3 +22,5 @@ ColorConverter.h:
WhiteboardMessage.h:
DeleteAllAnnotation.h:
RawMessage.h:
build/Debug/GNU-Linux-x86/RawMessage.o: RawMessage.cpp RawMessage.h \
Inflater.h SizedArray.h Message.h ProtocolPreferences.h Constants.h \
ColorConverter.h
RawMessage.h:
Inflater.h:
SizedArray.h:
Message.h:
ProtocolPreferences.h:
Constants.h:
ColorConverter.h:
......@@ -10,14 +10,14 @@ var x_getSeek=function(){
}
var x_getPosition=function(){
return x_audio.currentTime*1000;
return x_audio.currentTime;
}
var x_setPosition=function(pos){
x_audio.currentTime=pos/1000;
x_audio.currentTime=pos;
}
var x_getDuration=function(){
return x_audio.duration*1000;
return x_audio.duration;
}
var x_togglePlay=function(){
if(x_audio.paused)
......@@ -32,7 +32,7 @@ var x_rect;
var x_onFull;
var x_setupFullScreen=function(w, h){
var x_setupFullScreen=function(){
x_rect=x_canvas.getBoundingClientRect();
x_onFull=Module.cwrap('getOnFullScreenButton', 'bool');
x_canvas.addEventListener('click', function(e) {
......@@ -57,3 +57,12 @@ var x_audioLoaded=function(){
}
var x_getPath=function(end){
return "TTT/"+x_filename+"_a/"+x_filename+"."+end;
};
var x_setAudioSource=function(){
x_audio.innerHTML='<source src="'+x_getPath("ogg")+'" type="audio/ogg"><source src="'+x_getPath("mp3")+'" type="audio/mp3"><source src="'+x_getPath("wav")+'" type="audio/wav">Your browser does not support the audio element.';
}
x_setAudioSource();
......@@ -3,12 +3,12 @@ EM=em++ -02 -s ALLOW_MEMORY_GROWTH=1
CC=emcc -02 -s ALLOW_MEMORY_GROWTH=1
DIR=../
MESSAGES= $(DIR)DeleteAllAnnotation.cpp $(DIR)EmptyMessage.cpp $(DIR)HextileMessage.cpp $(DIR)Message.cpp $(DIR)WhiteboardMessage.cpp
ZSRC = libz/adler32.c libz/compress.c libz/crc32.c libz/deflate.c libz/gzclose.c libz/gzlib.c libz/gzread.c \
libz/gzwrite.c libz/infback.c libz/inffast.c libz/inflate.c libz/inftrees.c libz/trees.c libz/uncompr.c libz/zutil.c
MESSAGES= $(DIR)DeleteAllAnnotation.cpp $(DIR)EmptyMessage.cpp $(DIR)HextileMessage.cpp $(DIR)Message.cpp $(DIR)RawMessage.cpp $(DIR)WhiteboardMessage.cpp
#ZSRC = libz/adler32.c libz/compress.c libz/crc32.c libz/deflate.c libz/gzclose.c libz/gzlib.c libz/gzread.c \
# libz/gzwrite.c libz/infback.c libz/inffast.c libz/inflate.c libz/inftrees.c libz/trees.c libz/uncompr.c libz/zutil.c
SRC= $(DIR)AudioInterface.cpp $(DIR)AudioJS.cpp $(DIR)ColorConverter.cpp $(DIR)Constants.cpp $(DIR)Controls.cpp $(DIR)Inflater.cpp $(DIR)Player.cpp $(DIR)ProtocolPreferences.cpp $(DIR)SizedArray.cpp $(DIR)Video.cpp $(DIR)main.cpp $(MESSAGES)
EXPORT=-s "EXPORTED_FUNCTIONS=['_main', '_on_play', '_on_pause', '_set_path', '_getOnFullScreenButton']"
EXPORT=-s "EXPORTED_FUNCTIONS=['_main', '_on_play', '_on_pause', '_getOnFullScreenButton']"
PRELOAD= --preload-file TTT/Diskrete_Strukturen_2013_11_26_a/Diskrete_Strukturen_2013_11_26.ttt
#STATICLIB= libz.bc
......@@ -17,7 +17,7 @@ CFLAGS=-O
TEST_LDFLAGS=-L. libz.a
fileplayer.js: $(SRC) Makefile $(DIR)main.h pre.js
$(EM) $(SRC) $(EXPORT) -o $@ $(PRELOAD) libz.bc #--pre-js pre.js
$(EM) $(SRC) $(EXPORT) -o $@ libz.bc --pre-js pre.js
#libz.bc: $(ZSRC)
# $(CC) $(ZSRC) -s EXPORT_ALL=1 -o $@
......
......@@ -1214,17 +1214,21 @@
<progress value="0" max="100" id="progress" hidden=1></progress>
</div>
<script type='text/javascript'>
var x_filename="Programmiersprachen_2013_10_21"; //"<?php $path=$_GET['path']; echo $path; ?>"
</script>
<div class="emscripten_border" id="canvas_div">
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
<audio class="emscripten" id ="audioplayer" onloadeddata="x_audioLoaded()" onseeking="x_seeked=true;" >
<source src="TTT/Diskrete_Strukturen_2013_11_26_a/Diskrete_Strukturen_2013_11_26.ogg" type="audio/ogg">
<source src="TTT/Diskrete_Strukturen_2013_11_26_a/Diskrete_Strukturen_2013_11_26.mp3" type="audio/mp3">
<source src="TTT/Diskrete_Strukturen_2013_11_26_a/Diskrete_Strukturen_2013_11_26.wav" type="audio/wav">
Your browser does not support the audio element.
<!-- filled by Audio.js -->
</audio>
<script type="text/javascript" src="Audio.js"></script>
</div>