Exemplo n.º 1
0
void Logger::registerWriter(Logger::Type type, const std::string& param )
{
  switch( type )
  {
  case consolelog:
  {
    auto wr = ptr_make<ConsoleLogWriter>();
    registerWriter( "__console", wr.as<LogWriter>() );
  }
  break;

  case filelog:
  {
    vfs::Directory workdir( param );
    vfs::Path fullname = workdir/"stdout.txt";
    auto wr = ptr_make<FileLogWriter>( fullname.toString() );
    registerWriter( "__log", wr.as<LogWriter>() );
  }
  break;

  case count: break;
  }
}
Exemplo n.º 2
0
inline PROCESS_INFORMATION win32_start(const Executable &exe, const Arguments &args, const environment &env, stream_info &infoin, stream_info &infoout, stream_info &infoerr, const win32_setup &setup) 
{ 
    file_handle chin, chout, cherr; 

    BOOST_ASSERT(setup.startupinfo->cb >= sizeof(STARTUPINFOA)); 
    BOOST_ASSERT(!(setup.startupinfo->dwFlags & STARTF_USESTDHANDLES)); 

    boost::scoped_ptr<STARTUPINFOA> si(new STARTUPINFOA); 
    ::CopyMemory(si.get(), setup.startupinfo, sizeof(*setup.startupinfo)); 
    si->dwFlags |= STARTF_USESTDHANDLES; 

    switch (infoin.type_) 
    { 
    case stream_info::close: 
        { 
            break; 
        } 
    case stream_info::inherit: 
        { 
            chin = file_handle::win32_std(STD_INPUT_HANDLE, true); 
            break; 
        } 
    case stream_info::use_file: 
        { 
            HANDLE h = ::CreateFileA(infoin.file_.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 
            if (h == INVALID_HANDLE_VALUE) 
                boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::detail::win32_start: CreateFile failed")); 
            chin = file_handle(h); 
            break; 
        } 
    case stream_info::use_handle: 
        { 
            chin = infoin.handle_; 
            chin.win32_set_inheritable(true); 
            break; 
        } 
    case stream_info::use_pipe: 
        { 
            infoin.pipe_->rend().win32_set_inheritable(true); 
            chin = infoin.pipe_->rend(); 
            break; 
        } 
    default: 
        { 
            BOOST_ASSERT(false); 
            break; 
        } 
    } 

    si->hStdInput = chin.valid() ? chin.get() : INVALID_HANDLE_VALUE; 

    switch (infoout.type_) 
    { 
    case stream_info::close: 
        { 
            break; 
        } 
    case stream_info::inherit: 
        { 
            chout = file_handle::win32_std(STD_OUTPUT_HANDLE, true); 
            break; 
        } 
    case stream_info::use_file: 
        { 
            HANDLE h = ::CreateFileA(infoout.file_.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 
            if (h == INVALID_HANDLE_VALUE) 
                boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::detail::win32_start: CreateFile failed")); 
            chout = file_handle(h); 
            break; 
        } 
    case stream_info::use_handle: 
        { 
            chout = infoout.handle_; 
            chout.win32_set_inheritable(true); 
            break; 
        } 
    case stream_info::use_pipe: 
        { 
            infoout.pipe_->wend().win32_set_inheritable(true); 
            chout = infoout.pipe_->wend(); 
            break; 
        } 
    default: 
        { 
            BOOST_ASSERT(false); 
            break; 
        } 
    } 

    si->hStdOutput = chout.valid() ? chout.get() : INVALID_HANDLE_VALUE; 

    switch (infoerr.type_) 
    { 
    case stream_info::close: 
        { 
            break; 
        } 
    case stream_info::inherit: 
        { 
            cherr = file_handle::win32_std(STD_ERROR_HANDLE, true); 
            break; 
        } 
    case stream_info::redirect: 
        { 
            BOOST_ASSERT(infoerr.desc_to_ == 1); 
            BOOST_ASSERT(chout.valid()); 
            cherr = file_handle::win32_dup(chout.get(), true); 
            break; 
        } 
    case stream_info::use_file: 
        { 
            HANDLE h = ::CreateFileA(infoerr.file_.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 
            if (h == INVALID_HANDLE_VALUE) 
                boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::detail::win32_start: CreateFile failed")); 
            cherr = file_handle(h); 
            break; 
        } 
    case stream_info::use_handle: 
        { 
            cherr = infoerr.handle_; 
            cherr.win32_set_inheritable(true); 
            break; 
        } 
    case stream_info::use_pipe: 
        { 
            infoerr.pipe_->wend().win32_set_inheritable(true); 
            cherr = infoerr.pipe_->wend(); 
            break; 
        } 
    default: 
        { 
            BOOST_ASSERT(false); 
            break; 
        } 
    } 

    si->hStdError = cherr.valid() ? cherr.get() : INVALID_HANDLE_VALUE; 

    PROCESS_INFORMATION pi; 
    ::ZeroMemory(&pi, sizeof(pi)); 

    boost::shared_array<char> cmdline;

    boost::scoped_array<char> executable;
    // exe could be "", in which case call CreateProcess with NULL first argument
    if (exe.size()) {
        executable.reset(new char[exe.size() + 1]);
#if defined(__CYGWIN__) || defined(_SCL_SECURE_NO_DEPRECATE)
        ::strcpy(executable.get(), exe.c_str());
#else
        ::strcpy_s(executable.get(), exe.size() + 1, exe.c_str());
#endif
        cmdline = collection_to_win32_cmdline(args);
    }
    else if (args.size() == 1) {
        // No exe and just a single argument. Dont escape anything - pass it through unchanged.
        std::string const &c = args.front();
        cmdline.reset(new char[c.size() + 1]);
#if defined(__CYGWIN__) || defined(_SCL_SECURE_NO_DEPRECATE) 
        ::strcpy(cmdline.get(), c.c_str());
#else 
        ::strcpy_s(cmdline.get(), c.size() + 1, c.c_str());
#endif 
    }
    else {
        cmdline = collection_to_win32_cmdline(args);
    }

    boost::scoped_array<char> workdir(new char[setup.work_directory.size() + 1]); 
#if defined(__CYGWIN__) || defined(_SCL_SECURE_NO_DEPRECATE) 
    ::strcpy(workdir.get(), setup.work_directory.c_str()); 
#else 
    ::strcpy_s(workdir.get(), setup.work_directory.size() + 1, setup.work_directory.c_str()); 
#endif 

    boost::shared_array<char> envstrs = environment_to_win32_strings(env); 

    if (!::CreateProcessA(executable.get(), cmdline.get(), NULL, NULL, TRUE, 0, envstrs.get(), workdir.get(), si.get(), &pi)) 
        boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::detail::win32_start: CreateProcess failed")); 

    return pi; 
} 
Exemplo n.º 3
0
int	main(int argc, char *argv[])
{

	tu_memdebug::open();

	{	// for testing memory leaks

		assert(tu_types_validate());

		const char* infile = NULL;

		float	exit_timeout = 0;
		bool	do_render = true;
		bool	do_sound = true;
		bool	do_loop = true;
		bool	sdl_abort = true;
		bool	sdl_cursor = true;
		float	tex_lod_bias;
		bool	force_realtime_framerate = false;

	#ifdef _WIN32

		WSADATA wsaData;

		int iResult = WSAStartup( MAKEWORD(2,2), &wsaData );
		if ( iResult != NO_ERROR )
			printf("Error at WSAStartup()\n");
	#endif


		// -1.0 tends to look good.
		tex_lod_bias = -1.2f;
		tu_string flash_vars;

		int	width = 0;
		int	height = 0;

		gameswf::gc_ptr<gameswf::player> player = new gameswf::player();

		for (int arg = 1; arg < argc; arg++)
		{
			if (argv[arg][0] == '-')
			{
				// Looks like an option.

				if (argv[arg][1] == 'h')
				{
					// Help.
					print_usage();
					exit(1);
				}
				if (argv[arg][1] == 'u')
				{
					arg++;
					if (arg < argc)
					{
						flash_vars = argv[arg];
					}
					else
					{
						fprintf(stderr, "-u arg must be followed string like myvar=x&myvar2=y and so on\n");
						print_usage();
						exit(1);
					}

				}
				else if (argv[arg][1] == 'w')
				{
					arg++;
					if (arg < argc)
					{
						width = atoi(argv[arg]);
						const char* x = strstr(argv[arg], "x");
						if (x)
						{
							height = atoi(x + 1);
						}
					}

					if (width <=0 || height <= 0)
					{
						fprintf(stderr, "-w arg must be followed by the window size\n");
						print_usage();
						exit(1);
					}
				}
				else if (argv[arg][1] == 'c')
				{
					sdl_abort = false;
				}
                else if (argv[arg][1] == 'f')
                {
                    force_realtime_framerate = true;
                }
				else if (argv[arg][1] == 'k')
				{
					sdl_cursor = false;
				}
				else if (argv[arg][1] == 'a')
				{
					// Set antialiasing on or off.
					arg++;
					if (arg < argc)
					{
						s_aa_level = atoi(argv[arg]);
						s_antialiased = s_aa_level > 0 ? true : false;
					}
					else
					{
						fprintf(stderr, "-a arg must be followed by the antialiasing level\n");
						print_usage();
						exit(1);
					}
				}
				else if (argv[arg][1] == 'b')
				{
					// Set default bit depth.
					arg++;
					if (arg < argc)
					{
						s_bit_depth = atoi(argv[arg]);
						if (s_bit_depth != 16 && s_bit_depth != 24 && s_bit_depth != 32)
						{
							fprintf(stderr, "Command-line supplied bit depth %d, but it must be 16, 24 or 32", s_bit_depth);
							print_usage();
							exit(1);
						}
					}
					else
					{
						fprintf(stderr, "-b arg must be followed by 16 or 32 to set bit depth\n");
						print_usage();
						exit(1);
					}
				}
				else if (argv[arg][1] == 'd')
				{
					// Set a delay
					arg++;
					if (arg < argc)
					{
						s_delay = atoi(argv[arg]);
					}
					else
					{
						fprintf(stderr, "-d arg must be followed by number of milli-seconds to del in the main loop\n");
						print_usage();
						exit(1);
					}
				}
				else if (argv[arg][1] == 'p')
				{
					// Enable frame-rate/performance logging.
					s_measure_performance = true;
				}
				else if (argv[arg][1] == '1')
				{
					// Play once; don't loop.
					do_loop = false;
				}
				else if (argv[arg][1] == 'r')
				{
					// Set rendering on/off.
					arg++;
					if (arg < argc)
					{
						const int render_arg = atoi(argv[arg]);
						switch (render_arg) {
						case 0:
							// Disable both
							do_render = false;
							do_sound = false;
							break;
						case 1:
							// Enable both
							do_render = true;
							do_sound = true;
							break;
						case 2:
							// Disable just sound
							do_render = true;
							do_sound = false;
							break;
						default:
							fprintf(stderr, "-r must be followed by 0, 1 or 2 (%d is invalid)\n",
								render_arg);
							print_usage();
							exit(1);
							break;
						}
					} else {
						fprintf(stderr, "-r must be followed by 0 an argument to disable/enable rendering\n");
						print_usage();
						exit(1);
					}
				}
				else if (argv[arg][1] == 't')
				{
					// Set timeout.
					arg++;
					if (arg < argc)
					{
						exit_timeout = (float) atof(argv[arg]);
					}
					else
					{
						fprintf(stderr, "-t must be followed by an exit timeout, in seconds\n");
						print_usage();
						exit(1);
					}
				}
				else if (argv[arg][1] == 'v')
				{
					// Be verbose; i.e. print log messages to stdout.
					if (argv[arg][2] == 'a')
					{
						// Enable spew re: action.
						player->verbose_action(true);
					}
					else if (argv[arg][2] == 'p')
					{
						// Enable parse spew.
						player->verbose_parse(true);
					}
					// ...
				}
				else if (argv[arg][1] == 'm')
				{
					if (argv[arg][2] == 'l') {
						arg++;
						tex_lod_bias = (float) atof(argv[arg]);
						//printf("Texture LOD Bais is no %f\n", tex_lod_bias);
					}
					else
					{
						fprintf(stderr, "unknown variant of -m arg\n");
						print_usage();
						exit(1);
					}
				}
				else if (argv[arg][1] == 'n')
				{
					s_allow_http = true;
				}
				else if (argv[arg][1] == 'i')
				{
					player->set_separate_thread(false);
					player->set_log_bitmap_info(true);
				}
			}
			else
			{
				infile = argv[arg];
			}
		}

		if (infile == NULL)
		{
			printf("no input file\n");
			print_usage();
			exit(1);
		}

		//
		if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
		{
			fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
			exit(1);
		}
		atexit(SDL_Quit);
		
		//Use OpenGL 2.1
		SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 2 );
		SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 1 );

		// Set the video mode.
//				if (SDL_SetVideoMode(width, height, s_bit_depth, SDL_OPENGL | SDL_RESIZABLE) == 0)
		//if (SDL_SetVideoMode(width, height, s_bit_depth, SDL_OPENGL) == 0)
		window = SDL_CreateWindow("TestSWF",
											  SDL_WINDOWPOS_CENTERED,
								  			  SDL_WINDOWPOS_CENTERED,
											  512,
											  512,
											  SDL_WINDOW_OPENGL|SDL_WINDOW_SHOWN);
		if(!window)
		{
			fprintf(stderr, "SDL_CreateWindow() failed. %s", SDL_GetError());
			exit(1);
		}
		gContext = SDL_GL_CreateContext(window);
		if( gContext == NULL )
		{
			fprintf(stderr, "OpenGL context could not be created! SDL Error: %s\n", SDL_GetError() );
			exit(1);
		}
		//Use Vsync
		if( SDL_GL_SetSwapInterval( 1 ) < 0 )
		{
			fprintf(stderr, "Warning: Unable to set VSync! SDL Error: %s\n", SDL_GetError() );
		}

		SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);
		if(!renderer)
		{
			fprintf(stderr, "SDL_CreateRenderer() failed. %s", SDL_GetError());
			exit(1);
		}

		//SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
		//SDL_RenderClear(renderer);
		//SDL_RenderPresent(renderer);

		//
		player->set_force_realtime_framerate(force_realtime_framerate);

		// use this for multifile games
		// workdir is used when LoadMovie("myfile.swf", _root) is called
		{
			tu_string workdir;
			// Find last slash or backslash.
 			const char* ptr = infile + strlen(infile);
			for (; ptr >= infile && *ptr != '/' && *ptr != '\\'; ptr--) {}
			// Use everything up to last slash as the "workdir".
			int len = ptr - infile + 1;
			if (len > 0)
			{
				tu_string workdir(infile, len);
				player->set_workdir(workdir.c_str());
			}
		}

		gameswf::register_file_opener_callback(file_opener);
		gameswf::register_fscommand_callback(fs_callback);
		if (gameswf::get_verbose_parse())
		{
			gameswf::register_log_callback(log_callback);
		}
		
		gameswf::sound_handler*	sound = NULL;
		gameswf::render_handler*	render = NULL;
		if (do_render)
		{
			if (do_sound)
			{

#ifdef TU_USE_SDL
				sound = gameswf::create_sound_handler_sdl();
#endif

#ifdef TU_USE_OPENAL
				sound = gameswf::create_sound_handler_openal();
#endif

				gameswf::set_sound_handler(sound);
			}

#ifdef TU_USE_SDL
			render = gameswf::create_render_handler_ogl();
			gameswf::set_render_handler(render);
#endif

#ifdef TU_USE_OGLES
			render = gameswf::create_render_handler_ogles();
			gameswf::set_render_handler(render);
#endif

#if TU_CONFIG_LINK_TO_FREETYPE == 1
			gameswf::set_glyph_provider(gameswf::create_glyph_provider_freetype());
#else
			gameswf::set_glyph_provider(gameswf::create_glyph_provider_tu());
#endif
		}

		//
		//	set_proxy("192.168.1.201", 8080);
		//

		// gameswf::set_use_cache_files(true);

		player->set_flash_vars(flash_vars);
		{
			gameswf::gc_ptr<gameswf::root>	m = player->load_file(infile);
			if (m == NULL)
			{
				exit(1);
			}

			if (width == 0 || height == 0)
			{
				width = m->get_movie_width();
				height = m->get_movie_height();
			}
			float scale_x = (float) width / m->get_movie_width();
			float scale_y = (float) height / m->get_movie_height();

			float	movie_fps = m->get_movie_fps();

			if (do_render)
			{
				// Initialize the SDL subsystems we're using. Linux
				// and Darwin use Pthreads for SDL threads, Win32
				// doesn't. Otherwise the SDL event loop just polls.
				//if (sdl_abort)
				//{
				//	//  Other flags are SDL_INIT_JOYSTICK | SDL_INIT_CDROM
				//	//#ifdef _WIN32
				//	//if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO))
				//	//#else
				//	//if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_EVENTTHREAD ))
				//	if (SDL_Init(SDL_INIT_EVERYTHING))
				//		//#endif
				//	{
				//		fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
				//		exit(1);
				//	}
				//}
				//else
				//{
				//	fprintf(stderr, "warning: SDL won't trap core dumps \n");
				//	//#ifdef _WIN32
				//	//if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE  | SDL_INIT_EVENTTHREAD))
				//	//#else
				//	//if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE))
				//		//#endif
				//	if (SDL_Init(SDL_INIT_EVERYTHING))
				//	{
				//		fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
				//		exit(1);
				//	}
				//}

				//atexit(SDL_Quit);

				//SDL_EnableKeyRepeat(250, 33);
				//event.key.repeat
				SDL_ShowCursor(sdl_cursor ? SDL_ENABLE : SDL_DISABLE);

				switch (s_bit_depth)
				{
					case 16:
						// 16-bit color, surface creation is likely to succeed.
						SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
						SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
						SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
						SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 15);
						SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
						SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 5);
						break;

					case 24:
						// 24-bit color
						//	SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
						//	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
						//	SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
						//	SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
						//	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
						SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
						SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1);
						break;

					case 32:
						// 32-bit color etc, for getting dest alpha,
						// for MULTIPASS_ANTIALIASING (see gameswf_render_handler_ogl.cpp).
						SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
						SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
						SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
						SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
						SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
						SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
						SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
						break;

					default:
						assert(0);
				}

				// try to enable FSAA
				if (s_aa_level > 1)
				{
					SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
					SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, s_aa_level);
				}

				// Change the LOD BIAS values to tweak blurriness.
				if (tex_lod_bias != 0.0f) {
	#ifdef FIX_I810_LOD_BIAS	
					// If 2D textures weren't previously enabled, enable
					// them now and force the driver to notice the update,
					// then disable them again.
					if (!glIsEnabled(GL_TEXTURE_2D)) {
						// Clearing a mask of zero *should* have no
						// side effects, but coupled with enbling
						// GL_TEXTURE_2D it works around a segmentation
						// fault in the driver for the Intel 810 chip.
						glEnable(GL_TEXTURE_2D);
						glClear(0);
						glDisable(GL_TEXTURE_2D);
					}
	#endif // FIX_I810_LOD_BIAS
					glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, tex_lod_bias);
				}
				
				render->open();
				render->set_antialiased(s_antialiased);

				// Turn on alpha blending.
				glEnable(GL_BLEND);
				glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

				// Turn on line smoothing.  Antialiased lines can be used to
				// smooth the outsides of shapes.
				glEnable(GL_LINE_SMOOTH);
				glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);	// GL_NICEST, GL_FASTEST, GL_DONT_CARE

				glMatrixMode(GL_PROJECTION);
				glOrtho(-OVERSIZE, OVERSIZE, OVERSIZE, -OVERSIZE, -1, 1);
				glMatrixMode(GL_MODELVIEW);
				glLoadIdentity();

				// We don't need lighting effects
				glDisable(GL_LIGHTING);
				// glColorPointer(4, GL_UNSIGNED_BYTE, 0, *);
				// glInterleavedArrays(GL_T2F_N3F_V3F, 0, *)
				glPushAttrib (GL_ALL_ATTRIB_BITS);		
			}

			// Set Title
			//SDL_WM_SetCaption("TestSWF", NULL);

			// Mouse state.
			int	mouse_x = 0;
			int	mouse_y = 0;
			int	mouse_buttons = 0;

			float	speed_scale = 1.0f;
			Uint32	start_ticks = 0;
			if (do_render)
			{
				start_ticks = tu_timer::get_ticks();
			}
			Uint32	last_ticks = start_ticks;
			int	frame_counter = 0;
			int	last_logged_fps = last_ticks;
			int fps = 0;

			//TODO
	//		gameswf::player* p = gameswf::create_player();
	//		p.run();


			for (;;)
			{
				Uint32	ticks;
				if (do_render)
				{
					ticks = tu_timer::get_ticks();
				}
				else
				{
					// Simulate time.
					ticks = last_ticks + (Uint32) (1000.0f / movie_fps);
				}
				int	delta_ticks = ticks - last_ticks;
				float	delta_t = delta_ticks / 1000.f;
				last_ticks = ticks;

				// Check auto timeout counter.
				if (exit_timeout > 0
					&& ticks - start_ticks > (Uint32) (exit_timeout * 1000))
				{
					// Auto exit now.
					break;
				}

				bool ret = true;
				if (do_render)
				{
					SDL_Event	event;
					// Handle input.
					while (ret)
					{
						if (SDL_PollEvent(&event) == 0)
						{
							break;
						}

						//printf("EVENT Type is %d\n", event.type);
						switch (event.type)
						{
							//case SDL_VIDEORESIZE:
							//	TODO
							//					s_scale = (float) event.resize.w / (float) width;
							//					width = event.resize.w;
							//					height = event.resize.h;
							//					if (SDL_SetVideoMode(event.resize.w, event.resize.h, 0, SDL_OPENGL | SDL_RESIZABLE) == 0)
							//					{
							//						fprintf(stderr, "SDL_SetVideoMode() failed.");
							//						exit(1);
							//					}
							//					glOrtho(-OVERSIZE, OVERSIZE, OVERSIZE, -OVERSIZE, -1, 1);
							//break;

						case SDL_USEREVENT:
							//printf("SDL_USER_EVENT at %s, code %d%d\n", __FUNCTION__, __LINE__, event.user.code);
							ret = false;
							break;
						case SDL_KEYDOWN:
							{
								SDL_Keycode	key = event.key.keysym.sym;
								bool	ctrl = (event.key.keysym.mod & KMOD_CTRL) != 0;

								if (key == SDLK_ESCAPE
									|| (ctrl && key == SDLK_q)
									|| (ctrl && key == SDLK_w))
								{
									goto done;
								}
								else if (ctrl && key == SDLK_p)
								{
									// Toggle paused state.
									if (m->get_play_state() == gameswf::character::STOP)
									{
										m->set_play_state(gameswf::character::PLAY);
									}
									else
									{
										m->set_play_state(gameswf::character::STOP);
									}
								}
								else if (ctrl && key == SDLK_i)
								{
									// Init library, for detection of memory leaks (for testing purposes)
	/*
									// Clean up gameswf as much as possible, so valgrind will help find actual leaks.

									gameswf::set_sound_handler(NULL);
									delete sound;

									gameswf::set_render_handler(NULL);
									delete render;

									if (do_render)
									{
										if (do_sound)
										{
											sound = gameswf::create_sound_handler_sdl();
											gameswf::set_sound_handler(sound);
										}
										render = gameswf::create_render_handler_ogl();
										gameswf::set_render_handler(render);
									}
	*/
									// Load the actual movie.
									m = player->load_file(infile);
									if (m == NULL)
									{
										exit(1);
									}
								}
								else if (ctrl && (key == SDLK_LEFTBRACKET || key == SDLK_KP_MINUS))
								{
									m->goto_frame(m->get_current_frame()-1);
								}
								else if (ctrl && (key == SDLK_RIGHTBRACKET || key == SDLK_KP_PLUS))
								{
									m->goto_frame(m->get_current_frame()+1);
								}
								else if (ctrl && key == SDLK_a)
								{
									// Toggle antialiasing.
									s_antialiased = !s_antialiased;
									if (render)
									{
										render->set_antialiased(s_antialiased);
									}
								}
								else if (ctrl && key == SDLK_t)
								{
									// test text replacement / variable setting:
									m->set_variable("test.text", "set_edit_text was here...\nanother line of text for you to see in the text box");
								}
								else if (ctrl && key == SDLK_g)
								{
									// test get_variable.
									message_log("testing get_variable: '");
									message_log(m->get_variable("test.text"));
									message_log("'\n");
								}
								else if (ctrl && key == SDLK_m)
								{
									// Test call_method.
									const char* result = m->call_method(
										"test_call",
										"%d, %f, %s, %ls",
										200,
										1.0f,
										"Test string",
										L"Test long string");

									if (result)
									{
										message_log("call_method: result = ");
										message_log(result);
										message_log("\n");
									}
									else
									{
										message_log("call_method: null result\n");
									}
								}
								else if (ctrl && key == SDLK_b)
								{
									// toggle background color.
									s_background = !s_background;
								}
	//							else if (ctrl && key == SDLK_f)	//xxxxxx
	//							{
	//								extern bool gameswf_debug_show_paths;
	//								gameswf_debug_show_paths = !gameswf_debug_show_paths;
	//							}
								else if (ctrl && key == SDLK_EQUALS)
								{
									float	f = gameswf::get_curve_max_pixel_error();
									f *= 1.1f;
									gameswf::set_curve_max_pixel_error(f);
									printf("curve error tolerance = %f\n", f);
								}
								else if (ctrl && key == SDLK_MINUS)
								{
									float	f = gameswf::get_curve_max_pixel_error();
									f *= 0.9f;
									gameswf::set_curve_max_pixel_error(f);
									printf("curve error tolerance = %f\n", f);
								} else if (ctrl && key == SDLK_F2) {
									// Toggle wireframe.
									static bool wireframe_mode = false;
									wireframe_mode = !wireframe_mode;
									if (wireframe_mode) {
										glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
									} else {
										glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
									}
									// TODO: clean up this interafce and re-enable.
									// 					} else if (ctrl && key == SDLK_d) {
									// 						// Flip a special debug flag.
									// 						gameswf_tesselate_dump_shape = true;
								}

								gameswf::key::code c = translate_key(key);
								if (c != gameswf::key::INVALID)
								{
									player->notify_key_event(c, true);
								}

								break;
							}

						case SDL_KEYUP:
							{
								SDL_Keycode	key = event.key.keysym.sym;

								gameswf::key::code c = translate_key(key);
								if (c != gameswf::key::INVALID)
								{
									player->notify_key_event(c, false);
								}

								break;
							}

						case SDL_MOUSEMOTION:
							mouse_x = (int) (event.motion.x / scale_x);
							mouse_y = (int) (event.motion.y / scale_y);
							break;

						case SDL_MOUSEBUTTONDOWN:
						case SDL_MOUSEBUTTONUP:
							{
								int	mask = 1 << (event.button.button - 1);
								if (event.button.state == SDL_PRESSED)
								{
									mouse_buttons |= mask;
								}
								else
								{
									mouse_buttons &= ~mask;
								}
								break;
							}

						case SDL_QUIT:
							goto done;
							break;

						default:
							break;
						}
					}
				}

				if (do_render)
				{
					glDisable(GL_DEPTH_TEST);	// Disable depth testing.
					glDrawBuffer(GL_BACK);
				}

				renderTest();
				//m = player->get_root();
				//m->set_display_viewport(0, 0, width, height);
				//m->set_background_alpha(s_background ? 1.0f : 0.05f);
				//
				//m->notify_mouse_state(mouse_x, mouse_y, mouse_buttons);
				//
				//Uint32 t_advance = tu_timer::get_ticks();
				//m->advance(delta_t * speed_scale);
				//t_advance = tu_timer::get_ticks() - t_advance;
				//
				//if (do_sound && sound)
				//{
				//	sound->advance(delta_t * speed_scale);
				//}
				//
				Uint32 t_display = tu_timer::get_ticks();
				m->display();
				t_display = tu_timer::get_ticks() - t_display;

				if (do_render)
				{
					Uint32 t_swap = tu_timer::get_ticks();
					//SDL_GL_SwapBuffers();
					SDL_GL_SwapWindow(window);
					t_swap = tu_timer::get_ticks() - t_swap;
					//glPopAttrib ();


					frame_counter++;

					// Log the frame rate every second or so.
					if (last_ticks - last_logged_fps > 1000)
					{
						float	delta = (last_ticks - last_logged_fps) / 1000.f;
						fps = (int) ((float) frame_counter / delta);
						last_logged_fps = last_ticks;
						frame_counter = 0;
					}

					if (s_measure_performance == false)
					{
						// Don't hog the CPU.
						SDL_Delay(s_delay);
					}
					else
					{
						printf("fps = %d\n", fps);
					}

					// for perfomance testing
//					printf("advance time: %d, display time %d, swap buffers time = %d\n",
//						t_advance, t_display, t_swap);

#ifdef HAVE_PERFOMANCE_INFO
					char buffer[8];
					snprintf(buffer, 8, "%03d", t_advance);
					m->set_variable("t_Advance", buffer);
					snprintf(buffer, 8, "%03d", t_display);
					m->set_variable("t_Display", buffer);
					snprintf(buffer, 8, "%03d", t_swap);
					m->set_variable("t_SwapBuffers", buffer);
					snprintf(buffer, 8, "%d", fps);
					m->set_variable("FPS", buffer);
#endif
				}

				// TODO: clean up this interface and re-enable.
				//		gameswf_tesselate_dump_shape = false;  ///xxxxx

				// See if we should exit.
				if (do_loop == false && m->get_current_frame() + 1 == m->get_frame_count())
				{
					// We're reached the end of the movie; exit.
					break;
				}
			}

	done:


			gameswf::set_sound_handler(NULL);
			delete sound;

			gameswf::set_render_handler(NULL);
			delete render;

			SDL_Quit();
		}

	}	// for testing memory leaks

	tu_memdebug::close();
	return 0;
}