<commit_before>/*  This file is part of the KDE project
    Copyright (C) 2004-2006 Matthias Kretz <kretz@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License version 2 as published by the Free Software Foundation.

    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; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.

*/

#include "factory.h"
#include "base_p.h"

#include <kservicetypetrader.h>
#include <klibloader.h>
#include <kmessagebox.h>
#include <QFile>
#include <QList>
#include <klocale.h>
#include <kmimetype.h>
#include <kdebug.h>
#include <kstaticdeleter.h>

#include <QtDBus/QtDBus>
#include "backendinterface.h"

static KStaticDeleter<Phonon::Factory> sd;

#define PHONON_LOAD_BACKEND_GLOBAL 1

namespace Phonon
{
class Factory::Private
{
	public:
		Private()
			: backend( 0 )
		{
			qRegisterMetaType<qint64>( "qint64" );
			qRegisterMetaType<qint32>( "qint32" );
		}

		void createBackend()
		{
			const KService::List offers = KServiceTypeTrader::self()->query( "PhononBackend",
					"Type == 'Service' and [X-KDE-PhononBackendInfo-InterfaceVersion] == 1" );
			KService::List::const_iterator it = offers.begin();
			const KService::List::const_iterator end = offers.end();
			QStringList errormsg;
			for( ; it != end; ++it )
			{
				KService::Ptr ptr = *it;
				KLibFactory* factory = 0;
#ifdef PHONON_LOAD_BACKEND_GLOBAL
				// This code is in here temporarily until NMM gets fixed.
				// Currently the NMM backend will fail with undefined symbols if
				// the backend is not loaded with global symbol resolution
				KLibrary* library = KLibLoader::self()->library( QFile::encodeName( ptr->library() ), QLibrary::ExportExternalSymbolsHint );
				if( library )
					factory = library->factory();
#else
				factory = KLibLoader::self()->factory( QFile::encodeName( ptr->library() ) );
#endif
				if( factory )
				{
					backend = factory->create();
					if( 0 == backend )
					{
						QString e = i18n( "create method returned 0" );
						errormsg.append( e );
						kDebug( 600 ) << "Error getting backend from factory for " <<
							ptr->name() << ", " << ptr->library() << ":\n" << e << endl;
					}
					else
					{
						service = ptr;
						kDebug( 600 ) << "using backend: " << ptr->name() << endl;
						break;
					}
				}
				else
				{
					QString e = KLibLoader::self()->lastErrorMessage();
					errormsg.append( e );
					kDebug( 600 ) << "Error getting factory for " << ptr->name() <<
						":\n" << e << endl;
				}
			}
			if( 0 == backend )
			{
				if( offers.size() == 0 )
					KMessageBox::error( 0, i18n( "Unable to find a Multimedia Backend" ) );
				else
				{
					QString details = "<qt>
";
					QStringList::Iterator eit = errormsg.begin();
					QStringList::Iterator eend = errormsg.end();
					KService::List::const_iterator oit = offers.begin();
					const KService::List::const_iterator oend = offers.end();
					for( ; eit != eend || oit != oend; ++eit, ++oit )
						details += QString( "
%1	%2
" )
							.arg( ( *oit )->name() ).arg( *eit );
					details += "
</qt>";

					KMessageBox::detailedError( 0,
							i18n( "Unable to use any of the available Multimedia Backends" ), details );
				}
			}
		}

		QObject* backend;
		KService::Ptr service;

		QList<QObject*> objects;
		QList<BasePrivate*> basePrivateList;
};

Factory * Factory::m_self = 0;

Factory * Factory::self()
{
	if( ! m_self )
	{
		m_self = new Factory();
		::sd.setObject( m_self, m_self );
	}
	return m_self;
}

Factory::Factory()
	: d( new Private )
{
	QDBusConnection::sessionBus().connect(QString(), QString(), "org.kde.Phonon.Factory",
			"phononBackendChanged", this, SLOT(phononBackendChanged()));
}

Factory::~Factory()
{
	//kDebug( 600 ) << k_funcinfo << endl;
	emit aboutToBeDestroyed();

	foreach( BasePrivate* bp, d->basePrivateList )
		bp->deleteIface();
	qDeleteAll(d->objects);
	delete d->backend;
	delete d;
}

void Factory::registerFrontendObject( BasePrivate* bp )
{
	d->basePrivateList.append( bp );
}

void Factory::deregisterFrontendObject( BasePrivate* bp )
{
	d->basePrivateList.removeAll( bp );
}

void Factory::phononBackendChanged()
{
	if( d->backend )
	{
		foreach( BasePrivate* bp, d->basePrivateList )
			bp->deleteIface();
		if( d->objects.size() > 0 )
		{
			kWarning( 600 ) << "we were asked to change the backend but the application did\n"
				"not free all references to objects created by the factory. Therefore we can not\n"
				"change the backend without crashing. Now we have to wait for a restart to make\n"
				"backendswitching possible." << endl;
			// in case there were objects deleted give 'em a chance to recreate
			// them now
			foreach( BasePrivate* bp, d->basePrivateList )
				bp->createIface();
			return;
		}
		delete d->backend;
		d->backend = 0;
	}
	d->createBackend();
	foreach( BasePrivate* bp, d->basePrivateList )
		bp->createIface();
	emit backendChanged();
}

//X void Factory::freeSoundcardDevices()
//X {
//X 	if( d->backend )
//X 	{
//X 		d->backend->freeSoundcardDevices();
//X 	}
//X }

void Factory::objectDestroyed( QObject * obj )
{
	//kDebug( 600 ) << k_funcinfo << obj << endl;
	d->objects.removeAll( obj );
}

#define FACTORY_IMPL( classname ) \
QObject* Factory::create ## classname( QObject* parent ) \
{ \
	if( backend() ) \
	{ \
        return registerQObject(qobject_cast<BackendInterface*>(backend())->createObject0(BackendInterface::classname##Class, parent)); \
	} \
	return 0; \
}
#define FACTORY_IMPL_1ARG( classname ) \
QObject* Factory::create ## classname( int arg1, QObject* parent ) \
{ \
	if( backend() ) \
	{ \
        return registerQObject(qobject_cast<BackendInterface*>(backend())->createObject1(BackendInterface::classname##Class, parent, arg1)); \
	} \
	return 0; \
}

FACTORY_IMPL(MediaObject)
FACTORY_IMPL(MediaQueue)
FACTORY_IMPL(AvCapture)
FACTORY_IMPL(ByteStream)
FACTORY_IMPL(AudioPath)
FACTORY_IMPL_1ARG(AudioEffect)
FACTORY_IMPL(VolumeFaderEffect)
FACTORY_IMPL(AudioOutput)
FACTORY_IMPL(AudioDataOutput)
FACTORY_IMPL(Visualization)
FACTORY_IMPL(VideoPath)
FACTORY_IMPL_1ARG(VideoEffect)
FACTORY_IMPL(BrightnessControl)
FACTORY_IMPL(VideoDataOutput)

#undef FACTORY_IMPL

QObject* Factory::backend( bool createWhenNull )
{
	if( createWhenNull && d->backend == 0 )
	{
		d->createBackend();
		// XXX: might create "reentrancy" problems:
		// a method calls this method and is called again because the
		// backendChanged signal is emitted
		emit backendChanged();
	}
	return d->backend;
}

const char* Factory::uiLibrary()
{
	if( !backend() )
		return 0;
	const char* ret = 0;
	QMetaObject::invokeMethod( d->backend, "uiLibrary", Qt::DirectConnection, Q_RETURN_ARG( const char*, ret ) );
	return ret;
}

const char* Factory::uiSymbol()
{
	if( !backend() )
		return 0;
	const char* ret = 0;
	// the backend doesn't have to implement the symbol - the default factory
	// symbol will be used then
	if( QMetaObject::invokeMethod( d->backend, "uiSymbol", Qt::DirectConnection, Q_RETURN_ARG( const char*, ret ) ) )
		return ret;
	return 0;
}

QString Factory::identifier() const
{
    if (d->service) {
        return d->service->library();
    }
    return QString();
}

QString Factory::backendName() const
{
	if( d->service )
		return d->service->name();
	else
		return QString();
}

QString Factory::backendComment() const
{
	if( d->service )
		return d->service->comment();
	else
		return QString();
}

QString Factory::backendVersion() const
{
	if( d->service )
		return d->service->property( "X-KDE-PhononBackendInfo-Version" ).toString();
	else
		return QString();
}

QString Factory::backendIcon() const
{
	if( d->service )
		return d->service->icon();
	else
		return QString();
}

QString Factory::backendWebsite() const
{
	if( d->service )
		return d->service->property( "X-KDE-PhononBackendInfo-Website" ).toString();
	else
		return QString();
}

QObject* Factory::registerQObject( QObject* o )
{
	if( o )
	{
		connect( o, SIGNAL( destroyed( QObject* ) ), SLOT( objectDestroyed( QObject* ) ), Qt::DirectConnection );
		d->objects.append( o );
	}
	return o;
}

} //namespace Phonon

#include "factory.moc"

// vim: sw=4 ts=4
<commit_msg>KStaticDeleter might delete the backend too late (i.e. when QCoreApplication is gone), so add a post-routine to delete the backend before QCoreApplication becomes unusable<commit_after>/*  This file is part of the KDE project
    Copyright (C) 2004-2006 Matthias Kretz <kretz@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License version 2 as published by the Free Software Foundation.

    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; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.

*/

#include "factory.h"
#include "base_p.h"

#include <kservicetypetrader.h>
#include <klibloader.h>
#include <kmessagebox.h>
#include <QFile>
#include <QList>
#include <klocale.h>
#include <kmimetype.h>
#include <kdebug.h>
#include <kstaticdeleter.h>
#include <QCoreApplication>

#include <QtDBus/QtDBus>
#include "backendinterface.h"

static KStaticDeleter<Phonon::Factory> sd;

static void deleteBackend()
{
    sd.destructObject();
}

#define PHONON_LOAD_BACKEND_GLOBAL 1

namespace Phonon
{
class Factory::Private
{
	public:
		Private()
			: backend( 0 )
		{
			qRegisterMetaType<qint64>( "qint64" );
			qRegisterMetaType<qint32>( "qint32" );
		}

		void createBackend()
		{
			const KService::List offers = KServiceTypeTrader::self()->query( "PhononBackend",
					"Type == 'Service' and [X-KDE-PhononBackendInfo-InterfaceVersion] == 1" );
			KService::List::const_iterator it = offers.begin();
			const KService::List::const_iterator end = offers.end();
			QStringList errormsg;
			for( ; it != end; ++it )
			{
				KService::Ptr ptr = *it;
				KLibFactory* factory = 0;
#ifdef PHONON_LOAD_BACKEND_GLOBAL
				// This code is in here temporarily until NMM gets fixed.
				// Currently the NMM backend will fail with undefined symbols if
				// the backend is not loaded with global symbol resolution
				KLibrary* library = KLibLoader::self()->library( QFile::encodeName( ptr->library() ), QLibrary::ExportExternalSymbolsHint );
				if( library )
					factory = library->factory();
#else
				factory = KLibLoader::self()->factory( QFile::encodeName( ptr->library() ) );
#endif
				if( factory )
				{
					backend = factory->create();
					if( 0 == backend )
					{
						QString e = i18n( "create method returned 0" );
						errormsg.append( e );
						kDebug( 600 ) << "Error getting backend from factory for " <<
							ptr->name() << ", " << ptr->library() << ":\n" << e << endl;
					}
					else
					{
						service = ptr;
						kDebug( 600 ) << "using backend: " << ptr->name() << endl;
						break;
					}
				}
				else
				{
					QString e = KLibLoader::self()->lastErrorMessage();
					errormsg.append( e );
					kDebug( 600 ) << "Error getting factory for " << ptr->name() <<
						":\n" << e << endl;
				}
			}
			if( 0 == backend )
			{
				if( offers.size() == 0 )
					KMessageBox::error( 0, i18n( "Unable to find a Multimedia Backend" ) );
				else
				{
					QString details = "<qt>
";
					QStringList::Iterator eit = errormsg.begin();
					QStringList::Iterator eend = errormsg.end();
					KService::List::const_iterator oit = offers.begin();
					const KService::List::const_iterator oend = offers.end();
					for( ; eit != eend || oit != oend; ++eit, ++oit )
						details += QString( "
%1	%2
" )
							.arg( ( *oit )->name() ).arg( *eit );
					details += "
</qt>";

					KMessageBox::detailedError( 0,
							i18n( "Unable to use any of the available Multimedia Backends" ), details );
				}
			}
		}

		QObject* backend;
		KService::Ptr service;

		QList<QObject*> objects;
		QList<BasePrivate*> basePrivateList;
};

Factory * Factory::m_self = 0;

Factory * Factory::self()
{
	if( ! m_self )
	{
		m_self = new Factory();
		::sd.setObject( m_self, m_self );
	}
	return m_self;
}

Factory::Factory()
	: d( new Private )
{
	QDBusConnection::sessionBus().connect(QString(), QString(), "org.kde.Phonon.Factory",
			"phononBackendChanged", this, SLOT(phononBackendChanged()));
    qAddPostRoutine(deleteBackend);
}

Factory::~Factory()
{
    qRemovePostRoutine(deleteBackend);
	//kDebug( 600 ) << k_funcinfo << endl;
	emit aboutToBeDestroyed();

	foreach( BasePrivate* bp, d->basePrivateList )
		bp->deleteIface();
	qDeleteAll(d->objects);
	delete d->backend;
	delete d;
}

void Factory::registerFrontendObject( BasePrivate* bp )
{
	d->basePrivateList.append( bp );
}

void Factory::deregisterFrontendObject( BasePrivate* bp )
{
	d->basePrivateList.removeAll( bp );
}

void Factory::phononBackendChanged()
{
	if( d->backend )
	{
		foreach( BasePrivate* bp, d->basePrivateList )
			bp->deleteIface();
		if( d->objects.size() > 0 )
		{
			kWarning( 600 ) << "we were asked to change the backend but the application did\n"
				"not free all references to objects created by the factory. Therefore we can not\n"
				"change the backend without crashing. Now we have to wait for a restart to make\n"
				"backendswitching possible." << endl;
			// in case there were objects deleted give 'em a chance to recreate
			// them now
			foreach( BasePrivate* bp, d->basePrivateList )
				bp->createIface();
			return;
		}
		delete d->backend;
		d->backend = 0;
	}
	d->createBackend();
	foreach( BasePrivate* bp, d->basePrivateList )
		bp->createIface();
	emit backendChanged();
}

//X void Factory::freeSoundcardDevices()
//X {
//X 	if( d->backend )
//X 	{
//X 		d->backend->freeSoundcardDevices();
//X 	}
//X }

void Factory::objectDestroyed( QObject * obj )
{
	//kDebug( 600 ) << k_funcinfo << obj << endl;
	d->objects.removeAll( obj );
}

#define FACTORY_IMPL( classname ) \
QObject* Factory::create ## classname( QObject* parent ) \
{ \
	if( backend() ) \
	{ \
        return registerQObject(qobject_cast<BackendInterface*>(backend())->createObject0(BackendInterface::classname##Class, parent)); \
	} \
	return 0; \
}
#define FACTORY_IMPL_1ARG( classname ) \
QObject* Factory::create ## classname( int arg1, QObject* parent ) \
{ \
	if( backend() ) \
	{ \
        return registerQObject(qobject_cast<BackendInterface*>(backend())->createObject1(BackendInterface::classname##Class, parent, arg1)); \
	} \
	return 0; \
}

FACTORY_IMPL(MediaObject)
FACTORY_IMPL(MediaQueue)
FACTORY_IMPL(AvCapture)
FACTORY_IMPL(ByteStream)
FACTORY_IMPL(AudioPath)
FACTORY_IMPL_1ARG(AudioEffect)
FACTORY_IMPL(VolumeFaderEffect)
FACTORY_IMPL(AudioOutput)
FACTORY_IMPL(AudioDataOutput)
FACTORY_IMPL(Visualization)
FACTORY_IMPL(VideoPath)
FACTORY_IMPL_1ARG(VideoEffect)
FACTORY_IMPL(BrightnessControl)
FACTORY_IMPL(VideoDataOutput)

#undef FACTORY_IMPL

QObject* Factory::backend( bool createWhenNull )
{
	if( createWhenNull && d->backend == 0 )
	{
		d->createBackend();
		// XXX: might create "reentrancy" problems:
		// a method calls this method and is called again because the
		// backendChanged signal is emitted
		emit backendChanged();
	}
	return d->backend;
}

const char* Factory::uiLibrary()
{
	if( !backend() )
		return 0;
	const char* ret = 0;
	QMetaObject::invokeMethod( d->backend, "uiLibrary", Qt::DirectConnection, Q_RETURN_ARG( const char*, ret ) );
	return ret;
}

const char* Factory::uiSymbol()
{
	if( !backend() )
		return 0;
	const char* ret = 0;
	// the backend doesn't have to implement the symbol - the default factory
	// symbol will be used then
	if( QMetaObject::invokeMethod( d->backend, "uiSymbol", Qt::DirectConnection, Q_RETURN_ARG( const char*, ret ) ) )
		return ret;
	return 0;
}

QString Factory::identifier() const
{
    if (d->service) {
        return d->service->library();
    }
    return QString();
}

QString Factory::backendName() const
{
	if( d->service )
		return d->service->name();
	else
		return QString();
}

QString Factory::backendComment() const
{
	if( d->service )
		return d->service->comment();
	else
		return QString();
}

QString Factory::backendVersion() const
{
	if( d->service )
		return d->service->property( "X-KDE-PhononBackendInfo-Version" ).toString();
	else
		return QString();
}

QString Factory::backendIcon() const
{
	if( d->service )
		return d->service->icon();
	else
		return QString();
}

QString Factory::backendWebsite() const
{
	if( d->service )
		return d->service->property( "X-KDE-PhononBackendInfo-Website" ).toString();
	else
		return QString();
}

QObject* Factory::registerQObject( QObject* o )
{
	if( o )
	{
		connect( o, SIGNAL( destroyed( QObject* ) ), SLOT( objectDestroyed( QObject* ) ), Qt::DirectConnection );
		d->objects.append( o );
	}
	return o;
}

} //namespace Phonon

#include "factory.moc"

// vim: sw=4 ts=4
<|endoftext|>


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

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html 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 notices for more information.

=========================================================================*/

#include "mitkLightBoxResultImageWriter.h"

#ifdef CHILIPLUGIN
#include <chili/plugin.h>
#include <chili/qclightbox.h>
#include <chili/qclightboxmanager.h>
#include <chili/isg.h>
#endif

#include <mitkImage.h>
#include <mitkImageSliceSelector.h>
#include <mitkFrameOfReferenceUIDManager.h>
#include <mitkChiliPlugin.h>

#include <itkRootTreeIterator.h>
#include <itkImageFileReader.h>

mitk::LightBoxResultImageWriter::LightBoxResultImageWriter()
{
  m_ImageTypeName = "Image, Segmentation";
}

mitk::LightBoxResultImageWriter::~LightBoxResultImageWriter()
{
}

const mitk::Image *mitk::LightBoxResultImageWriter::GetInput(void)
{
  return static_cast< const mitk::Image * >(this->ProcessObject::GetInput(0));
}

void mitk::LightBoxResultImageWriter::SetInput(const mitk::Image *image)
{
  this->ProcessObject::SetNthInput( 0, const_cast< mitk::Image * >( image ) );
}

void mitk::LightBoxResultImageWriter::SetInputByNode(const mitk::DataTreeNode *node)
{
  if(node==NULL)
    return;

  SetInput(dynamic_cast<mitk::Image*>(node->GetData()));

  node->GetLevelWindow(m_LevelWindow, NULL, "levelWindow");
  node->GetLevelWindow(m_LevelWindow, NULL);
  char imageTypeName[200];
  if(node->GetStringProperty("type name", imageTypeName, NULL))
    SetImageTypeName(imageTypeName);
  char name[200];
  if (node->GetStringProperty("name", name, NULL))
    SetName(name);
}

const mitk::Image *mitk::LightBoxResultImageWriter::GetSourceImage(void)
{
  return static_cast< const mitk::Image * >(this->ProcessObject::GetInput(1));
}

void mitk::LightBoxResultImageWriter::SetSourceImage(const mitk::Image *source)
{
  this->ProcessObject::SetNthInput( 1, const_cast< mitk::Image * >( source ) );
}

bool mitk::LightBoxResultImageWriter::SetSourceByTreeSearch(mitk::DataTreeIteratorBase* iterator)
{
  if(iterator==NULL)
    return false;

  const mitk::Image* image = GetInput();

  if(image == NULL)
    return false;

  mitk::DataTreeIteratorClone it=new itk::RootTreeIterator<DataTreeBase>(iterator->GetTree(), iterator->GetNode());
  bool LoadedFromChili;
  while(!it->IsAtEnd())
  {
    //const char * name;
    //if(it->Get()->GetStringProperty("name", name, NULL))
    //{
    //  itkDebugMacro(<<"candidate: "<<name);
    //}
    //else
    //{
    //  itkDebugMacro(<<"candidate: no name");
    //}

    itkGenericOutputMacro(<<"it-> name"<<it->Get()->GetPropertyList()->GetProperty("name")->GetValueAsString());
    if(it->Get()->GetBoolProperty("LoadedFromChili", LoadedFromChili) && LoadedFromChili)
    {
      mitk::Image::Pointer sourcecandidate=dynamic_cast<mitk::Image*>(it->Get()->GetData());
      if(sourcecandidate.IsNotNull())
      {
        itkDebugMacro(<<"found sourcecandidate: ");
        if(image->GetDimension()<=sourcecandidate->GetDimension())
        {
          int i, dim=image->GetDimension();
          for(i=0; i<dim;++i)
            if(image->GetDimension(i)!=sourcecandidate->GetDimension(i))
              break;
          if(i==dim)
          {
            SetSourceImage(sourcecandidate);
            return true;
            itkDebugMacro(<<"dim incorrect: "<<i <<" "<<dim);
          }
        }
      }
    }
    ++it;
    itkDebugMacro(<<"xxxx");
  }
  itkDebugMacro(<<"yyyyyyyyyyyyyyyyyyyyy");
  return false;
}

void mitk::LightBoxResultImageWriter::SetLightBox(QcLightbox* lightbox)
{
  if(lightbox!=m_LightBox)
  {
    m_LightBox=lightbox;
    Modified();
  }
}

void mitk::LightBoxResultImageWriter::SetLightBoxToCurrentLightBox()
{
#ifdef CHILIPLUGIN
  QcPlugin* plugin = mitk::ChiliPlugin::GetPluginInstance();
  if(plugin==NULL)
  {
    itkExceptionMacro(<<"GetPluginInstance()==NULL: Plugin is not initialized correctly !");
  }
  SetLightBox(plugin->lightboxManager()->getActiveLightbox());
#endif
}

bool mitk::LightBoxResultImageWriter::SetLightBoxToNewLightBox()
{
#ifdef CHILIPLUGIN
  QcPlugin* plugin = mitk::ChiliPlugin::GetPluginInstance();
  if(plugin==NULL)
  {
    itkExceptionMacro(<<"GetPluginInstance()==NULL: Plugin is not initialized correctly !");
  }
  int lightboxCount = plugin->lightboxManager()->getLightboxes().count();
  QcLightbox * newLightbox;
  for (int i = 0; i < lightboxCount; i++)
  {
    newLightbox = plugin->lightboxManager()->getLightboxes().at(i);
    if (newLightbox->getFrames() == 0)
    {
      newLightbox->activate();
      newLightbox->show();
      SetLightBox(newLightbox);
      return true;
    }
  }
  return false;
  //QWidget* parentWidget = (QWidget*) plugin->parent();
  //QcLightbox * newLightbox = new QcLightbox(parentWidget,NULL,(uint)0) ;
  //SetLightBox(newLightbox);
#endif
  return false;
}

bool mitk::LightBoxResultImageWriter::SetLightBoxToCorrespondingLightBox()
{
#ifdef CHILIPLUGIN
  QcPlugin* plugin = mitk::ChiliPlugin::GetPluginInstance();
  if(plugin==NULL)
  {
    itkExceptionMacro(<<"GetPluginInstance()==NULL: Plugin is not initialized correctly !");
  }
  QcLightbox * activeLightbox = plugin->lightboxManager()->getActiveLightbox();
  ipPicDescriptor * currPic =	activeLightbox->fetchVolume();
  ipPicTSV_t* seriesDescriptionTag = ipPicQueryTag(currPic, "SERIES DESCRIPTION");
  if (seriesDescriptionTag)
  {
    if (*((char*)seriesDescriptionTag->value) == *(m_Name.c_str()))
    {
      activeLightbox->clear();
      SetLightBox(activeLightbox);
      return true;
    }
    else return false;
  }
  else return false;
#endif
  return false;
}

QcLightbox* mitk::LightBoxResultImageWriter::GetLightBox() const
{
  return m_LightBox;
}

void mitk::LightBoxResultImageWriter::GenerateData()
{
#ifdef CHILIPLUGIN
  itkDebugMacro(<<"GenerateData ");
  const Image* image = GetInput();
  const Image* sourceimage = GetSourceImage();
  if((image==NULL) || (sourceimage==NULL) || (m_LightBox==NULL))
  {
    itk::ImageFileReaderException e(__FILE__, __LINE__);
    itk::OStringStream msg;
    if(image==NULL)
      msg << "image not set. ";
    if(sourceimage==NULL)
      msg << "source-image not set. ";
    if(m_LightBox==NULL)
      msg << "lightbox not set. ";
    e.SetDescription(msg.str().c_str());
    throw e;
    return;
  }

  ImageSliceSelector::Pointer resultslice = ImageSliceSelector::New();
  ImageSliceSelector::Pointer sourceslice = ImageSliceSelector::New();

  resultslice->SetInput(image);
  sourceslice->SetInput(sourceimage);

  mitk::SlicedGeometry3D* sourceSlicedGeometry;
  mitk::Geometry3D* geometry3DofSlice;
  Point3D origin;
  Vector3D v;

  sourceSlicedGeometry = sourceimage->GetSlicedGeometry();

  origin = sourceSlicedGeometry->GetCornerPoint();

  interSliceGeometry_t isg;
  memcpy(isg.forUID, mitk::FrameOfReferenceUIDManager::GetFrameOfReferenceUID(sourceSlicedGeometry->GetFrameOfReferenceID()), 128);
  isg.psu = ipPicUtilMillimeter;

  ipPicDescriptor *cur, *source, *prev=NULL;
  LevelWindow levelwindow;
  int s, t;
  int smax, tmax;
  smax = image->GetDimension(2);
  tmax = image->GetDimension(3);
  itkDebugMacro(<<"writing image: "<<m_ImageTypeName);
  itkDebugMacro(<<"lv: "<<m_LevelWindow.GetMin() <<" "<<m_LevelWindow.GetMax());
  for(s=smax-1;s>=0;--s)
  {
    resultslice->SetSliceNr(s);
    sourceslice->SetSliceNr(s);
    for(t=0;t<tmax;++t)
    {
      resultslice->SetTimeNr(t);
      sourceslice->SetTimeNr(t);
      resultslice->Update();
      sourceslice->Update();

      geometry3DofSlice = sourceSlicedGeometry->GetGeometry2D(s);

      v=geometry3DofSlice->GetCornerPoint().GetVectorFromOrigin();
      itk2vtk(v, isg.o);

      v-=origin;
      isg.sl = v.GetNorm();

      v.Set_vnl_vector(geometry3DofSlice->GetMatrixColumn(0));
      isg.ps[0]=v.GetNorm();
      v/=isg.ps[0];
      itk2vtk(v, isg.u);

      v.Set_vnl_vector(geometry3DofSlice->GetMatrixColumn(1));
      isg.ps[1]=v.GetNorm();
      v/=isg.ps[1];
      itk2vtk(v, isg.v);

      v.Set_vnl_vector(geometry3DofSlice->GetMatrixColumn(2));
      isg.ps[2]=v.GetNorm();
      v/=isg.ps[2];
      itk2vtk(v, isg.w);

      itkDebugMacro(<<"isg: o("<<isg.o[0]<<" "<<isg.o[1]<<" "<<isg.o[2]<<") u("<<isg.u[0]<<" "<<isg.u[1]<<" "<<isg.u[2]<<") v("<<isg.v[0]<<" "<<isg.v[1]<<" "<<isg.v[2]<<") w("<<isg.w[0]<<" "<<isg.w[1]<<" "<<isg.w[2]<<") "<<t);

      itkDebugMacro(<<"writing slice: "<<s <<" "<<t);

      cur=ipPicClone(resultslice->GetOutput()->GetPic());
      ipPicDelTag( cur, "SOURCE HEADER" );

      source=ipPicClone(sourceslice->GetOutput()->GetPic());

      if (m_Name.c_str())
      {
        ipPicTSV_t* nameTag = (ipPicTSV_t *) malloc( sizeof(ipPicTSV_t) );
        nameTag->type = ipPicASCII;
        nameTag->bpe = 8;
        strcpy( nameTag->tag, "SERIES DESCRIPTION");
        nameTag->dim = 1;
        nameTag->value = malloc( strlen(m_Name.c_str()) );
        strncpy((char *)nameTag->value, m_Name.c_str(), strlen(m_Name.c_str()));
        nameTag->n[0] = strlen(m_Name.c_str());
        ipPicAddTag( source, nameTag );
        if (nameTag) {
          ipPicFreeTag (nameTag);
        }
      }

      QcPlugin::addTags( cur, source, prev==NULL );

      QcPlugin::addDicomHeader( cur, &isg );
      QcPlugin::addIcon( cur, true );

      QcPlugin::addLevelWindow( cur, (int)(m_LevelWindow.GetLevel()), (int)(m_LevelWindow.GetWindow()));

      QcPlugin::changeImageType( cur, const_cast<char*>(m_ImageTypeName.c_str()) );

      cur->dim = 2;

      if( prev )
        QcPlugin::changeSeries( cur, prev );
      m_LightBox->addImage( cur );

      prev = cur;
    }
  }

#endif
}

void mitk::LightBoxResultImageWriter::Write() const
{
  const_cast<mitk::LightBoxResultImageWriter*>(this)->GenerateData();
}
<commit_msg>just some short comments<commit_after>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html 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 notices for more information.

=========================================================================*/

#include "mitkLightBoxResultImageWriter.h"

#ifdef CHILIPLUGIN
#include <chili/plugin.h>
#include <chili/qclightbox.h>
#include <chili/qclightboxmanager.h>
#include <chili/isg.h>
#endif

#include <mitkImage.h>
#include <mitkImageSliceSelector.h>
#include <mitkFrameOfReferenceUIDManager.h>
#include <mitkChiliPlugin.h>

#include <itkRootTreeIterator.h>
#include <itkImageFileReader.h>

mitk::LightBoxResultImageWriter::LightBoxResultImageWriter()
{
  m_ImageTypeName = "Image, Segmentation";
}

mitk::LightBoxResultImageWriter::~LightBoxResultImageWriter()
{
}

const mitk::Image *mitk::LightBoxResultImageWriter::GetInput(void)
{
  return static_cast< const mitk::Image * >(this->ProcessObject::GetInput(0));
}

void mitk::LightBoxResultImageWriter::SetInput(const mitk::Image *image)
{
  this->ProcessObject::SetNthInput( 0, const_cast< mitk::Image * >( image ) );
}

void mitk::LightBoxResultImageWriter::SetInputByNode(const mitk::DataTreeNode *node)
{
  if(node==NULL)
    return;

  SetInput(dynamic_cast<mitk::Image*>(node->GetData()));

  node->GetLevelWindow(m_LevelWindow, NULL, "levelWindow");
  node->GetLevelWindow(m_LevelWindow, NULL);
  char imageTypeName[200];
  if(node->GetStringProperty("type name", imageTypeName, NULL))
    SetImageTypeName(imageTypeName);
  char name[200];
  if (node->GetStringProperty("name", name, NULL))
    SetName(name);
}

const mitk::Image *mitk::LightBoxResultImageWriter::GetSourceImage(void)
{
  return static_cast< const mitk::Image * >(this->ProcessObject::GetInput(1));
}

/// set the image that should be stored to the database
void mitk::LightBoxResultImageWriter::SetSourceImage(const mitk::Image *source)
{
  this->ProcessObject::SetNthInput( 1, const_cast< mitk::Image * >( source ) );
}

/// set the "example image" that is needed for writing (and already existent in the database)
bool mitk::LightBoxResultImageWriter::SetSourceByTreeSearch(mitk::DataTreeIteratorBase* iterator)
{
  if(iterator==NULL)
    return false;

  const mitk::Image* image = GetInput();

  if(image == NULL)
    return false;

  mitk::DataTreeIteratorClone it=new itk::RootTreeIterator<DataTreeBase>(iterator->GetTree(), iterator->GetNode());
  bool LoadedFromChili;
  while(!it->IsAtEnd())
  {
    //const char * name;
    //if(it->Get()->GetStringProperty("name", name, NULL))
    //{
    //  itkDebugMacro(<<"candidate: "<<name);
    //}
    //else
    //{
    //  itkDebugMacro(<<"candidate: no name");
    //}

    itkGenericOutputMacro(<<"it-> name"<<it->Get()->GetPropertyList()->GetProperty("name")->GetValueAsString());
    //if(it->Get()->GetBoolProperty("LoadedFromChili", LoadedFromChili) && LoadedFromChili)
    if (true)
    {
      mitk::Image::Pointer sourcecandidate=dynamic_cast<mitk::Image*>(it->Get()->GetData());
      if(sourcecandidate.IsNotNull())
      {
        itkDebugMacro(<<"found sourcecandidate: ");
        if(image->GetDimension()<=sourcecandidate->GetDimension())
        {
          int i, dim=image->GetDimension();
          for(i=0; i<dim;++i)
            if(image->GetDimension(i)!=sourcecandidate->GetDimension(i))
              break;
          if(i==dim)
          {
            SetSourceImage(sourcecandidate);
            return true;
            itkDebugMacro(<<"dim incorrect: "<<i <<" "<<dim);
          }
        }
      }
    }
    ++it;
    itkDebugMacro(<<"xxxx");
  }
  itkDebugMacro(<<"yyyyyyyyyyyyyyyyyyyyy");
  return false;
}

void mitk::LightBoxResultImageWriter::SetLightBox(QcLightbox* lightbox)
{
  if(lightbox!=m_LightBox)
  {
    m_LightBox=lightbox;
    Modified();
  }
}

void mitk::LightBoxResultImageWriter::SetLightBoxToCurrentLightBox()
{
#ifdef CHILIPLUGIN
  QcPlugin* plugin = mitk::ChiliPlugin::GetPluginInstance();
  if(plugin==NULL)
  {
    itkExceptionMacro(<<"GetPluginInstance()==NULL: Plugin is not initialized correctly !");
  }
  SetLightBox(plugin->lightboxManager()->getActiveLightbox());
#endif
}

bool mitk::LightBoxResultImageWriter::SetLightBoxToNewLightBox()
{
#ifdef CHILIPLUGIN
  QcPlugin* plugin = mitk::ChiliPlugin::GetPluginInstance();
  if(plugin==NULL)
  {
    itkExceptionMacro(<<"GetPluginInstance()==NULL: Plugin is not initialized correctly !");
  }
  int lightboxCount = plugin->lightboxManager()->getLightboxes().count();
  QcLightbox * newLightbox;
  for (int i = 0; i < lightboxCount; i++)
  {
    newLightbox = plugin->lightboxManager()->getLightboxes().at(i);
    if (newLightbox->getFrames() == 0)
    {
      newLightbox->activate();
      newLightbox->show();
      SetLightBox(newLightbox);
      return true;
    }
  }
  return false;
  //QWidget* parentWidget = (QWidget*) plugin->parent();
  //QcLightbox * newLightbox = new QcLightbox(parentWidget,NULL,(uint)0) ;
  //SetLightBox(newLightbox);
#endif
  return false;
}

bool mitk::LightBoxResultImageWriter::SetLightBoxToCorrespondingLightBox()
{
#ifdef CHILIPLUGIN
  QcPlugin* plugin = mitk::ChiliPlugin::GetPluginInstance();
  if(plugin==NULL)
  {
    itkExceptionMacro(<<"GetPluginInstance()==NULL: Plugin is not initialized correctly !");
  }
  QcLightbox * activeLightbox = plugin->lightboxManager()->getActiveLightbox();
  ipPicDescriptor * currPic =	activeLightbox->fetchVolume();
  ipPicTSV_t* seriesDescriptionTag = ipPicQueryTag(currPic, "SERIES DESCRIPTION");
  if (seriesDescriptionTag)
  {
    if (*((char*)seriesDescriptionTag->value) == *(m_Name.c_str()))
    {
      activeLightbox->clear();
      SetLightBox(activeLightbox);
      return true;
    }
    else return false;
  }
  else return false;
#endif
  return false;
}

QcLightbox* mitk::LightBoxResultImageWriter::GetLightBox() const
{
  return m_LightBox;
}

void mitk::LightBoxResultImageWriter::GenerateData()
{
#ifdef CHILIPLUGIN
  itkDebugMacro(<<"GenerateData ");
  const Image* image = GetInput();
  const Image* sourceimage = GetSourceImage();
  if((image==NULL) || (sourceimage==NULL) || (m_LightBox==NULL))
  {
    itk::ImageFileReaderException e(__FILE__, __LINE__);
    itk::OStringStream msg;
    if(image==NULL)
      msg << "image not set. ";
    if(sourceimage==NULL)
      msg << "source-image not set. ";
    if(m_LightBox==NULL)
      msg << "lightbox not set. ";
    e.SetDescription(msg.str().c_str());
    throw e;
    return;
  }

  ImageSliceSelector::Pointer resultslice = ImageSliceSelector::New();
  ImageSliceSelector::Pointer sourceslice = ImageSliceSelector::New();

  resultslice->SetInput(image);
  sourceslice->SetInput(sourceimage);

  mitk::SlicedGeometry3D* sourceSlicedGeometry;
  mitk::Geometry3D* geometry3DofSlice;
  Point3D origin;
  Vector3D v;

  sourceSlicedGeometry = sourceimage->GetSlicedGeometry();

  origin = sourceSlicedGeometry->GetCornerPoint();

  interSliceGeometry_t isg;
  memcpy(isg.forUID, mitk::FrameOfReferenceUIDManager::GetFrameOfReferenceUID(sourceSlicedGeometry->GetFrameOfReferenceID()), 128);
  isg.psu = ipPicUtilMillimeter;

  ipPicDescriptor *cur, *source, *prev=NULL;
  LevelWindow levelwindow;
  int s, t;
  int smax, tmax;
  smax = image->GetDimension(2);
  tmax = image->GetDimension(3);
  itkDebugMacro(<<"writing image: "<<m_ImageTypeName);
  itkDebugMacro(<<"lv: "<<m_LevelWindow.GetMin() <<" "<<m_LevelWindow.GetMax());
  for(s=smax-1;s>=0;--s)
  {
    resultslice->SetSliceNr(s);
    sourceslice->SetSliceNr(s);
    for(t=0;t<tmax;++t)
    {
      resultslice->SetTimeNr(t);
      sourceslice->SetTimeNr(t);
      resultslice->Update();
      sourceslice->Update();

      geometry3DofSlice = sourceSlicedGeometry->GetGeometry2D(s);

      v=geometry3DofSlice->GetCornerPoint().GetVectorFromOrigin();
      itk2vtk(v, isg.o);

      v-=origin;
      isg.sl = v.GetNorm();

      v.Set_vnl_vector(geometry3DofSlice->GetMatrixColumn(0));
      isg.ps[0]=v.GetNorm();
      v/=isg.ps[0];
      itk2vtk(v, isg.u);

      v.Set_vnl_vector(geometry3DofSlice->GetMatrixColumn(1));
      isg.ps[1]=v.GetNorm();
      v/=isg.ps[1];
      itk2vtk(v, isg.v);

      v.Set_vnl_vector(geometry3DofSlice->GetMatrixColumn(2));
      isg.ps[2]=v.GetNorm();
      v/=isg.ps[2];
      itk2vtk(v, isg.w);

      itkDebugMacro(<<"isg: o("<<isg.o[0]<<" "<<isg.o[1]<<" "<<isg.o[2]<<") u("<<isg.u[0]<<" "<<isg.u[1]<<" "<<isg.u[2]<<") v("<<isg.v[0]<<" "<<isg.v[1]<<" "<<isg.v[2]<<") w("<<isg.w[0]<<" "<<isg.w[1]<<" "<<isg.w[2]<<") "<<t);

      itkDebugMacro(<<"writing slice: "<<s <<" "<<t);

      cur=ipPicClone(resultslice->GetOutput()->GetPic());
      ipPicDelTag( cur, "SOURCE HEADER" );

      source=ipPicClone(sourceslice->GetOutput()->GetPic());

      if (m_Name.c_str())
      {
        ipPicTSV_t* nameTag = (ipPicTSV_t *) malloc( sizeof(ipPicTSV_t) );
        nameTag->type = ipPicASCII;
        nameTag->bpe = 8;
        strcpy( nameTag->tag, "SERIES DESCRIPTION");
        nameTag->dim = 1;
        nameTag->value = malloc( strlen(m_Name.c_str()) );
        strncpy((char *)nameTag->value, m_Name.c_str(), strlen(m_Name.c_str()));
        nameTag->n[0] = strlen(m_Name.c_str());
        ipPicAddTag( source, nameTag );
        if (nameTag) {
          ipPicFreeTag (nameTag);
        }
      }

      QcPlugin::addTags( cur, source, prev==NULL );

      QcPlugin::addDicomHeader( cur, &isg );
      QcPlugin::addIcon( cur, true );

      QcPlugin::addLevelWindow( cur, (int)(m_LevelWindow.GetLevel()), (int)(m_LevelWindow.GetWindow()));

      QcPlugin::changeImageType( cur, const_cast<char*>(m_ImageTypeName.c_str()) );

      cur->dim = 2;

      if( prev )
        QcPlugin::changeSeries( cur, prev ); // same series as previous slice
      m_LightBox->addImage( cur );

      prev = cur;
    }
  }

#endif
}

void mitk::LightBoxResultImageWriter::Write() const
{
  const_cast<mitk::LightBoxResultImageWriter*>(this)->GenerateData();
}
<|endoftext|>


<commit_before>/** @file
 *
 * @ingroup dspLibrary
 *
 * @brief Unit tests for the #TTSampleMatrix class
 *
 * @details
 *
 * @see TTSampleMatrix
 *
 * @authors Tim Place, Nathan Wolek
 *
 * @copyright Copyright © 2012 by Tim Place, Nathan Wolek @n
 * This code is licensed under the terms of the "New BSD License" @n
 * http://creativecommons.org/licenses/BSD/
 */

#include "TTSampleMatrix.h"

/* */
#define TESTFILE "/Users/nathanwolek/Desktop/geese_clip.aif"
#define TESTNUMCHANNELS 2
#define TESTSAMPLERATE 44100
#define TESTDURATIONINSAMPLES 88202
#define TESTDURATIONINSECONDS 2.00004535
#define TESTTITLE ""
#define TESTARTIST ""
#define TESTDATE ""
#define TESTANNOTATION ""
/* */

/*
 #define TESTFILE "/Volumes/Storage/Audio/200604femf15/pitched/ding_b2.aiff"
 #define TESTNUMCHANNELS 1
 #define TESTSAMPLERATE 44100
 #define TESTDURATIONINSAMPLES 39493
 #define TESTDURATIONINSECONDS 0.89553288
 #define TESTTITLE ""
 #define TESTARTIST ""
 #define TESTDATE ""
 #define TESTANNOTATION ""
 */

TTErr TTSampleMatrix::test(TTValue& returnedTestInfo)
{
	int					errorCount = 0;
	int					testAssertionCount = 0;

	// for tests
	TTInt16				numChannels = 2;
	TTUInt32			numSamples = 50000;  // TODO: xcode says this is ambiguous when signed?
	TTFloat32			duration = 1500;
	int                 test9Index = 10;
	int                 test10Index = 11;
	TTInt32				test1Return, test2Return, test7Return;
	TTFloat32			test3Return, test6Return;
	TTSampleValue		test9Return, test10Return, test11Return, test12return, test13return;

	TTTestLog("Test resizing of the SampleMatrix...");

	// TEST 1: can we set the number of channels?
	this->setAttributeValue("numChannels", numChannels);

	this->getAttributeValue("numChannels", test1Return);

	TTBoolean result = { numChannels == test1Return };

	TTTestAssertion("numChannels is set properly",
					result,
					testAssertionCount,
					errorCount);

	if(!result)
	{
		TTTestLog("Expected a value of %i, but returned value was %i", numChannels, test1Return);
	}

	// TEST 2: can we set the number of samples?
	//this->setAttributeValue("lengthInSamples", numSamples);  // TODO: xcode says this is ambiguous?
	this->setLengthInSamples(numSamples);

	this->getAttributeValue("lengthInSamples", test2Return);

	TTBoolean result2 = { numSamples == test2Return };

	TTTestAssertion("lengthInSamples is set properly",
								result2,
								testAssertionCount,
								errorCount);
	if(!result2)
	{
		TTTestLog("Expected a value of %i, but returned value was %i", numSamples, test2Return);
	}

	// TEST 3: is the length in sec computed properly after setting length in samples?
	TTFloat32 computedDuration3 = (numSamples / this->mSampleRate);

	this->getAttributeValue("lengthInSeconds", test3Return);

	TTBoolean result3 = TTTestFloatEquivalence(computedDuration3, test3Return);

	TTTestAssertion("after lengthInSamples is set, lengthInSeconds is correct",
								result3,
								testAssertionCount,
								errorCount);

	if(!result3)
	{
		TTTestLog("Expected a value of %f, but returned value was %f", computedDuration3, test3Return);
	}

	// TEST 4: is the matrix of samples the expected size? (lifted from TTMatrix.test.cpp)
	TTUInt32 computedDataSize4 = sizeof(TTFloat64) * numChannels * numSamples;

	TTBoolean result4 = { computedDataSize4 == this->mDataSize };

	TTTestAssertion("correct amount of data storage calculated",
								result4,
								testAssertionCount,
								errorCount);

	if(!result4)
	{
		TTTestLog("Expected a value of %i, but returned value was %i", computedDataSize4, this->mDataSize);
	}

	// TEST 5: Is the component stride right? (lifted from TTMatrix.test.cpp)
	TTBoolean result5 = { sizeof(TTFloat64) == this->mComponentStride };

	TTTestAssertion("correct byte-stride between values calculated",
								result5,
								testAssertionCount,
								errorCount);

	if(!result5)
	{
		TTTestLog("Expected a value of %i, but returned value was %i", sizeof(TTFloat64), this->mComponentStride);
	}

	// TEST 6: can we set the length in seconds?
	this->setAttributeValue("lengthInSeconds", duration);

	this->getAttributeValue("lengthInSeconds", test6Return);

	TTBoolean result6 = TTTestFloatEquivalence(duration, test6Return);

	TTTestAssertion("lengthInSeconds is set properly",
								result6,
								testAssertionCount,
								errorCount);

	if(!result6)
	{
		TTTestLog("Expected a value of %f, but returned value was %f", duration, test6Return);
	}

	// TEST 7: is the length in samples computed properly after setting length in ms?
	TTUInt32 computedSamples7 = TTUInt32(duration * this->mSampleRate);

	this->getAttributeValue("lengthInSamples", test7Return);

	TTBoolean result7 = { computedSamples7 == test7Return };

	TTTestAssertion("after lengthInSeconds is set, lengthInSamples is correct",
								result7,
								testAssertionCount,
								errorCount);

	if(!result7)
	{
		TTTestLog("Expected a value of %i, but returned value was %i", computedSamples7, test7Return);
	}

	// TEST 8 (REPEAT TEST 4 WITH NEW SIZE): is the matrix of samples the expected size?
	TTUInt32 computedDataSize8 = sizeof(TTFloat64) * numChannels * test7Return;

	TTBoolean result8 = { computedDataSize8 == this->mDataSize };

	TTTestAssertion("correct amount of data storage calculated with new length",
								result8,
								testAssertionCount,
								errorCount);

	if(!result8)
	{
		TTTestLog("Expected a value of %i, but returned value was %i", computedDataSize8, this->mDataSize);
	}

	// TEST 9 & 10: set the value of two consecutive samples
	TTSampleValue pokeValue9 = TTRandom64();
	TTSampleValue pokeValue10 = TTRandom64();

	this->poke(test9Index, 0, pokeValue9);
	this->poke(test10Index, 0, pokeValue10);

	this->peek(test9Index, 0, test9Return);
	this->peek(test10Index, 0, test10Return);

	TTBoolean result9 = { pokeValue9 == test9Return };

	TTTestAssertion("set value one of two consecutive samples",
								result9,
								testAssertionCount,
								errorCount);

	if(!result9)
	{
		TTTestLog("Expected a value of %f, but returned value was %f", pokeValue9, test9Return);
	}

	TTBoolean result10 = { pokeValue10 == test10Return };

	TTTestAssertion("set value two of two consecutive samples",
								result10,
								testAssertionCount,
								errorCount);

	if(!result10)
	{
		TTTestLog("Expected a value of %f, but returned value was %f", pokeValue10, test10Return);
	}

    // TEST 10a: confirm that pulling value via "peek" message works too

    TTValue input(test10Index);
    input.append(0);
    TTValue output;

    this->sendMessage("peek", input, output);

    TTBoolean result10a = { TTTestFloatEquivalence(pokeValue10, TTSampleValue(output)) };

	TTTestAssertion("set value two of two consecutive samples",
                    result10a,
                    testAssertionCount,
                    errorCount);

	if(!result10a)
	{
		TTTestLog("Expected a value of %f, but returned value was %f", pokeValue10, TTSampleValue(output));
	}

	// TEST 11: test for interpolation between two consecutive samples
	TTFloat64 computedInterpFraction = TTRandom64();
	TTFloat64 computedInterpIndex = test9Index + computedInterpFraction;
	TTSampleValue computedInterpValue11 = (computedInterpFraction * pokeValue10) + ((1.0 - computedInterpFraction) * pokeValue9);

	this->peeki(computedInterpIndex, 0, test11Return);

	TTBoolean result11 = TTTestFloatEquivalence(computedInterpValue11, test11Return);

	TTTestAssertion("interpolate between two consecutive samples",
								result11,
								testAssertionCount,
								errorCount);

	if(!result11)
	{
		TTTestLog("Expected a value of %f, but returned value was %f", computedInterpValue11, test11Return);
	}

	// TODO: inbounds testing on hold until sorted out at TTMatrix parent class

	// TEST 12 & 13: test whether out of bounds indices produce errors at head

	TTInt32 computedIndex12 = -1; // 1 before the head
	TTInt32 computedIndex13 = 0; // the head
	TTErr test12Err = this->peek(computedIndex12, 0, test12return);
	TTErr test13Err = this->peek(computedIndex13, 0, test13return);

	TTBoolean result12 = { test12Err == kTTErrOutOfBounds };
	TTBoolean result13 = { test13Err == kTTErrNone };

	TTTestAssertion("peeking sample before index 0 produces an error",
								result12,
								testAssertionCount,
								errorCount);

	if(!result12)
	{
		TTTestLog("Expected a value of %i, but returned value was %i", kTTErrOutOfBounds, test12Err);
	}

	TTTestAssertion("peeking sample at index 0 produces no error",
								result13,
								testAssertionCount,
								errorCount);

	if(!result13)
	{
		TTTestLog("Expected a value of %i, but returned value was %i", kTTErrNone, test13Err);
	}

	// TEST 14 & 15: test whether out of bounds indices produce errors at tail

	TTInt32 computedIndex14 = test7Return; // should be latest size in samples
	TTInt32 computedIndex15 = test7Return - 1; // the tail is actually one less
	TTErr test14Err = this->poke(computedIndex14, 0, test12return);
	TTErr test15Err = this->poke(computedIndex15, 0, test13return);

	TTBoolean result14 = { test14Err == kTTErrOutOfBounds };
	TTBoolean result15 = { test15Err == kTTErrNone };

	TTTestAssertion("poking sample after index max produces an error",
								result14,
								testAssertionCount,
								errorCount);

	if(!result14)
	{
		TTTestLog("Expected a value of %i, but returned value was %i", kTTErrOutOfBounds, test14Err);
	}

	TTTestAssertion("poking sample at index max produces no error",
								result15,
								testAssertionCount,
								errorCount);

	if(!result15)
	{
		TTTestLog("Expected a value of %i, but returned value was %i", kTTErrNone, test15Err);
	}

	// TEST 16 & 17: incrementing & decrementing userCount

	TTUInt16 test16expect = 4;
	TTUInt16 test17expect = 2;

	this->incrementUserCount();
	this->incrementUserCount();
	this->incrementUserCount();
	this->incrementUserCount();
	TTUInt16 test16return = this->mUserCount;

	this->decrementUserCount();
	this->decrementUserCount();
	TTUInt16 test17return = this->mUserCount;

	TTBoolean result16 = { test16expect == test16return };
	TTBoolean result17 = { test17expect == test17return };

	TTTestAssertion("incrementing userCount produces expected results",
								result16,
								testAssertionCount,
								errorCount);

	if(!result16)
	{
		TTTestLog("Expected a value of %i, but returned value was %i", test16expect, test16return);
	}

	TTTestAssertion("decrementing userCount produces expected results",
								result17,
								testAssertionCount,
								errorCount);

	if(!result17)
	{
		TTTestLog("Expected a value of %i, but returned value was %i", test17expect, test17return);
	}

	// TEST 18 & 19: setting & testing bufferPoolStage

	TTBoolean test18expect = true;
	TTBoolean test19expect = false;

	this->setBufferPoolStage(kSM_Active);
	TTBoolean test18return = this->isBufferPoolStage(kSM_Active);
	TTBoolean test19return = this->isBufferPoolStage(kSM_BecomingIdle);

	TTBoolean result18 = { test18expect == test18return };
	TTBoolean result19 = { test19expect == test19return };

	TTTestAssertion("reports bufferPoolStage as active",
								result18,
								testAssertionCount,
								errorCount);

	if(!result18)
	{
		TTTestLog("Expected a value of %i, but returned value was %i", test18expect, test18return);
	}

	TTTestAssertion("reports bufferPoolStage as NOT becoming idle",
								result19,
								testAssertionCount,
								errorCount);

	if(!result19)
	{
		TTTestLog("Expected a value of %i, but returned value was %i", test19expect, test19return);
	}

    /********/

    // NW: this test is dependent on the SoundfileLib extension and should therefore be moved to that project
    /*
    // TEST 20: load values from a sound file

    TTInt16				numChannels20 = 2;
	TTUInt32			numSamples20 = 500;  // TODO: xcode says this is ambiguous when signed?

    this->setAttributeValue("numChannels", numChannels20);
    this->setAttributeValue("lengthInSamples", numSamples20);

    TTTestLog("\nThe samplematrix currently has %i samples and %i channels", numChannels20, numSamples20);

    // set up TTValues passed to the public method
    TTValue loadInput, loadOuput;
    loadInput.append(TT(TESTFILE));

    TTBoolean result20 = { load(loadInput, loadOuput) == kTTErrNone };

    TTTestAssertion("load operates successfully",
                    result20,
                    testAssertionCount,
                    errorCount);

    TTTestLog("Let's look at the first 10 values...");

    TTSampleValue return20b;
    TTErr error20b;

    for (int channel=0;channel<numChannels20;channel++)
    {
        TTTestLog("Channel %i", channel);
        for (int sample=0;sample<10;sample++)
        {
            error20b = this->peek(sample,channel,return20b);
            if (error20b == kTTErrNone)
            {
                TTTestLog("peek sample %i returned the value %f", sample, return20b);
            } else {
                TTTestLog("peek returned an error for sample %i", sample);
            }
        }
    }
    // end of test that needs to be moved
    */

	/*

	int					badSampleCount = 0;
	TTAudioObjectBasePtr	samplematrixObject = NULL;
	TTAudioSignalPtr	input = NULL;
	TTAudioSignalPtr	output = NULL;

	// TODO: test filling with sine wave
	// TODO: test scaling (applying gain)
	// TODO: test normalizing (with optional arg, and also without an optional arg)

	TTObjectBaseInstantiate("samplematrix", &samplematrixObject, kTTVal1);

	TTObjectBaseRelease(&input);
	TTObjectBaseRelease(&output);
	TTObjectBaseRelease(&samplematrixObject);

	*/

	// Wrap up the test results to pass back to whoever called this test
	return TTTestFinish(testAssertionCount, errorCount, returnedTestInfo);
}

<commit_msg>some clean up from resolving #175<commit_after>/** @file
 *
 * @ingroup dspLibrary
 *
 * @brief Unit tests for the #TTSampleMatrix class
 *
 * @details
 *
 * @see TTSampleMatrix
 *
 * @authors Tim Place, Nathan Wolek
 *
 * @copyright Copyright © 2012 by Tim Place, Nathan Wolek @n
 * This code is licensed under the terms of the "New BSD License" @n
 * http://creativecommons.org/licenses/BSD/
 */

#include "TTSampleMatrix.h"

/* */
#define TESTFILE "/Users/nathanwolek/Desktop/geese_clip.aif"
#define TESTNUMCHANNELS 2
#define TESTSAMPLERATE 44100
#define TESTDURATIONINSAMPLES 88202
#define TESTDURATIONINSECONDS 2.00004535
#define TESTTITLE ""
#define TESTARTIST ""
#define TESTDATE ""
#define TESTANNOTATION ""
/* */

/*
 #define TESTFILE "/Volumes/Storage/Audio/200604femf15/pitched/ding_b2.aiff"
 #define TESTNUMCHANNELS 1
 #define TESTSAMPLERATE 44100
 #define TESTDURATIONINSAMPLES 39493
 #define TESTDURATIONINSECONDS 0.89553288
 #define TESTTITLE ""
 #define TESTARTIST ""
 #define TESTDATE ""
 #define TESTANNOTATION ""
 */

TTErr TTSampleMatrix::test(TTValue& returnedTestInfo)
{
	int					errorCount = 0;
	int					testAssertionCount = 0;

	// for tests
	TTInt16				numChannels = 2;
	TTUInt32			numSamples = 50000;  // TODO: xcode says this is ambiguous when signed?
	TTFloat32			duration = 1500;
	int                 test9Index = 10;
	int                 test10Index = 11;
	TTInt32				test1Return, test2Return, test7Return;
	TTFloat32			test3Return, test6Return;
	TTSampleValue		test9Return, test10Return, test11Return, test12return, test13return;

	TTTestLog("Test resizing of the SampleMatrix...");

	// TEST 1: can we set the number of channels?
	this->setAttributeValue("numChannels", numChannels);

	this->getAttributeValue("numChannels", test1Return);

	TTBoolean result = { numChannels == test1Return };

	TTTestAssertion("numChannels is set properly",
					result,
					testAssertionCount,
					errorCount);

	if(!result)
	{
		TTTestLog("Expected a value of %i, but returned value was %i", numChannels, test1Return);
	}

	// TEST 2: can we set the number of samples?
	//this->setAttributeValue("lengthInSamples", numSamples);  // TODO: xcode says this is ambiguous?
	this->setLengthInSamples(numSamples);

	this->getAttributeValue("lengthInSamples", test2Return);

	TTBoolean result2 = { numSamples == test2Return };

	TTTestAssertion("lengthInSamples is set properly",
								result2,
								testAssertionCount,
								errorCount);
	if(!result2)
	{
		TTTestLog("Expected a value of %i, but returned value was %i", numSamples, test2Return);
	}

	// TEST 3: is the length in sec computed properly after setting length in samples?
	TTFloat32 computedDuration3 = (numSamples / this->mSampleRate);

	this->getAttributeValue("lengthInSeconds", test3Return);

	TTBoolean result3 = TTTestFloatEquivalence(computedDuration3, test3Return);

	TTTestAssertion("after lengthInSamples is set, lengthInSeconds is correct",
								result3,
								testAssertionCount,
								errorCount);

	if(!result3)
	{
		TTTestLog("Expected a value of %f, but returned value was %f", computedDuration3, test3Return);
	}

	// TEST 4: is the matrix of samples the expected size? (lifted from TTMatrix.test.cpp)
	TTUInt32 computedDataSize4 = sizeof(TTFloat64) * numChannels * numSamples;

	TTBoolean result4 = { computedDataSize4 == this->mDataSize };

	TTTestAssertion("correct amount of data storage calculated",
								result4,
								testAssertionCount,
								errorCount);

	if(!result4)
	{
		TTTestLog("Expected a value of %i, but returned value was %i", computedDataSize4, this->mDataSize);
	}

	// TEST 5: Is the component stride right? (lifted from TTMatrix.test.cpp)
	TTBoolean result5 = { sizeof(TTFloat64) == this->mComponentStride };

	TTTestAssertion("correct byte-stride between values calculated",
								result5,
								testAssertionCount,
								errorCount);

	if(!result5)
	{
		TTTestLog("Expected a value of %i, but returned value was %i", sizeof(TTFloat64), this->mComponentStride);
	}

	// TEST 6: can we set the length in seconds?
	this->setAttributeValue("lengthInSeconds", duration);

	this->getAttributeValue("lengthInSeconds", test6Return);

	TTBoolean result6 = TTTestFloatEquivalence(duration, test6Return);

	TTTestAssertion("lengthInSeconds is set properly",
								result6,
								testAssertionCount,
								errorCount);

	if(!result6)
	{
		TTTestLog("Expected a value of %f, but returned value was %f", duration, test6Return);
	}

	// TEST 7: is the length in samples computed properly after setting length in ms?
	TTUInt32 computedSamples7 = TTUInt32(duration * this->mSampleRate);

	this->getAttributeValue("lengthInSamples", test7Return);

	TTBoolean result7 = { computedSamples7 == test7Return };

	TTTestAssertion("after lengthInSeconds is set, lengthInSamples is correct",
								result7,
								testAssertionCount,
								errorCount);

	if(!result7)
	{
		TTTestLog("Expected a value of %i, but returned value was %i", computedSamples7, test7Return);
	}

	// TEST 8 (REPEAT TEST 4 WITH NEW SIZE): is the matrix of samples the expected size?
	TTUInt32 computedDataSize8 = sizeof(TTFloat64) * numChannels * test7Return;

	TTBoolean result8 = { computedDataSize8 == this->mDataSize };

	TTTestAssertion("correct amount of data storage calculated with new length",
								result8,
								testAssertionCount,
								errorCount);

	if(!result8)
	{
		TTTestLog("Expected a value of %i, but returned value was %i", computedDataSize8, this->mDataSize);
	}

	// TEST 9 & 10: set the value of two consecutive samples
	TTSampleValue pokeValue9 = TTRandom64();
	TTSampleValue pokeValue10 = TTRandom64();

	this->poke(test9Index, 0, pokeValue9);
	this->poke(test10Index, 0, pokeValue10);

	this->peek(test9Index, 0, test9Return);
	this->peek(test10Index, 0, test10Return);

	TTBoolean result9 = { pokeValue9 == test9Return };

	TTTestAssertion("set value one of two consecutive samples",
								result9,
								testAssertionCount,
								errorCount);

	if(!result9)
	{
		TTTestLog("Expected a value of %f, but returned value was %f", pokeValue9, test9Return);
	}

	TTBoolean result10 = { pokeValue10 == test10Return };

	TTTestAssertion("set value two of two consecutive samples",
								result10,
								testAssertionCount,
								errorCount);

	if(!result10)
	{
		TTTestLog("Expected a value of %f, but returned value was %f", pokeValue10, test10Return);
	}

    // TEST 10a: confirm that pulling value via "peek" message works too

    TTValue input(test10Index);
    input.append(0);
    TTValue output;

    this->sendMessage("peek", input, output);

    TTBoolean result10a = { TTTestFloatEquivalence(pokeValue10, TTSampleValue(output)) };

	TTTestAssertion("set value two of two consecutive samples",
                    result10a,
                    testAssertionCount,
                    errorCount);

	if(!result10a)
	{
		TTTestLog("Expected a value of %f, but returned value was %f", pokeValue10, TTSampleValue(output));
	}

	// TEST 11: test for interpolation between two consecutive samples
	TTFloat64 computedInterpFraction = TTRandom64();
	TTFloat64 computedInterpIndex = test9Index + computedInterpFraction;
	TTSampleValue computedInterpValue11 = (computedInterpFraction * pokeValue10) + ((1.0 - computedInterpFraction) * pokeValue9);

	this->peeki(computedInterpIndex, 0, test11Return);

	TTBoolean result11 = TTTestFloatEquivalence(computedInterpValue11, test11Return);

	TTTestAssertion("interpolate between two consecutive samples",
								result11,
								testAssertionCount,
								errorCount);

	if(!result11)
	{
		TTTestLog("Expected a value of %f, but returned value was %f", computedInterpValue11, test11Return);
	}

	// TODO: inbounds testing on hold until sorted out at TTMatrix parent class

	// TEST 12 & 13: test whether out of bounds indices produce errors at head

	TTInt32 computedIndex12 = -1; // 1 before the head
	TTInt32 computedIndex13 = 0; // the head
	TTErr test12Err = this->peek(computedIndex12, 0, test12return);
	TTErr test13Err = this->peek(computedIndex13, 0, test13return);

	TTBoolean result12 = { test12Err == kTTErrOutOfBounds };
	TTBoolean result13 = { test13Err == kTTErrNone };

	TTTestAssertion("peeking sample before index 0 produces an error",
								result12,
								testAssertionCount,
								errorCount);

	if(!result12)
	{
		TTTestLog("Expected a value of %i, but returned value was %i", kTTErrOutOfBounds, test12Err);
	}

	TTTestAssertion("peeking sample at index 0 produces no error",
								result13,
								testAssertionCount,
								errorCount);

	if(!result13)
	{
		TTTestLog("Expected a value of %i, but returned value was %i", kTTErrNone, test13Err);
	}

	// TEST 14 & 15: test whether out of bounds indices produce errors at tail

	TTInt32 computedIndex14 = test7Return; // should be latest size in samples
	TTInt32 computedIndex15 = test7Return - 1; // the tail is actually one less
	TTErr test14Err = this->poke(computedIndex14, 0, test12return);
	TTErr test15Err = this->poke(computedIndex15, 0, test13return);

	TTBoolean result14 = { test14Err == kTTErrOutOfBounds };
	TTBoolean result15 = { test15Err == kTTErrNone };

	TTTestAssertion("poking sample after index max produces an error",
								result14,
								testAssertionCount,
								errorCount);

	if(!result14)
	{
		TTTestLog("Expected a value of %i, but returned value was %i", kTTErrOutOfBounds, test14Err);
	}

	TTTestAssertion("poking sample at index max produces no error",
								result15,
								testAssertionCount,
								errorCount);

	if(!result15)
	{
		TTTestLog("Expected a value of %i, but returned value was %i", kTTErrNone, test15Err);
	}

	// TEST 16 & 17: incrementing & decrementing userCount

	TTUInt16 test16expect = 4;
	TTUInt16 test17expect = 2;

	this->incrementUserCount();
	this->incrementUserCount();
	this->incrementUserCount();
	this->incrementUserCount();
	TTUInt16 test16return = this->mUserCount;

	this->decrementUserCount();
	this->decrementUserCount();
	TTUInt16 test17return = this->mUserCount;

	TTBoolean result16 = { test16expect == test16return };
	TTBoolean result17 = { test17expect == test17return };

	TTTestAssertion("incrementing userCount produces expected results",
								result16,
								testAssertionCount,
								errorCount);

	if(!result16)
	{
		TTTestLog("Expected a value of %i, but returned value was %i", test16expect, test16return);
	}

	TTTestAssertion("decrementing userCount produces expected results",
								result17,
								testAssertionCount,
								errorCount);

	if(!result17)
	{
		TTTestLog("Expected a value of %i, but returned value was %i", test17expect, test17return);
	}

	// TEST 18 & 19: setting & testing bufferPoolStage

	TTBoolean test18expect = true;
	TTBoolean test19expect = false;

	this->setBufferPoolStage(kSM_Active);
	TTBoolean test18return = this->isBufferPoolStage(kSM_Active);
	TTBoolean test19return = this->isBufferPoolStage(kSM_BecomingIdle);

	TTBoolean result18 = { test18expect == test18return };
	TTBoolean result19 = { test19expect == test19return };

	TTTestAssertion("reports bufferPoolStage as active",
								result18,
								testAssertionCount,
								errorCount);

	if(!result18)
	{
		TTTestLog("Expected a value of %i, but returned value was %i", test18expect, test18return);
	}

	TTTestAssertion("reports bufferPoolStage as NOT becoming idle",
								result19,
								testAssertionCount,
								errorCount);

	if(!result19)
	{
		TTTestLog("Expected a value of %i, but returned value was %i", test19expect, test19return);
	}

	/*

	int					badSampleCount = 0;
	TTAudioObjectBasePtr	samplematrixObject = NULL;
	TTAudioSignalPtr	input = NULL;
	TTAudioSignalPtr	output = NULL;

	// TODO: test filling with sine wave
	// TODO: test scaling (applying gain)
	// TODO: test normalizing (with optional arg, and also without an optional arg)

	TTObjectBaseInstantiate("samplematrix", &samplematrixObject, kTTVal1);

	TTObjectBaseRelease(&input);
	TTObjectBaseRelease(&output);
	TTObjectBaseRelease(&samplematrixObject);

	*/

	// Wrap up the test results to pass back to whoever called this test
	return TTTestFinish(testAssertionCount, errorCount, returnedTestInfo);
}

<|endoftext|>


<commit_before>/** This file is part of Qt Media Hub**

Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).*
All rights reserved.

Contact:  Nokia Corporation qmh-development@qt-project.org

You may use this file under the terms of the BSD license
as follows:

Redistribution and use in source and binary forms, with or
without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.

* Neither the name of Nokia Corporation and its Subsidiary(-ies)
nor the names of its contributors may be used to endorse or promote
products derived from this software without specific prior
written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. **/

#include "libraryinfo.h"
#include "globalsettings.h"

#include <QtCore>
#include <QtGui>

#ifdef QT5
#include <QGuiApplication>
#else
#include <QApplication>
//#include <QtWidgets>
#endif

static QStringList standardResourcePaths(GlobalSettings *settings, const GlobalSettings::Option option, const QString &suffix, const QString &relativeOffset = QString("/../"))
{
    static const QString platformBinOffset
        #ifdef Q_OS_MAC
            = settings->value(GlobalSettings::Installed).toBool() ? "/../Resources/" : "/../../../";
        #else
            = "";
        #endif

    // The order of the added paths is relevant!
    QStringList paths;

    // allows changing resource paths with -skinsPath on runtime
    const QString settingsPath = settings->value(option).toString();
    if (!settingsPath.isEmpty())
        paths << QDir(settingsPath).absolutePath();

    // Relative paths
    paths <<  QCoreApplication::applicationDirPath() % relativeOffset % platformBinOffset % suffix % "/";

    // allows changing resource paths with exporting with QMH_SKINS_PATH on runtime
    const QByteArray envPath = qgetenv(QString("QMH_" % suffix.toUpper() % "_PATH").toLatin1());
    if (!envPath.isEmpty())
        paths << QDir(envPath).absolutePath();

    paths << QMH_PROJECTROOT % QString::fromLatin1("/hub/share/qtmediahub/") % suffix % "/";
    paths << QMH_PREFIX % QString::fromLatin1("/share/qtmediahub/") % suffix % "/";

    paths << QDir::homePath() % QString::fromLatin1("/.qtmediahub/") % suffix % "/";

    return paths;
}

QStringList LibraryInfo::skinPaths(GlobalSettings *settings)
{
    return standardResourcePaths(settings, GlobalSettings::SkinsPath, "skins", "/../../../");
}

QStringList LibraryInfo::applicationPaths(GlobalSettings *settings)
{
    return standardResourcePaths(settings, GlobalSettings::AppsPath, "apps", "/../../../");
}

QStringList LibraryInfo::translationPaths(GlobalSettings *settings)
{
    return standardResourcePaths(settings, GlobalSettings::TranslationsPath, "translations");
}

QStringList LibraryInfo::resourcePaths(GlobalSettings *settings)
{
    return standardResourcePaths(settings, GlobalSettings::ResourcesPath, "resources");
}

QStringList LibraryInfo::keyboardMapPaths(GlobalSettings *settings)
{
    return standardResourcePaths(settings, GlobalSettings::KeymapsPath, "keymaps");
}

QStringList LibraryInfo::qmlImportPaths(GlobalSettings *settings)
{
    return standardResourcePaths(settings, GlobalSettings::ImportsPath, "imports");
}

QStringList LibraryInfo::pluginPaths(GlobalSettings *settings)
{
    QStringList ret;
    if (settings->value(GlobalSettings::Installed).toBool())
    {
#ifdef Q_OS_MAC
        ret << QCoreApplication::applicationDirPath() % QString::fromLatin1("../Resources/qtmediahub");
#else
        ret << QMH_PREFIX % QString::fromLatin1("/lib/qtmediahub/");
#endif
    } else {
        ret << QCoreApplication::applicationDirPath() % QString::fromLatin1("/../lib/qtmediahub/");
    }
    ret << QDir::homePath() % QString::fromLatin1("/.qtmediahub/lib");
    return ret;
}

QString LibraryInfo::thumbnailPath(GlobalSettings *settings)
{
    const QString path = settings->value(GlobalSettings::ThumbnailPath).toString();
    if (!path.isEmpty())
        return path;

    return QDir::homePath() % "/.thumbnails/" % qApp->applicationName() % "/";
}

QString LibraryInfo::databaseFilePath()
{
    return LibraryInfo::dataPath() % "/media.db";
}
<commit_msg>Fix relative paths after Johannes' shuffling of dirs<commit_after>/** This file is part of Qt Media Hub**

Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).*
All rights reserved.

Contact:  Nokia Corporation qmh-development@qt-project.org

You may use this file under the terms of the BSD license
as follows:

Redistribution and use in source and binary forms, with or
without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.

* Neither the name of Nokia Corporation and its Subsidiary(-ies)
nor the names of its contributors may be used to endorse or promote
products derived from this software without specific prior
written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. **/

#include "libraryinfo.h"
#include "globalsettings.h"

#include <QtCore>
#include <QtGui>

#ifdef QT5
#include <QGuiApplication>
#else
#include <QApplication>
//#include <QtWidgets>
#endif

static QStringList standardResourcePaths(GlobalSettings *settings, const GlobalSettings::Option option, const QString &suffix, const QString &relativeOffset = QString("/../"))
{
    static const QString platformBinOffset
        #ifdef Q_OS_MAC
            = settings->value(GlobalSettings::Installed).toBool() ? "/../Resources/" : "/../../../";
        #else
            = "";
        #endif

    // The order of the added paths is relevant!
    QStringList paths;

    // allows changing resource paths with -skinsPath on runtime
    const QString settingsPath = settings->value(option).toString();
    if (!settingsPath.isEmpty())
        paths << QDir(settingsPath).absolutePath();

    // In repo paths: skins, apps and friends when developing
    paths <<  QCoreApplication::applicationDirPath() % relativeOffset % platformBinOffset % suffix % "/";

    // allows changing resource paths with exporting with QMH_SKINS_PATH on runtime
    const QByteArray envPath = qgetenv(QString("QMH_" % suffix.toUpper() % "_PATH").toLatin1());
    if (!envPath.isEmpty())
        paths << QDir(envPath).absolutePath();

    // Executable relative paths
    paths <<  QCoreApplication::applicationDirPath() % relativeOffset % platformBinOffset % QString::fromLatin1("/share/qtmediahub/") % suffix % "/";

    paths << QMH_PROJECTROOT % QString::fromLatin1("/hub/share/qtmediahub/") % suffix % "/";
    paths << QMH_PREFIX % QString::fromLatin1("/share/qtmediahub/") % suffix % "/";

    paths << QDir::homePath() % QString::fromLatin1("/.qtmediahub/") % suffix % "/";

    return paths;
}

QStringList LibraryInfo::skinPaths(GlobalSettings *settings)
{
    return standardResourcePaths(settings, GlobalSettings::SkinsPath, "skins", "/../../../");
}

QStringList LibraryInfo::applicationPaths(GlobalSettings *settings)
{
    return standardResourcePaths(settings, GlobalSettings::AppsPath, "apps", "/../../../");
}

QStringList LibraryInfo::translationPaths(GlobalSettings *settings)
{
    return standardResourcePaths(settings, GlobalSettings::TranslationsPath, "translations");
}

QStringList LibraryInfo::resourcePaths(GlobalSettings *settings)
{
    return standardResourcePaths(settings, GlobalSettings::ResourcesPath, "resources");
}

QStringList LibraryInfo::keyboardMapPaths(GlobalSettings *settings)
{
    return standardResourcePaths(settings, GlobalSettings::KeymapsPath, "keymaps");
}

QStringList LibraryInfo::qmlImportPaths(GlobalSettings *settings)
{
    return standardResourcePaths(settings, GlobalSettings::ImportsPath, "imports");
}

QStringList LibraryInfo::pluginPaths(GlobalSettings *settings)
{
    QStringList ret;
    if (settings->value(GlobalSettings::Installed).toBool())
    {
#ifdef Q_OS_MAC
        ret << QCoreApplication::applicationDirPath() % QString::fromLatin1("../Resources/qtmediahub");
#else
        ret << QMH_PREFIX % QString::fromLatin1("/lib/qtmediahub/");
#endif
    } else {
        ret << QCoreApplication::applicationDirPath() % QString::fromLatin1("/../lib/qtmediahub/");
    }
    ret << QDir::homePath() % QString::fromLatin1("/.qtmediahub/lib");
    return ret;
}

QString LibraryInfo::thumbnailPath(GlobalSettings *settings)
{
    const QString path = settings->value(GlobalSettings::ThumbnailPath).toString();
    if (!path.isEmpty())
        return path;

    return QDir::homePath() % "/.thumbnails/" % qApp->applicationName() % "/";
}

QString LibraryInfo::databaseFilePath()
{
    return LibraryInfo::dataPath() % "/media.db";
}
<|endoftext|>


<commit_before>#include "ssh.hh"

namespace nix {

SSHMaster::SSHMaster(const std::string & host, const std::string & keyFile, bool useMaster, bool compress, int logFD)
    : host(host)
    , fakeSSH(host == "localhost")
    , keyFile(keyFile)
    , useMaster(useMaster && !fakeSSH)
    , compress(compress)
    , logFD(logFD)
{
    if (host == "" || hasPrefix(host, "-"))
        throw Error("invalid SSH host name '%s'", host);
}

void SSHMaster::addCommonSSHOpts(Strings & args)
{
    for (auto & i : tokenizeString<Strings>(getEnv("NIX_SSHOPTS").value_or("")))
        args.push_back(i);
    if (!keyFile.empty())
        args.insert(args.end(), {"-i", keyFile});
    if (compress)
        args.push_back("-C");
}

std::unique_ptr<SSHMaster::Connection> SSHMaster::startCommand(const std::string & command)
{
    Path socketPath = startMaster();

    Pipe in, out;
    in.create();
    out.create();

    auto conn = std::make_unique<Connection>();
    conn->sshPid = startProcess([&]() {
        restoreSignals();

        close(in.writeSide.get());
        close(out.readSide.get());

        if (dup2(in.readSide.get(), STDIN_FILENO) == -1)
            throw SysError("duping over stdin");
        if (dup2(out.writeSide.get(), STDOUT_FILENO) == -1)
            throw SysError("duping over stdout");
        if (logFD != -1 && dup2(logFD, STDERR_FILENO) == -1)
            throw SysError("duping over stderr");

        Strings args;

        if (fakeSSH) {
            args = { "bash", "-c" };
        } else {
            args = { "ssh", host.c_str(), "-x", "-a" };
            addCommonSSHOpts(args);
            if (socketPath != "")
                args.insert(args.end(), {"-S", socketPath});
            if (verbosity >= lvlChatty)
                args.push_back("-v");
        }

        args.push_back(command);
        execvp(args.begin()->c_str(), stringsToCharPtrs(args).data());

        throw SysError("executing '%s' on '%s'", command, host);
    });

    in.readSide = -1;
    out.writeSide = -1;

    conn->out = std::move(out.readSide);
    conn->in = std::move(in.writeSide);

    return conn;
}

Path SSHMaster::startMaster()
{
    if (!useMaster) return "";

    auto state(state_.lock());

    if (state->sshMaster != -1) return state->socketPath;

    state->tmpDir = std::make_unique<AutoDelete>(createTempDir("", "nix", true, true, 0700));

    state->socketPath = (Path) *state->tmpDir + "/ssh.sock";

    Pipe out;
    out.create();

    state->sshMaster = startProcess([&]() {
        restoreSignals();

        close(out.readSide.get());

        if (dup2(out.writeSide.get(), STDOUT_FILENO) == -1)
            throw SysError("duping over stdout");

        Strings args =
            { "ssh", host.c_str(), "-M", "-N", "-S", state->socketPath
            , "-o", "LocalCommand=echo started"
            , "-o", "PermitLocalCommand=yes"
            };
        if (verbosity >= lvlChatty)
            args.push_back("-v");
        addCommonSSHOpts(args);
        execvp(args.begin()->c_str(), stringsToCharPtrs(args).data());

        throw SysError("starting SSH master");
    });

    out.writeSide = -1;

    std::string reply;
    try {
        reply = readLine(out.readSide.get());
    } catch (EndOfFile & e) { }

    if (reply != "started")
        throw Error("failed to start SSH master connection to '%s'", host);

    return state->socketPath;
}

}
<commit_msg>libstore/ssh: Improve error message on failing `execvp`<commit_after>#include "ssh.hh"

namespace nix {

SSHMaster::SSHMaster(const std::string & host, const std::string & keyFile, bool useMaster, bool compress, int logFD)
    : host(host)
    , fakeSSH(host == "localhost")
    , keyFile(keyFile)
    , useMaster(useMaster && !fakeSSH)
    , compress(compress)
    , logFD(logFD)
{
    if (host == "" || hasPrefix(host, "-"))
        throw Error("invalid SSH host name '%s'", host);
}

void SSHMaster::addCommonSSHOpts(Strings & args)
{
    for (auto & i : tokenizeString<Strings>(getEnv("NIX_SSHOPTS").value_or("")))
        args.push_back(i);
    if (!keyFile.empty())
        args.insert(args.end(), {"-i", keyFile});
    if (compress)
        args.push_back("-C");
}

std::unique_ptr<SSHMaster::Connection> SSHMaster::startCommand(const std::string & command)
{
    Path socketPath = startMaster();

    Pipe in, out;
    in.create();
    out.create();

    auto conn = std::make_unique<Connection>();
    conn->sshPid = startProcess([&]() {
        restoreSignals();

        close(in.writeSide.get());
        close(out.readSide.get());

        if (dup2(in.readSide.get(), STDIN_FILENO) == -1)
            throw SysError("duping over stdin");
        if (dup2(out.writeSide.get(), STDOUT_FILENO) == -1)
            throw SysError("duping over stdout");
        if (logFD != -1 && dup2(logFD, STDERR_FILENO) == -1)
            throw SysError("duping over stderr");

        Strings args;
        const char * execInto;

        if (fakeSSH) {
            execInto = "bash";
            args = { "bash", "-c" };
        } else {
            execInto = "ssh";
            args = { "ssh", host.c_str(), "-x", "-a" };
            addCommonSSHOpts(args);
            if (socketPath != "")
                args.insert(args.end(), {"-S", socketPath});
            if (verbosity >= lvlChatty)
                args.push_back("-v");
        }

        args.push_back(command);
        execvp(args.begin()->c_str(), stringsToCharPtrs(args).data());

        // could not exec ssh/bash
        throw SysError("Failed to exec into %s. Is it in PATH?", execInto);
    });

    in.readSide = -1;
    out.writeSide = -1;

    conn->out = std::move(out.readSide);
    conn->in = std::move(in.writeSide);

    return conn;
}

Path SSHMaster::startMaster()
{
    if (!useMaster) return "";

    auto state(state_.lock());

    if (state->sshMaster != -1) return state->socketPath;

    state->tmpDir = std::make_unique<AutoDelete>(createTempDir("", "nix", true, true, 0700));

    state->socketPath = (Path) *state->tmpDir + "/ssh.sock";

    Pipe out;
    out.create();

    state->sshMaster = startProcess([&]() {
        restoreSignals();

        close(out.readSide.get());

        if (dup2(out.writeSide.get(), STDOUT_FILENO) == -1)
            throw SysError("duping over stdout");

        Strings args =
            { "ssh", host.c_str(), "-M", "-N", "-S", state->socketPath
            , "-o", "LocalCommand=echo started"
            , "-o", "PermitLocalCommand=yes"
            };
        if (verbosity >= lvlChatty)
            args.push_back("-v");
        addCommonSSHOpts(args);
        execvp(args.begin()->c_str(), stringsToCharPtrs(args).data());

        throw SysError("Failed to exec into ssh. Is it in PATH?");
    });

    out.writeSide = -1;

    std::string reply;
    try {
        reply = readLine(out.readSide.get());
    } catch (EndOfFile & e) { }

    if (reply != "started")
        throw Error("failed to start SSH master connection to '%s'", host);

    return state->socketPath;
}

}
<|endoftext|>


<commit_before>#include <kernel/cpu.h>
#include <kernel/irq.h>
#include <kernel/itoa.h>
#include <kernel/kb.h>
#include <kernel/panic.h>
#include <kernel/pic.h>
#include <kernel/ports.h>
#include <kernel/screen.h>
#include <kernel/state.h>

bool stdin_available = false;
char stdin_char = '\0';

static unsigned int alpha_counter;

extern "C" void isr_main(struct CPUState cpu_state) {
	if(cpu_state.interrupt == IRQ7) { return; }
	if(cpu_state.interrupt >= IRQ0) {
		ports_outb(PIC_PORT_MASTER, 0x20);
		if(cpu_state.interrupt == IRQ15) { return; }
		if(cpu_state.interrupt >= IRQ8) {
			ports_outb(PIC_PORT_SLAVE, 0x20);
		}
	}

	uint32_t cr2;
	__asm__ __volatile__ ("mov %%cr2, %0" : "=r" (cr2));

	char s0[] = "        ";
	char s1[] = "                                ";
	uint8_t scancode;

	switch(cpu_state.interrupt) {
	case 0x0: /* divide by zero */
		screen_print("divide-by-zero error\n");
		break;
	case 0xD: /* general protection fault */
		screen_print("GPF at 0x");
		uitoa((unsigned int)cpu_state.iret_eip, s0, 16);
		screen_print(s0);
		screen_print(" error=0b");
		uitoa((unsigned int)cpu_state.error, s1, 2);
		screen_print(s1);
		screen_put('\n');
		break;
	case 0xE: /* page fault */
		screen_print("page fault at 0x");
		uitoa((unsigned int)cpu_state.iret_eip, s0, 16);
		screen_print(s0);
		screen_print(" cr2=");
		uitoa((unsigned int)cr2, s0, 16);
		screen_print(s0);
		screen_print(" error=0b");
		uitoa((unsigned int)cpu_state.error, s1, 2);
		screen_print(s1);
		screen_put('\n');
		{
			void **ebp = (void **)cpu_state.ebp;
			for(unsigned int frame = 0; frame < 8; ++frame) {
				void * eip = ebp[1];
				if(eip == NULL) { break; }
				ebp = (void **)ebp[0];
				screen_print("from 0x");
				s0[uitoa((unsigned int)eip, s0, 16)] = '\0';
				screen_print(s0);
				screen_put('\n');
			}
		}
		if(cr2 == 0x1000000) {
			screen_print("allocating page at 0x");
			uitoa((unsigned int)cr2, s0, 16);
			screen_print(s0);
			screen_put('\n');

			Pager::TableID table = cr2 / PAGE_ALLOCATOR_PAGE_SIZE / 1024;
			Pager::PageID  page  = cr2 / PAGE_ALLOCATOR_PAGE_SIZE % 1024;
			_kernel_state.pager->AllocAt(table, page);
		} else {
			kernel_panic("page fault");
		}
		break;
	case IRQ0: /* PIT */
		//screen_print("yield\n");
		break;
	case IRQ1: /* keyboard */
		scancode = ports_inb(0x60); // read scancode from keyboard
		stdin_available = true;
		//stdin_char = 'a' + alpha_counter++ % 26;
		stdin_char = kb_scancode1_char(scancode);

		//screen_print("scancode = 0x");
		//uitoa((unsigned int)scancode, s0, 16);
		//screen_print(s0);
		//screen_put('\n');
		break;
	case IRQ14: /* primary ATA channel */
		break;
	default:
		screen_print("unhandled interrupt: 0x");
		uitoa((unsigned int)cpu_state.interrupt, s0, 16);
		screen_print(s0);
		screen_put('\n');
		break;
	}
}
<commit_msg>Fix PF stack trace for missing frames<commit_after>#include <kernel/cpu.h>
#include <kernel/irq.h>
#include <kernel/itoa.h>
#include <kernel/kb.h>
#include <kernel/panic.h>
#include <kernel/pic.h>
#include <kernel/ports.h>
#include <kernel/screen.h>
#include <kernel/state.h>

bool stdin_available = false;
char stdin_char = '\0';

static unsigned int alpha_counter;

extern "C" void isr_main(struct CPUState cpu_state) {
	if(cpu_state.interrupt == IRQ7) { return; }
	if(cpu_state.interrupt >= IRQ0) {
		ports_outb(PIC_PORT_MASTER, 0x20);
		if(cpu_state.interrupt == IRQ15) { return; }
		if(cpu_state.interrupt >= IRQ8) {
			ports_outb(PIC_PORT_SLAVE, 0x20);
		}
	}

	uint32_t cr2;
	__asm__ __volatile__ ("mov %%cr2, %0" : "=r" (cr2));

	char s0[] = "        ";
	char s1[] = "                ";
	char s2[] = "                                ";
	uint8_t scancode;

	switch(cpu_state.interrupt) {
	case 0x0: /* divide by zero */
		screen_print("divide-by-zero error\n");
		break;
	case 0xD: /* general protection fault */
		screen_print("GPF at 0x");
		uitoa((unsigned int)cpu_state.iret_eip, s0, 16);
		screen_print(s0);
		screen_print(" error=0b");
		uitoa((unsigned int)cpu_state.error, s2, 2);
		screen_print(s2);
		screen_put('\n');
		break;
	case 0xE: /* page fault */
		screen_print("page fault at 0x");
		uitoa((unsigned int)cpu_state.iret_eip, s0, 16);
		screen_print(s0);
		screen_print(" cr2=0x");
		uitoa((unsigned int)cr2, s0, 16);
		screen_print(s0);
		screen_print(" error=0b");
		uitoa((unsigned int)cpu_state.error, s1, 2);
		screen_print(s1);
		screen_put('\n');
		{
			void **ebp = (void **)cpu_state.ebp;
			for(unsigned int frame = 0; frame < 3; ++frame) {
				// if ebp is outside of stack region
				if(ebp < (void *)0x8000000 || ebp > (void *)(0x8000000 + 0x100000)) {
					screen_print("from <no frame pointer>\n");
					break;
				}

				void * eip = ebp[1];
				if(eip == NULL) { break; }
				ebp = (void **)ebp[0];

				screen_print("from 0x");
				s0[uitoa((unsigned int)eip, s0, 16)] = '\0';
				screen_print(s0);
				screen_put('\n');
			}
		}
		if(cr2 == 0x1000000) {
			screen_print("allocating page at 0x");
			uitoa((unsigned int)cr2, s0, 16);
			screen_print(s0);
			screen_put('\n');

			Pager::TableID table = cr2 / PAGE_ALLOCATOR_PAGE_SIZE / 1024;
			Pager::PageID  page  = cr2 / PAGE_ALLOCATOR_PAGE_SIZE % 1024;
			_kernel_state.pager->AllocAt(table, page);
		} else {
			kernel_panic("page fault");
		}
		break;
	case IRQ0: /* PIT */
		//screen_print("yield\n");
		break;
	case IRQ1: /* keyboard */
		scancode = ports_inb(0x60); // read scancode from keyboard
		stdin_available = true;
		//stdin_char = 'a' + alpha_counter++ % 26;
		stdin_char = kb_scancode1_char(scancode);

		//screen_print("scancode = 0x");
		//uitoa((unsigned int)scancode, s0, 16);
		//screen_print(s0);
		//screen_put('\n');
		break;
	case IRQ14: /* primary ATA channel */
		break;
	default:
		screen_print("unhandled interrupt: 0x");
		uitoa((unsigned int)cpu_state.interrupt, s0, 16);
		screen_print(s0);
		screen_put('\n');
		break;
	}
}
<|endoftext|>