#include <sys/ioctl.h>

#include "setup.h"
#include "vdrstatus.h"
#include "videostatus.h"
#include "setup.h"
#include "i18n.h"

#include "symbols/test/ar16943.xpm"
#include "symbols/test/ar169na.xpm"
#include "symbols/test/ar169ps.xpm"
#include "symbols/test/ar169vc.xpm"
#include "symbols/test/ar43169ps.xpm"
#include "symbols/test/ar43169vc.xpm"
#include "symbols/test/ar432211ps.xpm"
#include "symbols/test/ar432211psvc.xpm"
#include "symbols/test/ar432211vc.xpm"
#include "symbols/test/ar43na.xpm"

extern int fd_video;
#define DEV_DVB_VIDEO     "/dev/dvb/adapter%d/video%d"

cVideoStatus VideoStatus;

cBitmap cVideoStatusUpdate::bmar16943(ar16943_xpm);
cBitmap cVideoStatusUpdate::bmar169na(ar169na_xpm);
cBitmap cVideoStatusUpdate::bmar169ps(ar169ps_xpm);
cBitmap cVideoStatusUpdate::bmar169vc(ar169vc_xpm);
cBitmap cVideoStatusUpdate::bmar43169ps(ar43169ps_xpm);
cBitmap cVideoStatusUpdate::bmar43169vc(ar43169vc_xpm);
cBitmap cVideoStatusUpdate::bmar432211ps(ar432211ps_xpm);
cBitmap cVideoStatusUpdate::bmar432211psvc(ar432211psvc_xpm);
cBitmap cVideoStatusUpdate::bmar432211vc(ar432211vc_xpm);
cBitmap cVideoStatusUpdate::bmar43na(ar43na_xpm);

cVideoStatus::cVideoStatus(void) {
#ifdef DEBUG
    isyslog("skinelchi: cVideoStatus::cVideoStatus() is called");
#endif
    VideoStatusUpdate = new cVideoStatusUpdate;
    }

cVideoStatus::~cVideoStatus() {
#ifdef DEBUG
    isyslog("skinelchi: cVideoStatus::~cVideoStatus() is called");
#endif
    VideoStatusUpdate->Pid++;
    }

void cVideoStatus::Update() {
    VideoStatusUpdate->Update();
    }

int cVideoStatus::Width(void) {
    return VideoStatusUpdate->Width();
    }

int cVideoStatus::Height(void) {
    return VideoStatusUpdate->Height();
    }

int cVideoStatus::Ar(void) {
    return VideoStatusUpdate->Ar();
    }

bool cVideoStatus::NTSC(void) {
    int h = VideoStatusUpdate->Height();
    if ((h == 240) || (h == 480))
        return true;
    return false;
    }

const char *cVideoStatus::VideoFormat(void) {
    switch (VideoStatusUpdate->Ar()) {
	case VIDEO_FORMAT_4_3: 
		return "4:3";
	    break;
	case VIDEO_FORMAT_16_9:
		return "16:9";
	    break;
	case VIDEO_FORMAT_221_1:
		return "2.21:1";
	    break;
	default:
	    return "?:?";
	}
    }

const char *cVideoStatus::DisplayFormat(void) {
    return VideoStatusUpdate->DisplayFormat();
    }

cBitmap *cVideoStatus::DFbmp(void) {
    return VideoStatusUpdate->DFbmp();
    }

cVideoStatusUpdate::cVideoStatusUpdate(void) {
#ifdef DEBUG
    isyslog("skinelchi: cVideoStatusUpdate::cVideoStatusUpdate()");
#endif
    Start();
}

cVideoStatusUpdate::~cVideoStatusUpdate() {
#ifdef DEBUG
    isyslog("skinelchi: cVideoStatusUpdate::~cVideoStatusUpdate()");
#endif
    Pid++;
}

void cVideoStatusUpdate::Update() {
#ifdef DEBUG
    isyslog("skinelchi: cVideoStatusUpdate::Update() is called");
#endif
    if (cDevice::PrimaryDevice()->HasDecoder()) {
	Lock();
	if (fd_video != -1) {
	    close(fd_video);
    	    fd_video = -1;
    	    }
	if (SkinElchiSetup.videostatus) {
	    char *dev = NULL;
	    asprintf(&dev, DEV_DVB_VIDEO, cDevice::PrimaryDevice()->CardIndex(), 0);
	    fd_video = open(dev, O_RDONLY | O_NONBLOCK);
	    free(dev);
	    }
	Unlock();
	}
    Wait.Signal();
    }

int cVideoStatusUpdate::Width(void) {
    int w;
    Lock();
    w = width;
    Unlock();
    return w;
    }

int cVideoStatusUpdate::Height(void) {
    int h;
    Lock();
    h = height;
    Unlock();
    return h;
    }

int cVideoStatusUpdate::Ar(void) {
    int a;
    Lock();
    a = ar;
    Unlock();
    return a;
    }

const char *cVideoStatusUpdate::DisplayFormat(void) {
    const char *df;
    char *s;
    Lock();
    asprintf(&s, "(%d:%d:%d:%d:%d)", (int)videostatus.video_blank, (int)videostatus.play_state, (int)videostatus.stream_source, (int)(videostatus.video_format), (int)videostatus.display_format);
    Unlock();
    df = strdup(s);
    free(s);
    return df;
    }

cBitmap *cVideoStatusUpdate::DFbmp(void) {
    cBitmap *bm;
    Lock();
    bm = dfbmp;
    Unlock();
    return bm;
    }

void cVideoStatusUpdate::Action(void) {
    pid = Pid = (int)getpid();
#ifdef DEBUG
    isyslog("skinelchi: cVideoStatusUpdate::Action() - pid=%d", pid);
#endif
    while (Pid == pid) {
	int handle = fd_video;
	int getvssize = 0;
	if (handle >= 0) {
	    while (Pid == pid && getvssize == 0 && handle == fd_video) {
		getvssize = ioctl(handle, VIDEO_GET_SIZE, &vs);
		if (getvssize == 0) {
		    width = vs.w;
		    height = (int)vs.h;
		    ar = vs.aspect_ratio;
#ifdef DEBUG
		    isyslog("skinelchi: cVideoStatusUpdate %d*%d %d", vs.w, vs.h, vs.aspect_ratio);
#endif
		    switch (ar) {
			case VIDEO_FORMAT_4_3: 
			    break;
			case VIDEO_FORMAT_16_9:
			    break;
			case VIDEO_FORMAT_221_1:
			    break;
			default:
			    ar = -1;
			}
		    if (ar != -1) {
	    		if (ioctl(fd_video, VIDEO_GET_STATUS, &videostatus) == 0) {
			    dfbmp = NULL;
			    switch (
#ifdef DVB_OLDER_20050331
videostatus.video_format
#else
videostatus.display_format
#endif
) {
				case 
#ifdef DVB_OLDER_20050331
VIDEO_FORMAT_4_3
#else
VIDEO_PAN_SCAN
#endif
: {
				    switch (ar) {
					case 0: /*4:3???*/
					    dfbmp = Setup.VideoFormat ? &bmar16943 : &bmar43na;
					    break;
					case 1: /*16:9???*/
#if VDRVERSNUM >= 10322
		    			    if (Setup.VideoDisplayFormat != 0 && VdrStatus.ReplayingName && SkinElchiSetup.switchvideodisplayformat) /* must "check", VIDEO_FORMAT really show VIDEO_DISPLAY_FORMAT? */
				    		cDevice::PrimaryDevice()->SetVideoDisplayFormat(eVideoDisplayFormat(Setup.VideoDisplayFormat));
#endif
					    dfbmp = Setup.VideoFormat ? &bmar169na : &bmar43169ps;
					    break;
					case 2: /*2.21:1*/
					    dfbmp = Setup.VideoFormat ? &bmar169ps : &bmar432211ps;
					}
				    break;
				    }
				case 
#ifdef DVB_OLDER_20050331
VIDEO_FORMAT_16_9
#else
VIDEO_LETTER_BOX
#endif
: {
				    switch (ar) {
					case 0: /*4:3???*/
					    dfbmp = Setup.VideoFormat ? &bmar16943 : &bmar43na;
					    break;
					case 1: /*16:9???*/
#if VDRVERSNUM >= 10322
					    if (Setup.VideoDisplayFormat != 1 && VdrStatus.ReplayingName && SkinElchiSetup.switchvideodisplayformat) /* must "check", VIDEO_FORMAT really show VIDEO_DISPLAY_FORMAT? */
				    		cDevice::PrimaryDevice()->SetVideoDisplayFormat(eVideoDisplayFormat(Setup.VideoDisplayFormat));
#endif
					    dfbmp = Setup.VideoFormat ? &bmar169na : &bmar43169vc;
					    break;
					case 2: /*2.21:1*/
					    dfbmp = Setup.VideoFormat ? &bmar169vc : &bmar432211vc;
					}
				    break;
				    }
				case 
#ifdef DVB_OLDER_20050331
VIDEO_FORMAT_221_1
#else
VIDEO_CENTER_CUT_OUT
#endif
: {
				    switch (ar) {
					case 0: /*4:3???*/
					    dfbmp = Setup.VideoFormat ? &bmar16943 : &bmar43na;/*4:3 on 16:9*/
					    break;
					case 1: /*16:9???*/
					    dfbmp = Setup.VideoFormat ? &bmar169na : &bmar43169ps;
					    break;
					case 2: /*2.21:1*/
#if VDRVERSNUM >= 10322
		    			    if (Setup.VideoDisplayFormat != 2 && VdrStatus.ReplayingName && SkinElchiSetup.switchvideodisplayformat) /* must "check", VIDEO_FORMAT really show VIDEO_DISPLAY_FORMAT? */
		    		    		cDevice::PrimaryDevice()->SetVideoDisplayFormat(eVideoDisplayFormat(Setup.VideoDisplayFormat));
#endif
					    dfbmp = Setup.VideoFormat ? &bmar169vc : &bmar432211psvc;
					}
				    }
				}
			    }
#ifdef DEBUG
			isyslog("skinelchi: cVideoStatusUpdate %d:%d:%d:%d:%d", (int)videostatus.video_blank, (int)videostatus.play_state, (int)videostatus.stream_source, (int)(videostatus.video_format), (int)videostatus.display_format);
#endif
			}
		    Wait.Wait(1000);
		    }
		else { 
		    width = 0;
		    height = 0;
#ifdef DEBUG
		    isyslog("skinelchi: cVideoStatusUpdate - Error (pid=%d)", getvssize);
#endif
		    Wait.Wait(5000);
		    }
		}
	    }
        width = 0;
        height = 0;
	Wait.Wait(5000);
	}
#ifdef DEBUG
    isyslog("skinelchi: cVideoStatusUpdate - thread end (pid=%d)", pid);
#endif
}
