<commit_before>
#if defined(USE_SDL2)
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>

#if defined(__APPLE__) /* Brew got the headers wrong here */
# include <SDL.h>
#else
# include <SDL2/SDL.h>
#endif

#include "ifict.h"
#include "utils.h"
#include "debug.h"
#include "fatal.h"
#include "palette.h"

SDL_Window*			sdl_window = NULL;
SDL_Surface*			sdl_window_surface = NULL;
SDL_Surface*			sdl_game_surface = NULL;
SDL_Palette*			sdl_game_palette = NULL;
SDL_Color			sdl_pal[256];
Uint32				sdl_ticks_base = 0; /* use Uint32 type provided by SDL2 here to avoid problems */
bool				sdl_signal_to_quit = false;
ifevidinfo_t			ifevidinfo_sdl2;

static void p_SetPaletteColors(const unsigned int first,const unsigned int count,IFEPaletteEntry *pal) {
	unsigned int i;

	priv_SetPaletteColorsRangeCheck(first,count);

	for (i=0;i < count;i++) {
		sdl_pal[i+first].r = pal[i].r;
		sdl_pal[i+first].g = pal[i].g;
		sdl_pal[i+first].b = pal[i].b;
		sdl_pal[i+first].a = 0xFFu;
	}

	if (SDL_SetPaletteColors(sdl_game_palette,sdl_pal,first,count) != 0)
		IFEFatalError("SDL2 game palette set colors");
}

static uint32_t p_GetTicks(void) {
	return uint32_t(SDL_GetTicks() - sdl_ticks_base);
}

static void p_ResetTicks(const uint32_t base) {
	sdl_ticks_base += base; /* NTS: Use return value of IFEGetTicks() */
}

static void p_UpdateFullScreen(void) {
	if (SDL_BlitSurface(sdl_game_surface,NULL,sdl_window_surface,NULL) != 0)
		IFEFatalError("Game to window BlitSurface");

	if (SDL_UpdateWindowSurface(sdl_window) != 0)
		IFEFatalError("Window surface update");
}

static ifevidinfo_t* p_GetVidInfo(void) {
	return &ifevidinfo_sdl2;
}

static bool p_UserWantsToQuit(void) {
	return sdl_signal_to_quit;
}

static void priv_ProcessEvent(SDL_Event &ev) {
	if (ev.type == SDL_QUIT) {
		sdl_signal_to_quit = true;
	}
}

static void p_CheckEvents(void) {
	SDL_Event ev;

	if (SDL_PollEvent(&ev))
		priv_ProcessEvent(ev);
}

static void p_WaitEvent(const int wait_ms) {
	SDL_Event ev;

	if (SDL_WaitEventTimeout(&ev,wait_ms))
		priv_ProcessEvent(ev);
}

static bool p_BeginScreenDraw(void) {
	if (SDL_MUSTLOCK(sdl_game_surface) && SDL_LockSurface(sdl_game_surface) != 0)
		return false;
	if (sdl_game_surface->pixels == NULL)
		IFEFatalError("SDL2 game surface pixels == NULL"); /* that's a BUG if this happens! */
	if (sdl_game_surface->pitch < 0)
		IFEFatalError("SDL2 game surface pitch is negative");

	ifevidinfo_sdl2.buf_base = ifevidinfo_sdl2.buf_first_row = (unsigned char*)(sdl_game_surface->pixels);
	return true;
}

static void p_EndScreenDraw(void) {
	if (SDL_MUSTLOCK(sdl_game_surface))
		SDL_UnlockSurface(sdl_game_surface);

	ifevidinfo_sdl2.buf_base = ifevidinfo_sdl2.buf_first_row = NULL;
}

static void p_ShutdownVideo(void) {
	if (sdl_game_surface != NULL) {
		SDL_FreeSurface(sdl_game_surface);
		sdl_game_surface = NULL;
	}
	if (sdl_game_palette != NULL) {
		SDL_FreePalette(sdl_game_palette);
		sdl_game_palette = NULL;
	}
	if (sdl_window != NULL) {
		SDL_DestroyWindow(sdl_window);
		sdl_window_surface = NULL;
		sdl_window = NULL;
	}
	SDL_Quit();
}

static void p_InitVideo(void) {
	if (SDL_Init(SDL_INIT_VIDEO) < 0)
		IFEFatalError("SDL2 failed to initialize");

	memset(&ifevidinfo_sdl2,0,sizeof(ifevidinfo_sdl2));

	ifevidinfo_sdl2.width = 640;
	ifevidinfo_sdl2.height = 480;

	if (sdl_window == NULL && (sdl_window=SDL_CreateWindow("",SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,640,480,SDL_WINDOW_SHOWN)) == NULL)
		IFEFatalError("SDL2 window creation failed");
	if (sdl_window_surface == NULL && (sdl_window_surface=SDL_GetWindowSurface(sdl_window)) == NULL)
		IFEFatalError("SDL2 window surface failed");
	if (sdl_game_surface == NULL && (sdl_game_surface=SDL_CreateRGBSurfaceWithFormat(0,640,480,8,SDL_PIXELFORMAT_INDEX8)) == NULL)
		IFEFatalError("SDL2 game surface (256-color) failed");
	if (sdl_game_palette == NULL && (sdl_game_palette=SDL_AllocPalette(256)) == NULL)
		IFEFatalError("SDL2 game palette");

	ifevidinfo_sdl2.buf_alloc = ifevidinfo_sdl2.buf_size = sdl_game_surface->pitch * sdl_game_surface->h;
	ifevidinfo_sdl2.buf_pitch = sdl_game_surface->pitch;

	/* first color should be black, SDL2 will init palette to white for some reason */
	memset(sdl_pal,0,sizeof(SDL_Color));
	if (SDL_SetPaletteColors(sdl_game_palette,sdl_pal,0,1) != 0)
		IFEFatalError("SDL2 game palette set colors");

	/* apply palette to surface */
	if (SDL_SetSurfacePalette(sdl_game_surface,sdl_game_palette) != 0)
		IFEFatalError("SDL2 game palette set");

	/* make sure screen is cleared black */
	SDL_FillRect(sdl_game_surface,NULL,0);
	ifeapi->UpdateFullScreen();
	ifeapi->CheckEvents();
}

void p_FlushKeyboardInput(void) {
	IFEKeyQueueEmptyAll();
}

IFEKeyEvent *p_GetRawKeyboardInput(void) {
	return IFEKeyQueue.get();
}

IFECookedKeyEvent *p_GetCookedKeyboardInput(void) {
	return IFECookedKeyQueue.get();
}

ifeapi_t ifeapi_sdl2 = {
	"SDL2",
	p_SetPaletteColors,
	p_GetTicks,
	p_ResetTicks,
	p_UpdateFullScreen,
	p_GetVidInfo,
	p_UserWantsToQuit,
	p_CheckEvents,
	p_WaitEvent,
	p_BeginScreenDraw,
	p_EndScreenDraw,
	p_ShutdownVideo,
	p_InitVideo,
	p_FlushKeyboardInput,
	p_GetRawKeyboardInput,
	p_GetCookedKeyboardInput
};

bool priv_IFEMainInit(int argc,char **argv) {
	struct stat st;

	//not used yet
	(void)argc;
	(void)argv;

	/* if STDERR is a valid handle to something, enable debug */
	if (fstat(2/*STDERR*/,&st) == 0) {
		fprintf(stderr,"Will emit debug info to stderr\n");
		ifedbg_en = true;
	}

	return true;
}
#endif

<commit_msg>SDL2 keyboard events<commit_after>
#if defined(USE_SDL2)
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>

#if defined(__APPLE__) /* Brew got the headers wrong here */
# include <SDL.h>
#else
# include <SDL2/SDL.h>
#endif

#include "ifict.h"
#include "utils.h"
#include "debug.h"
#include "fatal.h"
#include "palette.h"

SDL_Window*			sdl_window = NULL;
SDL_Surface*			sdl_window_surface = NULL;
SDL_Surface*			sdl_game_surface = NULL;
SDL_Palette*			sdl_game_palette = NULL;
SDL_Color			sdl_pal[256];
Uint32				sdl_ticks_base = 0; /* use Uint32 type provided by SDL2 here to avoid problems */
bool				sdl_signal_to_quit = false;
ifevidinfo_t			ifevidinfo_sdl2;

static void p_SetPaletteColors(const unsigned int first,const unsigned int count,IFEPaletteEntry *pal) {
	unsigned int i;

	priv_SetPaletteColorsRangeCheck(first,count);

	for (i=0;i < count;i++) {
		sdl_pal[i+first].r = pal[i].r;
		sdl_pal[i+first].g = pal[i].g;
		sdl_pal[i+first].b = pal[i].b;
		sdl_pal[i+first].a = 0xFFu;
	}

	if (SDL_SetPaletteColors(sdl_game_palette,sdl_pal,first,count) != 0)
		IFEFatalError("SDL2 game palette set colors");
}

static uint32_t p_GetTicks(void) {
	return uint32_t(SDL_GetTicks() - sdl_ticks_base);
}

static void p_ResetTicks(const uint32_t base) {
	sdl_ticks_base += base; /* NTS: Use return value of IFEGetTicks() */
}

static void p_UpdateFullScreen(void) {
	if (SDL_BlitSurface(sdl_game_surface,NULL,sdl_window_surface,NULL) != 0)
		IFEFatalError("Game to window BlitSurface");

	if (SDL_UpdateWindowSurface(sdl_window) != 0)
		IFEFatalError("Window surface update");
}

static ifevidinfo_t* p_GetVidInfo(void) {
	return &ifevidinfo_sdl2;
}

static bool p_UserWantsToQuit(void) {
	return sdl_signal_to_quit;
}

static uint32_t SDKKeySymToIFE(const SDL_Scancode k) {
#define MAP(x,y) \
	case x: return y;
#define MSN(x) \
	case SDL_SCANCODE_##x: return IFEKEY_##x;

	switch (k) {
		MSN(RETURN);
		MSN(ESCAPE);
		MSN(BACKSPACE);
		MSN(TAB);
		MSN(SPACE);
		default: break;
	}
#undef MSN
#undef MAP

	return uint32_t(0);
}

static void priv_ProcessKeyboardEvent(const SDL_KeyboardEvent &ev) {
	IFEKeyEvent ke;

	memset(&ke,0,sizeof(ke));
	ke.raw_code = (uint32_t)ev.keysym.scancode;
	ke.code = SDKKeySymToIFE(ev.keysym.scancode);
	ke.flags = (ev.state == SDL_PRESSED) ? IFEKeyEvent_FLAG_DOWN : 0;

	if (!IFEKeyQueue.add(ke))
		IFEDBG("ProcessKeyboardEvent: Queue full");
}

static void priv_ProcessEvent(const SDL_Event &ev) {
	switch (ev.type) {
		case SDL_QUIT:
			sdl_signal_to_quit = true;
			break;
		case SDL_KEYDOWN:
		case SDL_KEYUP:
			priv_ProcessKeyboardEvent(ev.key);
			break;
		default:
			break;
	}
}

static void p_CheckEvents(void) {
	SDL_Event ev;

	if (SDL_PollEvent(&ev))
		priv_ProcessEvent(ev);
}

static void p_WaitEvent(const int wait_ms) {
	SDL_Event ev;

	if (SDL_WaitEventTimeout(&ev,wait_ms))
		priv_ProcessEvent(ev);
}

static bool p_BeginScreenDraw(void) {
	if (SDL_MUSTLOCK(sdl_game_surface) && SDL_LockSurface(sdl_game_surface) != 0)
		return false;
	if (sdl_game_surface->pixels == NULL)
		IFEFatalError("SDL2 game surface pixels == NULL"); /* that's a BUG if this happens! */
	if (sdl_game_surface->pitch < 0)
		IFEFatalError("SDL2 game surface pitch is negative");

	ifevidinfo_sdl2.buf_base = ifevidinfo_sdl2.buf_first_row = (unsigned char*)(sdl_game_surface->pixels);
	return true;
}

static void p_EndScreenDraw(void) {
	if (SDL_MUSTLOCK(sdl_game_surface))
		SDL_UnlockSurface(sdl_game_surface);

	ifevidinfo_sdl2.buf_base = ifevidinfo_sdl2.buf_first_row = NULL;
}

static void p_ShutdownVideo(void) {
	if (sdl_game_surface != NULL) {
		SDL_FreeSurface(sdl_game_surface);
		sdl_game_surface = NULL;
	}
	if (sdl_game_palette != NULL) {
		SDL_FreePalette(sdl_game_palette);
		sdl_game_palette = NULL;
	}
	if (sdl_window != NULL) {
		SDL_DestroyWindow(sdl_window);
		sdl_window_surface = NULL;
		sdl_window = NULL;
	}
	SDL_Quit();
}

static void p_InitVideo(void) {
	if (SDL_Init(SDL_INIT_VIDEO) < 0)
		IFEFatalError("SDL2 failed to initialize");

	memset(&ifevidinfo_sdl2,0,sizeof(ifevidinfo_sdl2));

	ifevidinfo_sdl2.width = 640;
	ifevidinfo_sdl2.height = 480;

	if (sdl_window == NULL && (sdl_window=SDL_CreateWindow("",SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,640,480,SDL_WINDOW_SHOWN)) == NULL)
		IFEFatalError("SDL2 window creation failed");
	if (sdl_window_surface == NULL && (sdl_window_surface=SDL_GetWindowSurface(sdl_window)) == NULL)
		IFEFatalError("SDL2 window surface failed");
	if (sdl_game_surface == NULL && (sdl_game_surface=SDL_CreateRGBSurfaceWithFormat(0,640,480,8,SDL_PIXELFORMAT_INDEX8)) == NULL)
		IFEFatalError("SDL2 game surface (256-color) failed");
	if (sdl_game_palette == NULL && (sdl_game_palette=SDL_AllocPalette(256)) == NULL)
		IFEFatalError("SDL2 game palette");

	ifevidinfo_sdl2.buf_alloc = ifevidinfo_sdl2.buf_size = sdl_game_surface->pitch * sdl_game_surface->h;
	ifevidinfo_sdl2.buf_pitch = sdl_game_surface->pitch;

	/* first color should be black, SDL2 will init palette to white for some reason */
	memset(sdl_pal,0,sizeof(SDL_Color));
	if (SDL_SetPaletteColors(sdl_game_palette,sdl_pal,0,1) != 0)
		IFEFatalError("SDL2 game palette set colors");

	/* apply palette to surface */
	if (SDL_SetSurfacePalette(sdl_game_surface,sdl_game_palette) != 0)
		IFEFatalError("SDL2 game palette set");

	/* make sure screen is cleared black */
	SDL_FillRect(sdl_game_surface,NULL,0);
	ifeapi->UpdateFullScreen();
	ifeapi->CheckEvents();
}

void p_FlushKeyboardInput(void) {
	IFEKeyQueueEmptyAll();
}

IFEKeyEvent *p_GetRawKeyboardInput(void) {
	return IFEKeyQueue.get();
}

IFECookedKeyEvent *p_GetCookedKeyboardInput(void) {
	return IFECookedKeyQueue.get();
}

ifeapi_t ifeapi_sdl2 = {
	"SDL2",
	p_SetPaletteColors,
	p_GetTicks,
	p_ResetTicks,
	p_UpdateFullScreen,
	p_GetVidInfo,
	p_UserWantsToQuit,
	p_CheckEvents,
	p_WaitEvent,
	p_BeginScreenDraw,
	p_EndScreenDraw,
	p_ShutdownVideo,
	p_InitVideo,
	p_FlushKeyboardInput,
	p_GetRawKeyboardInput,
	p_GetCookedKeyboardInput
};

bool priv_IFEMainInit(int argc,char **argv) {
	struct stat st;

	//not used yet
	(void)argc;
	(void)argv;

	/* if STDERR is a valid handle to something, enable debug */
	if (fstat(2/*STDERR*/,&st) == 0) {
		fprintf(stderr,"Will emit debug info to stderr\n");
		ifedbg_en = true;
	}

	return true;
}
#endif

<|endoftext|>


<commit_before>/*$Id$
 *
 * This source file is a part of the Berlin Project.
 * Copyright (C) 1999 Stefan Seefeld <seefelds@magellan.umontreal.ca>
 * http://www.berlin-consortium.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
 * MA 02139, USA.
 */
#ifndef _File_hh
#define _File_hh

#include <string>
#include <climits>
#include <sys/stat.h>
#include <sys/types.h>
#include <cerrno>
#include <cstdio>

namespace Prague
{

/* @Class{File}
 *
 * @Description{}
 */
class File
{
public:
  enum type_t { none = 0,
		link = S_IFLNK,
		reg  = S_IFREG,
		dir  = S_IFDIR,
		chr  = S_IFCHR,
		blk  = S_IFBLK,
		fifo = S_IFIFO,
		sock = S_IFSOCK};
  enum access_t { ur = S_IRUSR,
		  uw = S_IWUSR,
		  ux = S_IXUSR,
		  gr = S_IRGRP,
		  gw = S_IWGRP,
		  gx = S_IXGRP,
		  or = S_IROTH,
		  ow = S_IWOTH,
		  ox = S_IXOTH,
		  all= ur|uw|ux|gr|gw|gx|or|ow|ox};
  File(const string &);
  File(const File &);
  virtual ~File();
  File &operator = (const File &);
  File &operator = (const string &);
  File parent() const;
  const string &name() const { return shortname;}
  const string &longName() const { return longname;}
  bool is(type_t t) const { return (status.st_mode & S_IFMT) == (mode_t) t;}
  long type() const { return (status.st_mode & S_IFMT);}
  long access() const { return (status.st_mode & (ur|uw|ux));}
  uid_t uid() const { return status.st_uid;}
  gid_t gid() const { return status.st_gid;}
  long  size() const { return  status.st_size;}
  time_t accTime() const { return status.st_atime;}
  time_t modTime() const { return status.st_mtime;}
  time_t chTime() const { return status.st_ctime;}

  bool chmod(access_t);
  bool mv(const string &);
  bool rm();
  static string base(const string &);
  static string tmp() { return ::tmpnam(0);}
protected:
  struct stat status;
  string longname;
  string shortname;
  bool getStatus();
  const char *lastError() const;
  int error;
private:
};

inline string File::base(const string &s)
{
  string::size_type p = s.find_last_of('/');
  return p == string::npos ? s : s.substr(p + 1);
}

inline bool File::getStatus()
{
  if (stat(longname.c_str(), &status) == -1) { status.st_mode = 0; error = errno; return false;} return true;
}

};

#endif /* _File_hh */
<commit_msg>avoid 'or' keyword<commit_after>/*$Id$
 *
 * This source file is a part of the Berlin Project.
 * Copyright (C) 1999 Stefan Seefeld <stefan@berlin-consortium.org>
 * http://www.berlin-consortium.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
 * MA 02139, USA.
 */
#ifndef _File_hh
#define _File_hh

#include <string>
#include <climits>
#include <sys/stat.h>
#include <sys/types.h>
#include <cerrno>
#include <cstdio>

namespace Prague
{

/* @Class{File}
 *
 * @Description{}
 */
class File
{
public:
  enum type_t { none = 0,
		link = S_IFLNK,
		reg  = S_IFREG,
		dir  = S_IFDIR,
		chr  = S_IFCHR,
		blk  = S_IFBLK,
		fifo = S_IFIFO,
		sock = S_IFSOCK};
  enum access_t { ru = S_IRUSR,
		  wu = S_IWUSR,
		  xu = S_IXUSR,
		  rg = S_IRGRP,
		  wg = S_IWGRP,
		  xg = S_IXGRP,
		  ro = S_IROTH,
		  wo = S_IWOTH,
		  xo = S_IXOTH,
		  all= ru|wu|xu|rg|wg|xg|ro|wo|xo};
  File(const string &);
  File(const File &);
  virtual ~File();
  File &operator = (const File &);
  File &operator = (const string &);
  File parent() const;
  const string &name() const { return shortname;}
  const string &longName() const { return longname;}
  bool is(type_t t) const { return (status.st_mode & S_IFMT) == (mode_t) t;}
  long type() const { return (status.st_mode & S_IFMT);}
  long access() const { return (status.st_mode & (ru|wu|xu));}
  uid_t uid() const { return status.st_uid;}
  gid_t gid() const { return status.st_gid;}
  long  size() const { return  status.st_size;}
  time_t accTime() const { return status.st_atime;}
  time_t modTime() const { return status.st_mtime;}
  time_t chTime() const { return status.st_ctime;}

  bool chmod(access_t);
  bool mv(const string &);
  bool rm();
  static string base(const string &);
  static string tmp() { return ::tmpnam(0);}
protected:
  struct stat status;
  string longname;
  string shortname;
  bool getStatus();
  const char *lastError() const;
  int error;
private:
};

inline string File::base(const string &s)
{
  string::size_type p = s.find_last_of('/');
  return p == string::npos ? s : s.substr(p + 1);
}

inline bool File::getStatus()
{
  if (stat(longname.c_str(), &status) == -1) { status.st_mode = 0; error = errno; return false;} return true;
}

};

#endif /* _File_hh */
<|endoftext|>


<commit_before>/*
 * Worldvisions Weaver Software:
 *   Copyright (C) 1997-2002 Net Integration Technologies, Inc.
 *
 * This is the WvTFTP server daemon.
 */
#include "wvtftpserver.h"
#include "wvlogrcv.h"
#include "wvver.h"
#include <signal.h>

static bool want_to_die = false;

void sighandler_die(int signum)
{
    want_to_die = true;
}

static void usage(char *argv0)
{
    fprintf(stderr,
            "Usage: %s [-d] [-dd]\n"
            "     -d   Print debug messages\n"
            "     -dd  Print lots of debug messages\n"
            "     -V   Print version and exit\n",
            argv0);
    exit(1);
}

int main(int argc, char **argv)
{
    WvLog::LogLevel lvl = WvLog::Debug1;
    int c;
    signal(SIGTERM, sighandler_die);
    signal(SIGHUP, sighandler_die);
    signal(SIGINT, sighandler_die);
    while ((c = getopt(argc, argv, "dV?")) >= 0)
    {
        switch(c)
        {
        case 'd':
            if (lvl <= WvLog::Debug1)
                lvl = WvLog::Debug4;
            else
                lvl = WvLog::Debug5;
            break;
        case 'V':
            fprintf(stderr, "WvTFTPd version %s\n",WVTFTP_VER_STRING);
            exit(2);
        case '?':
            usage(argv[0]);
            break;
        }
    }

    WvConf cfg("/etc/wvtftpd.conf");
    WvTFTPServer tftps(cfg, 100);
    WvLogConsole logdisp(2, lvl);

    while (tftps.isok() && !want_to_die)
    {
	if (tftps.select(1000))
	    tftps.callback();
	else
	    cfg.flush();
    }
    cfg.save();
}
<commit_msg>WvTFTPd now gives a useful error message when it exits.<commit_after>/*
 * Worldvisions Weaver Software:
 *   Copyright (C) 1997-2002 Net Integration Technologies, Inc.
 *
 * This is the WvTFTP server daemon.
 */
#include "wvtftpserver.h"
#include "wvlogrcv.h"
#include "wvver.h"
#include <signal.h>
#include <errno.h>

static bool want_to_die = false;

void sighandler_die(int signum)
{
    want_to_die = true;
}

static void usage(char *argv0)
{
    fprintf(stderr,
            "Usage: %s [-d] [-dd]\n"
            "     -d   Print debug messages\n"
            "     -dd  Print lots of debug messages\n"
            "     -V   Print version and exit\n",
            argv0);
    exit(1);
}

int main(int argc, char **argv)
{
    WvLog::LogLevel lvl = WvLog::Debug1;
    int c;
    signal(SIGTERM, sighandler_die);
    signal(SIGHUP, sighandler_die);
    signal(SIGINT, sighandler_die);
    while ((c = getopt(argc, argv, "dV?")) >= 0)
    {
        switch(c)
        {
        case 'd':
            if (lvl <= WvLog::Debug1)
                lvl = WvLog::Debug4;
            else
                lvl = WvLog::Debug5;
            break;
        case 'V':
            fprintf(stderr, "WvTFTPd version %s\n",WVTFTP_VER_STRING);
            exit(2);
        case '?':
            usage(argv[0]);
            break;
        }
    }

    WvLog log("WvTFTP", WvLog::Critical);
    WvConf cfg("/etc/wvtftpd.conf");
    WvTFTPServer tftps(cfg, 100);
    WvLogConsole logdisp(2, lvl);

    while (tftps.isok() && !want_to_die)
    {
	if (tftps.select(1000))
	    tftps.callback();
	else
	    cfg.flush();
    }
    if (!tftps.isok() && tftps.geterr())
        log("%s.\n", strerror(tftps.geterr()));
    cfg.save();
}
<|endoftext|>


<commit_before>// sound.cxx -- Sound class implementation
//
// Started by Erik Hofman, February 2002
// (Reuses some code from  fg_fx.cxx created by David Megginson)
//
// Copyright (C) 2002  Curtis L. Olson - http://www.flightgear.org/~curt
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// $Id$

#include <simgear/compiler.h>

#ifdef SG_HAVE_STD_INCLUDES
#  include <cmath>
#else
#  include <math.h>
#endif
#include <string.h>

#include <simgear/debug/logstream.hxx>
#include <simgear/props/condition.hxx>
#include <simgear/math/fastmath.hxx>

#include "xmlsound.hxx"

// static double _snd_lin(double v)   { return v; }
static double _snd_inv(double v)   { return (v == 0) ? 1e99 : 1/v; }
static double _snd_abs(double v)   { return (v >= 0) ? v : -v; }
static double _snd_sqrt(double v)  { return (v < 0) ? sqrt(-v) : sqrt(v); }
static double _snd_log10(double v) { return (v < 1) ? 0 : fast_log10(v); }
static double _snd_log(double v)   { return (v < 1) ? 0 : fast_log(v); }
// static double _snd_sqr(double v)   { return v*v; }
// static double _snd_pow3(double v)  { return v*v*v; }

static const struct {
	char *name;
	double (*fn)(double);
} __sound_fn[] = {
//	{"lin", _snd_lin},
	{"inv", _snd_inv},
	{"abs", _snd_abs},
	{"sqrt", _snd_sqrt},
	{"log", _snd_log10},
	{"ln", _snd_log},
//	{"sqr", _snd_sqr},
//	{"pow3", _snd_pow3},
	{"", NULL}
};

SGXmlSound::SGXmlSound()
  : _sample(NULL),
    _condition(NULL),
    _active(false),
    _name(""),
    _mode(SGXmlSound::ONCE),
    _prev_value(0),
    _dt_play(0.0),
    _dt_stop(0.0),
    _stopping(0.0)
{
}

SGXmlSound::~SGXmlSound()
{
    _sample->stop();

    delete _condition;

    _volume.clear();
    _pitch.clear();
}

void
SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node, SGSoundMgr *sndmgr,
                 const string &path)
{

   //
   // set global sound properties
   //

   _name = node->getStringValue("name", "");
   SG_LOG(SG_GENERAL, SG_INFO, "Loading sound information for: " << _name );

   const char *mode_str = node->getStringValue("mode", "");
   if ( !strcmp(mode_str, "looped") ) {
       _mode = SGXmlSound::LOOPED;

   } else if ( !strcmp(mode_str, "in-transit") ) {
       _mode = SGXmlSound::IN_TRANSIT;

   } else {
      _mode = SGXmlSound::ONCE;

      if ( strcmp(mode_str, "") )
         SG_LOG(SG_GENERAL,SG_INFO, "  Unknown sound mode, default to 'once'");
   }

   _property = root->getNode(node->getStringValue("property", ""), true);
   SGPropertyNode *condition = node->getChild("condition");
   if (condition != NULL)
      _condition = sgReadCondition(root, condition);

   if (!_property && !_condition)
      SG_LOG(SG_GENERAL, SG_WARN,
             "  Neither a condition nor a property specified");

   //
   // set volume properties
   //
   unsigned int i;
   float v = 0.0;
   vector<SGPropertyNode_ptr> kids = node->getChildren("volume");
   for (i = 0; (i < kids.size()) && (i < SGXmlSound::MAXPROP); i++) {
      _snd_prop volume = {NULL, NULL, NULL, 1.0, 0.0, 0.0, 0.0, false};

      if (strcmp(kids[i]->getStringValue("property"), ""))
         volume.prop = root->getNode(kids[i]->getStringValue("property", ""), true);

      const char *intern_str = kids[i]->getStringValue("internal", "");
      if (!strcmp(intern_str, "dt_play"))
         volume.intern = &_dt_play;
      else if (!strcmp(intern_str, "dt_stop"))
         volume.intern = &_dt_stop;

      if ((volume.factor = kids[i]->getDoubleValue("factor", 1.0)) != 0.0)
         if (volume.factor < 0.0) {
            volume.factor = -volume.factor;
            volume.subtract = true;
         }

      const char *type_str = kids[i]->getStringValue("type", "");
      if ( strcmp(type_str, "") ) {

         for (int j=0; __sound_fn[j].fn; j++)
           if ( !strcmp(type_str, __sound_fn[j].name) ) {
               volume.fn = __sound_fn[j].fn;
               break;
            }

         if (!volume.fn)
            SG_LOG(SG_GENERAL,SG_INFO,
                   "  Unknown volume type, default to 'lin'");
      }

      volume.offset = kids[i]->getDoubleValue("offset", 0.0);

      if ((volume.min = kids[i]->getDoubleValue("min", 0.0)) < 0.0)
         SG_LOG( SG_GENERAL, SG_WARN,
          "Volume minimum value below 0. Forced to 0.");

      volume.max = kids[i]->getDoubleValue("max", 0.0);
      if (volume.max && (volume.max < volume.min) )
         SG_LOG(SG_GENERAL,SG_ALERT,
                "  Volume maximum below minimum. Neglected.");

      _volume.push_back(volume);
      v += volume.offset;

   }

   float reference_dist = node->getDoubleValue("reference-dist", 500.0);
   float max_dist = node->getDoubleValue("max-dist", 3000.0);

   //
   // set pitch properties
   //
   float p = 0.0;
   kids = node->getChildren("pitch");
   for (i = 0; (i < kids.size()) && (i < SGXmlSound::MAXPROP); i++) {
      _snd_prop pitch = {NULL, NULL, NULL, 1.0, 1.0, 0.0, 0.0, false};

      if (strcmp(kids[i]->getStringValue("property", ""), ""))
         pitch.prop = root->getNode(kids[i]->getStringValue("property", ""), true);

      const char *intern_str = kids[i]->getStringValue("internal", "");
      if (!strcmp(intern_str, "dt_play"))
         pitch.intern = &_dt_play;
      else if (!strcmp(intern_str, "dt_stop"))
         pitch.intern = &_dt_stop;

      if ((pitch.factor = kids[i]->getDoubleValue("factor", 1.0)) != 0.0)
         if (pitch.factor < 0.0) {
            pitch.factor = -pitch.factor;
            pitch.subtract = true;
         }

      const char *type_str = kids[i]->getStringValue("type", "");
      if ( strcmp(type_str, "") ) {

         for (int j=0; __sound_fn[j].fn; j++)
            if ( !strcmp(type_str, __sound_fn[j].name) ) {
               pitch.fn = __sound_fn[j].fn;
               break;
            }

         if (!pitch.fn)
            SG_LOG(SG_GENERAL,SG_INFO,
                   "  Unknown pitch type, default to 'lin'");
      }

      pitch.offset = kids[i]->getDoubleValue("offset", 1.0);

      if ((pitch.min = kids[i]->getDoubleValue("min", 0.0)) < 0.0)
         SG_LOG(SG_GENERAL,SG_WARN,
                "  Pitch minimum value below 0. Forced to 0.");

      pitch.max = kids[i]->getDoubleValue("max", 0.0);
      if (pitch.max && (pitch.max < pitch.min) )
         SG_LOG(SG_GENERAL,SG_ALERT,
                "  Pitch maximum below minimum. Neglected");

      _pitch.push_back(pitch);
      p += pitch.offset;
   }

   //
   // Relative position
   //
   sgVec3 offset_pos;
   sgSetVec3( offset_pos, 0.0, 0.0, 0.0 );
   SGPropertyNode_ptr pos = node->getChild("position");
   if ( pos != NULL ) {
       offset_pos[0] = pos->getDoubleValue("x", 0.0);
       offset_pos[1] = pos->getDoubleValue("y", 0.0);
       offset_pos[2] = pos->getDoubleValue("z", 0.0);
   }

   //
   // Orientation
   //
   sgVec3 dir;
   float inner, outer, outer_gain;
   sgSetVec3( dir, 0.0, 0.0, 0.0 );
   inner = outer = 360.0;
   outer_gain = 0.0;
   pos = node->getChild("orientation");
   if ( pos != NULL ) {
      dir[0] = pos->getDoubleValue("x", 0.0);
      dir[1] = pos->getDoubleValue("y", 0.0);
      dir[2] = pos->getDoubleValue("z", 0.0);
      inner = pos->getDoubleValue("inner-angle", 360.0);
      outer = pos->getDoubleValue("outer-angle", 360.0);
      outer_gain = pos->getDoubleValue("outer-gain", 0.0);
   }

   //
   // Initialize the sample
   //
   _mgr = sndmgr;
   if ( (_sample = _mgr->find(_name)) == NULL ) {
       // FIXME: Does it make sense to overwrite a previous entry's
       // configuration just because a new entry has the same name?
       // Note that we can't match on identical "path" because we the
       // new entry could be at a different location with different
       // configuration so we need a new sample which creates a new
       // "alSource".  The semantics of what is going on here seems
       // confused and needs to be thought through more carefully.
        _sample = new SGSoundSample( path.c_str(),
                                    node->getStringValue("path", "") );

       _mgr->add( _sample, _name );
   }

   _sample->set_offset_pos( offset_pos );
   _sample->set_orientation(dir, inner, outer, outer_gain);
   _sample->set_volume(v);
   _sample->set_reference_dist( reference_dist );
   _sample->set_max_dist( max_dist );
   _sample->set_pitch(p);
}

void
SGXmlSound::update (double dt)
{
   double curr_value = 0.0;

   //
   // If the state changes to false, stop playing.
   //
   if (_property)
       curr_value = _property->getDoubleValue();

   if (							// Lisp, anyone?
       (_condition && !_condition->test()) ||
       (!_condition && _property &&
        (
         !curr_value ||
         ( (_mode == SGXmlSound::IN_TRANSIT) && (curr_value == _prev_value) )
         )
        )
       )
   {
       if ((_mode != SGXmlSound::IN_TRANSIT) || (_stopping > MAX_TRANSIT_TIME)) {
           if (_sample->is_playing()) {
               SG_LOG(SG_GENERAL, SG_INFO, "Stopping audio after " << _dt_play
                      << " sec: " << _name );

               _sample->stop();
           }

           _active = false;
           _dt_stop += dt;
           _dt_play = 0.0;
       } else {
           _stopping += dt;
       }

       return;
   }

   //
   // If the mode is ONCE and the sound is still playing,
   //  we have nothing to do anymore.
   //
   if (_active && (_mode == SGXmlSound::ONCE)) {

      if (!_sample->is_playing()) {
         _dt_stop += dt;
         _dt_play = 0.0;
      } else {
         _dt_play += dt;
      }

      return;
   }

   //
   // Update the playing time, cache the current value and
   // clear the delay timer.
   //
   _dt_play += dt;
   _prev_value = curr_value;
   _stopping = 0.0;

   //
   // Update the volume
   //
   int i;
   int max = _volume.size();
   double volume = 1.0;
   double volume_offset = 0.0;

   for(i = 0; i < max; i++) {
      double v = 1.0;

      if (_volume[i].prop)
         v = _volume[i].prop->getDoubleValue();

      else if (_volume[i].intern)
         v = *_volume[i].intern;

      if (_volume[i].fn)
         v = _volume[i].fn(v);

      v *= _volume[i].factor;

      if (_volume[i].max && (v > _volume[i].max))
         v = _volume[i].max;

      else if (v < _volume[i].min)
         v = _volume[i].min;

      if (_volume[i].subtract)				// Hack!
         volume = _volume[i].offset - v;

      else {
         volume_offset += _volume[i].offset;
         volume *= v;
      }
   }

   //
   // Update the pitch
   //
   max = _pitch.size();
   double pitch = 1.0;
   double pitch_offset = 0.0;

   for(i = 0; i < max; i++) {
      double p = 1.0;

      if (_pitch[i].prop)
         p = _pitch[i].prop->getDoubleValue();

      else if (_pitch[i].intern)
         p = *_pitch[i].intern;

      if (_pitch[i].fn)
         p = _pitch[i].fn(p);

      p *= _pitch[i].factor;

      if (_pitch[i].max && (p > _pitch[i].max))
         p = _pitch[i].max;

      else if (p < _pitch[i].min)
         p = _pitch[i].min;

      if (_pitch[i].subtract)				// Hack!
         pitch = _pitch[i].offset - p;

      else {
         pitch_offset += _pitch[i].offset;
         pitch *= p;
      }
   }

   //
   // Change sample state
   //
   _sample->set_pitch( pitch_offset + pitch );
   if ((volume_offset + volume ) > 1.0)
   {
      _sample->set_volume( 1.0 );
      SG_LOG(SG_GENERAL, SG_WARN,
             "Volume larger than 1.0 in configuration for '" << _name
              << "', clipping.");
   } else
      _sample->set_volume( volume_offset + volume );

   //
   // Do we need to start playing the sample?
   //
   if (!_active) {

      if (_mode == SGXmlSound::ONCE)
         _sample->play(false);

      else
         _sample->play(true);

      SG_LOG(SG_GENERAL, SG_INFO, "Playing audio after " << _dt_stop
                                   << " sec: " << _name);
      SG_LOG(SG_GENERAL, SG_BULK,
                         "Playing " << ((_mode == ONCE) ? "once" : "looped"));

      _active = true;
      _dt_stop = 0.0;
   }
}
<commit_msg>create an absolute value before calling log or log10, this adds support for sound on negative numbers (thrust reverse for example).<commit_after>// sound.cxx -- Sound class implementation
//
// Started by Erik Hofman, February 2002
// (Reuses some code from  fg_fx.cxx created by David Megginson)
//
// Copyright (C) 2002  Curtis L. Olson - http://www.flightgear.org/~curt
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// $Id$

#include <simgear/compiler.h>

#ifdef SG_HAVE_STD_INCLUDES
#  include <cmath>
#else
#  include <math.h>
#endif
#include <string.h>

#include <simgear/debug/logstream.hxx>
#include <simgear/props/condition.hxx>
#include <simgear/math/fastmath.hxx>

#include "xmlsound.hxx"

#define LOG_ABS(x) (((x) > 1) ? (x) : (((x) < -1) ? -(x) : 0))
// static double _snd_lin(double v)   { return v; }
static double _snd_inv(double v)   { return (v == 0) ? 1e99 : 1/v; }
static double _snd_abs(double v)   { return (v >= 0) ? v : -v; }
static double _snd_sqrt(double v)  { return (v < 0) ? sqrt(-v) : sqrt(v); }
static double _snd_log10(double v) { return fast_log10( LOG_ABS(v) ); }
static double _snd_log(double v)   { return fast_log( LOG_ABS(v) ); }
// static double _snd_sqr(double v)   { return v*v; }
// static double _snd_pow3(double v)  { return v*v*v; }

static const struct {
	char *name;
	double (*fn)(double);
} __sound_fn[] = {
//	{"lin", _snd_lin},
	{"inv", _snd_inv},
	{"abs", _snd_abs},
	{"sqrt", _snd_sqrt},
	{"log", _snd_log10},
	{"ln", _snd_log},
//	{"sqr", _snd_sqr},
//	{"pow3", _snd_pow3},
	{"", NULL}
};

SGXmlSound::SGXmlSound()
  : _sample(NULL),
    _condition(NULL),
    _active(false),
    _name(""),
    _mode(SGXmlSound::ONCE),
    _prev_value(0),
    _dt_play(0.0),
    _dt_stop(0.0),
    _stopping(0.0)
{
}

SGXmlSound::~SGXmlSound()
{
    _sample->stop();

    delete _condition;

    _volume.clear();
    _pitch.clear();
}

void
SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node, SGSoundMgr *sndmgr,
                 const string &path)
{

   //
   // set global sound properties
   //

   _name = node->getStringValue("name", "");
   SG_LOG(SG_GENERAL, SG_INFO, "Loading sound information for: " << _name );

   const char *mode_str = node->getStringValue("mode", "");
   if ( !strcmp(mode_str, "looped") ) {
       _mode = SGXmlSound::LOOPED;

   } else if ( !strcmp(mode_str, "in-transit") ) {
       _mode = SGXmlSound::IN_TRANSIT;

   } else {
      _mode = SGXmlSound::ONCE;

      if ( strcmp(mode_str, "") )
         SG_LOG(SG_GENERAL,SG_INFO, "  Unknown sound mode, default to 'once'");
   }

   _property = root->getNode(node->getStringValue("property", ""), true);
   SGPropertyNode *condition = node->getChild("condition");
   if (condition != NULL)
      _condition = sgReadCondition(root, condition);

   if (!_property && !_condition)
      SG_LOG(SG_GENERAL, SG_WARN,
             "  Neither a condition nor a property specified");

   //
   // set volume properties
   //
   unsigned int i;
   float v = 0.0;
   vector<SGPropertyNode_ptr> kids = node->getChildren("volume");
   for (i = 0; (i < kids.size()) && (i < SGXmlSound::MAXPROP); i++) {
      _snd_prop volume = {NULL, NULL, NULL, 1.0, 0.0, 0.0, 0.0, false};

      if (strcmp(kids[i]->getStringValue("property"), ""))
         volume.prop = root->getNode(kids[i]->getStringValue("property", ""), true);

      const char *intern_str = kids[i]->getStringValue("internal", "");
      if (!strcmp(intern_str, "dt_play"))
         volume.intern = &_dt_play;
      else if (!strcmp(intern_str, "dt_stop"))
         volume.intern = &_dt_stop;

      if ((volume.factor = kids[i]->getDoubleValue("factor", 1.0)) != 0.0)
         if (volume.factor < 0.0) {
            volume.factor = -volume.factor;
            volume.subtract = true;
         }

      const char *type_str = kids[i]->getStringValue("type", "");
      if ( strcmp(type_str, "") ) {

         for (int j=0; __sound_fn[j].fn; j++)
           if ( !strcmp(type_str, __sound_fn[j].name) ) {
               volume.fn = __sound_fn[j].fn;
               break;
            }

         if (!volume.fn)
            SG_LOG(SG_GENERAL,SG_INFO,
                   "  Unknown volume type, default to 'lin'");
      }

      volume.offset = kids[i]->getDoubleValue("offset", 0.0);

      if ((volume.min = kids[i]->getDoubleValue("min", 0.0)) < 0.0)
         SG_LOG( SG_GENERAL, SG_WARN,
          "Volume minimum value below 0. Forced to 0.");

      volume.max = kids[i]->getDoubleValue("max", 0.0);
      if (volume.max && (volume.max < volume.min) )
         SG_LOG(SG_GENERAL,SG_ALERT,
                "  Volume maximum below minimum. Neglected.");

      _volume.push_back(volume);
      v += volume.offset;

   }

   float reference_dist = node->getDoubleValue("reference-dist", 500.0);
   float max_dist = node->getDoubleValue("max-dist", 3000.0);

   //
   // set pitch properties
   //
   float p = 0.0;
   kids = node->getChildren("pitch");
   for (i = 0; (i < kids.size()) && (i < SGXmlSound::MAXPROP); i++) {
      _snd_prop pitch = {NULL, NULL, NULL, 1.0, 1.0, 0.0, 0.0, false};

      if (strcmp(kids[i]->getStringValue("property", ""), ""))
         pitch.prop = root->getNode(kids[i]->getStringValue("property", ""), true);

      const char *intern_str = kids[i]->getStringValue("internal", "");
      if (!strcmp(intern_str, "dt_play"))
         pitch.intern = &_dt_play;
      else if (!strcmp(intern_str, "dt_stop"))
         pitch.intern = &_dt_stop;

      if ((pitch.factor = kids[i]->getDoubleValue("factor", 1.0)) != 0.0)
         if (pitch.factor < 0.0) {
            pitch.factor = -pitch.factor;
            pitch.subtract = true;
         }

      const char *type_str = kids[i]->getStringValue("type", "");
      if ( strcmp(type_str, "") ) {

         for (int j=0; __sound_fn[j].fn; j++)
            if ( !strcmp(type_str, __sound_fn[j].name) ) {
               pitch.fn = __sound_fn[j].fn;
               break;
            }

         if (!pitch.fn)
            SG_LOG(SG_GENERAL,SG_INFO,
                   "  Unknown pitch type, default to 'lin'");
      }

      pitch.offset = kids[i]->getDoubleValue("offset", 1.0);

      if ((pitch.min = kids[i]->getDoubleValue("min", 0.0)) < 0.0)
         SG_LOG(SG_GENERAL,SG_WARN,
                "  Pitch minimum value below 0. Forced to 0.");

      pitch.max = kids[i]->getDoubleValue("max", 0.0);
      if (pitch.max && (pitch.max < pitch.min) )
         SG_LOG(SG_GENERAL,SG_ALERT,
                "  Pitch maximum below minimum. Neglected");

      _pitch.push_back(pitch);
      p += pitch.offset;
   }

   //
   // Relative position
   //
   sgVec3 offset_pos;
   sgSetVec3( offset_pos, 0.0, 0.0, 0.0 );
   SGPropertyNode_ptr pos = node->getChild("position");
   if ( pos != NULL ) {
       offset_pos[0] = pos->getDoubleValue("x", 0.0);
       offset_pos[1] = pos->getDoubleValue("y", 0.0);
       offset_pos[2] = pos->getDoubleValue("z", 0.0);
   }

   //
   // Orientation
   //
   sgVec3 dir;
   float inner, outer, outer_gain;
   sgSetVec3( dir, 0.0, 0.0, 0.0 );
   inner = outer = 360.0;
   outer_gain = 0.0;
   pos = node->getChild("orientation");
   if ( pos != NULL ) {
      dir[0] = pos->getDoubleValue("x", 0.0);
      dir[1] = pos->getDoubleValue("y", 0.0);
      dir[2] = pos->getDoubleValue("z", 0.0);
      inner = pos->getDoubleValue("inner-angle", 360.0);
      outer = pos->getDoubleValue("outer-angle", 360.0);
      outer_gain = pos->getDoubleValue("outer-gain", 0.0);
   }

   //
   // Initialize the sample
   //
   _mgr = sndmgr;
   if ( (_sample = _mgr->find(_name)) == NULL ) {
       // FIXME: Does it make sense to overwrite a previous entry's
       // configuration just because a new entry has the same name?
       // Note that we can't match on identical "path" because we the
       // new entry could be at a different location with different
       // configuration so we need a new sample which creates a new
       // "alSource".  The semantics of what is going on here seems
       // confused and needs to be thought through more carefully.
        _sample = new SGSoundSample( path.c_str(),
                                    node->getStringValue("path", "") );

       _mgr->add( _sample, _name );
   }

   _sample->set_offset_pos( offset_pos );
   _sample->set_orientation(dir, inner, outer, outer_gain);
   _sample->set_volume(v);
   _sample->set_reference_dist( reference_dist );
   _sample->set_max_dist( max_dist );
   _sample->set_pitch(p);
}

void
SGXmlSound::update (double dt)
{
   double curr_value = 0.0;

   //
   // If the state changes to false, stop playing.
   //
   if (_property)
       curr_value = _property->getDoubleValue();

   if (							// Lisp, anyone?
       (_condition && !_condition->test()) ||
       (!_condition && _property &&
        (
         !curr_value ||
         ( (_mode == SGXmlSound::IN_TRANSIT) && (curr_value == _prev_value) )
         )
        )
       )
   {
       if ((_mode != SGXmlSound::IN_TRANSIT) || (_stopping > MAX_TRANSIT_TIME)) {
           if (_sample->is_playing()) {
               SG_LOG(SG_GENERAL, SG_INFO, "Stopping audio after " << _dt_play
                      << " sec: " << _name );

               _sample->stop();
           }

           _active = false;
           _dt_stop += dt;
           _dt_play = 0.0;
       } else {
           _stopping += dt;
       }

       return;
   }

   //
   // If the mode is ONCE and the sound is still playing,
   //  we have nothing to do anymore.
   //
   if (_active && (_mode == SGXmlSound::ONCE)) {

      if (!_sample->is_playing()) {
         _dt_stop += dt;
         _dt_play = 0.0;
      } else {
         _dt_play += dt;
      }

      return;
   }

   //
   // Update the playing time, cache the current value and
   // clear the delay timer.
   //
   _dt_play += dt;
   _prev_value = curr_value;
   _stopping = 0.0;

   //
   // Update the volume
   //
   int i;
   int max = _volume.size();
   double volume = 1.0;
   double volume_offset = 0.0;

   for(i = 0; i < max; i++) {
      double v = 1.0;

      if (_volume[i].prop)
         v = _volume[i].prop->getDoubleValue();

      else if (_volume[i].intern)
         v = *_volume[i].intern;

      if (_volume[i].fn)
         v = _volume[i].fn(v);

      v *= _volume[i].factor;

      if (_volume[i].max && (v > _volume[i].max))
         v = _volume[i].max;

      else if (v < _volume[i].min)
         v = _volume[i].min;

      if (_volume[i].subtract)				// Hack!
         volume = _volume[i].offset - v;

      else {
         volume_offset += _volume[i].offset;
         volume *= v;
      }
   }

   //
   // Update the pitch
   //
   max = _pitch.size();
   double pitch = 1.0;
   double pitch_offset = 0.0;

   for(i = 0; i < max; i++) {
      double p = 1.0;

      if (_pitch[i].prop)
         p = _pitch[i].prop->getDoubleValue();

      else if (_pitch[i].intern)
         p = *_pitch[i].intern;

      if (_pitch[i].fn)
         p = _pitch[i].fn(p);

      p *= _pitch[i].factor;

      if (_pitch[i].max && (p > _pitch[i].max))
         p = _pitch[i].max;

      else if (p < _pitch[i].min)
         p = _pitch[i].min;

      if (_pitch[i].subtract)				// Hack!
         pitch = _pitch[i].offset - p;

      else {
         pitch_offset += _pitch[i].offset;
         pitch *= p;
      }
   }

   //
   // Change sample state
   //
   _sample->set_pitch( pitch_offset + pitch );
   if ((volume_offset + volume ) > 1.0)
   {
      _sample->set_volume( 1.0 );
      SG_LOG(SG_GENERAL, SG_WARN,
             "Volume larger than 1.0 in configuration for '" << _name
              << "', clipping.");
   } else
      _sample->set_volume( volume_offset + volume );

   //
   // Do we need to start playing the sample?
   //
   if (!_active) {

      if (_mode == SGXmlSound::ONCE)
         _sample->play(false);

      else
         _sample->play(true);

      SG_LOG(SG_GENERAL, SG_INFO, "Playing audio after " << _dt_stop
                                   << " sec: " << _name);
      SG_LOG(SG_GENERAL, SG_BULK,
                         "Playing " << ((_mode == ONCE) ? "once" : "looped"));

      _active = true;
      _dt_stop = 0.0;
   }
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkCarbonTextMapper.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 1993-2002 Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkCarbonTextMapper.h"
#include "vtkCarbonRenderWindow.h"
#include <OpenGL/gl.h>
#include <AGL/agl.h>
#include "vtkObjectFactory.h"
#include "vtkgluPickMatrix.h"
#include "vtkString.h"

vtkCxxRevisionMacro(vtkCarbonTextMapper, "1.3");
vtkStandardNewMacro(vtkCarbonTextMapper);

struct vtkFontStruct
{
  vtkWindow *Window;
  int   Italic;
  int   Bold;
  int   FontSize;
  int   FontFamily;
  int   ListBase;
};

static vtkFontStruct *cache[30] = {
  NULL,NULL,NULL,NULL,NULL,
  NULL,NULL,NULL,NULL,NULL,
  NULL,NULL,NULL,NULL,NULL,
  NULL,NULL,NULL,NULL,NULL,
  NULL,NULL,NULL,NULL,NULL,
  NULL,NULL,NULL,NULL,NULL};
static int numCached = 0;

// Copy C string to Pascal string
// Some of the Carbon routines require Pascal strings
static void CStrToPStr (StringPtr outString, const char *inString)
{
  unsigned char x = 0;
  do
    *(((char*)outString) + x + 1) = *(inString + x++);
  while ((*(inString + x) != 0)  && (x < 256));
  *((char*)outString) = (char) x;
}

void vtkCarbonTextMapper::GetSize(vtkViewport* viewport, int *size)
{
  if ( this->NumberOfLines > 1 )
  {
    this->GetMultiLineSize(viewport, size);
    return;
  }

  if (this->Input == NULL)
  {
    size[0] = 0;
    size[1] = 0;
    return;
  }

  // Check to see whether we have to rebuild anything
  if ( this->GetMTime() < this->BuildTime)
  {
    size[0] = this->LastSize[0];
    size[1] = this->LastSize[1];
    return;
  }

  // Check for input
  if (this->Input == NULL)
  {
    vtkErrorMacro (<<"vtkCarbonTextMapper::GetSize - No input");
    return;
  }

  // Get the window information for display
  vtkWindow*  window = viewport->GetVTKWindow();
  // Get the device context from the window
  AGLDrawable hdc = (AGLDrawable) window->GetGenericContext();

  // Get the font number
  switch (this->FontFamily)
  {
    case VTK_ARIAL:
      GetFNum("\pArial", &(this->currentFontNum));
      break;
    case VTK_TIMES:
      GetFNum("\pTimes", &(this->currentFontNum));
      break;
    case VTK_COURIER:
      GetFNum("\pCourier", &(this->currentFontNum));
      break;
    default:
      GetFNum("\pArial", &(this->currentFontNum));
      break;
  }

  TextFont(this->currentFontNum);
  TextFace(normal + (italic*this->Italic) + (bold*this->Bold) +
           (shadow*this->Shadow));
  TextSize(this->FontSize);

  GetFontInfo(&(this->myFontInfo));

  // Calculate the size of the bounding rectangle
  Str255 testString = "\p"; //StringWidth needs a pascal string
  CStrToPStr(testString, this->Input);
  size[0] = StringWidth(testString);
  size[1] = (this->myFontInfo.ascent +
            this->myFontInfo.descent +
            this->myFontInfo.leading);

  this->LastSize[0] = size[0];
  this->LastSize[1] = size[1];
  this->BuildTime.Modified();
}

int vtkCarbonTextMapper::GetListBaseForFont(vtkViewport *vp)
{
  int i, j;
  vtkCarbonRenderWindow *win = (vtkCarbonRenderWindow *)(vp->GetVTKWindow());

  // has the font been cached ?
  for (i = 0; i < numCached; i++)
    {
    if (cache[i]->Window == win &&
        cache[i]->Italic == this->GetItalic() &&
        cache[i]->Bold == this->GetBold() &&
        cache[i]->FontSize == this->GetFontSize() &&
        cache[i]->FontFamily == this->GetFontFamily())
      {
      // make this the most recently used
      if (i != 0)
        {
        vtkFontStruct *tmp = cache[i];
        for (j = i-1; j >= 0; j--)
          {
          cache[j+1] = cache[j];
          }
        cache[0] = tmp;
        }
      return cache[0]->ListBase;
      }
    }

  AGLDrawable hdc = (AGLDrawable) win->GetGenericContext();

  // OK the font is not cached
  // so we need to make room for a new font
  if (numCached == 30)
    {
      aglSetCurrentContext((AGLContext)cache[29]->Window->GetGenericDisplayId());
    glDeleteLists(cache[29]->ListBase,255);
    aglSetCurrentContext((AGLContext)win->GetGenericDisplayId());
    numCached = 29;
    }

  // add the new font
  if (!cache[numCached])
    {
    cache[numCached] = new vtkFontStruct;
    int done = 0;
    cache[numCached]->ListBase = 1000;
    do
      {
      done = 1;
      cache[numCached]->ListBase += 260;
      for (i = 0; i < numCached; i++)
        {
        if (cache[i]->ListBase == cache[numCached]->ListBase)
          {
          done = 0;
          }
        }
      }
    while (!done);
    }

  short fNum = 0;
  // set the other info and build the font
  cache[numCached]->Window = win;
  cache[numCached]->Italic = this->GetItalic();
  cache[numCached]->Bold = this->GetBold();
  cache[numCached]->FontSize = this->GetFontSize();
  cache[numCached]->FontFamily = this->GetFontFamily();
  if (cache[numCached]->FontSize < 9)
    cache[numCached]->FontSize = 9; // minimum font size (or it goes blank!)
  aglUseFont((AGLContext)win->GetGenericDisplayId(), cache[numCached]->FontFamily,
             normal+(italic*this->Italic) + (bold*this->Bold) +
             (shadow*this->Shadow), cache[numCached]->FontSize, 0, 255, cache[numCached]->ListBase);
  GLenum err = aglGetError();
  if (AGL_NO_ERROR != err)
    cout << "vtkCarbonMapper AGLError: "<<(char *)aglErrorString(err)<<"\n";

  // now resort the list
  vtkFontStruct *tmp = cache[numCached];
  for (i = numCached-1; i >= 0; i--)
    {
    cache[i+1] = cache[i];
    }
  cache[0] = tmp;
  numCached++;
  return cache[0]->ListBase;
}

void vtkCarbonTextMapper::ReleaseGraphicsResources(vtkWindow *win)
{
  int i,j;

  // free up any cached font associated with this window
  // has the font been cached ?
  for (i = 0; i < numCached; i++)
    {
    if (cache[i]->Window == win)
      {
      win->MakeCurrent();
      glDeleteLists(cache[i]->ListBase,255);
      delete cache[i];
      // resort them
      numCached--;
      for (j = i; j < numCached; j++)
        {
        cache[j] = cache[j+1];
        }
      cache[numCached] = NULL;
      i--;
      }
    }

  this->LastWindow = NULL;

  // very important
  // the release of graphics resources indicates that significant changes have
  // occurred. Old fonts, cached sizes etc are all no longer valid, so we send
  // ourselves a general modified message.
  this->Modified();
}

vtkCarbonTextMapper::vtkCarbonTextMapper()
{
}

vtkCarbonTextMapper::~vtkCarbonTextMapper()
{
  if (this->LastWindow)
    {
    this->ReleaseGraphicsResources(this->LastWindow);
    }
}

void vtkCarbonTextMapper::RenderOverlay(vtkViewport* viewport,
                                             vtkActor2D* actor)
{
  vtkDebugMacro (<< "RenderOverlay");

  // turn off texturing in case it is on
  glDisable( GL_TEXTURE_2D );

  // Get the window information for display
  vtkWindow*  window = viewport->GetVTKWindow();
  if (this->LastWindow && this->LastWindow != window)
    {
    this->ReleaseGraphicsResources(this->LastWindow);
    }
  this->LastWindow = window;

  // Check for input
  if ( this->NumberOfLines > 1 )
    {
    this->RenderOverlayMultipleLines(viewport, actor);
    return;
    }

  if ( this->Input == NULL )
    {
    vtkErrorMacro (<<"Render - No input");
    return;
    }

  int size[2];
  this->GetSize(viewport, size);

  // Get the device context from the window
  AGLDrawable hdc = (AGLDrawable) window->GetGenericContext();

  // Get the position of the text actor
  Point ptDestOff;
  int* actorPos =
    actor->GetPositionCoordinate()->GetComputedViewportValue(viewport);
  ptDestOff.h = actorPos[0];
  ptDestOff.v = static_cast<long>(actorPos[1] - this->LineOffset);

  // Set up the font color from the text actor
  unsigned char red = 0;
  unsigned char green = 0;
  unsigned char blue = 0;
  unsigned char alpha = 0;

  float*  actorColor = actor->GetProperty()->GetColor();
  red = (unsigned char) (actorColor[0] * 255.0);
  green = (unsigned char) (actorColor[1] * 255.0);
  blue = (unsigned char) (actorColor[2] * 255.0);
  alpha = (unsigned char) (actorColor[3] * 255.0);

  // Set up the shadow color
  float intensity;
  intensity = (red + green + blue)/3.0;

  unsigned char shadowRed, shadowGreen, shadowBlue;
  if (intensity > 128)
    {
    shadowRed = shadowBlue = shadowGreen = 0;
    }
  else
    {
    shadowRed = shadowBlue = shadowGreen = 255;
    }

  // Define bounding rectangle
  Rect rect;
  rect.left = ptDestOff.h;
  rect.top = ptDestOff.v;
  rect.bottom = ptDestOff.v;
  rect.right = ptDestOff.h;

  rect.right = rect.left + size[0];
  rect.top = rect.bottom + size[1];

  switch (this->Justification)
    {
    int tmp;
    case VTK_TEXT_LEFT:
      break;
    case VTK_TEXT_CENTERED:
      tmp = rect.right - rect.left + 1;
      rect.left = rect.left - tmp/2;
      rect.right = rect.left + tmp;
      break;
    case VTK_TEXT_RIGHT:
      tmp = rect.right - rect.left + 1;
      rect.right = rect.left;
      rect.left = rect.left - tmp;
    }
  switch (this->VerticalJustification)
    {
    case VTK_TEXT_TOP:
      rect.top = rect.bottom;
      rect.bottom = rect.bottom - size[1];
      break;
    case VTK_TEXT_CENTERED:
      rect.bottom = rect.bottom - size[1]/2;
      rect.top = rect.bottom + size[1];
      break;
    case VTK_TEXT_BOTTOM:
      break;
    }

  // push a 2D matrix on the stack
  int *vsize = viewport->GetSize();
  glMatrixMode( GL_PROJECTION);
  glPushMatrix();
  glLoadIdentity();
  if(viewport->GetIsPicking())
    {
    vtkgluPickMatrix(viewport->GetPickX(), viewport->GetPickY(),
                     1, 1, viewport->GetOrigin(), viewport->GetSize());
    }

  glMatrixMode( GL_MODELVIEW );
  glPushMatrix();
  glLoadIdentity();
  glDisable( GL_LIGHTING);

  int front =
    (actor->GetProperty()->GetDisplayLocation() == VTK_FOREGROUND_LOCATION);

  float *tileViewport = viewport->GetVTKWindow()->GetTileViewport();
  float *vport = viewport->GetViewport();
  float visVP[4];
  visVP[0] = (vport[0] >= tileViewport[0]) ? vport[0] : tileViewport[0];
  visVP[1] = (vport[1] >= tileViewport[1]) ? vport[1] : tileViewport[1];
  visVP[2] = (vport[2] <= tileViewport[2]) ? vport[2] : tileViewport[2];
  visVP[3] = (vport[3] <= tileViewport[3]) ? vport[3] : tileViewport[3];
  if (visVP[0] == visVP[2])
    {
    return;
    }
  if (visVP[1] == visVP[3])
    {
    return;
    }

  int *winSize = viewport->GetVTKWindow()->GetSize();
  int xoff = static_cast<int>
    (rect.left - winSize[0]*((visVP[2] + visVP[0])/2.0 - vport[0]));
  int yoff = static_cast<int>
    (rect.bottom - winSize[1]*((visVP[3] + visVP[1])/2.0 - vport[1]));

  // When picking draw the bounds of the text as a rectangle,
  // as text only picks when the pick point is exactly on the
  // origin of the text
  if(viewport->GetIsPicking())
    {
    float width = 2.0 * ((float)rect.right - rect.left) / vsize[0];
    float height = 2.0 * ((float)rect.top - rect.bottom) / vsize[1];
    float x1 = (2.0 * (GLfloat)(rect.left) / vsize[0] - 1);
    float y1 = (2.0 * (GLfloat)(rect.bottom) / vsize[1] - 1);
    glRectf(x1, y1, x1+width, y1+height);

    // Clean up and return after drawing the rectangle
    glMatrixMode( GL_PROJECTION);
    glPopMatrix();
    glMatrixMode( GL_MODELVIEW);
    glPopMatrix();
    glEnable( GL_LIGHTING);

    return;
    }

  glListBase(this->GetListBaseForFont(viewport));

  // Set the colors for the shadow
  if (this->Shadow)
    {
    // set the colors for the foreground
    glColor4ub(shadowRed, shadowGreen, shadowBlue, alpha);
    glRasterPos3f(0,0,(front)?(-1):(.99999));

    // required for clipping to work correctly
    glBitmap(0, 0, 0, 0, xoff + 1, yoff - 1, NULL);

    // Draw the shadow text
    glCallLists (vtkString::Length(this->Input), GL_UNSIGNED_BYTE,
                 this->Input);
    }

  // set the colors for the foreground
  glColor4ub(red, green, blue, alpha);
  glRasterPos3f(0,0,(front)?(-1):(.99999));

  // required for clipping to work correctly
  glBitmap(0, 0, 0, 0, xoff, yoff, NULL);

  // display a string: // indicate start of glyph display lists
  glCallLists (vtkString::Length(this->Input), GL_UNSIGNED_BYTE,
               this->Input);

  glFlush();
  glMatrixMode( GL_PROJECTION);
  glPopMatrix();
  glMatrixMode( GL_MODELVIEW);
  glPopMatrix();
  glEnable( GL_LIGHTING);
}

<commit_msg>BUG: FontFamily used rather than fontNum<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkCarbonTextMapper.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 1993-2002 Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkCarbonTextMapper.h"
#include "vtkCarbonRenderWindow.h"
#include <OpenGL/gl.h>
#include <AGL/agl.h>
#include "vtkObjectFactory.h"
#include "vtkgluPickMatrix.h"
#include "vtkString.h"

vtkCxxRevisionMacro(vtkCarbonTextMapper, "1.4");
vtkStandardNewMacro(vtkCarbonTextMapper);

struct vtkFontStruct
{
  vtkWindow *Window;
  int   Italic;
  int   Bold;
  int   FontSize;
  int   FontFamily;
  int   ListBase;
};

static vtkFontStruct *cache[30] = {
  NULL,NULL,NULL,NULL,NULL,
  NULL,NULL,NULL,NULL,NULL,
  NULL,NULL,NULL,NULL,NULL,
  NULL,NULL,NULL,NULL,NULL,
  NULL,NULL,NULL,NULL,NULL,
  NULL,NULL,NULL,NULL,NULL};
static int numCached = 0;

// Copy C string to Pascal string
// Some of the Carbon routines require Pascal strings
static void CStrToPStr (StringPtr outString, const char *inString)
{
  unsigned char x = 0;
  do
    *(((char*)outString) + x + 1) = *(inString + x++);
  while ((*(inString + x) != 0)  && (x < 256));
  *((char*)outString) = (char) x;
}

void vtkCarbonTextMapper::GetSize(vtkViewport* viewport, int *size)
{
  if ( this->NumberOfLines > 1 )
  {
    this->GetMultiLineSize(viewport, size);
    return;
  }

  if (this->Input == NULL)
  {
    size[0] = 0;
    size[1] = 0;
    return;
  }

  // Check to see whether we have to rebuild anything
  if ( this->GetMTime() < this->BuildTime)
  {
    size[0] = this->LastSize[0];
    size[1] = this->LastSize[1];
    return;
  }

  // Check for input
  if (this->Input == NULL)
  {
    vtkErrorMacro (<<"vtkCarbonTextMapper::GetSize - No input");
    return;
  }

  // Get the window information for display
  vtkWindow*  window = viewport->GetVTKWindow();
  // Get the device context from the window
  AGLDrawable hdc = (AGLDrawable) window->GetGenericContext();

  // Get the font number
  switch (this->FontFamily)
  {
    case VTK_ARIAL:
      GetFNum("\pArial", &(this->currentFontNum));
      break;
    case VTK_TIMES:
      GetFNum("\pTimes", &(this->currentFontNum));
      break;
    case VTK_COURIER:
      GetFNum("\pCourier", &(this->currentFontNum));
      break;
    default:
      GetFNum("\pArial", &(this->currentFontNum));
      break;
  }

  TextFont(this->currentFontNum);
  TextFace(normal + (italic*this->Italic) + (bold*this->Bold) +
           (shadow*this->Shadow));
  if (this->FontSize < 9)
    {// adjust since smaller sizes disappear in aglUseFont
    this->FontSize = 9;
    }
  TextSize(this->FontSize);

  GetFontInfo(&(this->myFontInfo));

  // Calculate the size of the bounding rectangle
  Str255 testString = "\p"; //StringWidth needs a pascal string
  CStrToPStr(testString, this->Input);
  size[0] = StringWidth(testString);
  size[1] = (this->myFontInfo.ascent +
            this->myFontInfo.descent +
            this->myFontInfo.leading);

  this->LastSize[0] = size[0];
  this->LastSize[1] = size[1];
  this->BuildTime.Modified();
}

int vtkCarbonTextMapper::GetListBaseForFont(vtkViewport *vp)
{
  int i, j;
  vtkCarbonRenderWindow *win = (vtkCarbonRenderWindow *)(vp->GetVTKWindow());

  // has the font been cached ?
  for (i = 0; i < numCached; i++)
    {
    if (cache[i]->Window == win &&
        cache[i]->Italic == this->GetItalic() &&
        cache[i]->Bold == this->GetBold() &&
        cache[i]->FontSize == this->GetFontSize() &&
        cache[i]->FontFamily == this->GetFontFamily())
      {
      // make this the most recently used
      if (i != 0)
        {
        vtkFontStruct *tmp = cache[i];
        for (j = i-1; j >= 0; j--)
          {
          cache[j+1] = cache[j];
          }
        cache[0] = tmp;
        }
      return cache[0]->ListBase;
      }
    }

  AGLDrawable hdc = (AGLDrawable) win->GetGenericContext();

  // OK the font is not cached
  // so we need to make room for a new font
  if (numCached == 30)
    {
      aglSetCurrentContext((AGLContext)cache[29]->Window->GetGenericDisplayId());
    glDeleteLists(cache[29]->ListBase,255);
    aglSetCurrentContext((AGLContext)win->GetGenericDisplayId());
    numCached = 29;
    }

  // add the new font
  if (!cache[numCached])
    {
    cache[numCached] = new vtkFontStruct;
    int done = 0;
    cache[numCached]->ListBase = 1000;
    do
      {
      done = 1;
      cache[numCached]->ListBase += 260;
      for (i = 0; i < numCached; i++)
        {
        if (cache[i]->ListBase == cache[numCached]->ListBase)
          {
          done = 0;
          }
        }
      }
    while (!done);
    }

  short fNum = 0;
  // set the other info and build the font
  cache[numCached]->Window = win;
  cache[numCached]->Italic = this->GetItalic();
  cache[numCached]->Bold = this->GetBold();
  cache[numCached]->FontSize = this->GetFontSize();
  cache[numCached]->FontFamily = this->GetFontFamily();
  if (cache[numCached]->FontSize < 9)
    cache[numCached]->FontSize = 9; // minimum font size (or it goes blank!)
  aglUseFont((AGLContext)win->GetGenericDisplayId(), this->currentFontNum,
             normal+(italic*this->Italic) + (bold*this->Bold) +
             (shadow*this->Shadow), cache[numCached]->FontSize, 0, 256, cache[numCached]->ListBase);
  GLenum err = aglGetError();
  if (AGL_NO_ERROR != err)
    {
    vtkErrorMacro(<<"vtkCarbonMapper AGLError: "<<(char *)aglErrorString(err));
    }
  // now resort the list
  vtkFontStruct *tmp = cache[numCached];
  for (i = numCached-1; i >= 0; i--)
    {
    cache[i+1] = cache[i];
    }
  cache[0] = tmp;
  numCached++;
  return cache[0]->ListBase;
}

void vtkCarbonTextMapper::ReleaseGraphicsResources(vtkWindow *win)
{
  int i,j;

  // free up any cached font associated with this window
  // has the font been cached ?
  for (i = 0; i < numCached; i++)
    {
    if (cache[i]->Window == win)
      {
      win->MakeCurrent();
      glDeleteLists(cache[i]->ListBase,255);
      delete cache[i];
      // resort them
      numCached--;
      for (j = i; j < numCached; j++)
        {
        cache[j] = cache[j+1];
        }
      cache[numCached] = NULL;
      i--;
      }
    }

  this->LastWindow = NULL;

  // very important
  // the release of graphics resources indicates that significant changes have
  // occurred. Old fonts, cached sizes etc are all no longer valid, so we send
  // ourselves a general modified message.
  this->Modified();
}

vtkCarbonTextMapper::vtkCarbonTextMapper()
{
}

vtkCarbonTextMapper::~vtkCarbonTextMapper()
{
  if (this->LastWindow)
    {
    this->ReleaseGraphicsResources(this->LastWindow);
    }
}

void vtkCarbonTextMapper::RenderOverlay(vtkViewport* viewport,
                                             vtkActor2D* actor)
{
  vtkDebugMacro (<< "RenderOverlay");

  // turn off texturing in case it is on
  glDisable( GL_TEXTURE_2D );

  // Get the window information for display
  vtkWindow*  window = viewport->GetVTKWindow();
  if (this->LastWindow && this->LastWindow != window)
    {
    this->ReleaseGraphicsResources(this->LastWindow);
    }
  this->LastWindow = window;

  // Check for input
  if ( this->NumberOfLines > 1 )
    {
    this->RenderOverlayMultipleLines(viewport, actor);
    return;
    }

  if ( this->Input == NULL )
    {
    vtkErrorMacro (<<"Render - No input");
    return;
    }

  int size[2];
  this->GetSize(viewport, size);

  // Get the device context from the window
  AGLDrawable hdc = (AGLDrawable) window->GetGenericContext();

  // Get the position of the text actor
  Point ptDestOff;
  int* actorPos =
    actor->GetPositionCoordinate()->GetComputedViewportValue(viewport);
  ptDestOff.h = actorPos[0];
  ptDestOff.v = static_cast<long>(actorPos[1] - this->LineOffset);

  // Set up the font color from the text actor
  unsigned char red = 0;
  unsigned char green = 0;
  unsigned char blue = 0;
  unsigned char alpha = 0;

  float*  actorColor = actor->GetProperty()->GetColor();
  red = (unsigned char) (actorColor[0] * 255.0);
  green = (unsigned char) (actorColor[1] * 255.0);
  blue = (unsigned char) (actorColor[2] * 255.0);
  alpha = (unsigned char) (actorColor[3] * 255.0);

  // Set up the shadow color
  float intensity;
  intensity = (red + green + blue)/3.0;

  unsigned char shadowRed, shadowGreen, shadowBlue;
  if (intensity > 128)
    {
    shadowRed = shadowBlue = shadowGreen = 0;
    }
  else
    {
    shadowRed = shadowBlue = shadowGreen = 255;
    }

  // Define bounding rectangle
  Rect rect;
  rect.left = ptDestOff.h;
  rect.top = ptDestOff.v;
  rect.bottom = ptDestOff.v;
  rect.right = ptDestOff.h;

  rect.right = rect.left + size[0];
  rect.top = rect.bottom + size[1];

  switch (this->Justification)
    {
    int tmp;
    case VTK_TEXT_LEFT:
      break;
    case VTK_TEXT_CENTERED:
      tmp = rect.right - rect.left + 1;
      rect.left = rect.left - tmp/2;
      rect.right = rect.left + tmp;
      break;
    case VTK_TEXT_RIGHT:
      tmp = rect.right - rect.left + 1;
      rect.right = rect.left;
      rect.left = rect.left - tmp;
    }
  switch (this->VerticalJustification)
    {
    case VTK_TEXT_TOP:
      rect.top = rect.bottom;
      rect.bottom = rect.bottom - size[1];
      break;
    case VTK_TEXT_CENTERED:
      rect.bottom = rect.bottom - size[1]/2;
      rect.top = rect.bottom + size[1];
      break;
    case VTK_TEXT_BOTTOM:
      break;
    }

  // push a 2D matrix on the stack
  int *vsize = viewport->GetSize();
  glMatrixMode( GL_PROJECTION);
  glPushMatrix();
  glLoadIdentity();
  if(viewport->GetIsPicking())
    {
    vtkgluPickMatrix(viewport->GetPickX(), viewport->GetPickY(),
                     1, 1, viewport->GetOrigin(), viewport->GetSize());
    }

  glMatrixMode( GL_MODELVIEW );
  glPushMatrix();
  glLoadIdentity();
  glDisable( GL_LIGHTING);

  int front =
    (actor->GetProperty()->GetDisplayLocation() == VTK_FOREGROUND_LOCATION);

  float *tileViewport = viewport->GetVTKWindow()->GetTileViewport();
  float *vport = viewport->GetViewport();
  float visVP[4];
  visVP[0] = (vport[0] >= tileViewport[0]) ? vport[0] : tileViewport[0];
  visVP[1] = (vport[1] >= tileViewport[1]) ? vport[1] : tileViewport[1];
  visVP[2] = (vport[2] <= tileViewport[2]) ? vport[2] : tileViewport[2];
  visVP[3] = (vport[3] <= tileViewport[3]) ? vport[3] : tileViewport[3];
  if (visVP[0] == visVP[2])
    {
    return;
    }
  if (visVP[1] == visVP[3])
    {
    return;
    }

  int *winSize = viewport->GetVTKWindow()->GetSize();
  int xoff = static_cast<int>
    (rect.left - winSize[0]*((visVP[2] + visVP[0])/2.0 - vport[0]));
  int yoff = static_cast<int>
    (rect.bottom - winSize[1]*((visVP[3] + visVP[1])/2.0 - vport[1]));

  // When picking draw the bounds of the text as a rectangle,
  // as text only picks when the pick point is exactly on the
  // origin of the text
  if(viewport->GetIsPicking())
    {
    float width = 2.0 * ((float)rect.right - rect.left) / vsize[0];
    float height = 2.0 * ((float)rect.top - rect.bottom) / vsize[1];
    float x1 = (2.0 * (GLfloat)(rect.left) / vsize[0] - 1);
    float y1 = (2.0 * (GLfloat)(rect.bottom) / vsize[1] - 1);
    glRectf(x1, y1, x1+width, y1+height);

    // Clean up and return after drawing the rectangle
    glMatrixMode( GL_PROJECTION);
    glPopMatrix();
    glMatrixMode( GL_MODELVIEW);
    glPopMatrix();
    glEnable( GL_LIGHTING);

    return;
    }

  glListBase(this->GetListBaseForFont(viewport));

  // Set the colors for the shadow
  if (this->Shadow)
    {
    // set the colors for the foreground
    glColor4ub(shadowRed, shadowGreen, shadowBlue, alpha);
    glRasterPos3f(0,0,(front)?(-1):(.99999));

    // required for clipping to work correctly
    glBitmap(0, 0, 0, 0, xoff + 1, yoff - 1, NULL);

    // Draw the shadow text
    glCallLists (vtkString::Length(this->Input), GL_UNSIGNED_BYTE,
                 this->Input);
    }

  // set the colors for the foreground
  glColor4ub(red, green, blue, alpha);
  glRasterPos3f(0,0,(front)?(-1):(.99999));

  // required for clipping to work correctly
  glBitmap(0, 0, 0, 0, xoff, yoff, NULL);

  // display a string: // indicate start of glyph display lists
  glCallLists (vtkString::Length(this->Input), GL_UNSIGNED_BYTE,
               this->Input);

  glFlush();
  glMatrixMode( GL_PROJECTION);
  glPopMatrix();
  glMatrixMode( GL_MODELVIEW);
  glPopMatrix();
  glEnable( GL_LIGHTING);
}

<|endoftext|>


<commit_before>/* Copyright 2009-2016 Francesco Biscani (bluescarni@gmail.com)

This file is part of the mp++ library.

The mp++ library is free software; you can redistribute it and/or modify
it under the terms of either:

  * the GNU Lesser General Public License as published by the Free
    Software Foundation; either version 3 of the License, or (at your
    option) any later version.

or

  * the GNU General Public License as published by the Free Software
    Foundation; either version 3 of the License, or (at your option) any
    later version.

or both in parallel, as here.

The mp++ library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received copies of the GNU General Public License and the
GNU Lesser General Public License along with the mp++ library.  If not,
see https://www.gnu.org/licenses/. */

#include <cstddef>
#include <functional>
#include <gmp.h>
#include <random>
#include <tuple>
#include <type_traits>

#include <mp++.hpp>

#include "test_utils.hpp"

#define CATCH_CONFIG_MAIN
#include "catch.hpp"

static int ntries = 1000;

using namespace mppp;
using namespace mppp_test;

using sizes = std::tuple<std::integral_constant<std::size_t, 1>, std::integral_constant<std::size_t, 2>,
                         std::integral_constant<std::size_t, 3>, std::integral_constant<std::size_t, 6>,
                         std::integral_constant<std::size_t, 10>>;

static std::mt19937 rng;

struct hash_tester {
    template <typename S>
    inline void operator()(const S &) const
    {
        using integer = mp_integer<S::value>;
        const std::hash<integer> hasher;
        integer n1, n2;
        REQUIRE((hash(n1) == 0u));
        REQUIRE((hasher(n1) == 0u));
        n1.promote();
        REQUIRE((hash(n1) == 0u));
        REQUIRE((hasher(n1) == 0u));
        n1 = integer{12};
        n2 = n1;
        REQUIRE(n2.is_static());
        n1.promote();
        REQUIRE(n1.is_dynamic());
        REQUIRE((hash(n1) == hash(n2)));
        REQUIRE((hasher(n1) == hash(n2)));
        n1 = integer{-12};
        n2 = n1;
        REQUIRE(n2.is_static());
        n1.promote();
        REQUIRE(n1.is_dynamic());
        REQUIRE((hash(n1) == hash(n2)));
        REQUIRE((hash(n1) == hasher(n2)));
        mpz_raii tmp;
        std::uniform_int_distribution<int> sdist(0, 1);
        // Run a variety of tests with operands with x number of limbs.
        auto random_xy = [&](unsigned x) {
            for (int i = 0; i < ntries; ++i) {
                random_integer(tmp, x, rng);
                n1 = integer(mpz_to_str(&tmp.m_mpz));
                if (sdist(rng)) {
                    n1.neg();
                }
                n2 = n1;
                if (n2.is_static()) {
                    n1.promote();
                }
                REQUIRE((hash(n1) == hash(n2)));
                REQUIRE((hasher(n1) == hash(n2)));
            }
        };

        random_xy(0);
        random_xy(1);
        random_xy(2);
        random_xy(3);
        random_xy(4);
    }
};

TEST_CASE("hash")
{
    tuple_for_each(sizes{}, hash_tester{});
}
<commit_msg>Fix const init in test.<commit_after>/* Copyright 2009-2016 Francesco Biscani (bluescarni@gmail.com)

This file is part of the mp++ library.

The mp++ library is free software; you can redistribute it and/or modify
it under the terms of either:

  * the GNU Lesser General Public License as published by the Free
    Software Foundation; either version 3 of the License, or (at your
    option) any later version.

or

  * the GNU General Public License as published by the Free Software
    Foundation; either version 3 of the License, or (at your option) any
    later version.

or both in parallel, as here.

The mp++ library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received copies of the GNU General Public License and the
GNU Lesser General Public License along with the mp++ library.  If not,
see https://www.gnu.org/licenses/. */

#include <cstddef>
#include <functional>
#include <gmp.h>
#include <random>
#include <tuple>
#include <type_traits>

#include <mp++.hpp>

#include "test_utils.hpp"

#define CATCH_CONFIG_MAIN
#include "catch.hpp"

static int ntries = 1000;

using namespace mppp;
using namespace mppp_test;

using sizes = std::tuple<std::integral_constant<std::size_t, 1>, std::integral_constant<std::size_t, 2>,
                         std::integral_constant<std::size_t, 3>, std::integral_constant<std::size_t, 6>,
                         std::integral_constant<std::size_t, 10>>;

static std::mt19937 rng;

struct hash_tester {
    template <typename S>
    inline void operator()(const S &) const
    {
        using integer = mp_integer<S::value>;
        const std::hash<integer> hasher{};
        integer n1, n2;
        REQUIRE((hash(n1) == 0u));
        REQUIRE((hasher(n1) == 0u));
        n1.promote();
        REQUIRE((hash(n1) == 0u));
        REQUIRE((hasher(n1) == 0u));
        n1 = integer{12};
        n2 = n1;
        REQUIRE(n2.is_static());
        n1.promote();
        REQUIRE(n1.is_dynamic());
        REQUIRE((hash(n1) == hash(n2)));
        REQUIRE((hasher(n1) == hash(n2)));
        n1 = integer{-12};
        n2 = n1;
        REQUIRE(n2.is_static());
        n1.promote();
        REQUIRE(n1.is_dynamic());
        REQUIRE((hash(n1) == hash(n2)));
        REQUIRE((hash(n1) == hasher(n2)));
        mpz_raii tmp;
        std::uniform_int_distribution<int> sdist(0, 1);
        // Run a variety of tests with operands with x number of limbs.
        auto random_xy = [&](unsigned x) {
            for (int i = 0; i < ntries; ++i) {
                random_integer(tmp, x, rng);
                n1 = integer(mpz_to_str(&tmp.m_mpz));
                if (sdist(rng)) {
                    n1.neg();
                }
                n2 = n1;
                if (n2.is_static()) {
                    n1.promote();
                }
                REQUIRE((hash(n1) == hash(n2)));
                REQUIRE((hasher(n1) == hash(n2)));
            }
        };

        random_xy(0);
        random_xy(1);
        random_xy(2);
        random_xy(3);
        random_xy(4);
    }
};

TEST_CASE("hash")
{
    tuple_for_each(sizes{}, hash_tester{});
}
<|endoftext|>


<commit_before>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
team <http://www.bh107.org>.

Bohrium is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3
of the License, or (at your option) any later version.

Bohrium is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the
GNU Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/

/* This is a wrapper of the OpenCL C/C++ header. We need this to avoid warnings and handle OSX */

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"

#define CL_USE_DEPRECATED_OPENCL_1_1_APIS
#if defined(__APPLE__) || defined(__MACOSX)
#include <OpenCL/opencl.h>
#define CL_EXT_PREFIX__VERSION_1_1_DEPRECATED
#define CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED
#else
#include <CL/cl.h>
#endif
#undef CL_VERSION_1_2
#define __CL_ENABLE_EXCEPTIONS

#define CL_MINIMUM_OPENCL_VERSION 120
#define CL_TARGET_OPENCL_VERSION 120
#define CL_ENABLE_EXCEPTIONS

#include <CL/cl.hpp>

#pragma GCC diagnostic pop<commit_msg>Workaround for redefining macros on Mac<commit_after>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
team <http://www.bh107.org>.

Bohrium is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3
of the License, or (at your option) any later version.

Bohrium is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the
GNU Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/

/* This is a wrapper of the OpenCL C/C++ header. We need this to avoid warnings and handle OSX */

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"

#define CL_USE_DEPRECATED_OPENCL_1_1_APIS
#if defined(__APPLE__) || defined(__MACOSX)
    #include <OpenCL/opencl.h>

    // To avoid warnings from compiler about redefining needed macros
    #ifdef CL_EXT_PREFIX__VERSION_1_1_DEPRECATED
        #undef CL_EXT_PREFIX__VERSION_1_1_DEPRECATED
        #define CL_EXT_PREFIX__VERSION_1_1_DEPRECATED
    #endif
    #ifdef CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED
        #undef CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED
        #define CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED
    #endif
#else
    #include <CL/cl.h>
#endif

#undef CL_VERSION_1_2
#define __CL_ENABLE_EXCEPTIONS

#define CL_MINIMUM_OPENCL_VERSION 120
#define CL_TARGET_OPENCL_VERSION 120
#define CL_ENABLE_EXCEPTIONS

#include <CL/cl.hpp>

#pragma GCC diagnostic pop
<|endoftext|>


<commit_before><commit_msg>Use RtcpPacket to send REMB in RtcpSender<commit_after><|endoftext|>


<commit_before>/*************************************************
* FTW EntropySource Source File                  *
* (C) 1999-2008 Jack Lloyd                       *
*************************************************/

#include <botan/es_ftw.h>
#include <botan/secmem.h>
#include <botan/util.h>
#include <cstring>
#include <deque>

#ifndef _POSIX_C_SOURCE
  #define _POSIX_C_SOURCE 199309
#endif

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <fcntl.h>

namespace Botan {

namespace {

class Directory_Walker : public FTW_EntropySource::File_Descriptor_Source
   {
   public:
      Directory_Walker(const std::string& root) { add_directory(root); }
      ~Directory_Walker();

      int next_fd();
   private:
      void add_directory(const std::string&);

      std::deque<std::pair<DIR*, std::string> > dirs;
   };

void Directory_Walker::add_directory(const std::string& dirname)
   {
   DIR* dir = ::opendir(dirname.c_str());
   if(dir)
      dirs.push_back(std::make_pair(dir, dirname));
   }

Directory_Walker::~Directory_Walker()
   {
   while(dirs.size())
      {
      ::closedir(dirs[0].first);
      dirs.pop_front();
      }
   }

int Directory_Walker::next_fd()
   {
   while(dirs.size())
      {
      std::pair<DIR*, std::string> dirinfo = dirs[0];

      struct dirent* entry = ::readdir(dirinfo.first);

      if(!entry)
         {
         ::closedir(dirinfo.first);
         dirs.pop_front();
         continue;
         }

      const std::string filename = entry->d_name;

      if(filename == "." || filename == "..")
         continue;

      const std::string full_path = dirinfo.second + '/' + filename;

      struct stat stat_buf;
      if(::lstat(full_path.c_str(), &stat_buf) == -1)
         continue;

      if(S_ISDIR(stat_buf.st_mode))
         add_directory(full_path);
      else if(S_ISREG(stat_buf.st_mode))
         {
         int fd = ::open(full_path.c_str(), O_RDONLY | O_NOCTTY);

         if(fd > 0)
            return fd;
         }
      }

   return -1;
   }

}

/**
* FTW_EntropySource Constructor
*/
FTW_EntropySource::FTW_EntropySource(const std::string& p) : path(p)
   {
   dir = 0;
   }

/**
* FTW_EntropySource Destructor
*/
FTW_EntropySource::~FTW_EntropySource()
   {
   delete dir;
   }

u32bit FTW_EntropySource::slow_poll(byte buf[], u32bit length)
   {
   if(!dir)
      dir = new Directory_Walker(path);

   SecureVector<byte> read_buf(4096);

   u32bit bytes_read = 0;

   while(bytes_read < length * 32)
      {
      int fd = dir->next_fd();

      if(fd == -1)
         {
         delete dir;
         dir = new Directory_Walker(path);
         fd = dir->next_fd();

         if(fd == -1) // still fails (directory not mounted, etc) -> fail
            return 0;
         }

      ssize_t got = ::read(fd, read_buf.begin(), read_buf.size());

      if(got > 0 && got <= read_buf.size())
         {
         for(ssize_t i = 0; i != got; ++i)
            buf[i % length] ^= read_buf[i];

         // never count any one file for more than 128 bytes
         bytes_read += std::min<u32bit>(got, 128);
         }

      ::close(fd);
      }

   return length;
   }

u32bit FTW_EntropySource::fast_poll(byte[], u32bit)
   {
   return 0; // no op
   }

}
<commit_msg>Modify es_ftw to use xor_into_buf<commit_after>/*************************************************
* FTW EntropySource Source File                  *
* (C) 1999-2008 Jack Lloyd                       *
*************************************************/

#include <botan/es_ftw.h>
#include <botan/secmem.h>
#include <botan/xor_buf.h>
#include <cstring>
#include <deque>

#ifndef _POSIX_C_SOURCE
  #define _POSIX_C_SOURCE 199309
#endif

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <fcntl.h>

namespace Botan {

namespace {

class Directory_Walker : public FTW_EntropySource::File_Descriptor_Source
   {
   public:
      Directory_Walker(const std::string& root) { add_directory(root); }
      ~Directory_Walker();

      int next_fd();
   private:
      void add_directory(const std::string&);

      std::deque<std::pair<DIR*, std::string> > dirs;
   };

void Directory_Walker::add_directory(const std::string& dirname)
   {
   DIR* dir = ::opendir(dirname.c_str());
   if(dir)
      dirs.push_back(std::make_pair(dir, dirname));
   }

Directory_Walker::~Directory_Walker()
   {
   while(dirs.size())
      {
      ::closedir(dirs[0].first);
      dirs.pop_front();
      }
   }

int Directory_Walker::next_fd()
   {
   while(dirs.size())
      {
      std::pair<DIR*, std::string> dirinfo = dirs[0];

      struct dirent* entry = ::readdir(dirinfo.first);

      if(!entry)
         {
         ::closedir(dirinfo.first);
         dirs.pop_front();
         continue;
         }

      const std::string filename = entry->d_name;

      if(filename == "." || filename == "..")
         continue;

      const std::string full_path = dirinfo.second + '/' + filename;

      struct stat stat_buf;
      if(::lstat(full_path.c_str(), &stat_buf) == -1)
         continue;

      if(S_ISDIR(stat_buf.st_mode))
         add_directory(full_path);
      else if(S_ISREG(stat_buf.st_mode))
         {
         int fd = ::open(full_path.c_str(), O_RDONLY | O_NOCTTY);

         if(fd > 0)
            return fd;
         }
      }

   return -1;
   }

}

/**
* FTW_EntropySource Constructor
*/
FTW_EntropySource::FTW_EntropySource(const std::string& p) : path(p)
   {
   dir = 0;
   }

/**
* FTW_EntropySource Destructor
*/
FTW_EntropySource::~FTW_EntropySource()
   {
   delete dir;
   }

u32bit FTW_EntropySource::slow_poll(byte buf[], u32bit length)
   {
   if(!dir)
      dir = new Directory_Walker(path);

   SecureVector<byte> read_buf(4096);

   u32bit bytes_read = 0;
   u32bit buf_i = 0;

   while(bytes_read < length * 32)
      {
      int fd = dir->next_fd();

      if(fd == -1) // re-walk
         {
         delete dir;
         dir = new Directory_Walker(path);
         fd = dir->next_fd();

         if(fd == -1) // still fails (directory not mounted, etc) -> fail
            return 0;
         }

      ssize_t got = ::read(fd, read_buf.begin(), read_buf.size());

      if(got > 0 && got <= read_buf.size())
         {
         buf_i = xor_into_buf(buf, buf_i, length, read_buf, got);

         // never count any one file for more than 128 bytes
         bytes_read += std::min<u32bit>(got, 128);
         }

      ::close(fd);
      }

   return length;
   }

u32bit FTW_EntropySource::fast_poll(byte[], u32bit)
   {
   return 0; // no op
   }

}
<|endoftext|>