コード例 #1
0
ファイル: helpwindow.cpp プロジェクト: ChakaZulu/tuxbox_apps
eString eHelpWindow::loadHelpText(int helpIDtoLoad)
{
	FILE *in=fopen(TUXBOXDATADIR "/enigma/resources/help.xml", "rt");
	if (!in)
	{
		eDebug("cannot open help.xml");
		return "";
	}

	XMLTreeParser *parser=new XMLTreeParser("ISO-8859-1");
	char buf[2048];
	
	int done;
	do
	{
		unsigned int len=fread(buf, 1, sizeof(buf), in);
		done=len<sizeof(buf);
		if (!parser->Parse(buf, len, done))
		{
			eFatal("parse error: %s at line %d", parser->ErrorString(parser->GetErrorCode()), parser->GetCurrentLineNumber());
			fclose(in);
			delete parser;
			return "";
		}
	} while (!done);
	fclose(in);

	XMLTreeNode *root=parser->RootNode();
	if (!root)
		return "";
	if (strcmp(root->GetType(), "enigmahelp"))
	{
		eFatal("not a enigma help file.");
		return "";
	}
	
	XMLTreeNode *node=parser->RootNode();
	
	for (node=node->GetChild(); node; node=node->GetNext())
		if (!strcmp(node->GetType(), "help"))
		{
			for (XMLTreeNode *xam=node->GetChild(); xam; xam=xam->GetNext())
				if (!strcmp(xam->GetType(), "helptext"))
				{
					if (helpIDtoLoad==atoi(xam->GetAttributeValue("id")))
					{
						const char *helptext=xam->GetAttributeValue("text");
						eString ht(helptext);
						delete parser;
						return ht;
					}
				}
		}

	delete parser;
	return "";
}
コード例 #2
0
ファイル: demux.cpp プロジェクト: pizzelnet/enigma2-1
eDVBRecordFileThread::eDVBRecordFileThread(int packetsize, int bufferCount):
	eFilePushThreadRecorder(
		/* buffer */ (unsigned char*) ::mmap(NULL, bufferCount * packetsize * 1024, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, /*ignored*/-1, 0),
		/*buffersize*/ packetsize * 1024),
	 m_ts_parser(packetsize),
	 m_current_offset(0),
	 m_fd_dest(-1),
	 m_aio(bufferCount),
	 m_current_buffer(m_aio.begin()),
	 m_buffer_use_histogram(bufferCount+1, 0)
{
	if (m_buffer == MAP_FAILED)
		eFatal("Failed to allocate filepush buffer, contact MiLo\n");
	// m_buffer actually points to a data block large enough to hold ALL buffers. m_buffer will
	// move around during writes, so we must remember where the "head" is.
	m_allocated_buffer = m_buffer;
	// m_buffersize is thus the size of a single buffer in the queue
	// Initialize the buffer pointers
	int index = 0;
	for (AsyncIOvector::iterator it = m_aio.begin(); it != m_aio.end(); ++it)
	{
		it->buffer = m_allocated_buffer + (index * m_buffersize);
		++index;
	}
}
コード例 #3
0
ファイル: grc.cpp プロジェクト: Adga52/enigma2
gRC::gRC(): rp(0), wp(0)
#ifdef SYNC_PAINT
,m_notify_pump(eApp, 0)
#else
,m_notify_pump(eApp, 1)
#endif
,m_spinner_enabled(0), m_spinneronoff(1), m_prev_idle_count(0)
{
	ASSERT(!instance);
	instance=this;
	CONNECT(m_notify_pump.recv_msg, gRC::recv_notify);
#ifndef SYNC_PAINT
	pthread_mutex_init(&mutex, 0);
	pthread_cond_init(&cond, 0);
	pthread_attr_t attr;
	pthread_attr_init(&attr);
	if (pthread_attr_setstacksize(&attr, 2048*1024) != 0)
		eDebug("[gRC] pthread_attr_setstacksize failed");
	int res = pthread_create(&the_thread, &attr, thread_wrapper, this);
	pthread_attr_destroy(&attr);
	if (res)
		eFatal("RC thread couldn't be created");
	else
		eDebug("RC thread created successfully");
#endif
}
コード例 #4
0
ファイル: font.cpp プロジェクト: Anubisko/enigma2
std::string fontRenderClass::AddFont(const std::string &filename, const std::string &name, int scale, int renderflags)
{
	eDebugNoNewLine("[FONT] adding font %s...", filename.c_str());
	fflush(stdout);
	int error;
	fontListEntry *n=new fontListEntry;

	n->scale=scale;
	FT_Face face;
	singleLock s(ftlock);

	if ((error=FT_New_Face(library, filename.c_str(), 0, &face)))
		eFatal(" failed: %s", strerror(error));

	n->filename=filename;
	n->face=name;
	n->renderflags=renderflags;
	FT_Done_Face(face);

	n->next=font;
	eDebug("OK (%s)", n->face.c_str());
	font=n;

	return n->face;
}
コード例 #5
0
ファイル: gfbdc.cpp プロジェクト: kingvuplus/ME
gFBDC::gFBDC()
{
	fb=new fbClass;

	if (!fb->Available())
		eFatal("[gFBDC] no framebuffer available");

	int xres;
	int yres;
	int bpp;
	fb->getMode(xres, yres, bpp);

	/* we can only use one of these three modes: */
	if (!((xres == 720 && yres == 576)
		|| (xres == 1280 && yres == 720)
		|| (xres == 1920 && yres == 1080)))
	{
		/* fallback to a decent default */
		xres = 720;
		yres = 576;
	}

	surface.clut.data = 0;
	setResolution(xres, yres); // default res

	reloadSettings();
}
コード例 #6
0
ファイル: gfbdc.cpp プロジェクト: ChakaZulu/my_tuxbox_apps
void gFBDC::init_gFBDC()
{
	instance=this;
	fb=new fbClass;

	if (!fb->Available())
		eFatal("no framebuffer available");

	fb->SetMode(720, 576, 8);

	for (int y=0; y<576; y++)																		 // make whole screen transparent
		memset(fb->lfb+y*fb->Stride(), 0x00, fb->Stride());

	pixmap=new gPixmap();
	pixmap->x=720;
	pixmap->y=576;
	pixmap->bpp=8;
	pixmap->bypp=1;
	pixmap->stride=fb->Stride();
	pixmap->data=fb->lfb;
	
	pixmap->clut.colors=256;
	pixmap->clut.data=new gRGB[pixmap->clut.colors];
	memset(pixmap->clut.data, 0, sizeof(*pixmap->clut.data)*pixmap->clut.colors);
	reloadSettings();
}
コード例 #7
0
ファイル: serviceplaylist.cpp プロジェクト: GWARDAR/OpenPLi-1
eServicePlaylistHandler::eServicePlaylistHandler(): eServiceHandler(ID)
{
        //eDebug("[eServicePLaylistHandler] registering serviceInterface %d", id);
	if (eServiceInterface::getInstance()->registerHandler(id, this)<0)
		eFatal("couldn't register serviceHandler %d", id);
	CONNECT(eServiceFileHandler::getInstance()->fileHandlers, eServicePlaylistHandler::addFile);
	instance=this;
}
コード例 #8
0
void enigmaVCR::init_enigmaVCR()
{
	if ( !instance )
		instance = this;
	else
		eFatal("create more than one enigmaVCR instances");
	addActionMap(&i_enigmaVCRActions->map);
}
コード例 #9
0
void eEventDisplay::init_eEventDisplay(const ePtrList<EITEvent>* e)
{
	eventlist=0;
	events=0;

	scrollbar = new eProgress(this);
	scrollbar->setName("scrollbar");
	scrollbar->setStart(0);
	scrollbar->setPerc(100);

	descr = new eWidget(this);
	descr->setName("epg_description");

	eventTime = new eLabel(this);
	eventTime->setName("time");

	eventDate = new eLabel(this);
	eventDate->setName("date");

	channel = new eLabel(this);
	channel->setName("channel");

	timer_icon = new eLabel(this);
	timer_icon->setName("timer_icon");

	eSkin *skin=eSkin::getActive();
	if (skin->build(this, "eventview"))
		eFatal("skin load of \"eventview\" failed");

	long_description=new eLabel(descr);
	long_description->setFlags(RS_WRAP);

	// try to recalc long description label... ( no broken text lines.. )
	float lineheight=fontRenderClass::getInstance()->getLineHeight( long_description->getFont() );
	int lines = (int)(descr->getSize().height() / lineheight);
	pageHeight = (int)(lines * lineheight);
	descr->resize( eSize( descr->getSize().width(), pageHeight+(int)(lineheight/6)));
	long_description->resize(eSize(descr->getSize().width(), pageHeight*16));

#ifndef DISABLE_FILE
	addActionToHelpList( &i_epgSelectorActions->addDVRTimerEvent );
#endif
#ifndef DISABLE_NETWORK
	addActionToHelpList( &i_epgSelectorActions->addNGRABTimerEvent );
#endif
	addActionToHelpList( &i_epgSelectorActions->addSwitchTimerEvent );
	addActionToHelpList( &i_epgSelectorActions->removeTimerEvent );
	addActionToHelpList( &i_enigmaEventViewActions->close );

	if (e)
		setList(*e);
	else if (evt)
		setEvent(evt);
	addActionMap( &i_enigmaEventViewActions->map );
	addActionMap( &i_epgSelectorActions->map );
	
	setHelpID(11);
}
コード例 #10
0
ファイル: servicedvb.cpp プロジェクト: UkCvs/commando
eServiceHandlerDVB::~eServiceHandlerDVB()
{
#ifndef DISABLE_FILE
	if (recording)
		eDVB::getInstance()->recEnd();
#endif
	if (eServiceInterface::getInstance()->unregisterHandler(id)<0)
		eFatal("couldn't unregister serviceHandler %d", id);
}
コード例 #11
0
ファイル: grc.cpp プロジェクト: Adga52/enigma2
gRGB gDC::getRGB(gColor col)
{
	if ((!m_pixmap) || (!m_pixmap->surface->clut.data))
		return gRGB(col, col, col);
	if (col<0)
	{
		eFatal("bla transp");
		return gRGB(0, 0, 0, 0xFF);
	}
	return m_pixmap->surface->clut.data[col];
}
コード例 #12
0
eServiceHandlerExternal::eServiceHandlerExternal(): eServiceHandler(0x0fff)
{
	if (eServiceInterface::getInstance()->registerHandler(id, this) < 0)
	{
		eFatal("couldn't register eServiceHandlerExternal %d", id);
	}
	instance = this;
	CONNECT(eServiceFileHandler::getInstance()->fileHandlers, eServiceHandlerExternal::addFile);
	CONNECT(eServiceFileHandler::getInstance()->directoryHandlers, eServiceHandlerExternal::addDirectory);
	eDebug("eServiceHandlerExternal registered");
}
コード例 #13
0
ファイル: gfbdc.cpp プロジェクト: st7TEAM/bh-gui
gFBDC::gFBDC()
{
	fb=new fbClass;

	if (!fb->Available())
		eFatal("no framebuffer available");

	surface.clut.data = 0;
	setResolution(1280, 720); // default res
	reloadSettings();
}
コード例 #14
0
ファイル: servicemp3.cpp プロジェクト: TitanNit/tdt
void eHTTPStream::haveData(void *vdata, int len)
{
	__u8 *data=(__u8*)vdata;
	
	while (len)
	{
		int valid=len;
		if (!metadataleft)
		{
				// not in metadata mode.. process mp3 data (stream to input buffer)

				// are we just at the beginning of metadata? (pointer)
			if (metadatainterval && (metadatainterval == bytes))
			{
						// enable metadata mode
				metadataleft=*data++*16;
				metadatapointer=0;
				len--;
				bytes=0;
				continue;
			} else if (metadatainterval && (metadatainterval < bytes))
				eFatal("metadatainterval < bytes");

				// otherwise there's really data.
			if (metadatainterval)
			{
					// is metadata in our buffer?
				if ((valid + bytes) > metadatainterval)
					valid=metadatainterval-bytes;
			}
			buffer.write(data, valid);
			data+=valid;
			len-=valid;
			bytes+=valid;
		} else
		{
				// metadata ... process it.
			int meta=len;
			if (meta > metadataleft)
				meta=metadataleft;

			memcpy(metadata+metadatapointer, data, meta);

			metadatapointer+=meta;
			data+=meta;
			len-=meta;
			metadataleft-=meta;
			
			if (!metadataleft)
				processMetaData();
		}
	}
	dataAvailable();
}
コード例 #15
0
ファイル: gfbdc.cpp プロジェクト: GWARDAR/OpenPLi-1
void gFBDC::init_gFBDC()
{
	instance=this;
	fb=new fbClass;

	if (!fb->Available())
		eFatal("no framebuffer available");

	colorDepth = 8;
	pixmap = NULL;
	setMode();
}
コード例 #16
0
void eActionMap::unbindAction(const std::string &context, ePyObject function)
{
	//eDebug("[eActionMap] unbind function from %s", context.c_str());
	for (std::multimap<long long int, eActionBinding>::iterator i(m_bindings.begin()); i != m_bindings.end(); ++i)
		if (i->second.m_fnc && (PyObject_Compare(i->second.m_fnc, function) == 0))
		{
			Py_DECREF(i->second.m_fnc);
			m_bindings.erase(i);
			return;
		}
	eFatal("[eActionMap] unbindAction with illegal python reference");
}
コード例 #17
0
ファイル: thread.cpp プロジェクト: 1198s/enigma2
int eThread::sync(void)
{
	int res;
	int debug_val_before = m_state.value();
	m_state.down(); /* this might block */
	res = m_alive;
	if (m_state.value() != 0)
		eFatal("eThread::sync: m_state.value() == %d - was %d before", m_state.value(), debug_val_before);
	ASSERT(m_state.value() == 0);
	m_state.up();
	return res; /* 0: thread is guaranteed not to run. 1: state unknown. */
}
コード例 #18
0
ファイル: gfbdc.cpp プロジェクト: FFTEAM/evolux-spark-sh4
gFBDC::gFBDC()
{
	instance=this;
	fb=new fbClass;

	if (!fb->Available())
		eFatal("no framebuffer available");

	surface.clut.data = 0;
	setResolution(720, 576); // default res

	reloadSettings();
}
コード例 #19
0
ファイル: ebase.cpp プロジェクト: MCelliotG/enigma2-2
void eMainloop::removeSocketNotifier(eSocketNotifier *sn)
{
	int fd = sn->getFD();
	std::map<int,eSocketNotifier*>::iterator i(notifiers.find(fd));
	if (i != notifiers.end())
	{
		notifiers.erase(i);
		return;
	}
	for (i = notifiers.begin(); i != notifiers.end(); ++i)
		eDebug("[eMainloop::removeSocketNotifier] fd=%d, sn=%p", i->second->getFD(), (void*)i->second);
	eFatal("[eMainloop::removeSocketNotifier] removed socket notifier which is not present, fd=%d", fd);
}
コード例 #20
0
ファイル: tpeditwindow.cpp プロジェクト: backtrack2016/tdt
void eTransponderEditWindow::init_eTransponderEditWindow()
{
    addActionMap(&i_TransponderEditWindowActions->map);
    sat = new eButton(this);
    sat->setName("sat");
    CONNECT(sat->selected, eTransponderEditWindow::satPressed);
    add = new eButton(this);
    add->setName("add");
    CONNECT(add->selected, eTransponderEditWindow::addPressed);
    edit = new eButton(this);
    edit->setName("edit");
    CONNECT(edit->selected, eTransponderEditWindow::editPressed);
    remove = new eButton(this);
    remove->setName("remove");
    CONNECT(remove->selected, eTransponderEditWindow::removePressed);
    satellites = new eListBox<eListBoxEntryText>( this, 0, 0 );
    satellites->setName("satlist");
    transponders = new eListBox<eListBoxEntryTransponder>( this, 0, 0 );
    transponders->setName("transponderlist");
    transponders->FakeFocus( 0 );
    satellites->FakeFocus( 1 );
    if ( eSkin::getActive()->build( this, "TransponderWindow") )
        eFatal("eTransponderEditWindow build failed");

    eDVBServiceController *sapi=eDVB::getInstance()->getServiceAPI();
    eTransponder *tp=0;

    if (sapi && sapi->transponder)
        tp = sapi->transponder;

    eListBoxEntryText *sel=0;

    if( !eTransponderList::getInstance()->reloadNetworks() )
    {
        for ( std::list<tpPacket>::iterator i(eTransponderList::getInstance()->getNetworks().begin()); i != eTransponderList::getInstance()->getNetworks().end(); ++i)
            if ( tp && i->orbital_position == tp->satellite.orbital_position )
                sel = new eListBoxEntryText(satellites, i->name, (void*) &(*i));
            else
                new eListBoxEntryText(satellites, i->name, (void*) &(*i));
    }
    CONNECT(satellites->selchanged, eTransponderEditWindow::satSelChanged );

    if ( sel )
        satellites->setCurrent(sel);
    else
        satellites->setCurrent(0);

    CONNECT( eWidget::focusChanged, eTransponderEditWindow::focusChanged );
    satSelChanged( satellites->getCurrent() );
    setHelpID(64);
}
コード例 #21
0
ファイル: filepush.cpp プロジェクト: sklnet/openpli-enigma2
eFilePushThread::eFilePushThread(int blocksize, size_t buffersize):
	 m_sg(NULL),
	 m_stop(1),
	 m_send_pvr_commit(0),
	 m_stream_mode(0),
	 m_blocksize(blocksize),
	 m_buffersize(buffersize),
	 m_buffer((unsigned char *)malloc(buffersize)),
	 m_messagepump(eApp, 0),
	 m_run_state(0)
{
	if (m_buffer == NULL)
		eFatal("[eFilePushThread] Failed to allocate %d bytes", buffersize);
	CONNECT(m_messagepump.recv_msg, eFilePushThread::recvEvent);
}
コード例 #22
0
eFilePushThread::eFilePushThread(int io_prio_class, int io_prio_level, int blocksize, size_t buffersize)
	:prio_class(io_prio_class),
	 prio(io_prio_level),
	 m_sg(NULL),
	 m_stop(0),
	 m_send_pvr_commit(0),
	 m_stream_mode(0),
	 m_blocksize(blocksize),
	 m_buffersize(buffersize),
	 m_buffer((unsigned char *)malloc(buffersize)),
	 m_messagepump(eApp, 0)
{
	if (m_buffer == NULL)
		eFatal("Failed to allocate %d bytes", buffersize);
	CONNECT(m_messagepump.recv_msg, eFilePushThread::recvEvent);
}
コード例 #23
0
ファイル: ewidget.cpp プロジェクト: TitanNit/tdt
	/* das ist bestimmt ne einzige race hier :) */
int eWidget::exec()
{
	if (in_loop)
		eFatal("double exec");

	in_loop=-1;	// hey, exec hat angefangen aber noch nicht in der mainloop

	event(eWidgetEvent(eWidgetEvent::execBegin)); // hat jemand was dagegen einzuwenden?
	if (in_loop)	// hatte wohl jemand.
	{
		in_loop=1;		// wir betreten die mainloop
		eApp->enter_loop();		// oder wir machen das halt selber.
		in_loop=0; // nu sind wir jedenfalls draussen.
	}
	event(eWidgetEvent(eWidgetEvent::execDone));
	return result;
}
コード例 #24
0
ファイル: setupnetwork.cpp プロジェクト: OpenDMM/tuxbox-apps
static void writeSecretString( const eString &str )
{
	FILE *f = fopen("/etc/ppp/pap-secrets", "w");
	if (!f)
		eFatal("couldn't create /etc/ppp/pap-secrets");
	eString tmp;
	unsigned int pos =
		str.find('*');
	if ( pos != eString::npos )
	{
		tmp = '\"' + str.left(pos) + "\"\t*\t\"" +
			str.mid(pos+1, str.length()-pos ) + "\"\n";
	}
	fwrite( tmp.c_str(), 1, tmp.length(), f );

	fclose(f);
}
コード例 #25
0
ファイル: sdl.cpp プロジェクト: 1198s/enigma2
void gSDLDC::evSetVideoMode(unsigned long xres, unsigned long yres)
{
	m_screen = SDL_SetVideoMode(xres, yres, 32, SDL_HWSURFACE);
	if (!m_screen) {
		eFatal("Could not create SDL surface: %s", SDL_GetError());
		return;
	}

	m_surface.x = m_screen->w;
	m_surface.y = m_screen->h;
	m_surface.bpp = m_screen->format->BitsPerPixel;
	m_surface.bypp = m_screen->format->BytesPerPixel;
	m_surface.stride = m_screen->pitch;
	m_surface.data = m_screen->pixels;

	SDL_EnableUNICODE(1);
}
コード例 #26
0
ファイル: demux.cpp プロジェクト: FFTEAM/evolux-spark-sh4
eDVBRecordFileThread::eDVBRecordFileThread(int packetsize):
	eFilePushThreadRecorder(
		/* buffer */ (unsigned char*) ::mmap(NULL, recordingBufferCount * packetsize * 1024, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, /*ignored*/-1, 0),
		/*buffersize*/ packetsize * 1024),
	 m_ts_parser(packetsize),
	 m_current_offset(0),
	 m_fd_dest(-1),
	 offset_last_sync(0),
	 written_since_last_sync(0),
	 m_current_buffer(0),
	 m_aio(recordingBufferCount),
	 m_buffer_use_histogram(recordingBufferCount+1, 0)
{
	if (m_buffer == MAP_FAILED)
		eFatal("Failed to allocate filepush buffer, contact MiLo\n");
	// m_buffer actually points to a data block large enough to hold ALL buffers. m_buffer will
	// move around during writes, so we must remember where the "head" is.
	m_allocated_buffer = m_buffer;
	// m_buffersize is thus the size of a single buffer in the queue
}
コード例 #27
0
ファイル: grc.cpp プロジェクト: OpenPE/Enigma2PC-Old
gRC::gRC(): rp(0), wp(0)
#ifdef SYNC_PAINT
,m_notify_pump(eApp, 0)
#else
,m_notify_pump(eApp, 1)
#endif
{
	ASSERT(!instance);
	instance=this;
	CONNECT(m_notify_pump.recv_msg, gRC::recv_notify);
#ifndef SYNC_PAINT
	pthread_mutex_init(&mutex, 0);
	pthread_cond_init(&cond, 0);
	int res = pthread_create(&the_thread, 0, thread_wrapper, this);
	if (res)
		eFatal("RC thread couldn't be created");
	else
		eDebug("RC thread created successfully");
#endif
	m_spinner_enabled = 0;
}
コード例 #28
0
ファイル: ewidget.cpp プロジェクト: TitanNit/tdt
eWidget::~eWidget()
{
	if (pixmap)
		pixmap->compressdata();
	hide();
	if (takefocus)
	{
		getTLW()->focusList()->remove(this);
		if (getTLW()->focus == this)
			eFatal("focus still held.");
	}

	if (shortcut)
		getTLW()->actionListener.remove(this);

	if (parent && !parent->childlist.empty())
		parent->childlist.remove(this);

	while (!childlist.empty())
		delete childlist.front();
}
コード例 #29
0
ファイル: ewidget.cpp プロジェクト: TitanNit/tdt
void eWidget::releaseFocus()
{
		// desktop shouldnt receive global focus
	ASSERT (parent);
		// childs shouldnt receive global focus
	ASSERT (!parent->parent);
	ASSERT (have_focus);

	if (have_focus)
	{
	 	--have_focus;
		if (!have_focus)
		{
			removeActionMap(&i_focusActions->map);
			if (currentFocus==this)	// if we don't have lost the focus, ...
			{
				currentFocus=oldTLfocus;	// give it back
				/*emit*/ globalFocusChanged(currentFocus);
			}
			else
				eFatal("someone has stolen the focus");
		}
 	}
}
コード例 #30
0
ファイル: textinput.cpp プロジェクト: OpenDMM/tuxbox-apps
void eTextInputField::loadKeyMappings()
{
	FILE *in=0;
	char *filename=CONFIGDIR "/enigma/resources/keymappings.xml";
	in=fopen(filename, "rt");
	if (!in)
	{
		char *filename=TUXBOXDATADIR "/enigma/resources/keymappings.xml";
		in=fopen(filename, "rt");
	}
	if (!in)
	{
		eDebug("cannot open keymappings.xml");
		return;
	}

	XMLTreeParser parser("ISO-8859-1");
	char buf[2048];

	int done;
	do
	{
		unsigned int len=fread(buf, 1, sizeof(buf), in);
		done=len<sizeof(buf);
		if (!parser.Parse(buf, len, done))
		{
			eFatal("parse error: %s at line %d",
				parser.ErrorString(parser.GetErrorCode()),
				parser.GetCurrentLineNumber());
			fclose(in);
			return;
		}
	} while (!done);
	fclose(in);

	XMLTreeNode *node=parser.RootNode();
	if (!node)
	{
		eFatal("empty keymappings file?");
		return;
	}
	if (strcmp(node->GetType(), "keymappings"))
	{
		eFatal("not a keymappings file");
		return;
	}
	for (node=node->GetChild(); node; node=node->GetNext())
		if (!strcmp(node->GetType(), "keymapping"))
		{
			const char *code=node->GetAttributeValue("code");
			if (!code)
			{
				eFatal("no code specified");
				return;
			}
			keymappings[code]=std::vector< std::pair<eString,eString> >(12);
			int cnt=0;
			for (XMLTreeNode *xam=node->GetChild(); xam; xam=xam->GetNext())
			{
				if (!strcmp(xam->GetType(), "codes"))
				{
					const char 	*lower(xam->GetAttributeValue("lower")),
											*upper(xam->GetAttributeValue("upper"));
					if (!lower)
					{
						eFatal("no lower specified");
						return;
					}
					if (!upper)
					{
						eFatal("no upper specified");
						return;
					}
					keymappings[code][cnt].first=lower;
					keymappings[code][cnt].second=upper;
				}
				++cnt;
			}
		}
		else
		{
			eFatal("no keymapping specified");
			return;
		}
}