Controls.cpp 9.95 KB
Newer Older
1 2
/* 
 * File:   Controls.cpp
3
 * Author: Johannes Fischer
4 5 6 7 8
 * 
 * Created on July 13, 2014, 6:40 PM
 */

#include "Controls.h"
9
#include "Video.h"
daFischer's avatar
daFischer committed
10
#include "Player.h"
11 12

bool mouseOnFullScreenButton;
13
bool mouseOnPlayButton;
14 15 16 17 18

Controls::Controls(Video* video, AudioInterface* audio) {
    this->video=video;
    this->audio=audio;
    
19
    duration=audio->getDuration();
20
    ProtocolPreferences prefs;
21
    progress=0;
22
    
23
    //TODO: maybe make these relative to the screen's height
24
    timeLineHeight=16;
25
    height=timeLineHeight+32;
26 27
    
    width=prefs.framebufferWidth;
28
    screenHeight=prefs.framebufferHeight;
29
    y=screenHeight;
30 31 32 33
    
    timeLineClicked=false;
    volumeClicked=false;
    volume=1;
34 35
    speedClicked=false;
    speed=1;
36 37

    mouseOnFullScreenButton=false;
38
    mouseOnPlayButton=false;
39
#ifdef EMSCRIPTEN
40 41
    //Make Fullscreen and starting the <audio> element possible
    
42
    EM_ASM(
43
        x_setupListener();
44
    );
45
#endif
46 47 48 49
    surfPlay=SDL_LoadBMP("Assets/PlayPause.bmp");
    surfVolume=SDL_LoadBMP("Assets/volume.bmp");
    surfVolume2=SDL_LoadBMP("Assets/volume2.bmp");
    surfFullscreen=SDL_LoadBMP("Assets/fullscreen.bmp");
50 51 52 53
    surfSpeed=SDL_LoadBMP("Assets/speed.bmp");
    surfSpeed2=SDL_LoadBMP("Assets/speed2.bmp");
    
    if(surfPlay==NULL||surfVolume==NULL||surfVolume2==NULL||surfFullscreen==NULL||surfSpeed==NULL||surfSpeed2==NULL)
54
        printf("BMPs ARE NULL\n");
55 56
}

57 58 59 60
Controls::~Controls() {
    SDL_FreeSurface(surfPlay);
    SDL_FreeSurface(surfVolume);
    SDL_FreeSurface(surfVolume2);
61 62
    SDL_FreeSurface(surfSpeed);
    SDL_FreeSurface(surfSpeed2);
63 64 65 66 67
    SDL_FreeSurface(surfFullscreen);
    audio=NULL;
    video=NULL;
}

68 69 70
/**
 * Will be called after the user presses the left mouse button
 */
71 72
void Controls::registerClick(Uint16 mx, Uint16 my){
    if(my<y)
73 74
        return;
    if(my<y+timeLineHeight)
75 76 77 78 79
    {
        timeLineClicked=true;
    }
    else
    {
80
#ifndef EMSCRIPTEN
81 82 83 84
        if(mx<48)
            togglePlay();
        else if(mx>=width-48)
            toggleFullscreen();
85 86 87
        else
#endif
        if(mx<=128 && mx>=64)
88
            volumeClicked=true;
89 90
        else if(mx<=196 && mx>=160)
            speedClicked=true;
91
    }
92
    registerMovement(mx,my);
93 94
}

95 96 97
/**
 * Will be called after the user releases the left mouse button
 */
98
void Controls::registerMouseUp(){
daFischer's avatar
daFischer committed
99 100
    if(timeLineClicked)
    {
101
        skipTo(duration/width*mouseX);
daFischer's avatar
daFischer committed
102
    }
103 104
    timeLineClicked=false;
    volumeClicked=false;
105
    speedClicked=false;
106 107
}

108 109 110
/**
 * Will be called whenever the mouse has moved
 */
111
void Controls::registerMovement(Uint16 mx, Uint16 my) {
112
    //visible=(my>=screenHeight-height)||timeLineClicked||volumeClicked||speedClicked;
daFischer's avatar
daFischer committed
113 114
    mouseX=mx;
    mouseY=my;
115 116
    if(volumeClicked)
        changeVolume(max(min((float)(mx-64),(float)64),(float)0)/64);
117 118
    if(speedClicked)
        changeSpeed(max(min((float)(mx-160),(float)36),(float)0)/72+1);
119
//#ifdef EMSCRIPTEN
120
    mouseOnFullScreenButton=(mx>=width-48 && my>=y+timeLineHeight);
121
    mouseOnPlayButton=(mx<48 && my>=y+timeLineHeight);
122 123 124 125
//#endif
    
}

126
#ifdef EMSCRIPTEN
127 128 129 130
extern "C" bool getOnFullScreenButton(){
    return mouseOnFullScreenButton;
}

131 132 133 134
extern "C" bool getOnPlayButton(){
    return mouseOnPlayButton;
}
#endif
135

136 137 138
/**
 * When the mouse is not hovering over Controls' position, Controls moves out of the screen
 */
139
void Controls::update(){
140
    /*if(visible)
141 142 143 144 145 146 147 148 149 150 151 152 153 154
    {
        if(y>screenHeight-height)
            y-=4;
        redefineRect(&videoUpdate,0,y,width,0);
    }
    else
    {
        if(y>=screenHeight)
            redefineRect(&videoUpdate,0,screenHeight,width,0);
        else
        {
            redefineRect(&videoUpdate,0,y,width,4);
            y+=4;
        }
155
    }*/
156 157 158 159 160 161 162 163 164 165 166 167 168 169
}

void Controls::togglePlay(){
    audio->togglePlay();
}

void Controls::toggleFullscreen(){
    
#ifndef EMSCRIPTEN
    video->toggleFullscreen();
#endif
    
}

170
void Controls::draw(SDL_Surface *screen){
171
    
172 173
    
    //main body
174
    SDL_Rect rect = {0, y+timeLineHeight, width, height-timeLineHeight};
175
    SDL_FillRect(screen, &rect, emColor(0x000000));
176 177
    
    //play/pause
178
    SDL_Rect srcRect={0,0,48,32};
179 180 181 182 183 184 185 186 187
    redefineRect(&rect, 0, y+timeLineHeight, 48, height-timeLineHeight);
    if(surfPlay!=NULL)
    {
        if(audio->isPlaying())
            srcRect.x=48;
        else
            srcRect.x=0;
        SDL_BlitSurface(surfPlay,&srcRect,screen,&rect);
    }
188 189
    
    //volume
190 191 192 193 194 195
    if(surfVolume!=NULL && surfVolume2!=NULL)
    {
        redefineRect(&rect, 64, y+timeLineHeight, 64, 32);
        redefineRect(&srcRect,0,0,64, 32);
        SDL_BlitSurface(surfVolume2,&srcRect,screen,&rect);
        redefineRect(&srcRect,0,0,(int)(volume*64.0),32);
196 197
        redefineRect(&rect,64,y+timeLineHeight,srcRect.w,32);
        if(srcRect.w>=1)
198 199
                SDL_BlitSurface(surfVolume,&srcRect,screen,&rect);
    }
200
    
201 202 203 204 205 206 207 208 209 210 211 212
    //speed
    if(surfSpeed!=NULL && surfSpeed2!=NULL)
    {
        redefineRect(&rect, 160, y+timeLineHeight, 36, 32);
        redefineRect(&srcRect,0,0,36, 32);
        SDL_BlitSurface(surfSpeed2,&srcRect,screen,&rect);
        redefineRect(&srcRect,0,0,(int)(speed*72.0)-72,32);
        redefineRect(&rect,160,y+timeLineHeight,srcRect.w,32);
        if(srcRect.w>=1)
                SDL_BlitSurface(surfSpeed,&srcRect,screen,&rect);
    }
    
213
    //fullscreen button
214 215 216 217 218 219
    redefineRect(&rect, width-48, y+timeLineHeight, 48, height-timeLineHeight);
    if(surfFullscreen!=NULL)
    {
        redefineRect(&srcRect,0,0,48, 32);
        SDL_BlitSurface(surfFullscreen,&srcRect,screen,&rect);
    }
220
    
221 222 223
    if(duration==0)
        duration=audio->getDuration();
    
224
    //timeLine background
225 226
    redefineRect(&rect, 0, y, width, timeLineHeight);
    SDL_FillRect(screen, &rect, emColor(0x333333));
227 228
    if(progress>=0)
    {
229
        redefineRect(&rect, (progress/1000)*width/(duration/1000), y, width-(progress/1000)*width/(duration/1000), timeLineHeight);
230 231
        SDL_FillRect(screen, &rect, emColor(0x000000));
    }
232
    
daFischer's avatar
daFischer committed
233
    int currentPosition=audio->getPosition();
234
    //timeLine foreground
daFischer's avatar
daFischer committed
235
    if(!timeLineClicked)
236
        redefineRect(&rect, 0, y, (currentPosition/1000)*width/(duration/1000), timeLineHeight);
237
    else
daFischer's avatar
daFischer committed
238
        redefineRect(&rect, 0, y, mouseX, timeLineHeight);
239
    SDL_FillRect(screen, &rect, emColor(0xaa0000));
240
    
daFischer's avatar
daFischer committed
241
    //draw "time / duration"
daFischer's avatar
daFischer committed
242
    SDL_Color white = {0xff,0xff,0xff,0xff};
daFischer's avatar
daFischer committed
243
    ostringstream oss;
244
    oss << (currentPosition/1000)/60 << ":" << (((currentPosition/1000)%60<10) ? "0" : "") << (currentPosition/1000)%60 << "/" << (duration/1000)/60 << ":" << (((duration/1000)%60<10) ? "0" : "") << (duration/1000)%60;
daFischer's avatar
daFischer committed
245
    
daFischer's avatar
daFischer committed
246 247
    SDL_Surface* times=TTF_RenderText_Solid(Player::font,oss.str().c_str(),white);
#ifdef EMSCRIPTEN
248
    drawScaledText(screen,times,width-64-times->w*2,y+timeLineHeight+8,1);
daFischer's avatar
daFischer committed
249 250
#else
    redefineRect(&rect,width-64-times->w,y+timeLineHeight+4,times->w+4,times->h+4);
daFischer's avatar
daFischer committed
251
    SDL_BlitSurface(times,NULL,screen,&rect);
daFischer's avatar
daFischer committed
252
#endif
253
    SDL_FreeSurface(times);
daFischer's avatar
daFischer committed
254 255
    
    if(mouseY>=y&&mouseY<y+timeLineHeight)
daFischer's avatar
daFischer committed
256
    {
257
        video->drawThumbnail(duration/width*mouseX,mouseX,y);
daFischer's avatar
daFischer committed
258 259
        //draw time at cursor position
        ostringstream oss2;
260
        oss2 << (duration/1000)*mouseX/width/60 << ":" << ((((duration/1000)*mouseX/width)%60<10) ? "0" : "") << ((duration/1000)*mouseX/width)%60;
daFischer's avatar
daFischer committed
261 262 263 264 265 266 267
        SDL_Color black={0,0,0,0xff};
        /*TTF_SetFontOutline(Player::font,2);
        times=TTF_RenderText_Solid(Player::font,oss2.str().c_str(),black);
        redefineRect(&rect,max(0,min(width-times->w,mouseX-times->w/2 - 2)),y-24,times->w+4,times->h+4);
        SDL_BlitSurface(times,NULL,screen,&rect);
        SDL_FreeSurface(times);
        TTF_SetFontOutline(Player::font,0);*/
268
        times=TTF_RenderText_Solid(Player::font,oss2.str().c_str(),white);
daFischer's avatar
daFischer committed
269
#ifdef EMSCRIPTEN
270
        drawScaledText(screen,times,max(0,min(width-times->w*2,mouseX-times->w - 2)),y,1);
daFischer's avatar
daFischer committed
271
#else
272
        redefineRect(&rect,max(0,min(width-times->w,mouseX-times->w/2 - 2)),y-3,times->w+4,times->h+4);
daFischer's avatar
daFischer committed
273 274 275 276
        SDL_BlitSurface(times,NULL,screen,&rect);
#endif
        SDL_FreeSurface(times);
    }
daFischer's avatar
daFischer committed
277
    
278
    SDL_UpdateRect(screen, 0,y,width,screenHeight-y);
daFischer's avatar
daFischer committed
279
    //SDL_Flip(screen);
280 281 282
}

Uint32 Controls::emColor(unsigned int color){
daFischer's avatar
daFischer committed
283
    return SDL_MapRGBA(ProtocolPreferences::format,(color & 0xff0000)>>16,(color & 0x00ff00)>>8,color & 0x0000ff,0xff);
284 285 286 287 288 289 290 291
#if EMSCRIPTEN
    unsigned int r = (color & 0xff0000)>>16;
    unsigned int g = color & 0x00ff00;
    unsigned int b = (color & 0x0000ff)<<16;
    return 0xff000000|b|g|r ;
#else
    return 0xff000000|color;
#endif
292 293
}

294 295 296 297 298 299 300
/**
 * Needed to draw the text indicating the times scaled
 * @param source source text image
 * @param x
 * @param y
 * @return Color in the source images color format
 */
daFischer's avatar
daFischer committed
301 302 303 304 305 306 307 308 309 310 311 312
Uint32 Controls::readPixel(SDL_Surface* source, int x, int y){
    switch(source->format->BytesPerPixel)
    {
        case 1:
            return ((unsigned char*)source->pixels)[x+source->w*y];
        case 2:
            return ((unsigned short*)source->pixels)[x+source->w*y];
        default:
            return ((unsigned int*)source->pixels)[x+source->w*y];
    }
}

313 314 315 316 317 318 319 320
/**
 * Font size doesn't work right with Emscripten. Therefore we have to scale it up manually
 * @param screen the target surface
 * @param text the original (small) text image
 * @param x
 * @param y
 * @param factor how strong the image should be upscaled
 */
daFischer's avatar
daFischer committed
321 322 323 324 325 326 327 328 329 330 331 332 333
void Controls::drawScaledText(SDL_Surface* screen, SDL_Surface* text, short x, short y, char factor) {
    SDL_Rect rect={0,0,factor,factor};
    SDL_LockSurface(text);
    for(int i=0;i<text->w;i++)
        for(int j=0;j<text->h;j++)
        {
            rect.x=x+i*factor;
            rect.y=y+j*factor;
            SDL_FillRect(screen,&rect,readPixel(text,i,j));
        }
    SDL_UnlockSurface(text);
}

334 335 336 337 338 339 340 341
void Controls::redefineRect(SDL_Rect* rect, int x, int y, int w, int h){
    rect->x=x;
    rect->y=y;
    rect->w=w;
    rect->h=h;
}

void Controls::skipTo(int position){
342
    audio->setPosition(position);
343
    video->seekPosition(position, this);
344 345 346 347 348 349
}

void Controls::changeVolume(float volume){
    this->volume=volume;
    audio->changeVolume(volume);
}
350 351 352 353 354

void Controls::changeSpeed(float speed){
    this->speed=speed;
    audio->changeSpeed(speed);
}