<commit_before>#include "Maze.h"
#include "MainCharacter.h"
#include "Login.h"
#include "Status.h"
#include "MapsReceiver.h"
#include "EnemyCharacter.h"
#include "Obstacle.h"

#define MAP_COOR_SCALE 5
#define GAP_CLIMB 0.1

Model *model;
Status *status;
MainCharacter *character;
EnemyCharacter *enemy;
Obstacle *obstacle;

int counter = 0;
double lightComponent, factor = 3.0, duration = 10000.0; //change duration to increase/decrease effect tim

void Maze::Timer(int value) {
	if (status->daynight) {
		counter++;
		lightComponent = cos((counter / duration) * (2.0 * M_PI)) / factor + (factor - 1.0) / factor;
		GLfloat light[] = { lightComponent, lightComponent, lightComponent, 1.0 };
		//status->main_light = (GLfloat*)light;
		if (counter > duration) {
			counter = 0;
		}
	}

    glutTimerFunc(status->timer, Timer, 0);

	if (status->tecla_o) status->background_music->toggle();

	GLfloat nx = 0, ny = 0, z = character->position->z;

	if (status->up){
		if (Walk(1)) {
			nx = character->position->x + character->vel * cosf(character->dir);
			ny = character->position->y + character->vel * sinf(character->dir);
			character->position->x = nx;
			character->position->y = ny;
			character->position->z = CHARACTER_HEIGHT * 0.5;
			status->walking = GL_TRUE;

			//	Check if the character has fallen and drains some life
			if (character->position->z - z < -4.0)
				character->health -= 10;
		}
	}
	else if (status->down){
		if (Walk(-1)) {
			nx = character->position->x - character->vel * cosf(character->dir);
			ny = character->position->y - character->vel * sinf(character->dir);
			character->position->x = nx;
			character->position->y = ny;
			character->position->z = CHARACTER_HEIGHT * 0.5;
			status->walking = GL_TRUE;

			//	Check if the character has fallen and drains some life
			if (character->position->z - z < -4.0)
				character->health -= 10;

		}
	}
	else
		status->walking = GL_FALSE;

	if (status->left){
		character->dir += rad(2);
		status->camera->dir_long = character->dir;
	}
	else if (status->right){
		character->dir -= rad(2);
		status->camera->dir_long = character->dir;
	}

	if (status->walking && character->homer.GetSequence() != 3){
		character->homer.SetSequence(3);

	}
	else if (!status->walking && character->homer.GetSequence() == 3)
	{
		character->homer.SetSequence(0);
	}

	if (status->mapfile == "quarto1.grafo")
	{
		if (character->position->x > 0.331 && character->position->x<11.43 && character->position->y>292.529 && character->position->y < 292.605)
		{
			status->mapfile = "quarto2.grafo";
		}
		/*else if (character->position->x &&character->position->y){
			status->mapfile = "quarto3.grafo";
		}*/
	}
	else if (status->mapfile == "quarto2.grafo")
	{
		if (character->position->x>-137.506 && character->position->x<-134.058 && character->position->y>-266.794 && character->position->y<-256.512){
			status->mapfile = "quarto1.grafo";
		}
	}
	//else {
	//	if (character->position->x &&character->position->y){
	//		status->mapfile = "quarto1.grafo";
	//	}
	//}

	if (CollisionEnemy(character->position->x, character->position->y, character->position->z))
	{
		character->Die();
	}

    glutPostRedisplay();
}

bool Maze::Walk(int direction) {

	if (!character->IsDead())
	{
		// TODO: stop moving
	}

GLfloat nx = 0.0, ny = 0.0, nz = 0.0, lx, ly, alpha, si, projLength, sf, gap, nxx, nyy, nfxx, nfyy;

	nx = character->position->x + (direction * character->vel) * cosf(character->dir);
	ny = character->position->y + (direction * character->vel) * sinf(character->dir);

	for (int n = 0; n < numNos; n++){
		No ni = nos[n];

		if (pow(nx - (ni.x * MAP_COOR_SCALE), 2) + pow(ny - (ni.y * MAP_COOR_SCALE), 2) <= pow((ni.largura * 0.5) * MAP_COOR_SCALE, 2)) {
			nz = ni.z * MAP_COOR_SCALE + CHARACTER_HEIGHT * 0.5;
			if (nz > character->position->z && nz - character->position->z > 1)
				return false;

			character->position->x = nx;
			character->position->y = ny;
			character->position->z = nz;
			status->walking = GL_TRUE;
			return false;
		}
	}

	for (int i = 0; i < numArcos; i++) {

		No ni = nos[arcos[i].noi];
		No nf = nos[arcos[i].nof];
		si = ni.largura * 0.5 * MAP_COOR_SCALE;
		gap = nf.z * MAP_COOR_SCALE - ni.z * MAP_COOR_SCALE;
		sf = nf.largura * 0.5 * MAP_COOR_SCALE;
		projLength = sqrtf(powf(nf.x * MAP_COOR_SCALE - ni.x * MAP_COOR_SCALE, 2) + powf(nf.y * MAP_COOR_SCALE - ni.y * MAP_COOR_SCALE, 2)) - si - sf;
		alpha = atan2(nf.y * MAP_COOR_SCALE - ni.y * MAP_COOR_SCALE, nf.x * MAP_COOR_SCALE - ni.x * MAP_COOR_SCALE);
		lx = ((nx - ni.x * MAP_COOR_SCALE) * cosf(alpha) + (ny - ni.y * MAP_COOR_SCALE) * sinf(alpha));
		ly = ((ny - ni.y * MAP_COOR_SCALE) * cosf(alpha) - (nx - ni.x * MAP_COOR_SCALE) * sinf(alpha));
		nz = ni.z * MAP_COOR_SCALE + CHARACTER_HEIGHT * 0.5;

		nxx = (nx - ni.x * MAP_COOR_SCALE) * cos(alpha) + (ny - ni.y * MAP_COOR_SCALE) * sin(alpha);
		nyy = (ny - ni.y * MAP_COOR_SCALE) * cos(alpha) - (nx - ni.x * MAP_COOR_SCALE) * sin(alpha);

		nfxx = (nx - nf.x * MAP_COOR_SCALE) * cos(alpha + M_PI) + (ny - nf.y * MAP_COOR_SCALE) * sin(alpha + M_PI);
		nfyy = (ny - nf.y * MAP_COOR_SCALE) * cos(alpha + M_PI) - (nx - nf.x * MAP_COOR_SCALE) * sin(alpha + M_PI);

		if (0.0 <= nxx
			&& nxx <= si
			&& -arcos[i].largura * 0.5 * MAP_COOR_SCALE <= nyy
			&& nyy <= arcos[i].largura * 0.5 * MAP_COOR_SCALE) {

			nz = ni.z * MAP_COOR_SCALE + CHARACTER_HEIGHT * 0.5;
			if (nz > character->position->z && nz - character->position->z > 1)
				return false;

			character->position->x = nx;
			character->position->y = ny;
			character->position->z = nz;
			status->walking = GL_TRUE;
			return false;
		}

		if (0.0 <= nfxx
			&& nfxx <= sf
			&& -arcos[i].largura * 0.5 * MAP_COOR_SCALE <= nfyy
			&& nfyy <= arcos[i].largura * 0.5 * MAP_COOR_SCALE) {

			nz = nf.z * MAP_COOR_SCALE + CHARACTER_HEIGHT * 0.5;
			character->position->x = nx;
			character->position->y = ny;
			character->position->z = nz;
			status->walking = GL_TRUE;
			return false;
		}

		if (si < nxx
			&& nxx < si + projLength
			&& -arcos[i].largura * 0.5 * MAP_COOR_SCALE <= nyy
			&& nyy <= arcos[i].largura * 0.5 * MAP_COOR_SCALE) {

			nz = ni.z * MAP_COOR_SCALE + (lx - si) / projLength * gap + CHARACTER_HEIGHT * 0.5;
			if (nz > character->position->z && nz - character->position->z > 1)
				return false;

			character->position->x = nx;
			character->position->y = ny;
			character->position->z = nz;
			status->walking = GL_TRUE;
			return false;
		}
	}
}

bool Maze::CollisionEnemy(GLfloat x, GLfloat y, GLfloat z)
{
	GLfloat xMin, xMax;
	GLfloat yMin, yMax;
	GLfloat zMin, zMax;

	xMin = enemy->position->x - CHARACTER_WIDTH / 2;
	xMax = enemy->position->x + CHARACTER_WIDTH / 2;

	yMin = enemy->position->y - CHARACTER_LENGTH / 2;
	yMax = enemy->position->y + CHARACTER_LENGTH / 2;

	zMin = enemy->position->z - CHARACTER_HEIGHT / 2;
	zMax = enemy->position->z + CHARACTER_HEIGHT / 2;

	return x >= xMin && x <= xMax &&
		y >= yMin && y <= yMax &&
		z >= zMin && z <= zMax;
}

void Maze::showLoginWindow() {
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
	glutInitWindowSize(350, 350);
	glutCreateWindow("Login");
	glutDisplayFunc(Graphics::loginDisplay);
	glutKeyboardFunc(Keyboard::loginKeyboard);
	glutMainLoop();
}

void Maze::Launch(int argc, char **argv){
	status = new Status();
	//showLoginWindow(); // do not show yet, not 100% ready
	// there is a NEW BUG on receving the maps, dont know why so map is not saved ISSUE 47
	//MapsReceiver *receiver = new MapsReceiver();
	//string mapName = receiver->chooseMap();
	//if (!mapName.empty()) {
	//	//set choosen map
	//	status->mapfile = mapName + ".grafo";
		glutInit(&argc, argv);
		alutInit(&argc, argv);

		model = new Model();
		//status = new Status();
		character = new MainCharacter();
		enemy = new EnemyCharacter();
		obstacle = new Obstacle();

		/* need both double buffering and z buffer */

		glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
		glutInitWindowSize(640, 480);
		glutCreateWindow("OpenGL");
		glutReshapeFunc(Graphics::myReshape);
		glutDisplayFunc(Graphics::display);
		glutKeyboardFunc(Keyboard::keyboard);
		glutSpecialUpFunc(Keyboard::specialKeyUp);
		glutSpecialFunc(Keyboard::Special);
		glutMouseFunc(Mouse::mouse);
		glutTimerFunc(status->timer, Timer, 0);

		GLfloat LuzAmbiente[] = { 0.5, 0.5, 0.5, 0.0 };
		Graphics::createTextures(model->texID);

		glClearColor(0.0, 0.0, 0.0, 0.0);

		glEnable(GL_SMOOTH); /*enable smooth shading */
		glEnable(GL_LIGHTING); /* enable lighting */
		glEnable(GL_DEPTH_TEST); /* enable z buffer */
		glEnable(GL_NORMALIZE);
		glEnable(GL_TEXTURE_2D);

		glDepthFunc(GL_LESS);

		glLightModelfv(GL_LIGHT_MODEL_AMBIENT, LuzAmbiente);
		glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, status->lightViewer);
		glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);

		model->quad = gluNewQuadric();
		gluQuadricDrawStyle(model->quad, GLU_FILL);
		gluQuadricNormals(model->quad, GLU_OUTSIDE);

		leGrafo(status->mapfile);

		Keyboard::help();

		glutMainLoop();
/*	}*/

}
<commit_msg>Minor fix<commit_after>#include "Maze.h"
#include "MainCharacter.h"
#include "Login.h"
#include "Status.h"
#include "MapsReceiver.h"
#include "EnemyCharacter.h"
#include "Obstacle.h"

#define MAP_COOR_SCALE 5
#define GAP_CLIMB 0.1

Model *model;
Status *status;
MainCharacter *character;
EnemyCharacter *enemy;
Obstacle *obstacle;

int counter = 0;
double lightComponent, factor = 3.0, duration = 10000.0; //change duration to increase/decrease effect tim

void Maze::Timer(int value) {
	if (status->daynight) {
		counter++;
		lightComponent = cos((counter / duration) * (2.0 * M_PI)) / factor + (factor - 1.0) / factor;
		GLfloat light[] = { lightComponent, lightComponent, lightComponent, 1.0 };
		//status->main_light = (GLfloat*)light;
		if (counter > duration) {
			counter = 0;
		}
	}

    glutTimerFunc(status->timer, Timer, 0);

	if (status->tecla_o) status->background_music->toggle();

	GLfloat nx = 0, ny = 0, z = character->position->z;

	if (status->up){
		if (Walk(1)) {
			nx = character->position->x + character->vel * cosf(character->dir);
			ny = character->position->y + character->vel * sinf(character->dir);
			character->position->x = nx;
			character->position->y = ny;
			character->position->z = CHARACTER_HEIGHT * 0.5;
			status->walking = GL_TRUE;

			//	Check if the character has fallen and drains some life
			if (character->position->z - z < -4.0)
				character->health -= 10;
		}
	}
	else if (status->down){
		if (Walk(-1)) {
			nx = character->position->x - character->vel * cosf(character->dir);
			ny = character->position->y - character->vel * sinf(character->dir);
			character->position->x = nx;
			character->position->y = ny;
			character->position->z = CHARACTER_HEIGHT * 0.5;
			status->walking = GL_TRUE;

			//	Check if the character has fallen and drains some life
			if (character->position->z - z < -4.0)
				character->health -= 10;

		}
	}
	else
		status->walking = GL_FALSE;

	if (status->left){
		character->dir += rad(2);
		status->camera->dir_long = character->dir;
	}
	else if (status->right){
		character->dir -= rad(2);
		status->camera->dir_long = character->dir;
	}

	if (status->walking && character->homer.GetSequence() != 3){
		character->homer.SetSequence(3);

	}
	else if (!status->walking && character->homer.GetSequence() == 3)
	{
		character->homer.SetSequence(0);
	}

	if (status->mapfile == "quarto1.grafo")
	{
		if (character->position->x > 0.331 && character->position->x<11.43 && character->position->y>292.529 && character->position->y < 292.605)
		{
			status->mapfile = "quarto2.grafo";
		}
		/*else if (character->position->x &&character->position->y){
			status->mapfile = "quarto3.grafo";
		}*/
	}
	else if (status->mapfile == "quarto2.grafo")
	{
		if (character->position->x>-137.506 && character->position->x<-134.058 && character->position->y>-266.794 && character->position->y<-256.512){
			status->mapfile = "quarto1.grafo";
		}
	}
	//else {
	//	if (character->position->x &&character->position->y){
	//		status->mapfile = "quarto1.grafo";
	//	}
	//}

	if (CollisionEnemy(character->position->x, character->position->y, character->position->z))
	{
		character->Die();
	}

    glutPostRedisplay();
}

bool Maze::Walk(int direction) {

	if (!character->IsDead())
	{
		// TODO: stop moving
	}

GLfloat nx = 0.0, ny = 0.0, nz = 0.0, lx, ly, alpha, si, projLength, sf, gap, nxx, nyy, nfxx, nfyy;

	nx = character->position->x + (direction * character->vel) * cosf(character->dir);
	ny = character->position->y + (direction * character->vel) * sinf(character->dir);

	for (int n = 0; n < numNos; n++){
		No ni = nos[n];

		if (pow(nx - (ni.x * MAP_COOR_SCALE), 2) + pow(ny - (ni.y * MAP_COOR_SCALE), 2) <= pow((ni.largura * 0.5) * MAP_COOR_SCALE, 2)) {
			nz = ni.z * MAP_COOR_SCALE + CHARACTER_HEIGHT * 0.5;
			if (nz > character->position->z && nz - character->position->z > 1)
				return false;

			character->position->x = nx;
			character->position->y = ny;
			character->position->z = nz;
			status->walking = GL_TRUE;
			return false;
		}
	}

	for (int i = 0; i < numArcos; i++) {

		No ni = nos[arcos[i].noi];
		No nf = nos[arcos[i].nof];
		si = ni.largura * 0.5 * MAP_COOR_SCALE;
		gap = nf.z * MAP_COOR_SCALE - ni.z * MAP_COOR_SCALE;
		sf = nf.largura * 0.5 * MAP_COOR_SCALE;
		projLength = sqrtf(powf(nf.x * MAP_COOR_SCALE - ni.x * MAP_COOR_SCALE, 2) + powf(nf.y * MAP_COOR_SCALE - ni.y * MAP_COOR_SCALE, 2)) - si - sf;
		alpha = atan2(nf.y * MAP_COOR_SCALE - ni.y * MAP_COOR_SCALE, nf.x * MAP_COOR_SCALE - ni.x * MAP_COOR_SCALE);
		lx = ((nx - ni.x * MAP_COOR_SCALE) * cosf(alpha) + (ny - ni.y * MAP_COOR_SCALE) * sinf(alpha));
		ly = ((ny - ni.y * MAP_COOR_SCALE) * cosf(alpha) - (nx - ni.x * MAP_COOR_SCALE) * sinf(alpha));
		nz = ni.z * MAP_COOR_SCALE + CHARACTER_HEIGHT * 0.5;

		nxx = (nx - ni.x * MAP_COOR_SCALE) * cos(alpha) + (ny - ni.y * MAP_COOR_SCALE) * sin(alpha);
		nyy = (ny - ni.y * MAP_COOR_SCALE) * cos(alpha) - (nx - ni.x * MAP_COOR_SCALE) * sin(alpha);

		nfxx = (nx - nf.x * MAP_COOR_SCALE) * cos(alpha + M_PI) + (ny - nf.y * MAP_COOR_SCALE) * sin(alpha + M_PI);
		nfyy = (ny - nf.y * MAP_COOR_SCALE) * cos(alpha + M_PI) - (nx - nf.x * MAP_COOR_SCALE) * sin(alpha + M_PI);

		if (0.0 <= nxx
			&& nxx <= si
			&& -arcos[i].largura * 0.5 * MAP_COOR_SCALE <= nyy
			&& nyy <= arcos[i].largura * 0.5 * MAP_COOR_SCALE) {

			nz = ni.z * MAP_COOR_SCALE + CHARACTER_HEIGHT * 0.5;
			if (nz > character->position->z && nz - character->position->z > 1)
				return false;

			character->position->x = nx;
			character->position->y = ny;
			character->position->z = nz;
			status->walking = GL_TRUE;
			return false;
		}

		if (0.0 <= nfxx
			&& nfxx <= sf
			&& -arcos[i].largura * 0.5 * MAP_COOR_SCALE <= nfyy
			&& nfyy <= arcos[i].largura * 0.5 * MAP_COOR_SCALE) {

			nz = nf.z * MAP_COOR_SCALE + CHARACTER_HEIGHT * 0.5;
			if (nz > character->position->z && nz - character->position->z > 1)
				return false;

			character->position->x = nx;
			character->position->y = ny;
			character->position->z = nz;
			status->walking = GL_TRUE;
			return false;
		}

		if (si < nxx
			&& nxx < si + projLength
			&& -arcos[i].largura * 0.5 * MAP_COOR_SCALE <= nyy
			&& nyy <= arcos[i].largura * 0.5 * MAP_COOR_SCALE) {

			nz = ni.z * MAP_COOR_SCALE + (lx - si) / projLength * gap + CHARACTER_HEIGHT * 0.5;
			if (nz > character->position->z && nz - character->position->z > 1)
				return false;

			character->position->x = nx;
			character->position->y = ny;
			character->position->z = nz;
			status->walking = GL_TRUE;
			return false;
		}
	}
}

bool Maze::CollisionEnemy(GLfloat x, GLfloat y, GLfloat z)
{
	GLfloat xMin, xMax;
	GLfloat yMin, yMax;
	GLfloat zMin, zMax;

	xMin = enemy->position->x - CHARACTER_WIDTH / 2;
	xMax = enemy->position->x + CHARACTER_WIDTH / 2;

	yMin = enemy->position->y - CHARACTER_LENGTH / 2;
	yMax = enemy->position->y + CHARACTER_LENGTH / 2;

	zMin = enemy->position->z - CHARACTER_HEIGHT / 2;
	zMax = enemy->position->z + CHARACTER_HEIGHT / 2;

	return x >= xMin && x <= xMax &&
		y >= yMin && y <= yMax &&
		z >= zMin && z <= zMax;
}

void Maze::showLoginWindow() {
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
	glutInitWindowSize(350, 350);
	glutCreateWindow("Login");
	glutDisplayFunc(Graphics::loginDisplay);
	glutKeyboardFunc(Keyboard::loginKeyboard);
	glutMainLoop();
}

void Maze::Launch(int argc, char **argv){
	status = new Status();
	//showLoginWindow(); // do not show yet, not 100% ready
	// there is a NEW BUG on receving the maps, dont know why so map is not saved ISSUE 47
	//MapsReceiver *receiver = new MapsReceiver();
	//string mapName = receiver->chooseMap();
	//if (!mapName.empty()) {
	//	//set choosen map
	//	status->mapfile = mapName + ".grafo";
		glutInit(&argc, argv);
		alutInit(&argc, argv);

		model = new Model();
		//status = new Status();
		character = new MainCharacter();
		enemy = new EnemyCharacter();
		obstacle = new Obstacle();

		/* need both double buffering and z buffer */

		glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
		glutInitWindowSize(640, 480);
		glutCreateWindow("OpenGL");
		glutReshapeFunc(Graphics::myReshape);
		glutDisplayFunc(Graphics::display);
		glutKeyboardFunc(Keyboard::keyboard);
		glutSpecialUpFunc(Keyboard::specialKeyUp);
		glutSpecialFunc(Keyboard::Special);
		glutMouseFunc(Mouse::mouse);
		glutTimerFunc(status->timer, Timer, 0);

		GLfloat LuzAmbiente[] = { 0.5, 0.5, 0.5, 0.0 };
		Graphics::createTextures(model->texID);

		glClearColor(0.0, 0.0, 0.0, 0.0);

		glEnable(GL_SMOOTH); /*enable smooth shading */
		glEnable(GL_LIGHTING); /* enable lighting */
		glEnable(GL_DEPTH_TEST); /* enable z buffer */
		glEnable(GL_NORMALIZE);
		glEnable(GL_TEXTURE_2D);

		glDepthFunc(GL_LESS);

		glLightModelfv(GL_LIGHT_MODEL_AMBIENT, LuzAmbiente);
		glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, status->lightViewer);
		glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);

		model->quad = gluNewQuadric();
		gluQuadricDrawStyle(model->quad, GLU_FILL);
		gluQuadricNormals(model->quad, GLU_OUTSIDE);

		leGrafo(status->mapfile);

		Keyboard::help();

		glutMainLoop();
/*	}*/

}
<|endoftext|>


<commit_before>#include "JsPlayer.h"

#include <string.h>

#include <node_buffer.h>

#include <nah/NodeHelpers.h>

///////////////////////////////////////////////////////////////////////////////
struct JsPlayer::AsyncData
{
    virtual void process( JsPlayer* ) = 0;
};

///////////////////////////////////////////////////////////////////////////////
struct JsPlayer::AppSinkEventData : public JsPlayer::AsyncData
{
    AppSinkEventData( GstAppSink* appSink, JsPlayer::AppSinkEvent event ) :
        appSink( appSink), event( event ) {}

    void process( JsPlayer* );

    GstAppSink* appSink;
    const JsPlayer::AppSinkEvent event;
};

void JsPlayer::AppSinkEventData::process( JsPlayer* player )
{
    switch( event ) {
     case JsPlayer::AppSinkEvent::NewPreroll:
        player->onNewPreroll( appSink );
        break;
     case JsPlayer::AppSinkEvent::NewSample:
        player->onNewSample( appSink );
        break;
     case JsPlayer::AppSinkEvent::Eos:
        player->onEos( appSink );
        break;
    }
}

///////////////////////////////////////////////////////////////////////////////
v8::Persistent<v8::Function> JsPlayer::_jsConstructor;
std::set<JsPlayer*> JsPlayer::_instances;

void JsPlayer::initJsApi( const v8::Handle<v8::Object>& exports )
{
    node::AtExit( [] ( void* ) { JsPlayer::closeAll(); } );

    gst_init( 0, 0 );

    using namespace v8;

    Isolate* isolate = Isolate::GetCurrent();
    HandleScope scope( isolate );

    Local<FunctionTemplate> constructorTemplate = FunctionTemplate::New( isolate, jsCreate );
    constructorTemplate->SetClassName( String::NewFromUtf8( isolate, "Player", v8::String::kInternalizedString ) );

    Local<ObjectTemplate> instanceTemplate = constructorTemplate->InstanceTemplate();
    instanceTemplate->SetInternalFieldCount( 1 );

    instanceTemplate->Set( String::NewFromUtf8( isolate, "GST_STATE_VOID_PENDING", v8::String::kInternalizedString ),
                           Integer::New( isolate, GST_STATE_VOID_PENDING ),
                           static_cast<v8::PropertyAttribute>( ReadOnly | DontDelete ) );
    instanceTemplate->Set( String::NewFromUtf8( isolate, "GST_STATE_NULL", v8::String::kInternalizedString ),
                           Integer::New( isolate, GST_STATE_NULL ),
                           static_cast<v8::PropertyAttribute>( ReadOnly | DontDelete ) );
    instanceTemplate->Set( String::NewFromUtf8( isolate, "GST_STATE_READY", v8::String::kInternalizedString ),
                           Integer::New( isolate, GST_STATE_READY ),
                           static_cast<v8::PropertyAttribute>( ReadOnly | DontDelete ) );
    instanceTemplate->Set( String::NewFromUtf8( isolate, "GST_STATE_PAUSED", v8::String::kInternalizedString ),
                           Integer::New( isolate, GST_STATE_PAUSED ),
                           static_cast<v8::PropertyAttribute>( ReadOnly | DontDelete ) );
    instanceTemplate->Set( String::NewFromUtf8( isolate, "GST_STATE_PLAYING", v8::String::kInternalizedString ),
                           Integer::New( isolate, GST_STATE_PLAYING ),
                           static_cast<v8::PropertyAttribute>( ReadOnly | DontDelete ) );

    SET_METHOD( instanceTemplate, "parseLaunch", &JsPlayer::parseLaunch );
    SET_METHOD( instanceTemplate, "addAppSinkCallback", &JsPlayer::addAppSinkCallback );
    SET_METHOD( instanceTemplate, "setState", &JsPlayer::setState );

    Local<Function> constructor = constructorTemplate->GetFunction();
    _jsConstructor.Reset( isolate, constructor );

    exports->Set( String::NewFromUtf8( isolate, "createPlayer", v8::String::kInternalizedString ), constructor );
    exports->Set( String::NewFromUtf8( isolate, "Player", v8::String::kInternalizedString ), constructor );
}

void JsPlayer::jsCreate( const v8::FunctionCallbackInfo<v8::Value>& args )
{
    using namespace v8;

    Isolate* isolate = Isolate::GetCurrent();
    HandleScope scope( isolate );

    Local<Object> thisObject = args.Holder();
    if( args.IsConstructCall() ) {
        JsPlayer* jsPlayer = new JsPlayer( thisObject );
        args.GetReturnValue().Set( jsPlayer->handle() );
    } else {
        Local<Value> argv[] = { args[0] };
        Local<Function> constructor =
            Local<Function>::New( isolate, _jsConstructor );
        args.GetReturnValue().Set( constructor->NewInstance( sizeof( argv ) / sizeof( argv[0] ), argv ) );
    }
}

void JsPlayer::closeAll()
{
    for( JsPlayer* p : _instances ) {
        p->close();
    }

    gst_deinit();
}

JsPlayer::JsPlayer( v8::Local<v8::Object>& thisObject ) :
    _pipeline( nullptr ), _firstSample( true )
{
    Wrap( thisObject );

    _instances.insert( this );

    uv_loop_t* loop = uv_default_loop();

    uv_async_init( loop, &_async,
        [] ( uv_async_t* handle ) {
            if( handle->data )
                reinterpret_cast<JsPlayer*>( handle->data )->handleAsync();
        }
    );
    _async.data = this;

}

JsPlayer::~JsPlayer()
{
    close();

    _instances.erase( this );
}

void JsPlayer::close()
{
    _async.data = nullptr;
    uv_close( reinterpret_cast<uv_handle_t*>( &_async ), 0 );
}

void JsPlayer::handleAsync()
{
    while( !_asyncData.empty() ) {
        std::deque<std::unique_ptr<AsyncData> > tmpData;
        _asyncDataGuard.lock();
        _asyncData.swap( tmpData );
        _asyncDataGuard.unlock();

        for( const auto& i: tmpData ) {
            i->process( this );
        }
    }
}

GstFlowReturn JsPlayer::onNewPrerollProxy( GstAppSink *appSink, gpointer userData )
{
    JsPlayer* player = static_cast<JsPlayer*>( userData );

    player->_asyncDataGuard.lock();
    player->_asyncData.emplace_back( new AppSinkEventData( appSink, NewPreroll ) );
    player->_asyncDataGuard.unlock();
    uv_async_send( &player->_async );

    return GST_FLOW_OK;
}

GstFlowReturn JsPlayer::onNewSampleProxy( GstAppSink *appSink, gpointer userData )
{
    JsPlayer* player = static_cast<JsPlayer*>( userData );

    player->_appSinks[appSink].waitingSample.clear();
    player->_asyncDataGuard.lock();
    player->_asyncData.emplace_back( new AppSinkEventData( appSink, NewSample ) );
    player->_asyncDataGuard.unlock();
    uv_async_send( &player->_async );

    return GST_FLOW_OK;
}

void JsPlayer::onEosProxy( GstAppSink* appSink, gpointer userData )
{
    JsPlayer* player = static_cast<JsPlayer*>( userData );

    player->_asyncDataGuard.lock();
    player->_asyncData.emplace_back( new AppSinkEventData( appSink, Eos ) );
    player->_asyncDataGuard.unlock();
    uv_async_send( &player->_async );
}

void JsPlayer::callCallback( GstAppSink* appSink, JsPlayer::AppSinkEvent event,
                             std::initializer_list<v8::Local<v8::Value> > list )
{
    auto it = _appSinks.find( appSink );
    if( _appSinks.end() == it )
        return;

    if( it->second.callback.IsEmpty() )
        return;

    using namespace v8;

    Isolate* isolate = Isolate::GetCurrent();
    HandleScope scope( isolate );

    Local<Function> callbackFunc =
        Local<Function>::New( isolate, _appSinks[appSink].callback );

    std::vector<v8::Local<v8::Value> > argList;

    argList.push_back( Integer::New( isolate, event ) );
    argList.insert( argList.end(), list );
    callbackFunc->Call( handle(), static_cast<int>( argList.size() ), argList.data() );
}

void JsPlayer::onSetup( GstAppSink* appSink, const GstVideoInfo& videoInfo )
{
    if( !appSink )
        return;

    using namespace v8;

    Isolate* isolate = Isolate::GetCurrent();
    HandleScope scope( isolate );

    _firstSample = false;

    callCallback( appSink, Setup,
                  { String::NewFromUtf8( isolate, videoInfo.finfo->name, v8::String::kNormalString ),
                    Integer::New( isolate, videoInfo.width ),
                    Integer::New( isolate, videoInfo.height ),
                    Integer::New( isolate, videoInfo.finfo->format ) } );
}

void JsPlayer::onNewPreroll( GstAppSink* appSink )
{
    GstSample* sample = gst_app_sink_pull_preroll( appSink );

    onSample( appSink, sample, true );

    gst_sample_unref( sample );
}

void JsPlayer::onNewSample( GstAppSink* appSink )
{
    if( _appSinks[appSink].waitingSample.test_and_set() )
        return;

    GstSample* sample = gst_app_sink_pull_sample( appSink );

    _appSinks[appSink].waitingSample.test_and_set();

    onSample( appSink, sample, false );

    gst_sample_unref( sample );
}

void JsPlayer::onSample( GstAppSink* appSink, GstSample* sample, bool preroll )
{
    if( !sample )
        return;

    GstVideoInfo videoInfo;

    GstCaps* caps = gst_sample_get_caps( sample );
    if( !caps || !gst_video_info_from_caps( &videoInfo, caps ) )
        return;

    if( _firstSample )
        onSetup( appSink, videoInfo );

    GstBuffer* buffer = gst_sample_get_buffer( sample );

    if( !buffer )
        return;

    GstMapInfo mapInfo;
    if( gst_buffer_map( buffer, &mapInfo, GST_MAP_READ ) ) {
        using namespace v8;

        Isolate* isolate = Isolate::GetCurrent();
        HandleScope scope( isolate );

        v8::MaybeLocal<v8::Object> maybeFrame =
            node::Buffer::New( isolate, reinterpret_cast<char*>( mapInfo.data ), mapInfo.size,
                               [] ( char* data, void* hint ) {}, nullptr );

        Local<v8::Object> frame;
        if( maybeFrame.ToLocal( &frame ) ) {
            frame->ForceSet( String::NewFromUtf8( isolate, "pixelFormatName", v8::String::kInternalizedString ),
                             String::NewFromUtf8( isolate, videoInfo.finfo->name, v8::String::kNormalString ),
                             static_cast<v8::PropertyAttribute>( ReadOnly | DontDelete ) );
            frame->ForceSet( String::NewFromUtf8( isolate, "pixelFormat", v8::String::kInternalizedString ),
                             Integer::New( isolate, videoInfo.finfo->format ),
                             static_cast<v8::PropertyAttribute>( ReadOnly | DontDelete ) );

            frame->ForceSet( String::NewFromUtf8( isolate, "width", v8::String::kInternalizedString ),
                             Integer::New( isolate, videoInfo.width ),
                             static_cast<v8::PropertyAttribute>( ReadOnly | DontDelete ) );
            frame->ForceSet( String::NewFromUtf8( isolate, "height", v8::String::kInternalizedString ),
                             Integer::New( isolate, videoInfo.height ),
                             static_cast<v8::PropertyAttribute>( ReadOnly | DontDelete ) );

            Local<Array> planes = Array::New( isolate, videoInfo.finfo->n_planes );
            for( guint p = 0; p < videoInfo.finfo->n_planes; ++p ) {
                planes->Set( p, Integer::New( isolate, videoInfo.offset[p] ) );
            }

            frame->ForceSet( String::NewFromUtf8( isolate, "planes", v8::String::kInternalizedString ),
                             planes,
                             static_cast<v8::PropertyAttribute>( ReadOnly | DontDelete ) );

            callCallback( appSink, ( preroll ? NewPreroll : NewSample ), { frame } );
        }

        gst_buffer_unmap( buffer, &mapInfo );
    }
}

void JsPlayer::onEos( GstAppSink* appSink )
{
    callCallback( appSink, Eos );
}

bool JsPlayer::parseLaunch( const std::string& pipelineDescription )
{
    if( _pipeline ) {
        _appSinks.clear();
        gst_object_unref( _pipeline );
        _pipeline = nullptr;
        _firstSample = true;
    }

    GError* error = nullptr;
    _pipeline = gst_parse_launch( pipelineDescription.c_str(), &error );

    return ( nullptr != _pipeline );
}

bool JsPlayer::addAppSinkCallback( const std::string& appSinkName, v8::Local<v8::Value> value )
{
    if( !_pipeline || appSinkName.empty() )
        return false;

    GstElement* sink = gst_bin_get_by_name( GST_BIN( _pipeline ), appSinkName.c_str() );
    if( !sink )
        return false;

    GstAppSink* appSink = GST_APP_SINK_CAST( sink );
    if( !appSink )
        return appSink;

    using namespace v8;

    Local<Function> callbackFunc = Local<Function>::Cast( value );
    if( callbackFunc.IsEmpty() )
        return false;

    auto it = _appSinks.find( appSink );
    if( _appSinks.end() == it ) {
        gst_app_sink_set_drop( appSink, true );
        gst_app_sink_set_max_buffers( appSink, 1 );
        GstAppSinkCallbacks callbacks = { onEosProxy, onNewPrerollProxy, onNewSampleProxy };
        gst_app_sink_set_callbacks( appSink, &callbacks, this, nullptr );
        it = _appSinks.emplace( appSink, AppSinkData() ).first;
    }

    AppSinkData& sinkData = it->second;
    sinkData.callback.Reset( Isolate::GetCurrent(), callbackFunc );
    sinkData.waitingSample.test_and_set();
}

void JsPlayer::setState( unsigned state )
{
    if( _pipeline )
        gst_element_set_state( _pipeline, static_cast<GstState>( state ) );
}
<commit_msg>AppSink callback types constants added<commit_after>#include "JsPlayer.h"

#include <string.h>

#include <node_buffer.h>

#include <nah/NodeHelpers.h>

///////////////////////////////////////////////////////////////////////////////
struct JsPlayer::AsyncData
{
    virtual void process( JsPlayer* ) = 0;
};

///////////////////////////////////////////////////////////////////////////////
struct JsPlayer::AppSinkEventData : public JsPlayer::AsyncData
{
    AppSinkEventData( GstAppSink* appSink, JsPlayer::AppSinkEvent event ) :
        appSink( appSink), event( event ) {}

    void process( JsPlayer* );

    GstAppSink* appSink;
    const JsPlayer::AppSinkEvent event;
};

void JsPlayer::AppSinkEventData::process( JsPlayer* player )
{
    switch( event ) {
     case JsPlayer::AppSinkEvent::NewPreroll:
        player->onNewPreroll( appSink );
        break;
     case JsPlayer::AppSinkEvent::NewSample:
        player->onNewSample( appSink );
        break;
     case JsPlayer::AppSinkEvent::Eos:
        player->onEos( appSink );
        break;
    }
}

///////////////////////////////////////////////////////////////////////////////
v8::Persistent<v8::Function> JsPlayer::_jsConstructor;
std::set<JsPlayer*> JsPlayer::_instances;

void JsPlayer::initJsApi( const v8::Handle<v8::Object>& exports )
{
    node::AtExit( [] ( void* ) { JsPlayer::closeAll(); } );

    gst_init( 0, 0 );

    using namespace v8;

    Isolate* isolate = Isolate::GetCurrent();
    HandleScope scope( isolate );

    Local<FunctionTemplate> constructorTemplate = FunctionTemplate::New( isolate, jsCreate );
    constructorTemplate->SetClassName( String::NewFromUtf8( isolate, "Player", v8::String::kInternalizedString ) );

    Local<ObjectTemplate> instanceTemplate = constructorTemplate->InstanceTemplate();
    instanceTemplate->SetInternalFieldCount( 1 );

    instanceTemplate->Set( String::NewFromUtf8( isolate, "AppSinkSetup", v8::String::kInternalizedString ),
                           Integer::New( isolate, Setup ),
                           static_cast<v8::PropertyAttribute>( ReadOnly | DontDelete ) );
    instanceTemplate->Set( String::NewFromUtf8( isolate, "AppSinkNewPreroll", v8::String::kInternalizedString ),
                           Integer::New( isolate, NewPreroll ),
                           static_cast<v8::PropertyAttribute>( ReadOnly | DontDelete ) );
    instanceTemplate->Set( String::NewFromUtf8( isolate, "AppSinkNewSample", v8::String::kInternalizedString ),
                           Integer::New( isolate, NewSample ),
                           static_cast<v8::PropertyAttribute>( ReadOnly | DontDelete ) );
    instanceTemplate->Set( String::NewFromUtf8( isolate, "AppSinkEos", v8::String::kInternalizedString ),
                           Integer::New( isolate, Eos ),
                           static_cast<v8::PropertyAttribute>( ReadOnly | DontDelete ) );

    instanceTemplate->Set( String::NewFromUtf8( isolate, "GST_STATE_VOID_PENDING", v8::String::kInternalizedString ),
                           Integer::New( isolate, GST_STATE_VOID_PENDING ),
                           static_cast<v8::PropertyAttribute>( ReadOnly | DontDelete ) );
    instanceTemplate->Set( String::NewFromUtf8( isolate, "GST_STATE_NULL", v8::String::kInternalizedString ),
                           Integer::New( isolate, GST_STATE_NULL ),
                           static_cast<v8::PropertyAttribute>( ReadOnly | DontDelete ) );
    instanceTemplate->Set( String::NewFromUtf8( isolate, "GST_STATE_READY", v8::String::kInternalizedString ),
                           Integer::New( isolate, GST_STATE_READY ),
                           static_cast<v8::PropertyAttribute>( ReadOnly | DontDelete ) );
    instanceTemplate->Set( String::NewFromUtf8( isolate, "GST_STATE_PAUSED", v8::String::kInternalizedString ),
                           Integer::New( isolate, GST_STATE_PAUSED ),
                           static_cast<v8::PropertyAttribute>( ReadOnly | DontDelete ) );
    instanceTemplate->Set( String::NewFromUtf8( isolate, "GST_STATE_PLAYING", v8::String::kInternalizedString ),
                           Integer::New( isolate, GST_STATE_PLAYING ),
                           static_cast<v8::PropertyAttribute>( ReadOnly | DontDelete ) );

    SET_METHOD( instanceTemplate, "parseLaunch", &JsPlayer::parseLaunch );
    SET_METHOD( instanceTemplate, "addAppSinkCallback", &JsPlayer::addAppSinkCallback );
    SET_METHOD( instanceTemplate, "setState", &JsPlayer::setState );

    Local<Function> constructor = constructorTemplate->GetFunction();
    _jsConstructor.Reset( isolate, constructor );

    exports->Set( String::NewFromUtf8( isolate, "createPlayer", v8::String::kInternalizedString ), constructor );
    exports->Set( String::NewFromUtf8( isolate, "Player", v8::String::kInternalizedString ), constructor );
}

void JsPlayer::jsCreate( const v8::FunctionCallbackInfo<v8::Value>& args )
{
    using namespace v8;

    Isolate* isolate = Isolate::GetCurrent();
    HandleScope scope( isolate );

    Local<Object> thisObject = args.Holder();
    if( args.IsConstructCall() ) {
        JsPlayer* jsPlayer = new JsPlayer( thisObject );
        args.GetReturnValue().Set( jsPlayer->handle() );
    } else {
        Local<Value> argv[] = { args[0] };
        Local<Function> constructor =
            Local<Function>::New( isolate, _jsConstructor );
        args.GetReturnValue().Set( constructor->NewInstance( sizeof( argv ) / sizeof( argv[0] ), argv ) );
    }
}

void JsPlayer::closeAll()
{
    for( JsPlayer* p : _instances ) {
        p->close();
    }

    gst_deinit();
}

JsPlayer::JsPlayer( v8::Local<v8::Object>& thisObject ) :
    _pipeline( nullptr ), _firstSample( true )
{
    Wrap( thisObject );

    _instances.insert( this );

    uv_loop_t* loop = uv_default_loop();

    uv_async_init( loop, &_async,
        [] ( uv_async_t* handle ) {
            if( handle->data )
                reinterpret_cast<JsPlayer*>( handle->data )->handleAsync();
        }
    );
    _async.data = this;

}

JsPlayer::~JsPlayer()
{
    close();

    _instances.erase( this );
}

void JsPlayer::close()
{
    _async.data = nullptr;
    uv_close( reinterpret_cast<uv_handle_t*>( &_async ), 0 );
}

void JsPlayer::handleAsync()
{
    while( !_asyncData.empty() ) {
        std::deque<std::unique_ptr<AsyncData> > tmpData;
        _asyncDataGuard.lock();
        _asyncData.swap( tmpData );
        _asyncDataGuard.unlock();

        for( const auto& i: tmpData ) {
            i->process( this );
        }
    }
}

GstFlowReturn JsPlayer::onNewPrerollProxy( GstAppSink *appSink, gpointer userData )
{
    JsPlayer* player = static_cast<JsPlayer*>( userData );

    player->_asyncDataGuard.lock();
    player->_asyncData.emplace_back( new AppSinkEventData( appSink, NewPreroll ) );
    player->_asyncDataGuard.unlock();
    uv_async_send( &player->_async );

    return GST_FLOW_OK;
}

GstFlowReturn JsPlayer::onNewSampleProxy( GstAppSink *appSink, gpointer userData )
{
    JsPlayer* player = static_cast<JsPlayer*>( userData );

    player->_appSinks[appSink].waitingSample.clear();
    player->_asyncDataGuard.lock();
    player->_asyncData.emplace_back( new AppSinkEventData( appSink, NewSample ) );
    player->_asyncDataGuard.unlock();
    uv_async_send( &player->_async );

    return GST_FLOW_OK;
}

void JsPlayer::onEosProxy( GstAppSink* appSink, gpointer userData )
{
    JsPlayer* player = static_cast<JsPlayer*>( userData );

    player->_asyncDataGuard.lock();
    player->_asyncData.emplace_back( new AppSinkEventData( appSink, Eos ) );
    player->_asyncDataGuard.unlock();
    uv_async_send( &player->_async );
}

void JsPlayer::callCallback( GstAppSink* appSink, JsPlayer::AppSinkEvent event,
                             std::initializer_list<v8::Local<v8::Value> > list )
{
    auto it = _appSinks.find( appSink );
    if( _appSinks.end() == it )
        return;

    if( it->second.callback.IsEmpty() )
        return;

    using namespace v8;

    Isolate* isolate = Isolate::GetCurrent();
    HandleScope scope( isolate );

    Local<Function> callbackFunc =
        Local<Function>::New( isolate, _appSinks[appSink].callback );

    std::vector<v8::Local<v8::Value> > argList;

    argList.push_back( Integer::New( isolate, event ) );
    argList.insert( argList.end(), list );
    callbackFunc->Call( handle(), static_cast<int>( argList.size() ), argList.data() );
}

void JsPlayer::onSetup( GstAppSink* appSink, const GstVideoInfo& videoInfo )
{
    if( !appSink )
        return;

    using namespace v8;

    Isolate* isolate = Isolate::GetCurrent();
    HandleScope scope( isolate );

    _firstSample = false;

    callCallback( appSink, Setup,
                  { String::NewFromUtf8( isolate, videoInfo.finfo->name, v8::String::kNormalString ),
                    Integer::New( isolate, videoInfo.width ),
                    Integer::New( isolate, videoInfo.height ),
                    Integer::New( isolate, videoInfo.finfo->format ) } );
}

void JsPlayer::onNewPreroll( GstAppSink* appSink )
{
    GstSample* sample = gst_app_sink_pull_preroll( appSink );

    onSample( appSink, sample, true );

    gst_sample_unref( sample );
}

void JsPlayer::onNewSample( GstAppSink* appSink )
{
    if( _appSinks[appSink].waitingSample.test_and_set() )
        return;

    GstSample* sample = gst_app_sink_pull_sample( appSink );

    _appSinks[appSink].waitingSample.test_and_set();

    onSample( appSink, sample, false );

    gst_sample_unref( sample );
}

void JsPlayer::onSample( GstAppSink* appSink, GstSample* sample, bool preroll )
{
    if( !sample )
        return;

    GstVideoInfo videoInfo;

    GstCaps* caps = gst_sample_get_caps( sample );
    if( !caps || !gst_video_info_from_caps( &videoInfo, caps ) )
        return;

    if( _firstSample )
        onSetup( appSink, videoInfo );

    GstBuffer* buffer = gst_sample_get_buffer( sample );

    if( !buffer )
        return;

    GstMapInfo mapInfo;
    if( gst_buffer_map( buffer, &mapInfo, GST_MAP_READ ) ) {
        using namespace v8;

        Isolate* isolate = Isolate::GetCurrent();
        HandleScope scope( isolate );

        v8::MaybeLocal<v8::Object> maybeFrame =
            node::Buffer::New( isolate, reinterpret_cast<char*>( mapInfo.data ), mapInfo.size,
                               [] ( char* data, void* hint ) {}, nullptr );

        Local<v8::Object> frame;
        if( maybeFrame.ToLocal( &frame ) ) {
            frame->ForceSet( String::NewFromUtf8( isolate, "pixelFormatName", v8::String::kInternalizedString ),
                             String::NewFromUtf8( isolate, videoInfo.finfo->name, v8::String::kNormalString ),
                             static_cast<v8::PropertyAttribute>( ReadOnly | DontDelete ) );
            frame->ForceSet( String::NewFromUtf8( isolate, "pixelFormat", v8::String::kInternalizedString ),
                             Integer::New( isolate, videoInfo.finfo->format ),
                             static_cast<v8::PropertyAttribute>( ReadOnly | DontDelete ) );

            frame->ForceSet( String::NewFromUtf8( isolate, "width", v8::String::kInternalizedString ),
                             Integer::New( isolate, videoInfo.width ),
                             static_cast<v8::PropertyAttribute>( ReadOnly | DontDelete ) );
            frame->ForceSet( String::NewFromUtf8( isolate, "height", v8::String::kInternalizedString ),
                             Integer::New( isolate, videoInfo.height ),
                             static_cast<v8::PropertyAttribute>( ReadOnly | DontDelete ) );

            Local<Array> planes = Array::New( isolate, videoInfo.finfo->n_planes );
            for( guint p = 0; p < videoInfo.finfo->n_planes; ++p ) {
                planes->Set( p, Integer::New( isolate, videoInfo.offset[p] ) );
            }

            frame->ForceSet( String::NewFromUtf8( isolate, "planes", v8::String::kInternalizedString ),
                             planes,
                             static_cast<v8::PropertyAttribute>( ReadOnly | DontDelete ) );

            callCallback( appSink, ( preroll ? NewPreroll : NewSample ), { frame } );
        }

        gst_buffer_unmap( buffer, &mapInfo );
    }
}

void JsPlayer::onEos( GstAppSink* appSink )
{
    callCallback( appSink, Eos );
}

bool JsPlayer::parseLaunch( const std::string& pipelineDescription )
{
    if( _pipeline ) {
        _appSinks.clear();
        gst_object_unref( _pipeline );
        _pipeline = nullptr;
        _firstSample = true;
    }

    GError* error = nullptr;
    _pipeline = gst_parse_launch( pipelineDescription.c_str(), &error );

    return ( nullptr != _pipeline );
}

bool JsPlayer::addAppSinkCallback( const std::string& appSinkName, v8::Local<v8::Value> value )
{
    if( !_pipeline || appSinkName.empty() )
        return false;

    GstElement* sink = gst_bin_get_by_name( GST_BIN( _pipeline ), appSinkName.c_str() );
    if( !sink )
        return false;

    GstAppSink* appSink = GST_APP_SINK_CAST( sink );
    if( !appSink )
        return appSink;

    using namespace v8;

    Local<Function> callbackFunc = Local<Function>::Cast( value );
    if( callbackFunc.IsEmpty() )
        return false;

    auto it = _appSinks.find( appSink );
    if( _appSinks.end() == it ) {
        gst_app_sink_set_drop( appSink, true );
        gst_app_sink_set_max_buffers( appSink, 1 );
        GstAppSinkCallbacks callbacks = { onEosProxy, onNewPrerollProxy, onNewSampleProxy };
        gst_app_sink_set_callbacks( appSink, &callbacks, this, nullptr );
        it = _appSinks.emplace( appSink, AppSinkData() ).first;
    }

    AppSinkData& sinkData = it->second;
    sinkData.callback.Reset( Isolate::GetCurrent(), callbackFunc );
    sinkData.waitingSample.test_and_set();
}

void JsPlayer::setState( unsigned state )
{
    if( _pipeline )
        gst_element_set_state( _pipeline, static_cast<GstState>( state ) );
}
<|endoftext|>


<commit_before>// Scintilla source code edit control
/** @file KeyWords.cxx
 ** Colourise for particular languages.
 **/
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

const LexerModule *LexerModule::base = 0;
int LexerModule::nextLanguage = SCLEX_AUTOMATIC+1;

LexerModule::LexerModule(int language_,
	LexerFunction fnLexer_,
	const char *languageName_,
	LexerFunction fnFolder_,
	const char * const wordListDescriptions_[],
	int styleBits_) :
	language(language_),
	fnLexer(fnLexer_),
	fnFolder(fnFolder_),
	wordListDescriptions(wordListDescriptions_),
	styleBits(styleBits_),
	languageName(languageName_) {
	next = base;
	base = this;
	if (language == SCLEX_AUTOMATIC) {
		language = nextLanguage;
		nextLanguage++;
	}
}

int LexerModule::GetNumWordLists() const {
	if (wordListDescriptions == NULL) {
		return -1;
	} else {
		int numWordLists = 0;

		while (wordListDescriptions[numWordLists]) {
			++numWordLists;
		}

		return numWordLists;
	}
}

const char *LexerModule::GetWordListDescription(int index) const {
	static const char *emptyStr = "";

	PLATFORM_ASSERT(index < GetNumWordLists());
	if (index >= GetNumWordLists()) {
		return emptyStr;
	} else {
		return wordListDescriptions[index];
 	}
}

int LexerModule::GetStyleBitsNeeded() const {
	return styleBits;
}

const LexerModule *LexerModule::Find(int language) {
	const LexerModule *lm = base;
	while (lm) {
		if (lm->language == language) {
			return lm;
		}
		lm = lm->next;
	}
	return 0;
}

const LexerModule *LexerModule::Find(const char *languageName) {
	if (languageName) {
		const LexerModule *lm = base;
		while (lm) {
			if (lm->languageName && 0 == strcmp(lm->languageName, languageName)) {
				return lm;
			}
			lm = lm->next;
		}
	}
	return 0;
}

void LexerModule::Lex(unsigned int startPos, int lengthDoc, int initStyle,
	  WordList *keywordlists[], Accessor &styler) const {
	if (fnLexer)
		fnLexer(startPos, lengthDoc, initStyle, keywordlists, styler);
}

void LexerModule::Fold(unsigned int startPos, int lengthDoc, int initStyle,
	  WordList *keywordlists[], Accessor &styler) const {
	if (fnFolder) {
		int lineCurrent = styler.GetLine(startPos);
		// Move back one line in case deletion wrecked current line fold state
		if (lineCurrent > 0) {
			lineCurrent--;
			int newStartPos = styler.LineStart(lineCurrent);
			lengthDoc += startPos - newStartPos;
			startPos = newStartPos;
			initStyle = 0;
			if (startPos > 0) {
				initStyle = styler.StyleAt(startPos - 1);
			}
		}
		fnFolder(startPos, lengthDoc, initStyle, keywordlists, styler);
	}
}

// Alternative historical name for Scintilla_LinkLexers
int wxForceScintillaLexers(void) {
	return Scintilla_LinkLexers();
}

// To add or remove a lexer, add or remove its file and run LexGen.py.

// Force a reference to all of the Scintilla lexers so that the linker will
// not remove the code of the lexers.
int Scintilla_LinkLexers() {
	static int forcer = 0;

// Shorten the code that declares a lexer and ensures it is linked in by calling a method.
#define LINK_LEXER(lexer) extern LexerModule lexer; forcer += lexer.GetLanguage();

//++Autogenerated -- run src/LexGen.py to regenerate
//**\(\tLINK_LEXER(\*);\n\)
	LINK_LEXER(lmAbaqus);
	LINK_LEXER(lmAda);
	LINK_LEXER(lmAns1);
	LINK_LEXER(lmAPDL);
	LINK_LEXER(lmAsm);
	LINK_LEXER(lmASP);
	LINK_LEXER(lmASY);
	LINK_LEXER(lmAU3);
	LINK_LEXER(lmAVE);
	LINK_LEXER(lmBaan);
	LINK_LEXER(lmBash);
	LINK_LEXER(lmBatch);
	LINK_LEXER(lmBlitzBasic);
	LINK_LEXER(lmBullant);
	LINK_LEXER(lmCaml);
	LINK_LEXER(lmClw);
	LINK_LEXER(lmClwNoCase);
	LINK_LEXER(lmCmake);
	LINK_LEXER(lmCOBOL);
	LINK_LEXER(lmConf);
	LINK_LEXER(lmCPP);
	LINK_LEXER(lmCPPNoCase);
	LINK_LEXER(lmCsound);
	LINK_LEXER(lmCss);
	LINK_LEXER(lmD);
	LINK_LEXER(lmDiff);
	LINK_LEXER(lmEiffel);
	LINK_LEXER(lmEiffelkw);
	LINK_LEXER(lmErlang);
	LINK_LEXER(lmErrorList);
	LINK_LEXER(lmESCRIPT);
	LINK_LEXER(lmF77);
	LINK_LEXER(lmFlagShip);
	LINK_LEXER(lmForth);
	LINK_LEXER(lmFortran);
	LINK_LEXER(lmFreeBasic);
	LINK_LEXER(lmGAP);
	LINK_LEXER(lmGui4Cli);
	LINK_LEXER(lmHaskell);
	LINK_LEXER(lmHTML);
	LINK_LEXER(lmInno);
	LINK_LEXER(lmKix);
	LINK_LEXER(lmLatex);
	LINK_LEXER(lmLISP);
	LINK_LEXER(lmLot);
	LINK_LEXER(lmLout);
	LINK_LEXER(lmLua);
	LINK_LEXER(lmMagikSF);
	LINK_LEXER(lmMake);
	LINK_LEXER(lmMatlab);
	LINK_LEXER(lmMETAPOST);
	LINK_LEXER(lmMMIXAL);
	LINK_LEXER(lmMSSQL);
	LINK_LEXER(lmMySQL);
	LINK_LEXER(lmNimrod);
	LINK_LEXER(lmNncrontab);
	LINK_LEXER(lmNsis);
	LINK_LEXER(lmNull);
	LINK_LEXER(lmOctave);
	LINK_LEXER(lmOpal);
	LINK_LEXER(lmPascal);
	LINK_LEXER(lmPB);
	LINK_LEXER(lmPerl);
	LINK_LEXER(lmPHP);
	LINK_LEXER(lmPHPSCRIPT);
	LINK_LEXER(lmPLM);
	LINK_LEXER(lmPo);
	LINK_LEXER(lmPOV);
	LINK_LEXER(lmPowerPro);
	LINK_LEXER(lmPowerShell);
	LINK_LEXER(lmProgress);
	LINK_LEXER(lmProps);
	LINK_LEXER(lmPS);
	LINK_LEXER(lmPureBasic);
	LINK_LEXER(lmPython);
	LINK_LEXER(lmR);
	LINK_LEXER(lmREBOL);
	LINK_LEXER(lmRuby);
	LINK_LEXER(lmScriptol);
	LINK_LEXER(lmSmalltalk);
	LINK_LEXER(lmSML);
	LINK_LEXER(lmSorc);
	LINK_LEXER(lmSpecman);
	LINK_LEXER(lmSpice);
	LINK_LEXER(lmSQL);
	LINK_LEXER(lmTACL);
	LINK_LEXER(lmTADS3);
	LINK_LEXER(lmTAL);
	LINK_LEXER(lmTCL);
	LINK_LEXER(lmTeX);
	LINK_LEXER(lmVB);
	LINK_LEXER(lmVBScript);
	LINK_LEXER(lmVerilog);
	LINK_LEXER(lmVHDL);
	LINK_LEXER(lmXML);
	LINK_LEXER(lmYAML);

//--Autogenerated -- end of automatically generated section

	return 1;
}
<commit_msg>Removal of deprecated symbols.<commit_after>// Scintilla source code edit control
/** @file KeyWords.cxx
 ** Colourise for particular languages.
 **/
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

const LexerModule *LexerModule::base = 0;
int LexerModule::nextLanguage = SCLEX_AUTOMATIC+1;

LexerModule::LexerModule(int language_,
	LexerFunction fnLexer_,
	const char *languageName_,
	LexerFunction fnFolder_,
	const char * const wordListDescriptions_[],
	int styleBits_) :
	language(language_),
	fnLexer(fnLexer_),
	fnFolder(fnFolder_),
	wordListDescriptions(wordListDescriptions_),
	styleBits(styleBits_),
	languageName(languageName_) {
	next = base;
	base = this;
	if (language == SCLEX_AUTOMATIC) {
		language = nextLanguage;
		nextLanguage++;
	}
}

int LexerModule::GetNumWordLists() const {
	if (wordListDescriptions == NULL) {
		return -1;
	} else {
		int numWordLists = 0;

		while (wordListDescriptions[numWordLists]) {
			++numWordLists;
		}

		return numWordLists;
	}
}

const char *LexerModule::GetWordListDescription(int index) const {
	static const char *emptyStr = "";

	PLATFORM_ASSERT(index < GetNumWordLists());
	if (index >= GetNumWordLists()) {
		return emptyStr;
	} else {
		return wordListDescriptions[index];
 	}
}

int LexerModule::GetStyleBitsNeeded() const {
	return styleBits;
}

const LexerModule *LexerModule::Find(int language) {
	const LexerModule *lm = base;
	while (lm) {
		if (lm->language == language) {
			return lm;
		}
		lm = lm->next;
	}
	return 0;
}

const LexerModule *LexerModule::Find(const char *languageName) {
	if (languageName) {
		const LexerModule *lm = base;
		while (lm) {
			if (lm->languageName && 0 == strcmp(lm->languageName, languageName)) {
				return lm;
			}
			lm = lm->next;
		}
	}
	return 0;
}

void LexerModule::Lex(unsigned int startPos, int lengthDoc, int initStyle,
	  WordList *keywordlists[], Accessor &styler) const {
	if (fnLexer)
		fnLexer(startPos, lengthDoc, initStyle, keywordlists, styler);
}

void LexerModule::Fold(unsigned int startPos, int lengthDoc, int initStyle,
	  WordList *keywordlists[], Accessor &styler) const {
	if (fnFolder) {
		int lineCurrent = styler.GetLine(startPos);
		// Move back one line in case deletion wrecked current line fold state
		if (lineCurrent > 0) {
			lineCurrent--;
			int newStartPos = styler.LineStart(lineCurrent);
			lengthDoc += startPos - newStartPos;
			startPos = newStartPos;
			initStyle = 0;
			if (startPos > 0) {
				initStyle = styler.StyleAt(startPos - 1);
			}
		}
		fnFolder(startPos, lengthDoc, initStyle, keywordlists, styler);
	}
}

// Alternative historical name for Scintilla_LinkLexers
int wxForceScintillaLexers(void) {
	return Scintilla_LinkLexers();
}

// To add or remove a lexer, add or remove its file and run LexGen.py.

// Force a reference to all of the Scintilla lexers so that the linker will
// not remove the code of the lexers.
int Scintilla_LinkLexers() {
	static int forcer = 0;

// Shorten the code that declares a lexer and ensures it is linked in by calling a method.
#define LINK_LEXER(lexer) extern LexerModule lexer; forcer += lexer.GetLanguage();

//++Autogenerated -- run src/LexGen.py to regenerate
//**\(\tLINK_LEXER(\*);\n\)
	LINK_LEXER(lmAbaqus);
	LINK_LEXER(lmAda);
	LINK_LEXER(lmAns1);
	LINK_LEXER(lmAPDL);
	LINK_LEXER(lmAsm);
	LINK_LEXER(lmASY);
	LINK_LEXER(lmAU3);
	LINK_LEXER(lmAVE);
	LINK_LEXER(lmBaan);
	LINK_LEXER(lmBash);
	LINK_LEXER(lmBatch);
	LINK_LEXER(lmBlitzBasic);
	LINK_LEXER(lmBullant);
	LINK_LEXER(lmCaml);
	LINK_LEXER(lmClw);
	LINK_LEXER(lmClwNoCase);
	LINK_LEXER(lmCmake);
	LINK_LEXER(lmCOBOL);
	LINK_LEXER(lmConf);
	LINK_LEXER(lmCPP);
	LINK_LEXER(lmCPPNoCase);
	LINK_LEXER(lmCsound);
	LINK_LEXER(lmCss);
	LINK_LEXER(lmD);
	LINK_LEXER(lmDiff);
	LINK_LEXER(lmEiffel);
	LINK_LEXER(lmEiffelkw);
	LINK_LEXER(lmErlang);
	LINK_LEXER(lmErrorList);
	LINK_LEXER(lmESCRIPT);
	LINK_LEXER(lmF77);
	LINK_LEXER(lmFlagShip);
	LINK_LEXER(lmForth);
	LINK_LEXER(lmFortran);
	LINK_LEXER(lmFreeBasic);
	LINK_LEXER(lmGAP);
	LINK_LEXER(lmGui4Cli);
	LINK_LEXER(lmHaskell);
	LINK_LEXER(lmHTML);
	LINK_LEXER(lmInno);
	LINK_LEXER(lmKix);
	LINK_LEXER(lmLatex);
	LINK_LEXER(lmLISP);
	LINK_LEXER(lmLot);
	LINK_LEXER(lmLout);
	LINK_LEXER(lmLua);
	LINK_LEXER(lmMagikSF);
	LINK_LEXER(lmMake);
	LINK_LEXER(lmMatlab);
	LINK_LEXER(lmMETAPOST);
	LINK_LEXER(lmMMIXAL);
	LINK_LEXER(lmMSSQL);
	LINK_LEXER(lmMySQL);
	LINK_LEXER(lmNimrod);
	LINK_LEXER(lmNncrontab);
	LINK_LEXER(lmNsis);
	LINK_LEXER(lmNull);
	LINK_LEXER(lmOctave);
	LINK_LEXER(lmOpal);
	LINK_LEXER(lmPascal);
	LINK_LEXER(lmPB);
	LINK_LEXER(lmPerl);
	LINK_LEXER(lmPHPSCRIPT);
	LINK_LEXER(lmPLM);
	LINK_LEXER(lmPo);
	LINK_LEXER(lmPOV);
	LINK_LEXER(lmPowerPro);
	LINK_LEXER(lmPowerShell);
	LINK_LEXER(lmProgress);
	LINK_LEXER(lmProps);
	LINK_LEXER(lmPS);
	LINK_LEXER(lmPureBasic);
	LINK_LEXER(lmPython);
	LINK_LEXER(lmR);
	LINK_LEXER(lmREBOL);
	LINK_LEXER(lmRuby);
	LINK_LEXER(lmScriptol);
	LINK_LEXER(lmSmalltalk);
	LINK_LEXER(lmSML);
	LINK_LEXER(lmSorc);
	LINK_LEXER(lmSpecman);
	LINK_LEXER(lmSpice);
	LINK_LEXER(lmSQL);
	LINK_LEXER(lmTACL);
	LINK_LEXER(lmTADS3);
	LINK_LEXER(lmTAL);
	LINK_LEXER(lmTCL);
	LINK_LEXER(lmTeX);
	LINK_LEXER(lmVB);
	LINK_LEXER(lmVBScript);
	LINK_LEXER(lmVerilog);
	LINK_LEXER(lmVHDL);
	LINK_LEXER(lmXML);
	LINK_LEXER(lmYAML);

//--Autogenerated -- end of automatically generated section

	return 1;
}
<|endoftext|>


<commit_before>//-----------------------------------------------------------------------------
// Title:      tb_ahb_mem.cpp
//
// ScssId:
//
// Origin:     HW-SW SystemC Co-Simulation SoC Validation Platform
//
// Purpose:    Provide a test bench memory class with AHB slave interface.
//
// Method:     Memory is modeled with a map.
//             Considered field of the tlm_generic_payload are:
//                - command
//                - address
//                - data_ptr
//                - data_length
//                - response
//             All other fields are ignored.
//             Delays are not modeled.
//
// Modified on $Date$
//          at $Revision$
//          by $Author$
//
// Principal:  European Space Agency
// Author:     VLSI working group @ IDA @ TUBS
// Maintainer: Soeren Brinkmann
// Reviewed:
//-----------------------------------------------------------------------------

#include "tb_ahb_mem.h"
#include <fstream>
#include <iostream>
#include <iomanip>
#include "verbose.h"

/// Constructor
Ctb_ahb_mem::Ctb_ahb_mem(sc_core::sc_module_name nm,   // Module name
                           uint16_t haddr,   // AMBA AHB address (12 bit)
                           uint16_t hmask,   // AMBA AHB address mask (12 bit)
                           char infile[],    // Memory initialization file
                           uint32_t addr) :  // Address for memory initalization
   sc_module(nm),
   pnpahb(
      0x04, // vendor_id: ESA
      0,    // device: TODO: get real device ID
      0,    //
      0,    // IRQ
      GrlibBAR(CGrlibDevice::AHBMEM, hmask, 0, 0, haddr),    // GrlibBAR 0
      0,    // GrlibBAR 1
      0,    // GrlibBAR 2
      0     // GrlibBAR 3
   ),
   ahb(
      "ahb",            // sc_module_name
      amba::amba_AHB,   // bus type
      amba::amba_LT,    // abstraction level
      false             // is arbiter
   ), name(nm) {

      ahb.register_b_transport(this, &Ctb_ahb_mem::b_transport);
      if(infile!=NULL) {
         readmem(infile, addr);
      }
}  // End constructor

/// Destructor
Ctb_ahb_mem::~Ctb_ahb_mem() {

//    cout << name << " Memory content: \n" << endl;
//    for(std::map<unsigned int, unsigned char>::iterator it=mem.begin();
//        it!=mem.end(); it++) {
//       printf("@%#8.8x: %#2.2x\n", it->first, it->second);
//    }
   mem.clear();
}  // End destructor

/// TLM blocking transport function
void Ctb_ahb_mem::b_transport(tlm::tlm_generic_payload &gp,
                               sc_core::sc_time &delay) {

   switch(gp.get_command()) {
      // Read command
      case tlm::TLM_READ_COMMAND:
         for(uint32_t i=0; i<gp.get_data_length(); i++) {

            *(gp.get_data_ptr() + i) = mem[i];

         }
         gp.set_response_status(tlm::TLM_OK_RESPONSE);
         break;

      // Write command
      case tlm::TLM_WRITE_COMMAND:
         for(uint32_t i=0; i<gp.get_data_length(); i++) {

            mem[i] = *(gp.get_data_ptr() + i);

         }
         gp.set_response_status(tlm::TLM_OK_RESPONSE);
         break;

      // Neither read or write command
      default:
         VWARN << name << ": Received unknown command.\n";
         gp.set_response_status(tlm::TLM_COMMAND_ERROR_RESPONSE);
         break;
   }
}  // void Ctb_ahb_mem::b_transport()

/// Method to initialize memory contents from a text file
int Ctb_ahb_mem::readmem(char infile_[], uint32_t addr) {

   std::ifstream infile(infile_, ios::in);
   char buffer = 0;
   uint8_t nibble_buffer = 0;
   unsigned char data = 0;
   unsigned int nibble = 0;
   bool process_char = 0;

   // Parse input file
   if(infile.good()) {
      while(!infile.eof()) {
         // Read one byte from file
         infile.read(&buffer, 1);
         // Convert char into binary
         nibble_buffer = char2nibble(&buffer);

         // combine two ascii chars into one byte and write into memory
         if(!(nibble_buffer & 0xf0)) {
            if(nibble) {
               data |= nibble_buffer;
               mem[addr++] = data;
               data = 0x0;
               nibble = 0;
            } else {
               data |= (nibble_buffer << 4);
               nibble++;
            }
            process_char = 0;
         }
      }  // while(!infile.eof())

      // Warn if data stream ended unexpected
      if(nibble) {
         VWARN << name << ": Incomplete byte detected in memory file\n";
      }

      // close file
      infile.close();
      return 0;
   } else {
      VERROR << name << ": File \"" << infile_ << "\" not found or readable\n";
      return infile.good();
   }
}  // int Ctb_ahb_mem::readmem(char infile_[], unsigned int addr)

/// Method to convert ascii characters into their binary representation
uint8_t Ctb_ahb_mem::char2nibble(const char *ch) const {
   switch(*ch) {
      case '\n':
         return 0x10;
         break;
      case ' ':
         return 0x20;
         break;
      case '\t':
         return 0x20;
         break;
      case '0':
         return 0x00;
         break;
      case '1':
         return 0x01;
         break;
      case '2':
         return 0x02;
         break;
      case '3':
         return 0x03;
         break;
      case '4':
         return 0x04;
         break;
      case '5':
         return 0x05;
         break;
      case '6':
         return 0x06;
         break;
      case '7':
         return 0x07;
         break;
      case '8':
         return 0x08;
         break;
      case '9':
         return 0x09;
         break;
      case 'a':
         return 0x0a;
         break;
      case 'b':
         return 0x0b;
         break;
      case 'c':
         return 0x0c;
         break;
      case 'd':
         return 0x0d;
         break;
      case 'e':
         return 0x0e;
         break;
      case 'f':
         return 0x0f;
         break;
      case 'A':
         return 0x0a;
         break;
      case 'B':
         return 0x0b;
         break;
      case 'C':
         return 0x0c;
         break;
      case 'D':
         return 0x0d;
         break;
      case 'E':
         return 0x0e;
         break;
      case 'F':
         return 0x0f;
         break;
      default:
         VWARN << name << ": Illegal character in memory file: \'"
            << *ch << "\'\n";
         return 0x80;
         break;
   }
}  // uint8_t Ctb_ahb_mem::char2nibble(char *ch) const

/// Method to dump the memory content into an text file
int Ctb_ahb_mem::dumpmem(char outfile_[]) {

   std::ofstream outfile(outfile_, ios::out);

   if(outfile.good()) {
      for(std::map<unsigned int, unsigned char>::iterator it=mem.begin();
          it!=mem.end(); it++) {
         outfile << "@0x" << std::hex << std::setw(8) << std::setfill('0')
            << it->first << ": 0x" << std::setw(2)
            << static_cast<unsigned int>(it->second) << endl;
      }
      return 0;
   } else {
      VERROR << name << ": Unable to open dump file\n";
      return outfile.good();
   }
}  // int tb_ahb_mem::dumpmem(char outfile_[])
<commit_msg>Revised format of memory dump file.<commit_after>//-----------------------------------------------------------------------------
// Title:      tb_ahb_mem.cpp
//
// ScssId:
//
// Origin:     HW-SW SystemC Co-Simulation SoC Validation Platform
//
// Purpose:    Provide a test bench memory class with AHB slave interface.
//
// Method:     Memory is modeled with a map.
//             Considered field of the tlm_generic_payload are:
//                - command
//                - address
//                - data_ptr
//                - data_length
//                - response
//             All other fields are ignored.
//             Delays are not modeled.
//
// Modified on $Date$
//          at $Revision$
//          by $Author$
//
// Principal:  European Space Agency
// Author:     VLSI working group @ IDA @ TUBS
// Maintainer: Soeren Brinkmann
// Reviewed:
//-----------------------------------------------------------------------------

#include "tb_ahb_mem.h"
#include <fstream>
#include <iostream>
#include <iomanip>
#include "verbose.h"

/// Constructor
Ctb_ahb_mem::Ctb_ahb_mem(sc_core::sc_module_name nm,   // Module name
                           uint16_t haddr,   // AMBA AHB address (12 bit)
                           uint16_t hmask,   // AMBA AHB address mask (12 bit)
                           char infile[],    // Memory initialization file
                           uint32_t addr) :  // Address for memory initalization
   sc_module(nm),
   pnpahb(
      0x04, // vendor_id: ESA
      0,    // device: TODO: get real device ID
      0,    //
      0,    // IRQ
      GrlibBAR(CGrlibDevice::AHBMEM, hmask, 0, 0, haddr),    // GrlibBAR 0
      0,    // GrlibBAR 1
      0,    // GrlibBAR 2
      0     // GrlibBAR 3
   ),
   ahb(
      "ahb",            // sc_module_name
      amba::amba_AHB,   // bus type
      amba::amba_LT,    // abstraction level
      false             // is arbiter
   ), name(nm) {

      ahb.register_b_transport(this, &Ctb_ahb_mem::b_transport);
      if(infile!=NULL) {
         readmem(infile, addr);
      }
}  // End constructor

/// Destructor
Ctb_ahb_mem::~Ctb_ahb_mem() {

//    cout << name << " Memory content: \n" << endl;
//    for(std::map<unsigned int, unsigned char>::iterator it=mem.begin();
//        it!=mem.end(); it++) {
//       printf("@%#8.8x: %#2.2x\n", it->first, it->second);
//    }
   mem.clear();
}  // End destructor

/// TLM blocking transport function
void Ctb_ahb_mem::b_transport(tlm::tlm_generic_payload &gp,
                               sc_core::sc_time &delay) {

   switch(gp.get_command()) {
      // Read command
      case tlm::TLM_READ_COMMAND:
         for(uint32_t i=0; i<gp.get_data_length(); i++) {

            *(gp.get_data_ptr() + i) = mem[i];

         }
         gp.set_response_status(tlm::TLM_OK_RESPONSE);
         break;

      // Write command
      case tlm::TLM_WRITE_COMMAND:
         for(uint32_t i=0; i<gp.get_data_length(); i++) {

            mem[i] = *(gp.get_data_ptr() + i);

         }
         gp.set_response_status(tlm::TLM_OK_RESPONSE);
         break;

      // Neither read or write command
      default:
         VWARN << name << ": Received unknown command.\n";
         gp.set_response_status(tlm::TLM_COMMAND_ERROR_RESPONSE);
         break;
   }
}  // void Ctb_ahb_mem::b_transport()

/// Method to initialize memory contents from a text file
int Ctb_ahb_mem::readmem(char infile_[], uint32_t addr) {

   std::ifstream infile(infile_, ios::in);
   char buffer = 0;
   uint8_t nibble_buffer = 0;
   unsigned char data = 0;
   unsigned int nibble = 0;
   bool process_char = 0;

   // Parse input file
   if(infile.good()) {
      while(!infile.eof()) {
         // Read one byte from file
         infile.read(&buffer, 1);
         // Convert char into binary
         nibble_buffer = char2nibble(&buffer);

         // combine two ascii chars into one byte and write into memory
         if(!(nibble_buffer & 0xf0)) {
            if(nibble) {
               data |= nibble_buffer;
               mem[addr++] = data;
               data = 0x0;
               nibble = 0;
            } else {
               data |= (nibble_buffer << 4);
               nibble++;
            }
            process_char = 0;
         }
      }  // while(!infile.eof())

      // Warn if data stream ended unexpected
      if(nibble) {
         VWARN << name << ": Incomplete byte detected in memory file.\n";
      }

      // close file
      infile.close();
      return 0;
   } else {
      VERROR << name << ": File \"" << infile_ << "\" not found or readable.\n";
      return infile.good();
   }
}  // int Ctb_ahb_mem::readmem(char infile_[], unsigned int addr)

/// Method to convert ascii characters into their binary representation
uint8_t Ctb_ahb_mem::char2nibble(const char *ch) const {
   switch(*ch) {
      case '\n':
         return 0x10;
         break;
      case ' ':
         return 0x20;
         break;
      case '\t':
         return 0x20;
         break;
      case '0':
         return 0x00;
         break;
      case '1':
         return 0x01;
         break;
      case '2':
         return 0x02;
         break;
      case '3':
         return 0x03;
         break;
      case '4':
         return 0x04;
         break;
      case '5':
         return 0x05;
         break;
      case '6':
         return 0x06;
         break;
      case '7':
         return 0x07;
         break;
      case '8':
         return 0x08;
         break;
      case '9':
         return 0x09;
         break;
      case 'a':
         return 0x0a;
         break;
      case 'b':
         return 0x0b;
         break;
      case 'c':
         return 0x0c;
         break;
      case 'd':
         return 0x0d;
         break;
      case 'e':
         return 0x0e;
         break;
      case 'f':
         return 0x0f;
         break;
      case 'A':
         return 0x0a;
         break;
      case 'B':
         return 0x0b;
         break;
      case 'C':
         return 0x0c;
         break;
      case 'D':
         return 0x0d;
         break;
      case 'E':
         return 0x0e;
         break;
      case 'F':
         return 0x0f;
         break;
      default:
         VWARN << name << ": Illegal character in memory file: \'"
            << *ch << "\'\n";
         return 0x80;
         break;
   }
}  // uint8_t Ctb_ahb_mem::char2nibble(char *ch) const

/// Method to dump the memory content into an text file
int Ctb_ahb_mem::dumpmem(char outfile_[]) {

   std::ofstream outfile(outfile_, ios::out);
   uint32_t word = 0;
   int      position = 0;

   // check if memory is filled
   if(mem.empty()) {
      VINFO << name << ": Memory is empty. Nothing do dump.\n";
      return 1;
   }
   // reate map iterator and initialize to first element
   std::map<uint32_t, uint8_t>::iterator it      = mem.begin();
   std::map<uint32_t, uint8_t>::iterator it_next = mem.begin();
   it_next++;

   if(outfile.good()) {
      // print first address in file
      outfile << "@" << std::hex << std::setw(8) << std::setfill('0')
         << (it->first & 0xfffffffc) << endl;

      for(it=mem.begin(); it!=mem.end(); it++, it_next++) {

         position = it->first % 4;
         word |= (it->second << (8*position));

         // Next byte not within current word
         if( (3 - position - static_cast<int>(it_next->first - it->first)) < 0) {
            // print word
            outfile << std::hex << std::setw(8) << std::setfill('0') << word
               << endl;
            word = 0;

            // print address if necessary
            if( (7 - position - static_cast<int>(it_next->first - it->first)) < 0) {
               outfile << "@" << std::hex << std::setw(8) << std::setfill('0')
                  << (it_next->first & 0xfffffffc) << endl;
            }
         }
      }
      // print last word
      outfile << std::hex << std::setw(8) << std::setfill('0') << word
         << endl;
      return 0;
   } else {
      VERROR << name << ": Unable to open dump file.\n";
      return outfile.good();
   }
}  // int tb_ahb_mem::dumpmem(char outfile_[])
<|endoftext|>


<commit_before>/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                        Intel License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of Intel Corporation may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

#include "precomp.hpp"

#if _MSC_VER >= 1200
#pragma warning( disable: 4711 )
#endif

#if defined _M_X64 && defined _MSC_VER && !defined CV_ICC
#pragma optimize("",off)
#endif

namespace cv
{

template<> void Ptr<CvCapture>::delete_obj()
{ cvReleaseCapture(&obj); }

template<> void Ptr<CvVideoWriter>::delete_obj()
{ cvReleaseVideoWriter(&obj); }

}

/************************* Reading AVIs & Camera data **************************/

CV_IMPL void cvReleaseCapture( CvCapture** pcapture )
{
    if( pcapture && *pcapture )
    {
        delete *pcapture;
        *pcapture = 0;
    }
}

CV_IMPL IplImage* cvQueryFrame( CvCapture* capture )
{
    if(!capture)
        return 0;
    if(!capture->grabFrame())
        return 0;
    return capture->retrieveFrame(0);
}

CV_IMPL int cvGrabFrame( CvCapture* capture )
{
    return capture ? capture->grabFrame() : 0;
}

CV_IMPL IplImage* cvRetrieveFrame( CvCapture* capture, int idx )
{
    return capture ? capture->retrieveFrame(idx) : 0;
}

CV_IMPL double cvGetCaptureProperty( CvCapture* capture, int id )
{
    return capture ? capture->getProperty(id) : 0;
}

CV_IMPL int cvSetCaptureProperty( CvCapture* capture, int id, double value )
{
    return capture ? capture->setProperty(id, value) : 0;
}

CV_IMPL int cvGetCaptureDomain( CvCapture* capture)
{
    return capture ? capture->getCaptureDomain() : 0;
}

/**
 * Camera dispatching method: index is the camera number.
 * If given an index from 0 to 99, it tries to find the first
 * API that can access a given camera index.
 * Add multiples of 100 to select an API.
 */
CV_IMPL CvCapture * cvCreateCameraCapture (int index)
{
    int  domains[] =
    {
#ifdef HAVE_VIDEOINPUT
        CV_CAP_DSHOW,
#endif
        CV_CAP_IEEE1394,   // identical to CV_CAP_DC1394
        CV_CAP_STEREO,
        CV_CAP_PVAPI,
        CV_CAP_VFW,        // identical to CV_CAP_V4L
        CV_CAP_MIL,
        CV_CAP_QT,
        CV_CAP_UNICAP,
#ifdef HAVE_OPENNI
        CV_CAP_OPENNI,
#endif
#ifdef HAVE_ANDROID_NATIVE_CAMERA
        CV_CAP_ANDROID,
#endif
#ifdef HAVE_XIMEA
        CV_CAP_XIAPI,
#endif
        -1
    };

    // interpret preferred interface (0 = autodetect)
    int pref = (index / 100) * 100;
    if (pref)
    {
        domains[0]=pref;
        index %= 100;
        domains[1]=-1;
    }

    // try every possibly installed camera API
    for (int i = 0; domains[i] >= 0; i++)
    {
        #if defined(HAVE_VIDEOINPUT) || defined(HAVE_TYZX) || defined(HAVE_VFW) || \
        defined(HAVE_CAMV4L) || defined (HAVE_CAMV4L2) || defined(HAVE_GSTREAMER) || \
        defined(HAVE_DC1394_2) || defined(HAVE_DC1394) || defined(HAVE_CMU1394) || \
        defined(HAVE_GSTREAMER) || defined(HAVE_MIL) || defined(HAVE_QUICKTIME) || \
        defined(HAVE_UNICAP) || defined(HAVE_PVAPI) || defined(HAVE_OPENNI) || defined(HAVE_ANDROID_NATIVE_CAMERA)
        // local variable to memorize the captured device
        CvCapture *capture;
        #endif

        switch (domains[i])
        {
        #ifdef HAVE_VIDEOINPUT
        case CV_CAP_DSHOW:
            capture = cvCreateCameraCapture_DShow (index);
            if (capture)
                return capture;
            break;
        #endif

        #ifdef HAVE_TYZX
        case CV_CAP_STEREO:
            capture = cvCreateCameraCapture_TYZX (index);
            if (capture)
                return capture;
            break;
        #endif

        case CV_CAP_VFW:
        #ifdef HAVE_VFW
            capture = cvCreateCameraCapture_VFW (index);
            if (capture)
                return capture;
        #endif
        #if defined HAVE_LIBV4L || (defined (HAVE_CAMV4L) && defined (HAVE_CAMV4L2))
            capture = cvCreateCameraCapture_V4L (index);
            if (capture)
                return capture;
        #endif
        #ifdef HAVE_GSTREAMER
            capture = cvCreateCapture_GStreamer(CV_CAP_GSTREAMER_V4L2, 0);
            if (capture)
                return capture;
            capture = cvCreateCapture_GStreamer(CV_CAP_GSTREAMER_V4L, 0);
            if (capture)
                return capture;
        #endif
            break;

        case CV_CAP_FIREWIRE:
        #ifdef HAVE_DC1394_2
            capture = cvCreateCameraCapture_DC1394_2 (index);
            if (capture)
                return capture;
        #endif
        #ifdef HAVE_DC1394
            capture = cvCreateCameraCapture_DC1394 (index);
            if (capture)
                return capture;
        #endif
        #ifdef HAVE_CMU1394
            capture = cvCreateCameraCapture_CMU (index);
            if (capture)
                return capture;
        #endif
    /* Re-enable again when gstreamer 1394 support will land in the backend code
        #ifdef HAVE_GSTREAMER
            capture = cvCreateCapture_GStreamer(CV_CAP_GSTREAMER_1394, 0);
            if (capture)
                return capture;
        #endif
    */
            break;
        #ifdef HAVE_MIL
        case CV_CAP_MIL:
            capture = cvCreateCameraCapture_MIL (index);
            if (capture)
                return capture;
            break;
        #endif

        #ifdef HAVE_QUICKTIME
        case CV_CAP_QT:
            capture = cvCreateCameraCapture_QT (index);
            if (capture)
                return capture;
            break;
        #endif

        #ifdef HAVE_UNICAP
        case CV_CAP_UNICAP:
            capture = cvCreateCameraCapture_Unicap (index);
            if (capture)
                return capture;
        break;
        #endif

        #ifdef HAVE_PVAPI
        case CV_CAP_PVAPI:
            capture = cvCreateCameraCapture_PvAPI (index);
            if (capture)
                return capture;
        break;
        #endif

        #ifdef HAVE_OPENNI
        case CV_CAP_OPENNI:
            capture = cvCreateCameraCapture_OpenNI (index);
            if (capture)
                return capture;
        break;
        #endif

        #ifdef HAVE_ANDROID_NATIVE_CAMERA
        case CV_CAP_ANDROID:
            capture = cvCreateCameraCapture_Android (index);
            if (capture)
                return capture;
        break;
        #endif

        #ifdef HAVE_XIMEA
        case CV_CAP_XIAPI:
            capture = cvCreateCameraCapture_Ximea (index);
            if (capture)
                return capture;
        break;
        #endif
        }
    }

    // failed open a camera
    return 0;
}

/**
 * Videoreader dispatching method: it tries to find the first
 * API that can access a given filename.
 */
CV_IMPL CvCapture * cvCreateFileCapture (const char * filename)
{
    CvCapture * result = 0;

    if (! result)
        result = cvCreateFileCapture_FFMPEG_proxy (filename);

    #ifdef HAVE_XINE
    if (! result)
        result = cvCreateFileCapture_XINE (filename);
    #endif

    #ifdef HAVE_GSTREAMER
    if (! result)
        result = cvCreateCapture_GStreamer (CV_CAP_GSTREAMER_FILE, filename);
    #endif

    #ifdef HAVE_QUICKTIME
    if (! result)
        result = cvCreateFileCapture_QT (filename);
    #endif

    if (! result)
        result = cvCreateFileCapture_Images (filename);

    return result;
}

/**
 * Videowriter dispatching method: it tries to find the first
 * API that can write a given stream.
 */
CV_IMPL CvVideoWriter* cvCreateVideoWriter( const char* filename, int fourcc,
                                            double fps, CvSize frameSize, int is_color )
{
	//CV_FUNCNAME( "cvCreateVideoWriter" );

	CvVideoWriter *result = 0;

	if(!fourcc || !fps)
		result = cvCreateVideoWriter_Images(filename);

	if(!result)
		result = cvCreateVideoWriter_FFMPEG_proxy (filename, fourcc, fps, frameSize, is_color);

/*	#ifdef HAVE_XINE
	if(!result)
		result = cvCreateVideoWriter_XINE(filename, fourcc, fps, frameSize, is_color);
	#endif
*/

	#ifdef HAVE_QUICKTIME
	if(!result)
		result = cvCreateVideoWriter_QT(filename, fourcc, fps, frameSize, is_color);
	#endif
    #ifdef HAVE_GSTREAMER
    if (! result)
        result = cvCreateVideoWriter_GStreamer(filename, fourcc, fps, frameSize, is_color);
    #endif
	if(!result)
		result = cvCreateVideoWriter_Images(filename);

	return result;
}

CV_IMPL int cvWriteFrame( CvVideoWriter* writer, const IplImage* image )
{

    return writer ? writer->writeFrame(image) : 0;
}

CV_IMPL void cvReleaseVideoWriter( CvVideoWriter** pwriter )
{
    if( pwriter && *pwriter )
    {
        delete *pwriter;
        *pwriter = 0;
    }
}

namespace cv
{

VideoCapture::VideoCapture()
{}

VideoCapture::VideoCapture(const string& filename)
{
    open(filename);
}

VideoCapture::VideoCapture(int device)
{
    open(device);
}

VideoCapture::~VideoCapture()
{
    cap.release();
}

bool VideoCapture::open(const string& filename)
{
    cap = cvCreateFileCapture(filename.c_str());
    return isOpened();
}

bool VideoCapture::open(int device)
{
    cap = cvCreateCameraCapture(device);
    return isOpened();
}

bool VideoCapture::isOpened() const { return !cap.empty(); }

void VideoCapture::release()
{
    cap.release();
}

bool VideoCapture::grab()
{
    return cvGrabFrame(cap) != 0;
}

bool VideoCapture::retrieve(Mat& image, int channel)
{
    IplImage* _img = cvRetrieveFrame(cap, channel);
    if( !_img )
    {
        image.release();
        return false;
    }
    if(_img->origin == IPL_ORIGIN_TL)
        image = Mat(_img);
    else
    {
        Mat temp(_img);
        flip(temp, image, 0);
    }
    return true;
}

bool VideoCapture::read(Mat& image)
{
    if(!grab())
        image.release();
    else
        retrieve(image);
    return !image.empty();
}

VideoCapture& VideoCapture::operator >> (Mat& image)
{
    if(!grab())
        image.release();
    else
        retrieve(image);
    return *this;
}

bool VideoCapture::set(int propId, double value)
{
    return cvSetCaptureProperty(cap, propId, value) != 0;
}

double VideoCapture::get(int propId)
{
    return cvGetCaptureProperty(cap, propId);
}

VideoWriter::VideoWriter()
{}

VideoWriter::VideoWriter(const string& filename, int fourcc, double fps, Size frameSize, bool isColor)
{
    open(filename, fourcc, fps, frameSize, isColor);
}

VideoWriter::~VideoWriter()
{
    writer.release();
}

bool VideoWriter::open(const string& filename, int fourcc, double fps, Size frameSize, bool isColor)
{
    writer = cvCreateVideoWriter(filename.c_str(), fourcc, fps, frameSize, isColor);
    return isOpened();
}

bool VideoWriter::isOpened() const
{
    return !writer.empty();
}

void VideoWriter::write(const Mat& image)
{
    IplImage _img = image;
    cvWriteFrame(writer, &_img);
}

VideoWriter& VideoWriter::operator << (const Mat& image)
{
    write(image);
    return *this;
}

}
<commit_msg>fixed Ximea constructor call<commit_after>/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                        Intel License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of Intel Corporation may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

#include "precomp.hpp"

#if _MSC_VER >= 1200
#pragma warning( disable: 4711 )
#endif

#if defined _M_X64 && defined _MSC_VER && !defined CV_ICC
#pragma optimize("",off)
#endif

namespace cv
{

template<> void Ptr<CvCapture>::delete_obj()
{ cvReleaseCapture(&obj); }

template<> void Ptr<CvVideoWriter>::delete_obj()
{ cvReleaseVideoWriter(&obj); }

}

/************************* Reading AVIs & Camera data **************************/

CV_IMPL void cvReleaseCapture( CvCapture** pcapture )
{
    if( pcapture && *pcapture )
    {
        delete *pcapture;
        *pcapture = 0;
    }
}

CV_IMPL IplImage* cvQueryFrame( CvCapture* capture )
{
    if(!capture)
        return 0;
    if(!capture->grabFrame())
        return 0;
    return capture->retrieveFrame(0);
}

CV_IMPL int cvGrabFrame( CvCapture* capture )
{
    return capture ? capture->grabFrame() : 0;
}

CV_IMPL IplImage* cvRetrieveFrame( CvCapture* capture, int idx )
{
    return capture ? capture->retrieveFrame(idx) : 0;
}

CV_IMPL double cvGetCaptureProperty( CvCapture* capture, int id )
{
    return capture ? capture->getProperty(id) : 0;
}

CV_IMPL int cvSetCaptureProperty( CvCapture* capture, int id, double value )
{
    return capture ? capture->setProperty(id, value) : 0;
}

CV_IMPL int cvGetCaptureDomain( CvCapture* capture)
{
    return capture ? capture->getCaptureDomain() : 0;
}

/**
 * Camera dispatching method: index is the camera number.
 * If given an index from 0 to 99, it tries to find the first
 * API that can access a given camera index.
 * Add multiples of 100 to select an API.
 */
CV_IMPL CvCapture * cvCreateCameraCapture (int index)
{
    int  domains[] =
    {
#ifdef HAVE_VIDEOINPUT
        CV_CAP_DSHOW,
#endif
        CV_CAP_IEEE1394,   // identical to CV_CAP_DC1394
        CV_CAP_STEREO,
        CV_CAP_PVAPI,
        CV_CAP_VFW,        // identical to CV_CAP_V4L
        CV_CAP_MIL,
        CV_CAP_QT,
        CV_CAP_UNICAP,
#ifdef HAVE_OPENNI
        CV_CAP_OPENNI,
#endif
#ifdef HAVE_ANDROID_NATIVE_CAMERA
        CV_CAP_ANDROID,
#endif
#ifdef HAVE_XIMEA
        CV_CAP_XIAPI,
#endif
        -1
    };

    // interpret preferred interface (0 = autodetect)
    int pref = (index / 100) * 100;
    if (pref)
    {
        domains[0]=pref;
        index %= 100;
        domains[1]=-1;
    }

    // try every possibly installed camera API
    for (int i = 0; domains[i] >= 0; i++)
    {
        #if defined(HAVE_VIDEOINPUT) || defined(HAVE_TYZX) || defined(HAVE_VFW) || \
        defined(HAVE_CAMV4L) || defined (HAVE_CAMV4L2) || defined(HAVE_GSTREAMER) || \
        defined(HAVE_DC1394_2) || defined(HAVE_DC1394) || defined(HAVE_CMU1394) || \
        defined(HAVE_GSTREAMER) || defined(HAVE_MIL) || defined(HAVE_QUICKTIME) || \
        defined(HAVE_UNICAP) || defined(HAVE_PVAPI) || defined(HAVE_OPENNI) || defined(HAVE_ANDROID_NATIVE_CAMERA)
        // local variable to memorize the captured device
        CvCapture *capture;
        #endif

        switch (domains[i])
        {
        #ifdef HAVE_VIDEOINPUT
        case CV_CAP_DSHOW:
            capture = cvCreateCameraCapture_DShow (index);
            if (capture)
                return capture;
            break;
        #endif

        #ifdef HAVE_TYZX
        case CV_CAP_STEREO:
            capture = cvCreateCameraCapture_TYZX (index);
            if (capture)
                return capture;
            break;
        #endif

        case CV_CAP_VFW:
        #ifdef HAVE_VFW
            capture = cvCreateCameraCapture_VFW (index);
            if (capture)
                return capture;
        #endif
        #if defined HAVE_LIBV4L || (defined (HAVE_CAMV4L) && defined (HAVE_CAMV4L2))
            capture = cvCreateCameraCapture_V4L (index);
            if (capture)
                return capture;
        #endif
        #ifdef HAVE_GSTREAMER
            capture = cvCreateCapture_GStreamer(CV_CAP_GSTREAMER_V4L2, 0);
            if (capture)
                return capture;
            capture = cvCreateCapture_GStreamer(CV_CAP_GSTREAMER_V4L, 0);
            if (capture)
                return capture;
        #endif
            break;

        case CV_CAP_FIREWIRE:
        #ifdef HAVE_DC1394_2
            capture = cvCreateCameraCapture_DC1394_2 (index);
            if (capture)
                return capture;
        #endif
        #ifdef HAVE_DC1394
            capture = cvCreateCameraCapture_DC1394 (index);
            if (capture)
                return capture;
        #endif
        #ifdef HAVE_CMU1394
            capture = cvCreateCameraCapture_CMU (index);
            if (capture)
                return capture;
        #endif
    /* Re-enable again when gstreamer 1394 support will land in the backend code
        #ifdef HAVE_GSTREAMER
            capture = cvCreateCapture_GStreamer(CV_CAP_GSTREAMER_1394, 0);
            if (capture)
                return capture;
        #endif
    */
            break;
        #ifdef HAVE_MIL
        case CV_CAP_MIL:
            capture = cvCreateCameraCapture_MIL (index);
            if (capture)
                return capture;
            break;
        #endif

        #ifdef HAVE_QUICKTIME
        case CV_CAP_QT:
            capture = cvCreateCameraCapture_QT (index);
            if (capture)
                return capture;
            break;
        #endif

        #ifdef HAVE_UNICAP
        case CV_CAP_UNICAP:
            capture = cvCreateCameraCapture_Unicap (index);
            if (capture)
                return capture;
        break;
        #endif

        #ifdef HAVE_PVAPI
        case CV_CAP_PVAPI:
            capture = cvCreateCameraCapture_PvAPI (index);
            if (capture)
                return capture;
        break;
        #endif

        #ifdef HAVE_OPENNI
        case CV_CAP_OPENNI:
            capture = cvCreateCameraCapture_OpenNI (index);
            if (capture)
                return capture;
        break;
        #endif

        #ifdef HAVE_ANDROID_NATIVE_CAMERA
        case CV_CAP_ANDROID:
            capture = cvCreateCameraCapture_Android (index);
            if (capture)
                return capture;
        break;
        #endif

        #ifdef HAVE_XIMEA
        case CV_CAP_XIAPI:
            capture = cvCreateCameraCapture_XIMEA (index);
            if (capture)
                return capture;
        break;
        #endif
        }
    }

    // failed open a camera
    return 0;
}

/**
 * Videoreader dispatching method: it tries to find the first
 * API that can access a given filename.
 */
CV_IMPL CvCapture * cvCreateFileCapture (const char * filename)
{
    CvCapture * result = 0;

    if (! result)
        result = cvCreateFileCapture_FFMPEG_proxy (filename);

    #ifdef HAVE_XINE
    if (! result)
        result = cvCreateFileCapture_XINE (filename);
    #endif

    #ifdef HAVE_GSTREAMER
    if (! result)
        result = cvCreateCapture_GStreamer (CV_CAP_GSTREAMER_FILE, filename);
    #endif

    #ifdef HAVE_QUICKTIME
    if (! result)
        result = cvCreateFileCapture_QT (filename);
    #endif

    if (! result)
        result = cvCreateFileCapture_Images (filename);

    return result;
}

/**
 * Videowriter dispatching method: it tries to find the first
 * API that can write a given stream.
 */
CV_IMPL CvVideoWriter* cvCreateVideoWriter( const char* filename, int fourcc,
                                            double fps, CvSize frameSize, int is_color )
{
	//CV_FUNCNAME( "cvCreateVideoWriter" );

	CvVideoWriter *result = 0;

	if(!fourcc || !fps)
		result = cvCreateVideoWriter_Images(filename);

	if(!result)
		result = cvCreateVideoWriter_FFMPEG_proxy (filename, fourcc, fps, frameSize, is_color);

/*	#ifdef HAVE_XINE
	if(!result)
		result = cvCreateVideoWriter_XINE(filename, fourcc, fps, frameSize, is_color);
	#endif
*/

	#ifdef HAVE_QUICKTIME
	if(!result)
		result = cvCreateVideoWriter_QT(filename, fourcc, fps, frameSize, is_color);
	#endif
    #ifdef HAVE_GSTREAMER
    if (! result)
        result = cvCreateVideoWriter_GStreamer(filename, fourcc, fps, frameSize, is_color);
    #endif
	if(!result)
		result = cvCreateVideoWriter_Images(filename);

	return result;
}

CV_IMPL int cvWriteFrame( CvVideoWriter* writer, const IplImage* image )
{

    return writer ? writer->writeFrame(image) : 0;
}

CV_IMPL void cvReleaseVideoWriter( CvVideoWriter** pwriter )
{
    if( pwriter && *pwriter )
    {
        delete *pwriter;
        *pwriter = 0;
    }
}

namespace cv
{

VideoCapture::VideoCapture()
{}

VideoCapture::VideoCapture(const string& filename)
{
    open(filename);
}

VideoCapture::VideoCapture(int device)
{
    open(device);
}

VideoCapture::~VideoCapture()
{
    cap.release();
}

bool VideoCapture::open(const string& filename)
{
    cap = cvCreateFileCapture(filename.c_str());
    return isOpened();
}

bool VideoCapture::open(int device)
{
    cap = cvCreateCameraCapture(device);
    return isOpened();
}

bool VideoCapture::isOpened() const { return !cap.empty(); }

void VideoCapture::release()
{
    cap.release();
}

bool VideoCapture::grab()
{
    return cvGrabFrame(cap) != 0;
}

bool VideoCapture::retrieve(Mat& image, int channel)
{
    IplImage* _img = cvRetrieveFrame(cap, channel);
    if( !_img )
    {
        image.release();
        return false;
    }
    if(_img->origin == IPL_ORIGIN_TL)
        image = Mat(_img);
    else
    {
        Mat temp(_img);
        flip(temp, image, 0);
    }
    return true;
}

bool VideoCapture::read(Mat& image)
{
    if(!grab())
        image.release();
    else
        retrieve(image);
    return !image.empty();
}

VideoCapture& VideoCapture::operator >> (Mat& image)
{
    if(!grab())
        image.release();
    else
        retrieve(image);
    return *this;
}

bool VideoCapture::set(int propId, double value)
{
    return cvSetCaptureProperty(cap, propId, value) != 0;
}

double VideoCapture::get(int propId)
{
    return cvGetCaptureProperty(cap, propId);
}

VideoWriter::VideoWriter()
{}

VideoWriter::VideoWriter(const string& filename, int fourcc, double fps, Size frameSize, bool isColor)
{
    open(filename, fourcc, fps, frameSize, isColor);
}

VideoWriter::~VideoWriter()
{
    writer.release();
}

bool VideoWriter::open(const string& filename, int fourcc, double fps, Size frameSize, bool isColor)
{
    writer = cvCreateVideoWriter(filename.c_str(), fourcc, fps, frameSize, isColor);
    return isOpened();
}

bool VideoWriter::isOpened() const
{
    return !writer.empty();
}

void VideoWriter::write(const Mat& image)
{
    IplImage _img = image;
    cvWriteFrame(writer, &_img);
}

VideoWriter& VideoWriter::operator << (const Mat& image)
{
    write(image);
    return *this;
}

}
<|endoftext|>