Commit d915c14c authored by daFischer's avatar daFischer
Browse files

Made the loading more fluent

parent efc5633b
......@@ -8,10 +8,6 @@
#ifndef AUDIOINTERFACE_H
#define AUDIOINTERFACE_H
#ifndef _STDIO_H
using namespace std;
#endif
using namespace std;
class AudioInterface {
......
......@@ -9,17 +9,22 @@
#include "Inflater.h"
Index::Index(Inflater* in, int numBytes) {
this->numBytes=numBytes;
in->readShort(&entryNumber);
this->numBytes -= 2;
}
bool Index::readIndexEntry(Inflater* in) {
int timestamp;
unsigned char titleLength;
char* title;
int searchableLength;
SizedArray* searchableArray;
SDL_Surface* image;
short entryNumber;
in->readShort(&entryNumber);
numBytes -= 2;
for (int i = 0; i < entryNumber; i++) {
if(entryNumber>0) {
entryNumber--;
in->readInt(&timestamp);
in->readByte((char*) &titleLength);
title = in->readCharArray(titleLength, true);
......@@ -31,14 +36,17 @@ Index::Index(Inflater* in, int numBytes) {
numBytes -= 9 + titleLength + searchableLength;
image = readThumbnail(in, &numBytes);
index.push_back(new IndexEntry(title, timestamp, searchableArray, image));
return true;
}
if (numBytes > 0) {
printf("Index skipping %d bytes\n", numBytes);
in->skipBytes(numBytes);
}
it = index.begin();
//TODO: what if too many bytes have been read?
return false;
}
Index::Index(Message** messages, int numMessages) {
......@@ -161,9 +169,9 @@ SDL_Surface* Index::readThumbnail(Inflater* in, int* numBytes) {
}
}
void Index::fillSurface(SDL_Surface* screen, Message** messages, int numMessages, ProtocolPreferences* prefs) {
bool Index::fillSurface(SDL_Surface* screen, Message** messages, int numMessages, ProtocolPreferences* prefs) {
if (it == index.end())
return;
return false;
SDL_Surface* waypoint = SDL_CreateRGBSurface(SDL_ANYFORMAT, screen->w, screen->h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
if (it == index.begin()) {
......@@ -184,6 +192,7 @@ void Index::fillSurface(SDL_Surface* screen, Message** messages, int numMessages
(*it)->setWaypoint(waypoint);
it++;
return true;
}
IndexEntry* Index::lastBefore(int timestamp) {
......
......@@ -26,7 +26,8 @@ public:
Index(Message** messages, int numMessages);
virtual ~Index();
IndexEntry* lastBefore(int timestamp);
void fillSurface(SDL_Surface* screen, Message** messages, int numMessages, ProtocolPreferences* prefs);
bool fillSurface(SDL_Surface* screen, Message** messages, int numMessages, ProtocolPreferences* prefs);
bool readIndexEntry(Inflater* in);
private:
//void fillSurfaces(SDL_Surface* screen, Message** messages, int numMessages, ProtocolPreferences* prefs);
......@@ -34,6 +35,9 @@ private:
list<IndexEntry*> index;
std::list<IndexEntry*>::iterator it;
int currentMessage;
short entryNumber;
int numBytes;
};
#endif /* INDEXEXTENSION_H */
......
......@@ -75,13 +75,19 @@ Inflater::~Inflater()
bool Inflater::readByte(char* Byte)
{
if(addedChars.size()>0)
{
*Byte=addedChars[0];
addedChars=addedChars.substr(1);
return ret;
}
if (ret != Z_OK)
{
//printf("Video Inflation failed: %d\n",ret);
*Byte=0;
return Z_ERRNO;
}
if(outOffset >= CHUNK - strm.avail_out) //Array out has to be refilled
while(outOffset >= CHUNK - strm.avail_out) //Array out has to be refilled
{
//printf("Refill Array out, %d\n", ret);
if (ret == Z_STREAM_END)
......@@ -212,6 +218,13 @@ bool Inflater::skipBytes(int number) {
return r;
}
void Inflater::addChar(char c) {
addedChars+=c;
}
long int Inflater::getProgress() {
return ftell(source);
}
bool Inflater::endOfFile(){
return ret!=Z_OK;
......
......@@ -31,6 +31,9 @@ public:
//bool readLong(long* s);
bool skipBytes(int number);
bool endOfFile();
long int getProgress();
void addChar(char c);
private:
FILE* source;
......@@ -40,6 +43,8 @@ private:
int ret;
z_stream strm;
string addedChars;
};
#endif /* INFLATER_H */
......
......@@ -19,7 +19,7 @@ DeleteAnnotation::~DeleteAnnotation() {
void DeleteAnnotation::paint(SDL_Surface *screen, ProtocolPreferences* prefs)
{
//printf("Deleted Annotation at (%d, %d)\n",x,y);
printf("Deleted Annotation at (%d, %d)\n",x,y);
deleteAnnotation(x,y);
mustRedraw=true;
}
......@@ -48,20 +48,27 @@ void setUp(){
containsWhiteboard = false;
}
list<Message*> readMessages(Inflater* in, ProtocolPreferences* prefs){
list<Message*> messages;
bool readMessages(list<Message*>* messages, Inflater* in, ProtocolPreferences* prefs){
int timestamp;
if(messages->size()==0)
{
setUp();
timestamp = 0;
}
else
timestamp=messages->back()->timestamp;
Message* message;
int timestamp = 0;
while(!in->endOfFile()){
if(!in->endOfFile()){
// TODO: show progress
message=readMessage(in, prefs);
if(message==NULL)//empty message
{
continue;
return true;
}
// TODO: maybe adding additional timestamp is better suited
if (messages.size() == 0)
if (messages->size() == 0)
message->timestamp = 0;
// use previous timestamp if unset
......@@ -74,12 +81,9 @@ list<Message*> readMessages(Inflater* in, ProtocolPreferences* prefs){
//Maybe output the change for debugging?
message->timestamp = timestamp;
}
// keep timestamp
timestamp = message->timestamp;
// add message to message array
messages.push_back(message);
messages->push_back(message);
// set flags
switch (message->encoding) {
......@@ -118,9 +122,10 @@ list<Message*> readMessages(Inflater* in, ProtocolPreferences* prefs){
printf("Error: message with encoding %d gets no type?\n",message->encoding);
break;
}
return true;
}
//printf("#Messages: %d\n",messages.size());
return messages;
//printf("#Messages: %d\n",messages->size());
return false;
}
Message* readMessage(Inflater* in, ProtocolPreferences* prefs){
......
......@@ -40,7 +40,7 @@ extern bool containsCursorMessages;
extern bool containsAnnotations;
extern bool containsWhiteboard;
extern list<Message*> readMessages(Inflater* in, ProtocolPreferences* prefs);
extern bool readMessages(list<Message*>* messages, Inflater* in, ProtocolPreferences* prefs);
extern Message* readMessage(Inflater* in, ProtocolPreferences* prefs);
extern void setUp();
......
......@@ -26,7 +26,7 @@ WhiteboardMessage::~WhiteboardMessage() {
void WhiteboardMessage::paint(SDL_Surface *screen, ProtocolPreferences* prefs)
{
printf("paint Whiteboard at %d\n",timestamp);
//printf("paint Whiteboard at %d\n",timestamp);
mustRedraw=true;
annotations.clear();
if(pageNumber>0)
......
......@@ -45,16 +45,52 @@ Player::Player(const char* cpath, const char* cfilename) {
return;
}
video=new Video((path+"/"+filename+"_a/"+filename+".ttt").c_str());
#ifdef EMSCRIPTEN
audio=new AudioJS();
#else
audio=new Audio((path+"/"+filename+"_a/"+filename).c_str());
#endif
if(video->failed||audio->hasFailed())
if(audio->hasFailed())
{
printf("Audio failed.\n");
return;
}
video=new Video((path+"/"+filename+"_a/"+filename+".ttt").c_str());
#ifdef EMSCRIPTEN
emscripten_set_main_loop(loadAsync,0,0);
#else
while(loadAsync()){}
#endif
}
#ifdef EMSCRIPTEN
void Player::loadAsync() {
if(player->video->loadAsync())
return; //continue loading
else //finished loading
{
emscripten_cancel_main_loop();
player->videoCallback();
}
}
#else
bool Player::loadAsync() {
if(player->video->loadAsync())
return true; //continue loading
else //finished loading
{
player->videoCallback();
return false;
}
}
#endif
void Player::videoCallback() {
if(video->failed)
{
printf("Audio failed: %s\nVideo failed: %s\n",audio->hasFailed() ? "true" : "false",video->failed ? "true" : "false");
printf("Video failed.\n");
return;
}
......
......@@ -37,6 +37,12 @@ public:
Player(const char*, const char*);
void loop();
virtual ~Player();
#ifdef EMSCRIPTEN
static void loadAsync();
#else
static bool loadAsync();
#endif
void videoCallback();
static TTF_Font* font;
......
......@@ -16,10 +16,17 @@ Video::Video(const char* path) {
original=true;
failed=true;
FILE* f = fopen (path , "r");
progress=0;
fseek(f,0,SEEK_END);
fileSize=ftell(f);
fseek(f,0,SEEK_SET);
fread(prefs.versionMsg, 1, 12, f);
// TODO: test version
if(VERBOSE)
printf("File Version: %s",prefs.versionMsg);
Inflater* inflater=new Inflater(f);
inflater=new Inflater(f);
if(readServerInit(inflater))
if(VERBOSE)
......@@ -27,48 +34,110 @@ Video::Video(const char* path) {
index=NULL;
readExtensions(inflater);
if(inflater->readInt(&prefs.starttime)!=Z_OK)
return;
inflater->readInt(&prefs.starttime);
//printf("Sizeof long = %d\n",sizeof(long));
//Start reading Messages
setUp();
list<Message*> m = readMessages(inflater, &prefs);
numMessages=m.size();
messages=(Message**) malloc(numMessages*sizeof(Message*));
currentMessage=0;
for(int i=0; i<numMessages; i++)
{
messages[i] = m.front();
m.pop_front();
}
if(VERBOSE)
printf("Read %d messages successfully\n", numMessages);
delete(inflater);
if(VERBOSE)
printf("%d x %d, color depth: %d\n",prefs.framebufferWidth, prefs.framebufferHeight, prefs.bytesPerPixel);
screen = SDL_SetVideoMode(prefs.framebufferWidth, prefs.framebufferHeight, prefs.bitsPerPixel, SDL_ANYFORMAT|SDL_DOUBLEBUF);
//prefs.format->Amask=0xffffffff-screen->format->Rmask-screen->format->Gmask-screen->format->Bmask;
rawScreen=SDL_CreateRGBSurface(screen->flags,screen->w,screen->h,screen->format->BitsPerPixel,screen->format->Rmask,screen->format->Gmask,screen->format->Bmask,0xffffffff-screen->format->Rmask-screen->format->Gmask-screen->format->Bmask);
prefs.format=rawScreen->format;
if(containsAnnotations)
loadPhase=0;
}
void Video::showProgress() {
if(loadPhase<=7)
{
annScreen=SDL_CreateRGBSurface(screen->flags,screen->w,screen->h,screen->format->BitsPerPixel,screen->format->Rmask,screen->format->Gmask,screen->format->Bmask,0xffffffff-screen->format->Rmask-screen->format->Gmask-screen->format->Bmask);
long int old=progress;
progress=inflater->getProgress();
if(progress/(fileSize/100)>old/(fileSize/100))
#ifdef EMSCRIPTEN
EM_ASM_INT({
x_setProgress($0);
return 0;
},progress/(fileSize/100));
#else
printf("%ld percent\n",progress/(fileSize/100));
#endif
}
if (screen == NULL)
{
printf("Unable to set video mode: %s\n", SDL_GetError());
return;
}
bool Video::loadAsync() {
showProgress();
long int old;
switch(loadPhase){
case 0:
readExtension(inflater);
break;
case 1: //IndexExtension has been found
for(int i=0;i<10;i++)
if(!index->readIndexEntry(inflater))
{
loadPhase=0; // read the next extension
break;
}
break;
//keeping space for extensions that might be added in the future
case 5:
if(inflater->readInt(&prefs.starttime)!=Z_OK)
return false;
inflater->readInt(&prefs.starttime);
//printf("Sizeof long = %d\n",sizeof(long));
//Start reading Messages
loadPhase++;
case 6:
old=progress;
do{
for(int i=0;i<30;i++)
if(!readMessages(&m, inflater, &prefs))
{
loadPhase++;
return failed;
}
}while(inflater->getProgress()/(fileSize/100)<=old/(fileSize/100));
break;
case 7:
delete(inflater);
inflater=NULL;
numMessages=m.size();
messages=(Message**) malloc(numMessages*sizeof(Message*));
currentMessage=0;
for(int i=0; i<numMessages; i++)
{
messages[i] = m.front();
m.pop_front();
}
if(VERBOSE)
printf("Read %d messages successfully\n", numMessages);
if(VERBOSE)
printf("%d x %d, color depth: %d\n",prefs.framebufferWidth, prefs.framebufferHeight, prefs.bytesPerPixel);
screen = SDL_SetVideoMode(prefs.framebufferWidth, prefs.framebufferHeight, prefs.bitsPerPixel, SDL_ANYFORMAT|SDL_DOUBLEBUF);
//prefs.format->Amask=0xffffffff-screen->format->Rmask-screen->format->Gmask-screen->format->Bmask;
rawScreen=SDL_CreateRGBSurface(screen->flags,screen->w,screen->h,screen->format->BitsPerPixel,screen->format->Rmask,screen->format->Gmask,screen->format->Bmask,0xffffffff-screen->format->Rmask-screen->format->Gmask-screen->format->Bmask);
prefs.format=rawScreen->format;
if(containsAnnotations)
{
annScreen=SDL_CreateRGBSurface(screen->flags,screen->w,screen->h,screen->format->BitsPerPixel,screen->format->Rmask,screen->format->Gmask,screen->format->Bmask,0xffffffff-screen->format->Rmask-screen->format->Gmask-screen->format->Bmask);
}
if (screen == NULL)
{
printf("Unable to set video mode: %s\n", SDL_GetError());
return false;
}
if(index==NULL)
index=new Index(messages,numMessages);
lastThumbnail.w=0;
loadPhase=8;
case 8:
for(int i=0;i<3;i++)
if(!index->fillSurface(screen,messages,numMessages,&prefs))
{
loadPhase=9;
break;
}
break;
case 9:
failed=false;
break;
}
if(index==NULL)
index=new Index(messages,numMessages);
lastThumbnail.w=0;
failed=false;
return failed;
}
void Video::update(int zeit, Controls* controls)
......@@ -79,14 +148,12 @@ void Video::update(int zeit, Controls* controls)
if(zeit<=2 && (currentMessage>0 && messages[currentMessage-1]->timestamp>zeit*1000+5000))
currentMessage=0;
if(zeit>=2)
index->fillSurface(screen,messages,numMessages,&prefs);
while(currentMessage<numMessages)
{
if(messages[currentMessage]->timestamp > zeit*1000)
break;
//printf("%d\n",messages[currentMessage]->encoding);
if(zeit>445 && zeit<460)
printf("message: %d\n",messages[currentMessage]->encoding);
switch(messages[currentMessage]->type){
case ANNOTATION:
blitAnn=true;
......@@ -216,7 +283,11 @@ void Video::seekPosition(int position, Controls* controls){
if( (firstRaw!=0 || (lastEntry >= messages[i]->timestamp && indexEntry->hasImages)) &&
(firstAnnotation!=0 || !containsAnnotations) &&
(foundCursor || !containsCursorMessages))
{
firstRaw=std::max(i,firstRaw);
firstAnnotation=std::max(i,firstAnnotation);
break;
}
if(i==currentMessage && currentMessage<=min)
{
firstRaw=std::max(i,firstRaw);
......@@ -230,7 +301,7 @@ void Video::seekPosition(int position, Controls* controls){
firstAnnotation=i;
break;
case RAW:
if((lastEntry >= messages[i]->timestamp && indexEntry->hasImages) || (firstRaw==0 && messages[i]->completeScreen(prefs.framebufferWidth, prefs.framebufferHeight)))
if((lastEntry < messages[i]->timestamp || !indexEntry->hasImages) && (firstRaw==0 && messages[i]->completeScreen(prefs.framebufferWidth, prefs.framebufferHeight)))
firstRaw=i;
break;
case CURSOR:
......@@ -245,24 +316,25 @@ void Video::seekPosition(int position, Controls* controls){
if(lastEntry>=messages[firstRaw]->timestamp && indexEntry->hasImages)
{
indexEntry->paintWaypoint(rawScreen);
//firstRaw=lastEntry;
}
for(int i=firstRaw;i<min;i++)
if(messages[i]->type==RAW)
messages[i]->paint(rawScreen,&prefs);
if(firstAnnotation!=currentMessage)
{
//after the search, Annotations must be redrawn
Annotation::mustRedraw=true;
Annotation::annotations.clear();
if(containsAnnotations){
if(firstAnnotation!=currentMessage)
{
//after the search, Annotations must be redrawn
Annotation::mustRedraw=true;
Annotation::annotations.clear();
}
for(int i=firstAnnotation;i<min;i++)
if(messages[i]->type==ANNOTATION)
messages[i]->paint(annScreen,&prefs);
if(firstAnnotation!=currentMessage||Annotation::mustRedraw)
Annotation::redraw(annScreen,&prefs);
}
for(int i=firstAnnotation;i<min;i++)
if(messages[i]->type==ANNOTATION)
messages[i]->paint(annScreen,&prefs);
if(firstAnnotation!=currentMessage||Annotation::mustRedraw)
Annotation::redraw(annScreen,&prefs);
currentMessage=min;
......@@ -308,23 +380,27 @@ bool readServerInit(Inflater* in)
in->readByte(&prefs.greenShift);
in->readByte(&prefs.blueShift);
for(int i=0;i<3;i++) //padding
in->readByte(&toRead);
in->skipBytes(3); //padding
int nameLength;
if(in->readInt(&nameLength)==Z_OK)
{
prefs.name=in->readCharArray(nameLength,true);
// For some reason sometimes nameLength is 1 larger than it should be
// In that case we have to give a byte back, or the Inflater becomes corrupt.
if(nameLength>strlen(prefs.name))
in->addChar(0);
return true;
}
return false;
}
void Video::readExtensions(Inflater* in){
void Video::readExtension(Inflater* in){
int len;
in->readInt(&len);
char tag;
while (len > 0) {
if (len > 0) {
in->readByte(&tag);
switch(tag){
case EXTENSION_INDEX_TABLE:
......@@ -333,6 +409,7 @@ void Video::readExtensions(Inflater* in){
// no original, but modified recording
original = false;
index=new Index(in, len-1);
loadPhase=1;
break;
//TODO: EXTENSION_SEARCHBASE_TABLE_WITH_COORDINATES
......@@ -352,8 +429,9 @@ void Video::readExtensions(Inflater* in){
}
break;
}
in->readInt(&len);
}
else
loadPhase=5;
}
Video::~Video() {
......
......@@ -32,8 +32,8 @@ using namespace std;
class Video {
public:
Video(const char* path);
//Video(const Video& orig);
virtual ~Video();
bool loadAsync();
void update(int zeit, Controls* controls);
void redrawScreen(Controls* controls, bool fully);
void toggleFullscreen();
......@@ -44,17 +44,25 @@ public:
bool hasThumbnails;