Commit 9a7ee09f authored by daFischer's avatar daFischer

IndexExtension is now working

parent 6f60d1e6
......@@ -12,6 +12,7 @@
#define EXTENSION_INDEX_TABLE 1
#define EXTENSION_SEARCHBASE_TABLE_WITH_COORDINATES 2
#define ENCODINGFLAGTIMESTAMP 128
#define ENCODINGFLAGUPDATE 64
#define ENCODINGMASK 63
......
......@@ -7,6 +7,7 @@
#include "Controls.h"
#include "Video.h"
#include "Player.h"
bool mouseOnFullScreenButton;
......@@ -28,8 +29,6 @@ Controls::Controls(Video* video, AudioInterface* audio) {
redefineRect(&videoUpdate,0,0,width,screenHeight);
timeLineClicked=false;
timeLineChange=-1;
volumeClicked=false;
volume=1;
......@@ -42,14 +41,20 @@ Controls::Controls(Video* video, AudioInterface* audio) {
surfVolume=SDL_LoadBMP("Assets/volume.bmp");
surfVolume2=SDL_LoadBMP("Assets/volume2.bmp");
surfFullscreen=SDL_LoadBMP("Assets/fullscreen.bmp");
font = TTF_OpenFont("/Assets/arial.ttf",20);
#else
surfPlay=SDL_LoadBMP("/home/user/NetBeansProjects/TTTPlayer/emBuild/Assets/PlayPause.bmp");
surfVolume=SDL_LoadBMP("/home/user/NetBeansProjects/TTTPlayer/emBuild/Assets/volume.bmp");
surfVolume2=SDL_LoadBMP("/home/user/NetBeansProjects/TTTPlayer/emBuild/Assets/volume2.bmp");
surfFullscreen=SDL_LoadBMP("/home/user/NetBeansProjects/TTTPlayer/emBuild/Assets/fullscreen.bmp");
font = TTF_OpenFont("/home/user/NetBeansProjects/TTTPlayer/emBuild//Assets/arial.ttf",20);
#endif
if(surfPlay==NULL||surfVolume==NULL||surfVolume2==NULL||surfFullscreen==NULL)
printf("BMPs ARE NULL\n");
if(font==NULL)
printf("FONT IS NULL\n");
else
printf("font is ok\n");
}
void Controls::registerClick(Uint16 mx, Uint16 my){
......@@ -72,14 +77,19 @@ void Controls::registerClick(Uint16 mx, Uint16 my){
}
void Controls::registerMouseUp(){
if(timeLineClicked)
{
redefineRect(&videoUpdate,0,0,width,screenHeight-height);
skipTo(duration*mouseX/width);
}
timeLineClicked=false;
volumeClicked=false;
}
void Controls::registerMovement(Uint16 mx, Uint16 my) {
visible=(my>=screenHeight-height)||timeLineClicked||volumeClicked;
if(timeLineClicked)
timeLineChange=mx;
mouseX=mx;
mouseY=my;
if(volumeClicked)
changeVolume(max(min((float)(mx-64),(float)64),(float)0)/64);
//#ifdef EMSCRIPTEN
......@@ -112,12 +122,6 @@ void Controls::update(){
y+=4;
}
}
if(!timeLineClicked && timeLineChange>=0)
{
redefineRect(&videoUpdate,0,0,width,screenHeight-height);
skipTo(duration*timeLineChange/width);
timeLineChange=-1;
}
}
void Controls::togglePlay(){
......@@ -186,18 +190,32 @@ void Controls::draw(SDL_Surface *screen, bool hasDrawn){
redefineRect(&rect, 0, y, width, timeLineHeight);
SDL_FillRect(screen, &rect, emColor(0x333333));
int currentPosition=audio->getPosition();
//timeLine foreground
if(timeLineChange==-1)
redefineRect(&rect, 0, y, audio->getPosition()*width/duration, timeLineHeight);
if(!timeLineClicked)
redefineRect(&rect, 0, y, currentPosition*width/duration, timeLineHeight);
else
redefineRect(&rect, 0, y, timeLineChange, timeLineHeight);
redefineRect(&rect, 0, y, mouseX, timeLineHeight);
SDL_FillRect(screen, &rect, emColor(0xaa0000));
//draw "time / duration"
SDL_Color color = {0xff,0xff,0xff,0xff};
ostringstream oss;
oss << currentPosition/60 << ":" << ((currentPosition%60<10) ? "0" : "") << currentPosition%60 << "/" << duration/60 << ":" << ((duration%60<10) ? "0" : "") << duration%60;
SDL_Surface* times=TTF_RenderText_Solid(font,oss.str().c_str(),color);
redefineRect(&rect,192,y+timeLineHeight+4,times->w+4,times->h+4);
SDL_BlitSurface(times,NULL,screen,&rect);
if(mouseY>=y&&mouseY<y+timeLineHeight)
video->drawThumbnail(duration*mouseX/width,mouseX,y);
SDL_UpdateRect(screen, 0,y,width,screenHeight-y);
SDL_Flip(screen);
//SDL_Flip(screen);
}
Uint32 Controls::emColor(unsigned int color){
return SDL_MapRGBA(ProtocolPreferences::format,(color & 0xff0000)>>16,(color & 0x00ff00)>>8,color & 0x0000ff,0xff);
#if EMSCRIPTEN
unsigned int r = (color & 0xff0000)>>16;
unsigned int g = color & 0x00ff00;
......
......@@ -9,6 +9,8 @@
#define CONTROLS_H
#include <SDL/SDL.h>
#include <SDL/SDL_ttf.h>
#include <sstream>
#include "AudioInterface.h"
//#include "Video.h"
......@@ -45,7 +47,7 @@ private:
int width, height, screenHeight;
int timeLineHeight;
bool timeLineClicked;
int timeLineChange; //For when the user seeks through the video
int mouseX, mouseY;
bool volumeClicked;
float volume;
int duration;
......@@ -54,6 +56,7 @@ private:
SDL_Surface* surfVolume;
SDL_Surface* surfVolume2;
SDL_Surface* surfFullscreen;
TTF_Font* font;
void togglePlay();
void toggleFullscreen();
......
/*
* File: Index.cpp
* Author: user
*
* Created on July 23, 2014, 10:10 PM
*/
#include "Index.h"
#include "Inflater.h"
Index::Index(Inflater* in, int numBytes) {
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++)
{
in->readInt(&timestamp);
in->readByte((char*) &titleLength);
title=in->readCharArray(titleLength,true);
title[titleLength]=0;
in->readInt(&searchableLength);
searchableArray=new SizedArray(searchableLength);
in->readSizedArray(searchableArray);
numBytes-=9+titleLength+searchableLength;
image=readThumbnail(in, &numBytes);
index.push_back(new IndexEntry(title,timestamp,searchableArray,image));
}
if(numBytes>0)
{
printf("Index skipping %d bytes\n", numBytes);
in->skipBytes(numBytes);
}
//TODO: what if too many bytes have been read?
}
SDL_Surface* Index::readThumbnail(Inflater* in, int* numBytes) {
int imageSize;
in->readInt(&imageSize);
*numBytes-=4;
if(imageSize==0)
// thumbnail not available
return NULL;
else
{
char* imageArray = (char*) malloc(imageSize);
imageArray=in->readCharArray(imageSize,false);
*numBytes-=imageSize;/*
//#ifdef EMSCRIPTEN
//write to file (emscripten has no IMG_LoadPNG_RW method, but IMG_Load exists)
ofstream file;
file.open("Assets/thumbnail.png",ofstream::out | ofstream::trunc);
file.write(imageArray,imageSize);
file.close();
//create from file
SDL_Surface* bufferedImage = IMG_Load("Assets/thumbnail.png");*/
//#else
SDL_Surface* bufferedImage = IMG_Load_RW(SDL_RWFromMem((void*)imageArray,imageSize),1);
//#endif
delete(imageArray);
//ImageIO.read(new ByteArrayInputStream(image_array));
//thumbnail_scale_factor = recording.prefs.framebufferHeight / bufferedImage.getHeight();
return bufferedImage;
}
}
IndexEntry* Index::lastBefore(int timestamp) {
for(std::list<IndexEntry*>::reverse_iterator it=index.rbegin();it!=index.rend();it++)
if((*it)->timestamp <= timestamp*1000)
return (IndexEntry*) *it;
return index.front();
}
Index::~Index() {
}
/*
* File: Index.h
* Author: user
*
* Created on July 23, 2014, 10:10 PM
*/
#ifndef INDEXEXTENSION_H
#define INDEXEXTENSION_H
#include <stdio.h>
#include <list>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <iostream>
#include <fstream>
#include "IndexEntry.h"
#include "Inflater.h"
#include "Messages/Message.h"
using namespace std;
class Index {
public:
Index(Inflater* in, int numBytes);
Index(Message**, int numMessages);
virtual ~Index();
IndexEntry* lastBefore(int timestamp);
private:
SDL_Surface* readThumbnail(Inflater* in, int* numBytes);
list<IndexEntry*> index;
};
#endif /* INDEXEXTENSION_H */
/*
* File: IndexEntry.cpp
* Author: user
*
* Created on July 24, 2014, 12:54 AM
*/
#include <SDL/SDL_video.h>
#include "IndexEntry.h"
IndexEntry::IndexEntry(char* title, int timestamp, SizedArray* searchable, SDL_Surface* image) {
this->title=title;
this->timestamp=timestamp;
this->searchable=searchable;
this->image=image;
}
IndexEntry::~IndexEntry() {
SDL_FreeSurface(image);
}
SDL_Rect IndexEntry::getRect(SDL_Surface* screen, int x, int y) {
SDL_Rect r= {max(0,min(screen->w-image->w,x-image->w/2)),y-image->h,image->w,image->h};
return r;
}
void IndexEntry::paintAt(SDL_Surface* screen, int x, int y) {
SDL_Rect rect = getRect(screen,x,y);
SDL_UpdateRect(screen, rect.x,rect.y,rect.w,rect.h);
SDL_BlitSurface(image,NULL,screen,&rect);
}
/*
* File: IndexEntry.h
* Author: user
*
* Created on July 24, 2014, 12:54 AM
*/
#ifndef INDEXENTRY_H
#define INDEXENTRY_H
#include <stdio.h>
#include <SDL/SDL.h>
#include <fstream>
#include "SizedArray.h"
using namespace std;
class IndexEntry {
public:
IndexEntry(char* title, int timestamp, SizedArray* searchable, SDL_Surface* image);
virtual ~IndexEntry();
SDL_Rect getRect(SDL_Surface* screen, int x, int y);
void paintAt(SDL_Surface* screen, int x, int y);
int timestamp;
private:
char* title;
SizedArray* searchable;
SDL_Surface* image;
};
#endif /* INDEXENTRY_H */
......@@ -117,6 +117,8 @@ bool Inflater::readByte(char* Byte)
return ret;
}
/* The SizedArray has to be initialized beforehand
*/
bool Inflater::readSizedArray(SizedArray* sArray)
{
bool r;
......@@ -129,17 +131,22 @@ bool Inflater::readSizedArray(SizedArray* sArray)
return Z_OK;
}
bool Inflater::readCharArray(char* ByteArray, int length)
/* mallocs and fills the [length] bytes in memory, starting from [byteArray]
* if [end], the char array ends with \0 (malloced bytes are [length]+1 in that case)
*/
char* Inflater::readCharArray(int length, bool end)
{
bool r;
char* byteArray=(char*)malloc(length+ (end ? 1 : 0));
for(int i=0;i<length;i++)
{
r=readByte(&(ByteArray[i]));
r=readByte(&(byteArray[i]));
if(r!=Z_OK)
return r;
return NULL;
}
ByteArray[length]=0;
return Z_OK;
if(end)
byteArray[length]=0;
return byteArray;
}
bool Inflater::readShort(short* s)
......@@ -168,6 +175,19 @@ bool Inflater::readInt(int* s)
return Z_OK;
}
bool Inflater::skipBytes(int number) {
bool r;
char waste;
for(int i=0;i<number;i++)
{
r=readByte(&waste);
if(r!=Z_OK)
return r;
}
return Z_OK;
}
bool Inflater::endOfFile(){
return ret!=Z_OK;
}
\ No newline at end of file
......@@ -25,10 +25,11 @@ public:
~Inflater();
bool readByte(char* Byte);
bool readSizedArray(SizedArray* sArray);
bool readCharArray(char* ByteArray, int length);
char* readCharArray(int length, bool end);
bool readShort(short* s);
bool readInt(int* s);
bool readLong(long* s);
bool skipBytes(int number);
bool endOfFile();
private:
......
......@@ -31,11 +31,12 @@ void Annotation::draw(SDL_Surface* screen, ProtocolPreferences* prefs) {
void Annotation::redraw(SDL_Surface *screen ,ProtocolPreferences *prefs) {
//refresh screen
printf("redraw Annotations\n");
SDL_Rect rect={0,0,screen->w,screen->h};
SDL_FillRect(screen,&rect,0x00000000);
SDL_UpdateRect(screen,0,0,rect.w,rect.h);
SDL_LockSurface(screen);
memset(screen->pixels,0,screen->w*screen->h*screen->format->BytesPerPixel);
SDL_UnlockSurface(screen);
mustRedraw=false;
//redraw all active Annotations
for(list<Annotation*>::iterator it = annotations.begin(); it!= annotations.end(); it++)
......
......@@ -170,14 +170,9 @@ Message* readMessage(Inflater* in, ProtocolPreferences* prefs){
break;
case ANNOTATIONDELETEALL:
//TODO:test
message = new DeleteAllAnnotation(timestamp);
break;
/*case ENCODINGTTTCURSORPOSITION:
message = new CursorPositionMessage(timestamp, in);
break;*/
case ENCODINGWHITEBOARD:
//TODO:test
printf("ENCODINGWHITEBOARD\n");
......@@ -201,6 +196,10 @@ Message* readMessage(Inflater* in, ProtocolPreferences* prefs){
message = new EmptyMessage(timestamp);
break;
case ENCODINGTTTCURSORPOSITION:
message = new CursorPositionMessage(timestamp, in);
break;
case ENCODINGTTTRICHCURSOR:
case ENCODINGTTTXCURSOR:
message = new CursorMessage(timestamp, encoding, in, size);
......@@ -210,8 +209,7 @@ Message* readMessage(Inflater* in, ProtocolPreferences* prefs){
printf("skipping unsupported message: Encoding = %d\t%d bytes\n", encoding, size);
if(size>0)
{
char skip[size+1];
in->readCharArray(skip, size);
in->skipBytes(size);
}
size = 0;
......
......@@ -30,9 +30,18 @@ RectangleAnnotation::~RectangleAnnotation() {
void RectangleAnnotation::draw(SDL_Surface *screen, ProtocolPreferences* prefs){
printf("draw RectangleAnnotation(%d,%d,%d,%d),%d\n",x,y,w,h,this->con.getAnnotationColor(color,screen->format));
SDL_Rect rect = {x, y, w, h};
//SDL_Rect rect = {x, y, w, h};
//SDL_FillRect(screen, &rect, this->con.getAnnotationColor(color,screen->format));
//SDL_UpdateRect(screen,x,y,w,h);
SDL_Rect rect = {x-linewidth, y-linewidth, linewidth, h+2*linewidth}; //left
SDL_FillRect(screen, &rect, this->con.getAnnotationColor(color,screen->format));
SDL_UpdateRect(screen,x,y,w,h);
SDL_Rect rect2 = {x, y-linewidth, w+linewidth, linewidth}; //upper
SDL_FillRect(screen, &rect2, this->con.getAnnotationColor(color,screen->format));
SDL_Rect rect3 = {x+w, y, linewidth, h+linewidth}; //right
SDL_FillRect(screen, &rect3, this->con.getAnnotationColor(color,screen->format));
SDL_Rect rect4 = {x, y+h, w, linewidth}; //bottom
SDL_FillRect(screen, &rect4, this->con.getAnnotationColor(color,screen->format));
SDL_UpdateRect(screen,x-linewidth,y-linewidth,w+2*linewidth,h+2*linewidth);
}
bool RectangleAnnotation::completeScreen(int w, int h) {
......
......@@ -24,6 +24,7 @@ public:
private:
const static char linewidth=2;
char color;
};
......
......@@ -10,6 +10,7 @@
#include "Controls.h"
Player *player;
//TTF_Font* font;
Player::Player(const char* cpath, const char* cfilename) {
......@@ -17,15 +18,26 @@ Player::Player(const char* cpath, const char* cfilename) {
player=this;
std::string filename=cfilename;
std::string path=cpath;
//Initialize BOTH SDL video and SDL audio
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) != 0)
{
printf("Unable to initialize SDL: %s\n", SDL_GetError());
return;
}
else
atexit(SDL_Quit);
std::string filename=cfilename;
std::string path=cpath;
if(TTF_Init()<0){
printf("Unable to initialize TTF: %s\n", TTF_GetError());
return;
}
else
{
}
video=new Video((path+"/"+filename+"_a/"+filename+".ttt").c_str());
#ifdef EMSCRIPTEN
......
......@@ -37,6 +37,8 @@ public:
void loop();
virtual ~Player();
//static TTF_Font* font;
private:
AudioInterface *audio;
Video *video;
......
......@@ -22,6 +22,8 @@ Video::Video(const char* path) {
if(readServerInit(inflater))
printf("Video Initialization success: \n%s\n", prefs.name);
index=NULL;
readExtensions(inflater);
inflater->readInt(&prefs.starttime);
inflater->readInt(&prefs.starttime);
......@@ -38,18 +40,16 @@ Video::Video(const char* path) {
m.pop_front();
}
printf("Read %d messages successfully\n", numMessages);
//if(index==NULL)
// index=new Index(messages,numMessages);
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=screen->format;
rawScreen=SDL_CreateRGBSurface(screen->flags,screen->w,screen->h,screen->format->BitsPerPixel,screen->format->Rmask,screen->format->Gmask,screen->format->Bmask,screen->format->Amask);
rawScreen=SDL_CreateRGBSurface(SDL_SRCALPHA,screen->w,screen->h,screen->format->BitsPerPixel,screen->format->Rmask,screen->format->Gmask,screen->format->Bmask,screen->format->Amask);
if(containsAnnotations)
{
printf("Create AnnScreen\n");
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);
printf("screen=(%d,%d,%d,%d)\n",screen->format->Amask,screen->format->Rmask,screen->format->Gmask,screen->format->Bmask);
//SDL_Rect rect={0,0,annScreen->w,annScreen->h};
//SDL_SetAlpha(annScreen,SDL_SRCALPHA,0x00);
}
if (screen == NULL)
......@@ -65,6 +65,10 @@ void Video::update(int zeit, Controls* controls)
bool blitRaw=false;
bool blitAnn=false;
Annotation* annotation;
//check whether audio has restarted
if(zeit<=2 && (currentMessage>=numMessages || (currentMessage>0 && messages[currentMessage-1]->timestamp>zeit-2)))
currentMessage=0;
while(currentMessage<numMessages)
{
if(messages[currentMessage]->timestamp > zeit*1000)
......@@ -104,19 +108,37 @@ void Video::redrawScreen(Controls* controls, bool fully) {
SDL_Rect rect = {0,0,screen->w,controls->videoUpdate.y+controls->videoUpdate.h};
SDL_BlitSurface(rawScreen,&rect,screen,&rect);
SDL_BlitSurface(annScreen,&rect,screen,&rect);
SDL_Flip(screen);
}
else if(controls->videoUpdate.h!=0)
else
{
//only redraw the part that controls releases when moving downwards
SDL_BlitSurface(rawScreen,&controls->videoUpdate,screen,&controls->videoUpdate);
SDL_BlitSurface(annScreen,&controls->videoUpdate,screen,&controls->videoUpdate);
SDL_Flip(screen);
if(lastThumbnail.w!=0)
{
//redraw screen where thumbnail was before
SDL_BlitSurface(rawScreen,&lastThumbnail,screen,&lastThumbnail);
SDL_BlitSurface(annScreen,&lastThumbnail,screen,&lastThumbnail);
lastThumbnail.w=0;
}
if(controls->videoUpdate.h!=0)
{
//only redraw the part that controls releases when moving downwards
SDL_BlitSurface(rawScreen,&controls->videoUpdate,screen,&controls->videoUpdate);
SDL_BlitSurface(annScreen,&controls->videoUpdate,screen,&controls->videoUpdate);
}
}
//always redraw controls
controls->draw(screen, fully);
SDL_Flip(screen);
}
void Video::drawThumbnail(int zeit, int x, int y) {
if(index!=NULL)
{
index->lastBefore(zeit)->paintAt(screen,x,y);
lastThumbnail=index->lastBefore(zeit)->getRect(screen,x,y);
}
}
void Video::toggleFullscreen(){
return; //doesn't work yet, but not really important
{
......@@ -127,7 +149,6 @@ void Video::toggleFullscreen(){
void Video::seekPosition(int position, Controls* controls){
printf("seeking...\n");
//binary search for message closest to position
int min, max;
min=1;
......@@ -191,7 +212,6 @@ void Video::seekPosition(int position, Controls* controls){
Annotation::redraw(annScreen,&prefs);
redrawScreen(controls,true);
printf("redrawn after seeking (%d, %d)\n", firstRaw, firstAnnotation);
/*//search backwards for raw message that changes the whole screen
printf("From %d ",currentMessage);
......@@ -239,10 +259,7 @@ bool readServerInit(Inflater* in)
int nameLength;
if(in->readInt(&nameLength)==Z_OK)
{
char name[nameLength+1];
in->readCharArray(name,nameLength);
prefs.name=(char*)malloc(nameLength+1);
prefs.name=name;
prefs.name=in->readCharArray(nameLength,true);
//printf("%s, %d\n", name, nameLength);
return true;
}
......@@ -250,32 +267,79 @@ bool readServerInit(Inflater* in)
}
void Video::readExtensions(Inflater* in){
// new format without total length of all extensions
int len;
in->readInt(&len);
char tag;
while (len > 0) {
in->readByte(&tag);
switch(tag){
case EXTENSION_INDEX_TABLE:
// no original, but modified recording
original = false;
index=new Index(in, len-1);
break;
/*case EXTENSION_SEARCHBASE_TABLE_WITH_COORDINATES:
// no original, but modified recording
original = false;
break;*/
default:
//'tag' is the first byte, so skip one less than len
printf("Unknown extension: %d. Skipping %d bytes.\n",tag,len-1);
in->skipBytes(len-1);
break;
}
in->readInt(&len);
}
/*// new format without total length of all extensions
int len;
in->readInt(&len);
while (len > 0) {
SizedArray* extension=new SizedArray(len);
printf("About to read #bytes: %d\n", len);
in->readSizedArray(extension);
//if (TTT.verbose)
#if VERBOSE
printf("Extension: Tag[%d] %d bytes\n", extension->array[0], len);
//TODO:
//extensions.push_back(extension);
delete extension;
#endif
extensions.push_back(extension);
//delete extension;
in->readInt(&len);
}
/*TODO:
//if (TTT.verbose)
//TODO:
#if VERBOSE
printf("%d extensions found.\n", extensions.size());
parseExtensions();
#endif
// no original, but modified recording
if (extensions.size() > 0)
original = false;
*/
original = extensions.size() == 0;
parseExtensions();*/
}
/*void Video::parseExtensions() {
SizedArray* ext;
while(extensions.size()>0)
{
ext=extensions.front();
switch(ext->array[0]){
case EXTENSION_INDEX_TABLE:
break;
case EXTENSION_SEARCHBASE_TABLE_WITH_COORDINATES:
break;
default: