<commit_before>#include "SINRunTester.h"

#include "Common.h"
#include "SINTest.h"
#include "SINLogger.h"
#include "SINASTNode.h"
#include "SINConstants.h"
#include "SINParserAPI.h"
#include "SINTestingCommon.h"
#include "SINLoggerManager.h"
#include "SINFileOutputStream.h"
#include "SINBufferedOutputStream.h"
#include "SINTreeEvaluationVisitor.h"
#include "SINPreserveASTEvaluatorVisitor.h"
#include "SINASTTreeVisualisationVisitor.h"
#include "SINASTMITTreeVisualizerXMLProducerVisitor.h"
#include "SINLibrary.h"
#include "SINLibraryFunction.h"
#include "SINLibraryFunctions.h"
#include "SINMemoryCellLibFunction.h"
#include "SINAlloc.h"
#include "SINASTTreeCtrlVisitor.h"
#include "SINShiftToMetaEvaluatorASTVisitor.h"
#include "SINASTUnparseTreeVisitor.h"
#include "SINASTCloneVisitor.h"

#define SIN_TESTS_RUN_RUN(NAME)               SINTESTS_RUNTEST(NAME)
#define SIN_TESTS_RUN_TESTDEF(NAME,TESTCODE)  SINTESTS_TESTDEF(NAME,TESTCODE)
#define SIN_TESTS_RUN_TESTRUN(NAME)           SINTESTS_CALLTEST(NAME)

#ifdef _MSC_VER
	#define FILE_PATH	".\\..\\..\\..\\Tests\\SINRun_Test\\Resource\\sin_run_test.sin"
#else
	#define FILE_PATH	"./../../../Tests/SINRun_Test/Resource/sin_run_test.sin"
#endif

namespace SIN {
	namespace Tests {
		namespace Run {
			static InstanceProxy<SIN::Logger> logger;
			static InstanceProxy<TestFactory> test_factory;

			namespace { static void __list_parsing_errors(ParserAPI const& _papi) {
				for (
					LexAndBisonParseArguments::Errors::const_iterator ite = _papi.GetErrors().begin(),
						end = _papi.GetErrors().end();
					ite != end;
					++ite
				)
					logger->Error(to_string("Parsing error: line ") << ite->second <<
						": " << ite->first);
			}}

			//------------------------------------------------------------------
			class RunFileTest : public Test {
			public:
				RunFileTest(void): Test("RunFileTest") { }
			protected:
				virtual void TestLogic(void);
			};

			static void __print_handler(SIN::String const& _msg) {
				//SIN::LoggerManager::StreamLogger oot("STDOUT: ", SIN::Logging::Record::FINEST, SIN::STDOUT, SIN::Logging::RecordPrinter());
				//oot.Notice(_msg);
				static_cast<OutputStream&>(STDOUT) << _msg;
			}

			//------------------------------------------------------------------

			void RunFileTest::TestLogic(void) {
				ParserAPI test;
				test.ParseFile(FILE_PATH);
				if (test.HasError()) {
					__list_parsing_errors(test);
					ASSERT(!test.HasError()); // certain failure here, to stop the test
				}
				ASTNode* root = test.GetAST();
				ASSERT(root != 0x00);

				FileOutputStream _foutxml("RunTreeVisualisation.xml", FileOutputStream::Mode::Truncate());
				FileOutputStream _fouttxt("RunTreeVisualisation.txt", FileOutputStream::Mode::Truncate());
				FileOutputStream _ctrltxt("RunTreeCtrlVisualisation.txt", FileOutputStream::Mode::Truncate());
				FileOutputStream _metatxt("ShiftToMetaEvaluatorASTVisitor.txt", FileOutputStream::Mode::Truncate());

				BufferedOutputStream foutxml(_foutxml);
				BufferedOutputStream fouttxt(_fouttxt);
				BufferedOutputStream ctrltxt(_ctrltxt);
				BufferedOutputStream metatxt(_metatxt);

				ASTTreeCtrlVisitor						ctrlvis(ctrltxt);
				ASTTreeVisualisationVisitor				visitor(fouttxt);
				//ASTTreeVisualisationVisitor				metaVisualVisitor(metatxt);
				//ASTMITTreeVisualizerXMLProducerVisitor	mitvis(foutxml);
				//ASTCloneVisitor							cloneVisitor;
				//ASTUnparseTreeVisitor					uparseVisitor;
				//
				root->Accept(&visitor);
				root->Accept(&ctrlvis);
				//root->Accept(&mitvis);
				//root->Accept(&uparseVisitor);
				//root->Accept(&cloneVisitor);

				//String unpasedString1 = uparseVisitor.UnparsedString();
				//uparseVisitor.CleanUnparsedString();

				//cloneVisitor.Root()->Accept(&uparseVisitor);
				//String unpasedString2 = uparseVisitor.UnparsedString();
				//
				//SINASSERT(unpasedString1 == unpasedString2);

				//

				//static_cast<OutputStream&>(STDOUT) << "\n\n" << unpasedString2 << "\n\n\n";

				foutxml.flush();
				fouttxt.flush();
				ctrltxt.flush();

				//ASTNode & lastKid = static_cast<ASTNode &>(*root->rbegin());
				//cloneVisitor.Resset();
				//lastKid.Accept(&cloneVisitor);
				//uparseVisitor.CleanUnparsedString();
				//ASTNode * cloneRoot = cloneVisitor.Root();
				//cloneRoot->Accept(&uparseVisitor);
				//static_cast<OutputStream&>(STDOUT) << "\n\n" << uparseVisitor.UnparsedString() << "\n\n\n";
				//cloneVisitor.DeleteListAndAST();

				VM::VirtualState vs;
				vs.SetPrintHandler(&__print_handler);

				Library::Library lib;

				Library::Functions::print			print;
				Library::Functions::println			println;
				Library::Functions::arguments		arguments;
				Library::Functions::totalarguments	totalarguments;
				Library::Functions::tostring		tostring;
				Library::Functions::strtonum		strtonum;
				Library::Functions::typeof			typeof;
				Library::Functions::fileopen        fileopen;
				Library::Functions::fileread        fileread;

				lib.InstallFunction(&print			);
				lib.InstallFunction(&println		);
				lib.InstallFunction(&arguments		);
				lib.InstallFunction(&totalarguments	);
				lib.InstallFunction(&tostring		);
				lib.InstallFunction(&strtonum		);
				lib.InstallFunction(&typeof			);
				lib.InstallFunction(&fileopen       );
				lib.InstallFunction(&fileread       );

				// TODO remove the reference here and watch it burn
				SymbolTable *globalSymTable = &vs.CurrentStable();
				globalSymTable->Insert("print",          SINEWCLASS(MemoryCellLibFunction, (&print)));
				globalSymTable->Insert("println",        SINEWCLASS(MemoryCellLibFunction, (&println)));
				globalSymTable->Insert("arguments",      SINEWCLASS(MemoryCellLibFunction, (&arguments)));
				globalSymTable->Insert("totalarguments", SINEWCLASS(MemoryCellLibFunction, (&totalarguments)));
				globalSymTable->Insert("tostring",       SINEWCLASS(MemoryCellLibFunction, (&tostring)));
				globalSymTable->Insert("strtonum",       SINEWCLASS(MemoryCellLibFunction, (&strtonum)));
				globalSymTable->Insert("typeof",         SINEWCLASS(MemoryCellLibFunction, (&typeof)));
				globalSymTable->Insert("fileopen",       SINEWCLASS(MemoryCellLibFunction, (&fileopen)));
				globalSymTable->Insert("fileread",       SINEWCLASS(MemoryCellLibFunction, (&fileread)));

				TreeEvaluationVisitor eval(&lib, &vs);
				root->Accept(&eval);

				//ShiftToMetaEvaluatorASTVisitor shifter(eval);
				//root->Accept(&shifter);
				//shifter.Root()->Accept(&metaVisualVisitor);

				metatxt.flush();
				test.DeleteListAndAST();
//				shifter.DeleteListAndAST();
			}

			//------------------------------------------------------------------
			static void test_RunFile(void){
				SINTESTS_RUNTEST(RunFile);
			}

			//------------------------------------------------------------------

			void test(InstanceProxy<TestFactory> const &tf) {
				logger = LoggerManager::SingletonGetInstance()->GetLogger("SIN::Tests::Run");
				test_factory = tf;
				SIN_TESTS_RUN_TESTRUN(RunFile);
				LoggerManager::SingletonGetInstance()->GetDefaultLoggerFactory()->DestroyLogger(logger);
			}
		}	//namespace Parser
	}		//namespace Tests
}			//namspace SIN
<commit_msg>Runner support run time errors handling.<commit_after>#include "SINRunTester.h"

#include "Common.h"
#include "SINTest.h"
#include "SINLogger.h"
#include "SINASTNode.h"
#include "SINConstants.h"
#include "SINParserAPI.h"
#include "SINTestingCommon.h"
#include "SINLoggerManager.h"
#include "SINFileOutputStream.h"
#include "SINBufferedOutputStream.h"
#include "SINTreeEvaluationVisitor.h"
#include "SINPreserveASTEvaluatorVisitor.h"
#include "SINASTTreeVisualisationVisitor.h"
#include "SINASTMITTreeVisualizerXMLProducerVisitor.h"
#include "SINLibrary.h"
#include "SINLibraryFunction.h"
#include "SINLibraryFunctions.h"
#include "SINMemoryCellLibFunction.h"
#include "SINAlloc.h"
#include "SINASTTreeCtrlVisitor.h"
#include "SINShiftToMetaEvaluatorASTVisitor.h"
#include "SINASTUnparseTreeVisitor.h"
#include "SINASTCloneVisitor.h"
#include "SINRunTimeError.h"

#define SIN_TESTS_RUN_RUN(NAME)               SINTESTS_RUNTEST(NAME)
#define SIN_TESTS_RUN_TESTDEF(NAME,TESTCODE)  SINTESTS_TESTDEF(NAME,TESTCODE)
#define SIN_TESTS_RUN_TESTRUN(NAME)           SINTESTS_CALLTEST(NAME)

#ifdef _MSC_VER
	#define FILE_PATH	".\\..\\..\\..\\Tests\\SINRun_Test\\Resource\\sin_run_test.sin"
#else
	#define FILE_PATH	"./../../../Tests/SINRun_Test/Resource/sin_run_test.sin"
#endif

namespace SIN {
	namespace Tests {
		namespace Run {
			static InstanceProxy<SIN::Logger> logger;
			static InstanceProxy<TestFactory> test_factory;

			namespace { static void __list_parsing_errors(ParserAPI const& _papi) {
				for (
					LexAndBisonParseArguments::Errors::const_iterator ite = _papi.GetErrors().begin(),
						end = _papi.GetErrors().end();
					ite != end;
					++ite
				)
					logger->Error(to_string("Parsing error: line ") << ite->second <<
						": " << ite->first);
			}}

			//------------------------------------------------------------------
			class RunFileTest : public Test {
			public:
				RunFileTest(void): Test("RunFileTest") { }
			protected:
				virtual void TestLogic(void);
			};

			static void __print_handler(SIN::String const& _msg) {
				//SIN::LoggerManager::StreamLogger oot("STDOUT: ", SIN::Logging::Record::FINEST, SIN::STDOUT, SIN::Logging::RecordPrinter());
				//oot.Notice(_msg);
				static_cast<OutputStream&>(STDOUT) << _msg;
			}

			//------------------------------------------------------------------

			void RunFileTest::TestLogic(void) {
				ParserAPI test;
				test.ParseFile(FILE_PATH);
				if (test.HasError()) {
					__list_parsing_errors(test);
					ASSERT(!test.HasError()); // certain failure here, to stop the test
				}
				ASTNode* root = test.GetAST();
				ASSERT(root != 0x00);

				FileOutputStream _foutxml("RunTreeVisualisation.xml", FileOutputStream::Mode::Truncate());
				FileOutputStream _fouttxt("RunTreeVisualisation.txt", FileOutputStream::Mode::Truncate());
				FileOutputStream _ctrltxt("RunTreeCtrlVisualisation.txt", FileOutputStream::Mode::Truncate());
				FileOutputStream _metatxt("ShiftToMetaEvaluatorASTVisitor.txt", FileOutputStream::Mode::Truncate());

				BufferedOutputStream foutxml(_foutxml);
				BufferedOutputStream fouttxt(_fouttxt);
				BufferedOutputStream ctrltxt(_ctrltxt);
				BufferedOutputStream metatxt(_metatxt);

				ASTTreeCtrlVisitor						ctrlvis(ctrltxt);
				ASTTreeVisualisationVisitor				visitor(fouttxt);
				//ASTTreeVisualisationVisitor				metaVisualVisitor(metatxt);
				//ASTMITTreeVisualizerXMLProducerVisitor	mitvis(foutxml);
				//ASTCloneVisitor							cloneVisitor;
				//ASTUnparseTreeVisitor					uparseVisitor;
				//
				root->Accept(&visitor);
				root->Accept(&ctrlvis);
				//root->Accept(&mitvis);
				//root->Accept(&uparseVisitor);
				//root->Accept(&cloneVisitor);

				//String unpasedString1 = uparseVisitor.UnparsedString();
				//uparseVisitor.CleanUnparsedString();

				//cloneVisitor.Root()->Accept(&uparseVisitor);
				//String unpasedString2 = uparseVisitor.UnparsedString();
				//
				//SINASSERT(unpasedString1 == unpasedString2);

				//

				//static_cast<OutputStream&>(STDOUT) << "\n\n" << unpasedString2 << "\n\n\n";

				foutxml.flush();
				fouttxt.flush();
				ctrltxt.flush();

				//ASTNode & lastKid = static_cast<ASTNode &>(*root->rbegin());
				//cloneVisitor.Resset();
				//lastKid.Accept(&cloneVisitor);
				//uparseVisitor.CleanUnparsedString();
				//ASTNode * cloneRoot = cloneVisitor.Root();
				//cloneRoot->Accept(&uparseVisitor);
				//static_cast<OutputStream&>(STDOUT) << "\n\n" << uparseVisitor.UnparsedString() << "\n\n\n";
				//cloneVisitor.DeleteListAndAST();

				VM::VirtualState vs;
				vs.SetPrintHandler(&__print_handler);

				Library::Library lib;

				Library::Functions::print			print;
				Library::Functions::println			println;
				Library::Functions::arguments		arguments;
				Library::Functions::totalarguments	totalarguments;
				Library::Functions::tostring		tostring;
				Library::Functions::strtonum		strtonum;
				Library::Functions::typeof			typeof;
				Library::Functions::fileopen        fileopen;
				Library::Functions::fileread        fileread;

				lib.InstallFunction(&print			);
				lib.InstallFunction(&println		);
				lib.InstallFunction(&arguments		);
				lib.InstallFunction(&totalarguments	);
				lib.InstallFunction(&tostring		);
				lib.InstallFunction(&strtonum		);
				lib.InstallFunction(&typeof			);
				lib.InstallFunction(&fileopen       );
				lib.InstallFunction(&fileread       );

				// TODO remove the reference here and watch it burn
				SymbolTable *globalSymTable = &vs.CurrentStable();
				globalSymTable->Insert("print",          SINEWCLASS(MemoryCellLibFunction, (&print)));
				globalSymTable->Insert("println",        SINEWCLASS(MemoryCellLibFunction, (&println)));
				globalSymTable->Insert("arguments",      SINEWCLASS(MemoryCellLibFunction, (&arguments)));
				globalSymTable->Insert("totalarguments", SINEWCLASS(MemoryCellLibFunction, (&totalarguments)));
				globalSymTable->Insert("tostring",       SINEWCLASS(MemoryCellLibFunction, (&tostring)));
				globalSymTable->Insert("strtonum",       SINEWCLASS(MemoryCellLibFunction, (&strtonum)));
				globalSymTable->Insert("typeof",         SINEWCLASS(MemoryCellLibFunction, (&typeof)));
				globalSymTable->Insert("fileopen",       SINEWCLASS(MemoryCellLibFunction, (&fileopen)));
				globalSymTable->Insert("fileread",       SINEWCLASS(MemoryCellLibFunction, (&fileread)));

				TreeEvaluationVisitor eval(&lib, &vs);

				try {
					root->Accept(&eval);
				} catch(SIN::RunTimeError rte) {
					static_cast<OutputStream&>(STDOUT) << rte.CompleteMessage() << "\n";
					exit(-1);
				} catch(...) {
					static_cast<OutputStream&>(STDOUT) << "Unexpected exception" << "\n";
					exit(-1);
				}
				//ShiftToMetaEvaluatorASTVisitor shifter(eval);
				//root->Accept(&shifter);
				//shifter.Root()->Accept(&metaVisualVisitor);

				metatxt.flush();
				test.DeleteListAndAST();
//				shifter.DeleteListAndAST();
			}

			//------------------------------------------------------------------
			static void test_RunFile(void){
				SINTESTS_RUNTEST(RunFile);
			}

			//------------------------------------------------------------------

			void test(InstanceProxy<TestFactory> const &tf) {
				logger = LoggerManager::SingletonGetInstance()->GetLogger("SIN::Tests::Run");
				test_factory = tf;
				SIN_TESTS_RUN_TESTRUN(RunFile);
				LoggerManager::SingletonGetInstance()->GetDefaultLoggerFactory()->DestroyLogger(logger);
			}
		}	//namespace Parser
	}		//namespace Tests
}			//namspace SIN
<|endoftext|>


<commit_before>//****************************************************************************
// Copyright © 2015 Jan Erik Breimo. All rights reserved.
// Created by Jan Erik Breimo on 2015-12-04.
//
// This file is distributed under the BSD License.
// License text is included with the source distribution.
//****************************************************************************
#include "JsonReaderException.hpp"

#include <sstream>

namespace Yson
{

    JsonReaderException::JsonReaderException()
        : std::logic_error("Unspecified error."),
          m_LineNumber(0),
          m_ColumnNumber(0)
    {
    }

    JsonReaderException::JsonReaderException(const std::string& msg)
        : std::logic_error(msg),
          m_LineNumber(0),
          m_ColumnNumber(0)
    {
    }

    JsonReaderException::JsonReaderException(
            const std::string& msg,
            const std::string& sourceFileName,
            int sourceFileLineNumber,
            const std::string& funcName)
        : std::logic_error(msg)
    {
        std::stringstream ss;
        if (!funcName.empty())
            ss << funcName << "() in ";
        ss << sourceFileName << ":" << sourceFileLineNumber << ": " << msg;
        m_Message = ss.str();
    }

    JsonReaderException::JsonReaderException(
            const std::string& msg,
            const std::string& sourceFileName,
            int sourceFileLineNumber,
            const std::string& funcName,
            size_t fileLineNumber,
            size_t fileColumnNumber)
        : std::logic_error(msg),
          m_LineNumber(fileLineNumber),
          m_ColumnNumber(fileColumnNumber)
    {
        std::stringstream ss;
        if (!funcName.empty())
            ss << funcName << "() in ";
        ss << sourceFileName << ":" << sourceFileLineNumber << ": "
           << "On line " << fileLineNumber
           << ", column " << fileColumnNumber
           << ": " << msg;
        m_Message = ss.str();
    }

    const char* JsonReaderException::what() const _NOEXCEPT
    {
        if (!m_Message.empty())
            return m_Message.c_str();
        return std::exception::what();
    }
}
<commit_msg>Only include debug information in error messages in debug builds.<commit_after>//****************************************************************************
// Copyright © 2015 Jan Erik Breimo. All rights reserved.
// Created by Jan Erik Breimo on 2015-12-04.
//
// This file is distributed under the BSD License.
// License text is included with the source distribution.
//****************************************************************************
#include "JsonReaderException.hpp"

#include <sstream>

namespace Yson
{
    JsonReaderException::JsonReaderException()
        : std::logic_error("Unspecified error."),
          m_LineNumber(0),
          m_ColumnNumber(0)
    {}

    JsonReaderException::JsonReaderException(const std::string& msg)
        : std::logic_error(msg),
          m_LineNumber(0),
          m_ColumnNumber(0)
    {}

    JsonReaderException::JsonReaderException(
            const std::string& msg,
            const std::string& sourceFileName,
            int sourceFileLineNumber,
            const std::string& funcName)
        : std::logic_error(msg)
    {
        #ifndef NDEBUG
            std::stringstream ss;
            if (!funcName.empty())
                ss << funcName << "() in ";
            ss << sourceFileName << ":" << sourceFileLineNumber << ": "
               << msg;
            m_Message = ss.str();
        #endif
    }

    JsonReaderException::JsonReaderException(
            const std::string& msg,
            const std::string& sourceFileName,
            int sourceFileLineNumber,
            const std::string& funcName,
            size_t fileLineNumber,
            size_t fileColumnNumber)
        : std::logic_error(msg),
          m_LineNumber(fileLineNumber),
          m_ColumnNumber(fileColumnNumber)
    {
        std::stringstream ss;
        #ifndef NDEBUG
            if (!funcName.empty())
                ss << funcName << "() in ";
            ss << sourceFileName << ":" << sourceFileLineNumber << ": ";
        #endif
        ss << "On line " << fileLineNumber
           << ", column " << fileColumnNumber
           << ": " << msg;
        m_Message = ss.str();
    }

    const char* JsonReaderException::what() const _NOEXCEPT
    {
        if (!m_Message.empty())
            return m_Message.c_str();
        return std::exception::what();
    }
}
<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2009 Torus Knot Software Ltd
Also see acknowledgements in Readme.html

You may use this sample code for anything you like, it is not covered by the
same license as the rest of the engine.
-----------------------------------------------------------------------------
*/

#include "MaterialControls.h"
#include "OgreLogManager.h"
#include "OgreStringVector.h"
#include "OgreStringConverter.h"
#include "OgreConfigFile.h"
#include "OgreResourceGroupManager.h"
#include "OgreException.h"

/********************************************************************************
            MaterialControls Methods
*********************************************************************************/
void MaterialControls::addControl(const Ogre::String& params)
{
    // params is a string containing using the following format:
    //  "<Control Name>, <Shader parameter name>, <Parameter Type>, <Min Val>, <Max Val>, <Parameter Sub Index>"

    // break up long string into components
    Ogre::StringVector vecparams = Ogre::StringUtil::split(params, ",");

    // if there are not five elements then log error and move on
    if (vecparams.size() != 6)
    {
        Ogre::LogManager::getSingleton().logMessage(
            "Incorrect number of parameters passed in params string for MaterialControls::addControl()" );

        return;
    }

    ShaderControl newControl;
    Ogre::StringUtil::trim(vecparams[0]);
    newControl.Name = vecparams[0];

    Ogre::StringUtil::trim(vecparams[1]);
    newControl.ParamName = vecparams[1];

    Ogre::StringUtil::trim(vecparams[2]);
    if (vecparams[2] == "GPU_VERTEX")
        newControl.ValType = GPU_VERTEX;
    else if (vecparams[2] == "GPU_FRAGMENT")
        newControl.ValType = GPU_FRAGMENT;

    newControl.MinVal = Ogre::StringConverter::parseReal(vecparams[3]);
    newControl.MaxVal = Ogre::StringConverter::parseReal(vecparams[4]);
    newControl.ElementIndex = Ogre::StringConverter::parseInt(vecparams[5]);

    mShaderControlsContainer.push_back(newControl);

}

void loadMaterialControlsFile(MaterialControlsContainer& controlsContainer, const Ogre::String& filename)
{
    // Load material controls from config file
    Ogre::ConfigFile cf;

    try
    {

        cf.load(filename, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "\t;=", true);

        // Go through all sections & controls in the file
        Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();

        Ogre::String secName, typeName, materialName, dataString;

        while (seci.hasMoreElements())
        {
            secName = seci.peekNextKey();
            Ogre::ConfigFile::SettingsMultiMap* settings = seci.getNext();
            if (!secName.empty() && settings)
            {
                materialName = cf.getSetting("material", secName);

                MaterialControls newMaaterialControls(secName, materialName);
                controlsContainer.push_back(newMaaterialControls);

                size_t idx = controlsContainer.size() - 1;

                Ogre::ConfigFile::SettingsMultiMap::iterator i;

                for (i = settings->begin(); i != settings->end(); ++i)
                {
                    typeName = i->first;
                    dataString = i->second;
                    if (typeName == "control")
                        controlsContainer[idx].addControl(dataString);
                }
            }
        }

	    Ogre::LogManager::getSingleton().logMessage( "Material Controls setup" );
    }
    catch (Ogre::Exception e)
    {
        // Guess the file didn't exist
    }
}

void loadAllMaterialControlFiles(MaterialControlsContainer& controlsContainer)
{
    Ogre::StringVectorPtr fileStringVector = Ogre::ResourceGroupManager::getSingleton().findResourceNames( "Popular", "*.controls");
	Ogre::StringVector::iterator controlsFileNameIterator = fileStringVector->begin();

    while ( controlsFileNameIterator != fileStringVector->end() )
	{
        loadMaterialControlsFile(controlsContainer, *controlsFileNameIterator);
        ++controlsFileNameIterator;
	}
}
<commit_msg>Ocean demo: added code to show only supported materials.<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2009 Torus Knot Software Ltd
Also see acknowledgements in Readme.html

You may use this sample code for anything you like, it is not covered by the
same license as the rest of the engine.
-----------------------------------------------------------------------------
*/

#include "MaterialControls.h"
#include "OgreLogManager.h"
#include "OgreStringVector.h"
#include "OgreStringConverter.h"
#include "OgreConfigFile.h"
#include "OgreResourceGroupManager.h"
#include "OgreException.h"
#include "OgreMaterial.h"
#include "OgreTechnique.h"
#include "OgreMaterialManager.h"

/********************************************************************************
            MaterialControls Methods
*********************************************************************************/
void MaterialControls::addControl(const Ogre::String& params)
{
    // params is a string containing using the following format:
    //  "<Control Name>, <Shader parameter name>, <Parameter Type>, <Min Val>, <Max Val>, <Parameter Sub Index>"

    // break up long string into components
    Ogre::StringVector vecparams = Ogre::StringUtil::split(params, ",");

    // if there are not five elements then log error and move on
    if (vecparams.size() != 6)
    {
        Ogre::LogManager::getSingleton().logMessage(
            "Incorrect number of parameters passed in params string for MaterialControls::addControl()" );

        return;
    }

    ShaderControl newControl;
    Ogre::StringUtil::trim(vecparams[0]);
    newControl.Name = vecparams[0];

    Ogre::StringUtil::trim(vecparams[1]);
    newControl.ParamName = vecparams[1];

    Ogre::StringUtil::trim(vecparams[2]);
    if (vecparams[2] == "GPU_VERTEX")
        newControl.ValType = GPU_VERTEX;
    else if (vecparams[2] == "GPU_FRAGMENT")
        newControl.ValType = GPU_FRAGMENT;

    newControl.MinVal = Ogre::StringConverter::parseReal(vecparams[3]);
    newControl.MaxVal = Ogre::StringConverter::parseReal(vecparams[4]);
    newControl.ElementIndex = Ogre::StringConverter::parseInt(vecparams[5]);

    mShaderControlsContainer.push_back(newControl);

}

void loadMaterialControlsFile(MaterialControlsContainer& controlsContainer, const Ogre::String& filename)
{
    // Load material controls from config file
    Ogre::ConfigFile cf;

    try
    {

        cf.load(filename, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "\t;=", true);

        // Go through all sections & controls in the file
        Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();

        Ogre::String secName, typeName, materialName, dataString;

        while (seci.hasMoreElements())
        {
            secName = seci.peekNextKey();
            Ogre::ConfigFile::SettingsMultiMap* settings = seci.getNext();
            if (!secName.empty() && settings)
            {
                materialName = cf.getSetting("material", secName);

				Ogre::MaterialPtr curMat = Ogre::MaterialManager::getSingleton().getByName(materialName);
				curMat->load();
				Ogre::Technique * curTec = curMat->getBestTechnique();
				if (!curTec || !curTec->isSupported())
				{
					continue;
				}

                MaterialControls newMaaterialControls(secName, materialName);
                controlsContainer.push_back(newMaaterialControls);

                size_t idx = controlsContainer.size() - 1;

                Ogre::ConfigFile::SettingsMultiMap::iterator i;

                for (i = settings->begin(); i != settings->end(); ++i)
                {
                    typeName = i->first;
                    dataString = i->second;
                    if (typeName == "control")
                        controlsContainer[idx].addControl(dataString);
                }
            }
        }

	    Ogre::LogManager::getSingleton().logMessage( "Material Controls setup" );
    }
    catch (Ogre::Exception e)
    {
        // Guess the file didn't exist
    }
}

void loadAllMaterialControlFiles(MaterialControlsContainer& controlsContainer)
{
    Ogre::StringVectorPtr fileStringVector = Ogre::ResourceGroupManager::getSingleton().findResourceNames( "Popular", "*.controls");
	Ogre::StringVector::iterator controlsFileNameIterator = fileStringVector->begin();

    while ( controlsFileNameIterator != fileStringVector->end() )
	{
        loadMaterialControlsFile(controlsContainer, *controlsFileNameIterator);
        ++controlsFileNameIterator;
	}
}
<|endoftext|>


<commit_before>// tsukasa.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

int main(int argc, char *argv[])
{

#ifdef _WIN32
    _setmode(_fileno(stdin), _O_BINARY);
#endif

    int i;
    unsigned int j;
    int data_pos;
    int audio_stream_number = 0;

    /* Object ID */
    unsigned char asf_stream_bitrate_properties_object[16] = { 0xce, 0x75, 0xf8, 0x7b, 0x8d, 0x46, 0xd1, 0x11, 0x8d, 0x82, 0x00, 0x60, 0x97, 0xc9, 0xa2, 0xb2 };
    unsigned char asf_file_properties_object[16] = { 0xa1, 0xdc, 0xab, 0x8c, 0x47, 0xa9, 0xcf, 0x11, 0x8e, 0xe4, 0x00, 0xc0, 0xc, 0x20, 0x53, 0x65 };
    unsigned char asf_stream_properties_object[16] = { 0x91, 0x7, 0xdc, 0xb7, 0xb7, 0xa9, 0xcf, 0x11, 0x8e, 0xe6, 0x00, 0xc0, 0xc, 0x20, 0x53, 0x65 };

    unsigned char asf_audio_media[16] = { 0x40, 0x9e, 0x69, 0xf8, 0x4d, 0x5b, 0xcf, 0x11, 0xa8, 0xfd, 0x00, 0x80, 0x5f, 0x5c, 0x44, 0x2b };
    unsigned char asf_no_error_correction[16] = { 0x00, 0x57, 0xfb, 0x20, 0x55, 0x5b, 0xcf, 0x11, 0xa8, 0xfd, 0x00, 0x80, 0x5f, 0x5c, 0x44, 0x2b };

    /* 8bit */
    unsigned char framing_header[12];
    unsigned char *data;
    char bitrate_records[127] = "";

    /* 16bit */
    unsigned short data_size;
    unsigned short old_data_size;

    /* 32bit */
    unsigned long number_of_header_objects = 0;
    unsigned long maximum_bitrate = 0;
    unsigned long average_number_of_bytes_per_second = 0;

    /* 64bit */
    unsigned long long header_object_size = 0;
    unsigned long long object_size;

    if (argc == 1)
    {
        exit(EXIT_FAILURE);
    }

    /* framing_headerをSTDINから読み込む */
    std::cin.read((char *)framing_header, 12);
    if (std::cin.gcount() < 12)
    {
        exit(EXIT_FAILURE);
    }

    /* PacketIDのエラーチェック */
    if (framing_header[0] != '$' || framing_header[1] != 'H')
    {
        exit(EXIT_FAILURE);
    }

    /* MMS Data Packetのエラーチェック */

    /* LocationIdとIncarnationが0以外はエラー */
    for (i = 0; i < 5; i++)
    {
        if (framing_header[4 + i] != 0)
        {
            exit(EXIT_FAILURE);
        }
    }

    /* AFFlagsが12以外はエラー */
    if (framing_header[9] != 12)
    {
        exit(EXIT_FAILURE);
    }

    /* PacketSizeがPacketLengthとサイズが違うとエラー */
    for (i = 0; i < 2; i++) {
        if (framing_header[10 + i] != framing_header[2 + i])
        {
            exit(EXIT_FAILURE);
        }
    }

    /* data_sizeを取得、8バイトのMMS Data Packetをdata_sizeから引く */
    data_size = 0;
    for (i = 0; i < 2; i++)
    {
        data_size += (unsigned short)framing_header[2 + i] << 8 * i;
    }
    data_size -= 8;

    /* dataにdata_size+792のメモリを確保 */
    /* 792はasf_stream_bitrate_properties_objectの最大サイズ(788)とFraming Headerのサイズ(4)の合計 */
    /* 788 = 26 + 6 * 127 */
    data = new unsigned char[data_size + 792];
    std::memcpy(data, framing_header, 2);

    /* STDINからデータを読み込む */
    std::cin.read((char *)data + 4, data_size);
    if (std::cin.gcount() < data_size)
    {
        exit(EXIT_FAILURE);
    }

    /* header_object_sizeを取得 */
    for (i = 0; i < 8; i++)
    {
        header_object_size += (unsigned long long)data[20 + i] << 8 * i;
    }

    /* number_of_header_objectsを取得 */
    for (i = 0; i < 4; i++)
    {
        number_of_header_objects += (unsigned long)data[28 + i] << 8 * i;
    }

    /* data_posをasf_header_objectの終端に設定 */
    data_pos = 34;

    for (j = 0; j < number_of_header_objects; j++)
    {
        /* object_sizeを取得 */
        object_size = 0;
        for (i = 0; i < 8; i++)
        {
            object_size += (unsigned long long)data[data_pos + 16 + i] << 8 * i;
        }

        /* asf_file_properties_objectかどうか */
        if (std::memcmp(data + data_pos, asf_file_properties_object, 16) == 0)
        {
            /* file_idの末端を0xFFにする */
            data[data_pos + 39] = 0xFF;

            /* maximum_bitrateを取得 */
            for (i = 0; i < 4; i++)
            {
                maximum_bitrate += (unsigned long)data[data_pos + 100 + i] << 8 * i;
            }

            /* maximum_bitrateが0xFFFFFFFFの場合はmaximum_bitrateに128000を書き込む */
            if (maximum_bitrate == 0xFFFFFFFF)
            {
                maximum_bitrate = 128000;
                for (i = 0; i < 4; i++)
                {
                    data[data_pos + 100 + i] = (maximum_bitrate >> 8 * i) & 0xFF;
                }
            }
        }

        /* asf_stream_properties_objectかどうか */
        if (std::memcmp(data + data_pos, asf_stream_properties_object, 16) == 0)
        {
            /* stream_typeがasf_audio_mediaかどうか */
            if (std::memcmp(data + data_pos + 24, asf_audio_media, 16) == 0)
            {
                /* error_correction_typeをasf_no_error_correctionに設定 */
                std::memcpy(data + data_pos + 40, asf_no_error_correction, 16);

                /* average_number_of_bytes_per_secondを取得 */
                average_number_of_bytes_per_second = 0;
                for (i = 0; i < 4; i++)
                {
                    average_number_of_bytes_per_second += (unsigned long)data[data_pos + 86 + i] << 8 * i;
                }

                /* average_number_of_bytes_per_secondが0の場合はaverage_number_of_bytes_per_secondに16000を書き込む※MP3のVBR対応のために必要 */
                if (average_number_of_bytes_per_second == 0)
                {
                    average_number_of_bytes_per_second = 16000;
                    for (i = 0; i < 4; i++)
                    {
                        data[data_pos + 86 + i] = (average_number_of_bytes_per_second >> 8 * i) & 0xFF;
                    }
                }

                audio_stream_number = data[data_pos + 72];
            }

            /* bitrate_recordsにstream_numberを追加 */
            bitrate_records[std::strlen(bitrate_records)] = data[data_pos + 72];
        }

        /* data_posにobject_sizeを加算 */
        data_pos += (int)object_size;
    }

    /* asf_data_object */
    /* file_idの末端を0xFFにする※これをしないとKagaminにPush出来ない */
    data[data_pos + 39] = 0xFF;

    /* asf_stream_bitrate_properties_objectを作成 */
    object_size = 26 + 6 * std::strlen(bitrate_records);

    /* asf_stream_bitrate_properties_objectの領域を確保 */
    std::memmove(data + data_pos + object_size, data + data_pos, data_size + 4 - data_pos);

    /* object_idを書き込む */
    for (i = 0; i < 16; i++)
    {
        data[data_pos + i] = asf_stream_bitrate_properties_object[i];
    }

    /* object_sizeを書き込む */
    for (i = 0; i < 8; i++)
    {
        data[data_pos + 16 + i] = (object_size >> 8 * i) & 0xFF;
    }

    /* bitrate_records_countを書き込む */
    for (i = 0; i < 2; i++)
    {
        data[data_pos + 24 + i] = (std::strlen(bitrate_records) >> 8 * i) & 0xFF;
    }

    /* bitrate_recordsを書き込む */
    for (j = 0; j < strlen(bitrate_records); j++)
    {
        /* stream_numberを書き込む */
        data[data_pos + 26 + j * 6] = bitrate_records[j];
        /* reservedを書き込む */
        data[data_pos + 27 + j * 6] = 0;
        /* average_bitrateを書き込む */
        if (bitrate_records[j] == audio_stream_number)
        {
            for (i = 0; i < 4; i++)
            {
                data[data_pos + 28 + i + j * 6] = ((average_number_of_bytes_per_second * 8) >> 8 * i) & 0xFF;
            }
        }
        else
        {
            for (i = 0; i < 4; i++)
            {
                data[data_pos + 28 + i + j * 6] = ((maximum_bitrate - average_number_of_bytes_per_second * 8) >> 8 * i) & 0xFF;
            }
        }
    }

    /* 各種サイズを更新  */
    number_of_header_objects += 1;
    header_object_size += object_size;
    data_size += (unsigned short)object_size;

    /* 新しいnumber_of_header_objectsを書き込む */
    for (i = 0; i < 4; i++)
    {
        data[28 + i] = (number_of_header_objects >> 8 * i) & 0xFF;
    }

    /* 新しいheader_object_sizeを書き込む */
    for (i = 0; i < 8; i++)
    {
        data[20 + i] = (header_object_size >> 8 * i) & 0xFF;
    }

    /* 新しいdata_sizeを書き込む */
    for (i = 0; i < 2; i++)
    {
        data[2 + i] = (data_size >> 8 * i) & 0xFF;
    }

    Poco::URI uri(argv[1]);

    Poco::Net::HTTPClientSession client(uri.getHost(), uri.getPort());
    Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_POST, uri.getPathAndQuery(), Poco::Net::HTTPMessage::HTTP_1_1);
    Poco::Net::HTTPResponse response;

    request.setContentType("application/x-wms-pushsetup");
    request.set("Cookie", "push-id=0");

    client.sendRequest(request);
    client.receiveResponse(response);

    std::string cookie = response.get("Set-Cookie");

    request.setContentType("application/x-wms-pushstart");
    request.set("Cookie", cookie);

    /* pushstartを送信 */
    std::ostream &os = client.sendRequest(request);
    os.write((char *)data, data_size + 4);
    os.flush();

    /* old_data_sizeにdata_sizeの値を入れる */
    old_data_size = data_size;

    /* $D */

    while (true)
    {
        /* framing_headerをSTDINから読み込む */
        std::cin.read((char *)framing_header, 12);
        if (std::cin.gcount() < 12)
        {
            exit(EXIT_FAILURE);
        }

        /* PacketIDのエラーチェック */
        if (framing_header[0] != '$' || (framing_header[1] != 'D' && framing_header[1] != 'E'))
        {
            exit(EXIT_FAILURE);
        }

        /* MMS Data Packetのエラーチェック */

        /* IncarnationとAFFlagsが0以外はエラー */
        for (i = 0; i < 2; i++)
        {
            if (framing_header[8 + i] != 0)
            {
                exit(EXIT_FAILURE);
            }
        }

        /* PacketSizeがPacketLengthとサイズが違うとエラー */
        for (i = 0; i < 2; i++)
        {
            if (framing_header[10 + i] != framing_header[2 + i])
            {
                exit(EXIT_FAILURE);
            }
        }

        /* data_sizeを取得、8バイトのMMS Data Packetをdata_sizeから引く */
        data_size = 0;
        for (i = 0; i < 2; i++)
        {
            data_size += (unsigned short)framing_header[2 + i] << 8 * i;
        }
        data_size -= 8;

        /* data_sizeとold_data_sizeが違う場合は新しくメモリを確保 */
        if (data_size != old_data_size)
        {
            /* dataのメモリを開放 */
            delete[] data;

            /* dataにdata_size+4(Framing Headerのサイズ)のメモリを確保 */
            data = new unsigned char[data_size + 4];
        }

        /* framing_headerをdataにコピー */
        std::memcpy(data, framing_header, 2);

        /* 新しいdata_sizeを書き込む */
        for (i = 0; i < 2; i++)
        {
            data[2 + i] = (data_size >> 8 * i) & 0xFF;
        }

        /* STDINからデータを読み込む */
        std::cin.read((char *)data + 4, data_size);
        if (std::cin.gcount() < data_size)
        {
            exit(EXIT_FAILURE);
        }

        /* dataを送信 */
        os.write((char *)data, data_size + 4);
        os.flush();

        /* old_data_sizeにdata_sizeの値を入れる */
        old_data_size = data_size;

        /* PacketIDが$Eだったら終了 */
        if (framing_header[1] == 'E')
        {
            break;
        }
    }

    return EXIT_SUCCESS;
}
<commit_msg>forで変数を宣言するようにした<commit_after>// tsukasa.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

int main(int argc, char *argv[])
{

#ifdef _WIN32
    _setmode(_fileno(stdin), _O_BINARY);
#endif

    int data_pos;
    int audio_stream_number = 0;

    /* Object ID */
    unsigned char asf_stream_bitrate_properties_object[16] = { 0xce, 0x75, 0xf8, 0x7b, 0x8d, 0x46, 0xd1, 0x11, 0x8d, 0x82, 0x00, 0x60, 0x97, 0xc9, 0xa2, 0xb2 };
    unsigned char asf_file_properties_object[16] = { 0xa1, 0xdc, 0xab, 0x8c, 0x47, 0xa9, 0xcf, 0x11, 0x8e, 0xe4, 0x00, 0xc0, 0xc, 0x20, 0x53, 0x65 };
    unsigned char asf_stream_properties_object[16] = { 0x91, 0x7, 0xdc, 0xb7, 0xb7, 0xa9, 0xcf, 0x11, 0x8e, 0xe6, 0x00, 0xc0, 0xc, 0x20, 0x53, 0x65 };

    unsigned char asf_audio_media[16] = { 0x40, 0x9e, 0x69, 0xf8, 0x4d, 0x5b, 0xcf, 0x11, 0xa8, 0xfd, 0x00, 0x80, 0x5f, 0x5c, 0x44, 0x2b };
    unsigned char asf_no_error_correction[16] = { 0x00, 0x57, 0xfb, 0x20, 0x55, 0x5b, 0xcf, 0x11, 0xa8, 0xfd, 0x00, 0x80, 0x5f, 0x5c, 0x44, 0x2b };

    /* 8bit */
    unsigned char framing_header[12];
    unsigned char *data;
    char bitrate_records[127] = "";

    /* 16bit */
    unsigned short data_size;
    unsigned short old_data_size;

    /* 32bit */
    unsigned long number_of_header_objects = 0;
    unsigned long maximum_bitrate = 0;
    unsigned long average_number_of_bytes_per_second = 0;

    /* 64bit */
    unsigned long long header_object_size = 0;
    unsigned long long object_size;

    if (argc == 1)
    {
        exit(EXIT_FAILURE);
    }

    /* framing_headerをSTDINから読み込む */
    std::cin.read((char *)framing_header, 12);
    if (std::cin.gcount() < 12)
    {
        exit(EXIT_FAILURE);
    }

    /* PacketIDのエラーチェック */
    if (framing_header[0] != '$' || framing_header[1] != 'H')
    {
        exit(EXIT_FAILURE);
    }

    /* MMS Data Packetのエラーチェック */

    /* LocationIdとIncarnationが0以外はエラー */
    for (int i = 0; i < 5; i++)
    {
        if (framing_header[4 + i] != 0)
        {
            exit(EXIT_FAILURE);
        }
    }

    /* AFFlagsが12以外はエラー */
    if (framing_header[9] != 12)
    {
        exit(EXIT_FAILURE);
    }

    /* PacketSizeがPacketLengthとサイズが違うとエラー */
    for (int i = 0; i < 2; i++) {
        if (framing_header[10 + i] != framing_header[2 + i])
        {
            exit(EXIT_FAILURE);
        }
    }

    /* data_sizeを取得、8バイトのMMS Data Packetをdata_sizeから引く */
    data_size = 0;
    for (int i = 0; i < 2; i++)
    {
        data_size += (unsigned short)framing_header[2 + i] << 8 * i;
    }
    data_size -= 8;

    /* dataにdata_size+792のメモリを確保 */
    /* 792はasf_stream_bitrate_properties_objectの最大サイズ(788)とFraming Headerのサイズ(4)の合計 */
    /* 788 = 26 + 6 * 127 */
    data = new unsigned char[data_size + 792];
    std::memcpy(data, framing_header, 2);

    /* STDINからデータを読み込む */
    std::cin.read((char *)data + 4, data_size);
    if (std::cin.gcount() < data_size)
    {
        exit(EXIT_FAILURE);
    }

    /* header_object_sizeを取得 */
    for (int i = 0; i < 8; i++)
    {
        header_object_size += (unsigned long long)data[20 + i] << 8 * i;
    }

    /* number_of_header_objectsを取得 */
    for (int i = 0; i < 4; i++)
    {
        number_of_header_objects += (unsigned long)data[28 + i] << 8 * i;
    }

    /* data_posをasf_header_objectの終端に設定 */
    data_pos = 34;

    for (unsigned int j = 0; j < number_of_header_objects; j++)
    {
        /* object_sizeを取得 */
        object_size = 0;
        for (int i = 0; i < 8; i++)
        {
            object_size += (unsigned long long)data[data_pos + 16 + i] << 8 * i;
        }

        /* asf_file_properties_objectかどうか */
        if (std::memcmp(data + data_pos, asf_file_properties_object, 16) == 0)
        {
            /* file_idの末端を0xFFにする */
            data[data_pos + 39] = 0xFF;

            /* maximum_bitrateを取得 */
            for (int i = 0; i < 4; i++)
            {
                maximum_bitrate += (unsigned long)data[data_pos + 100 + i] << 8 * i;
            }

            /* maximum_bitrateが0xFFFFFFFFの場合はmaximum_bitrateに128000を書き込む */
            if (maximum_bitrate == 0xFFFFFFFF)
            {
                maximum_bitrate = 128000;
                for (int i = 0; i < 4; i++)
                {
                    data[data_pos + 100 + i] = (maximum_bitrate >> 8 * i) & 0xFF;
                }
            }
        }

        /* asf_stream_properties_objectかどうか */
        if (std::memcmp(data + data_pos, asf_stream_properties_object, 16) == 0)
        {
            /* stream_typeがasf_audio_mediaかどうか */
            if (std::memcmp(data + data_pos + 24, asf_audio_media, 16) == 0)
            {
                /* error_correction_typeをasf_no_error_correctionに設定 */
                std::memcpy(data + data_pos + 40, asf_no_error_correction, 16);

                /* average_number_of_bytes_per_secondを取得 */
                average_number_of_bytes_per_second = 0;
                for (int i = 0; i < 4; i++)
                {
                    average_number_of_bytes_per_second += (unsigned long)data[data_pos + 86 + i] << 8 * i;
                }

                /* average_number_of_bytes_per_secondが0の場合はaverage_number_of_bytes_per_secondに16000を書き込む※MP3のVBR対応のために必要 */
                if (average_number_of_bytes_per_second == 0)
                {
                    average_number_of_bytes_per_second = 16000;
                    for (int i = 0; i < 4; i++)
                    {
                        data[data_pos + 86 + i] = (average_number_of_bytes_per_second >> 8 * i) & 0xFF;
                    }
                }

                audio_stream_number = data[data_pos + 72];
            }

            /* bitrate_recordsにstream_numberを追加 */
            bitrate_records[std::strlen(bitrate_records)] = data[data_pos + 72];
        }

        /* data_posにobject_sizeを加算 */
        data_pos += (int)object_size;
    }

    /* asf_data_object */
    /* file_idの末端を0xFFにする※これをしないとKagaminにPush出来ない */
    data[data_pos + 39] = 0xFF;

    /* asf_stream_bitrate_properties_objectを作成 */
    object_size = 26 + 6 * std::strlen(bitrate_records);

    /* asf_stream_bitrate_properties_objectの領域を確保 */
    std::memmove(data + data_pos + object_size, data + data_pos, data_size + 4 - data_pos);

    /* object_idを書き込む */
    for (int i = 0; i < 16; i++)
    {
        data[data_pos + i] = asf_stream_bitrate_properties_object[i];
    }

    /* object_sizeを書き込む */
    for (int i = 0; i < 8; i++)
    {
        data[data_pos + 16 + i] = (object_size >> 8 * i) & 0xFF;
    }

    /* bitrate_records_countを書き込む */
    for (int i = 0; i < 2; i++)
    {
        data[data_pos + 24 + i] = (std::strlen(bitrate_records) >> 8 * i) & 0xFF;
    }

    /* bitrate_recordsを書き込む */
    for (unsigned int j = 0; j < strlen(bitrate_records); j++)
    {
        /* stream_numberを書き込む */
        data[data_pos + 26 + j * 6] = bitrate_records[j];
        /* reservedを書き込む */
        data[data_pos + 27 + j * 6] = 0;
        /* average_bitrateを書き込む */
        if (bitrate_records[j] == audio_stream_number)
        {
            for (int i = 0; i < 4; i++)
            {
                data[data_pos + 28 + i + j * 6] = ((average_number_of_bytes_per_second * 8) >> 8 * i) & 0xFF;
            }
        }
        else
        {
            for (int i = 0; i < 4; i++)
            {
                data[data_pos + 28 + i + j * 6] = ((maximum_bitrate - average_number_of_bytes_per_second * 8) >> 8 * i) & 0xFF;
            }
        }
    }

    /* 各種サイズを更新  */
    number_of_header_objects += 1;
    header_object_size += object_size;
    data_size += (unsigned short)object_size;

    /* 新しいnumber_of_header_objectsを書き込む */
    for (int i = 0; i < 4; i++)
    {
        data[28 + i] = (number_of_header_objects >> 8 * i) & 0xFF;
    }

    /* 新しいheader_object_sizeを書き込む */
    for (int i = 0; i < 8; i++)
    {
        data[20 + i] = (header_object_size >> 8 * i) & 0xFF;
    }

    /* 新しいdata_sizeを書き込む */
    for (int i = 0; i < 2; i++)
    {
        data[2 + i] = (data_size >> 8 * i) & 0xFF;
    }

    Poco::URI uri(argv[1]);

    Poco::Net::HTTPClientSession client(uri.getHost(), uri.getPort());
    Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_POST, uri.getPathAndQuery(), Poco::Net::HTTPMessage::HTTP_1_1);
    Poco::Net::HTTPResponse response;

    request.setContentType("application/x-wms-pushsetup");
    request.set("Cookie", "push-id=0");

    client.sendRequest(request);
    client.receiveResponse(response);

    std::string cookie = response.get("Set-Cookie");

    request.setContentType("application/x-wms-pushstart");
    request.set("Cookie", cookie);

    /* pushstartを送信 */
    std::ostream &os = client.sendRequest(request);
    os.write((char *)data, data_size + 4);
    os.flush();

    /* old_data_sizeにdata_sizeの値を入れる */
    old_data_size = data_size;

    /* $D */

    while (true)
    {
        /* framing_headerをSTDINから読み込む */
        std::cin.read((char *)framing_header, 12);
        if (std::cin.gcount() < 12)
        {
            exit(EXIT_FAILURE);
        }

        /* PacketIDのエラーチェック */
        if (framing_header[0] != '$' || (framing_header[1] != 'D' && framing_header[1] != 'E'))
        {
            exit(EXIT_FAILURE);
        }

        /* MMS Data Packetのエラーチェック */

        /* IncarnationとAFFlagsが0以外はエラー */
        for (int i = 0; i < 2; i++)
        {
            if (framing_header[8 + i] != 0)
            {
                exit(EXIT_FAILURE);
            }
        }

        /* PacketSizeがPacketLengthとサイズが違うとエラー */
        for (int i = 0; i < 2; i++)
        {
            if (framing_header[10 + i] != framing_header[2 + i])
            {
                exit(EXIT_FAILURE);
            }
        }

        /* data_sizeを取得、8バイトのMMS Data Packetをdata_sizeから引く */
        data_size = 0;
        for (int i = 0; i < 2; i++)
        {
            data_size += (unsigned short)framing_header[2 + i] << 8 * i;
        }
        data_size -= 8;

        /* data_sizeとold_data_sizeが違う場合は新しくメモリを確保 */
        if (data_size != old_data_size)
        {
            /* dataのメモリを開放 */
            delete[] data;

            /* dataにdata_size+4(Framing Headerのサイズ)のメモリを確保 */
            data = new unsigned char[data_size + 4];
        }

        /* framing_headerをdataにコピー */
        std::memcpy(data, framing_header, 2);

        /* 新しいdata_sizeを書き込む */
        for (int i = 0; i < 2; i++)
        {
            data[2 + i] = (data_size >> 8 * i) & 0xFF;
        }

        /* STDINからデータを読み込む */
        std::cin.read((char *)data + 4, data_size);
        if (std::cin.gcount() < data_size)
        {
            exit(EXIT_FAILURE);
        }

        /* dataを送信 */
        os.write((char *)data, data_size + 4);
        os.flush();

        /* old_data_sizeにdata_sizeの値を入れる */
        old_data_size = data_size;

        /* PacketIDが$Eだったら終了 */
        if (framing_header[1] == 'E')
        {
            break;
        }
    }

    return EXIT_SUCCESS;
}
<|endoftext|>


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

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

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

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.

*/

#include "outputdevicechoice.h"

#include <QtCore/QList>
#include <QtCore/QSettings>
#include <QtGui/QHeaderView>
#include <QtGui/QPalette>

#include <phonon/backendcapabilities.h>
#include <phonon/objectdescription.h>
#include <phonon/phononnamespace.h>
#include "../libkaudiodevicelist/audiodeviceenumerator.h"
#include "../libkaudiodevicelist/audiodevice.h"

#include <klocale.h>
#include <kstandarddirs.h>
#include <kdebug.h>

#ifndef METATYPE_QLIST_INT_DEFINED
#define METATYPE_QLIST_INT_DEFINED
// Want this exactly once, see phonondefs_p.h kcm/outputdevicechoice.cpp
Q_DECLARE_METATYPE(QList<int>)
#endif

class QSettingsGroup
{
    public:
        QSettingsGroup(QSettings *settings, const QString &name)
            : m_s(settings),
            m_group(name + QLatin1Char('/'))
        {
        }

        template<typename T>
        inline T value(const QString &key, const T &def) const
        {
            return qvariant_cast<T>(value(key, QVariant::fromValue(def)));
        }

        QVariant value(const QString &key, const QVariant &def) const
        {
            return m_s->value(m_group + key, def);
        }

        template<typename T>
        inline void setValue(const QString &key, const T &value)
        {
            m_s->setValue(m_group + key, QVariant::fromValue(value));
        }

    private:
        QSettings *const m_s;
        QString m_group;
};

class CategoryItem : public QStandardItem {
    public:
        CategoryItem(Phonon::Category cat)
            : QStandardItem(Phonon::categoryToString(cat)),
            m_cat(cat)
        {
        }

        int type() const { return 1001; }
        Phonon::Category category() const { return m_cat; }

    private:
        Phonon::Category m_cat;
};

OutputDeviceChoice::OutputDeviceChoice(QWidget *parent)
    : QWidget(parent)
{
    setupUi(this);
    removeButton->setIcon(KIcon("list-remove"));
    deferButton->setIcon(KIcon("arrow-down"));
    preferButton->setIcon(KIcon("arrow-up"));
    //categoryTree->setDragEnabled(true);
    //categoryTree->setAcceptDrops(true);
    //categoryTree->setDropIndicatorShown(true);
    //categoryTree->setDragDropMode(QAbstractItemView::InternalMove);
//X     deviceList->setDragEnabled(true);
//X     deviceList->setAcceptDrops(true);
//X     deviceList->setDropIndicatorShown(true);
    deviceList->setDragDropMode(QAbstractItemView::InternalMove);
    const QColor bgColor = deviceList->viewport()->palette().color(deviceList->viewport()->backgroundRole());
    const QString stylesheet = QString("QListView {"
            "background-color: %1;"
            "background-image: url(%2);"
            "background-position: bottom left;"
            "background-attachment: fixed;"
            "background-repeat: no-repeat;"
            "}")
        .arg(bgColor.name())
        .arg(KStandardDirs::locate("data", "kcm_phonon/listview-background.png"));
    kDebug() << stylesheet;
    deviceList->setStyleSheet(stylesheet);
    deviceList->setAlternatingRowColors(false);
    QStandardItem *parentItem = m_categoryModel.invisibleRootItem();
    QStandardItem *outputItem = new QStandardItem(i18n("Audio Output"));
    outputItem->setEditable(false);
    outputItem->setSelectable(false);
    parentItem->appendRow(outputItem);
    /*
    m_captureItem = new QStandardItem(i18n("Audio Capture"));
    m_captureItem->setEditable(false);
    parentItem->appendRow(m_captureItem);
    */

    parentItem = outputItem;
    for (int i = 0; i <= Phonon::LastCategory; ++i) {
        m_outputModel[i] = new Phonon::AudioOutputDeviceModel;
        QStandardItem *item = new CategoryItem(static_cast<Phonon::Category>(i));
        item->setEditable(false);
        parentItem->appendRow(item);
    }
    //parentItem = m_captureItem;

    categoryTree->setModel(&m_categoryModel);
    if (categoryTree->header()) {
        categoryTree->header()->hide();
    }
    categoryTree->expandAll();

    connect(categoryTree->selectionModel(),
            SIGNAL(currentChanged(const QModelIndex &,const QModelIndex &)),
            SLOT(updateDeviceList()));

    for (int i = 0; i <= Phonon::LastCategory; ++i) {
        connect(m_outputModel[i], SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SIGNAL(changed()));
        connect(m_outputModel[i], SIGNAL(rowsRemoved(const QModelIndex &, int, int)), this, SIGNAL(changed()));
        connect(m_outputModel[i], SIGNAL(layoutChanged()), this, SIGNAL(changed()));
        connect(m_outputModel[i], SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this, SIGNAL(changed()));
    }
    /*
    connect(&m_captureModel, SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SIGNAL(changed()));
    connect(&m_captureModel, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), this, SIGNAL(changed()));
    connect(&m_captureModel, SIGNAL(layoutChanged()), this, SIGNAL(changed()));
    connect(&m_captureModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this, SIGNAL(changed()));
    */

    connect(Phonon::BackendCapabilities::notifier(), SIGNAL(availableAudioOutputDevicesChanged()), SLOT(updateAudioOutputDevices()));

    if (!categoryTree->currentIndex().isValid()) {
        categoryTree->setCurrentIndex(m_categoryModel.index(0, 0).child(0, 0));
    }
}

void OutputDeviceChoice::updateDeviceList()
{
    QStandardItem *currentItem = m_categoryModel.itemFromIndex(categoryTree->currentIndex());
    if (deviceList->selectionModel()) {
        disconnect(deviceList->selectionModel(),
                SIGNAL(currentRowChanged(const QModelIndex &,const QModelIndex &)),
                this, SLOT(updateButtonsEnabled()));
    }
    if (currentItem->type() == 1001) {
        CategoryItem *catItem = static_cast<CategoryItem *>(currentItem);
        deviceList->setModel(m_outputModel[catItem->category()]);
        /*
    } else if (currentItem == m_captureItem) {
        deviceList->setModel(&m_captureModel);
        */
    } else {
        deviceList->setModel(0);
    }
    updateButtonsEnabled();
    if (deviceList->selectionModel()) {
        connect(deviceList->selectionModel(),
                SIGNAL(currentRowChanged(const QModelIndex &,const QModelIndex &)),
                this, SLOT(updateButtonsEnabled()));
    }
}

void OutputDeviceChoice::updateAudioOutputDevices()
{
    QList<Phonon::AudioOutputDevice> list = Phonon::BackendCapabilities::availableAudioOutputDevices();
    QHash<int, Phonon::AudioOutputDevice> hash;
    foreach (Phonon::AudioOutputDevice dev, list) {
        hash.insert(dev.index(), dev);
    }
    for (int i = 0; i <= Phonon::LastCategory; ++i) {
        Phonon::AudioOutputDeviceModel *model = m_outputModel.value(i);
        Q_ASSERT(model);

        QHash<int, Phonon::AudioOutputDevice> hashCopy(hash);
        QList<Phonon::AudioOutputDevice> orderedList;
        if (model->rowCount() > 0) {
            QList<int> order = m_outputModel.value(i)->tupleIndexOrder();
            foreach (int idx, order) {
                if (hashCopy.contains(idx)) {
                    orderedList << hashCopy.take(idx);
                }
            }
            if (hashCopy.size() > 1) {
                // keep the order of the original list
                foreach (const Phonon::AudioOutputDevice &dev, list) {
                    if (hashCopy.contains(dev.index())) {
                        orderedList << hashCopy.take(dev.index());
                    }
                }
            } else if (hashCopy.size() == 1) {
                orderedList += hashCopy.values();
            }
            model->setModelData(orderedList);
        } else {
            model->setModelData(list);
        }
    }
}

void OutputDeviceChoice::load()
{
    QSettings phononConfig(QLatin1String("kde.org"), QLatin1String("libphonon"));
    QSettingsGroup outputDeviceGroup(&phononConfig, QLatin1String("AudioOutputDevice"));
    QSettingsGroup captureDeviceGroup(&phononConfig, QLatin1String("AudioCaptureDevice"));

    QList<Phonon::AudioOutputDevice> list = Phonon::BackendCapabilities::availableAudioOutputDevices();
    QHash<int, Phonon::AudioOutputDevice> hash;
    foreach (Phonon::AudioOutputDevice dev, list) {
        hash.insert(dev.index(), dev);
    }
    for (int i = 0; i <= Phonon::LastCategory; ++i) {
        QHash<int, Phonon::AudioOutputDevice> hashCopy(hash);
        QList<int> order = outputDeviceGroup.value(QLatin1String("Category") + QString::number(i), QList<int>());
        QList<Phonon::AudioOutputDevice> orderedList;
        foreach (int idx, order) {
            if (hashCopy.contains(idx)) {
                orderedList << hashCopy.take(idx);
            }
        }
        if (hashCopy.size() > 1) {
            // keep the order of the original list
            foreach (const Phonon::AudioOutputDevice &dev, list) {
                if (hashCopy.contains(dev.index())) {
                    orderedList << hashCopy.take(dev.index());
                }
            }
        } else if (hashCopy.size() == 1) {
            orderedList += hashCopy.values();
        }
        m_outputModel[i]->setModelData(orderedList);
    }

    /*
    QList<Phonon::AudioCaptureDevice> list2 = Phonon::BackendCapabilities::availableAudioCaptureDevices();
    QList<int> order = captureDeviceGroup.value(QLatin1String("DeviceOrder"), QList<int>());
    QList<Phonon::AudioCaptureDevice> orderedList;
    foreach (int idx, order) {
        for (int i = 0; i < list2.size(); ++i) {
            if (list2.at(i).index() == idx) {
                orderedList << list2.takeAt(i);
                break; // out of the inner for loop to get the next idx
            }
        }
    }
    foreach (Phonon::AudioCaptureDevice dev, list2) {
        orderedList << dev;
    }
    m_captureModel.setModelData(orderedList);
    */
}

void OutputDeviceChoice::save()
{
    QSettings config(QLatin1String("kde.org"), QLatin1String("libphonon"));
    {
        QSettingsGroup globalGroup(&config, QLatin1String("AudioOutputDevice"));
        for (int i = 0; i <= Phonon::LastCategory; ++i) {
            if (m_outputModel.value(i)) {
                globalGroup.setValue(QLatin1String("Category") + QString::number(i), m_outputModel.value(i)->tupleIndexOrder());
            }
        }
    }
    /*
    {
        QSettingsGroup globalGroup(&config, QLatin1String("AudioCaptureDevice"));
        globalGroup.setValue(QLatin1String("DeviceOrder"), m_captureModel.tupleIndexOrder());
    }
    */
}

void OutputDeviceChoice::defaults()
{
    QList<Phonon::AudioOutputDevice> list = Phonon::BackendCapabilities::availableAudioOutputDevices();
    for (int i = 0; i <= Phonon::LastCategory; ++i) {
        m_outputModel[i]->setModelData(list);
    }

    /*
    QList<Phonon::AudioCaptureDevice> list2 = Phonon::BackendCapabilities::availableAudioCaptureDevices();
    m_captureModel.setModelData(list2);
    */
}

void OutputDeviceChoice::on_preferButton_clicked()
{
    QAbstractItemModel *model = deviceList->model();
    Phonon::AudioOutputDeviceModel *deviceModel = qobject_cast<Phonon::AudioOutputDeviceModel *>(model);
    if (deviceModel) {
        deviceModel->moveUp(deviceList->currentIndex());
        updateButtonsEnabled();
        emit changed();
    }
}

void OutputDeviceChoice::on_deferButton_clicked()
{
    QAbstractItemModel *model = deviceList->model();
    Phonon::AudioOutputDeviceModel *deviceModel = qobject_cast<Phonon::AudioOutputDeviceModel *>(model);
    if (deviceModel) {
        deviceModel->moveDown(deviceList->currentIndex());
        updateButtonsEnabled();
        emit changed();
    }
}

void OutputDeviceChoice::on_removeButton_clicked()
{
    QModelIndex idx = deviceList->currentIndex();

    QAbstractItemModel *model = deviceList->model();
    Phonon::AudioOutputDeviceModel *playbackModel = qobject_cast<Phonon::AudioOutputDeviceModel *>(model);
    if (playbackModel && idx.isValid()) {
        Phonon::AudioOutputDevice deviceToRemove = playbackModel->modelData(idx);
        QList<Phonon::AudioDevice> deviceList = Phonon::AudioDeviceEnumerator::availablePlaybackDevices();
        foreach (Phonon::AudioDevice dev, deviceList) {
            if (dev.index() == deviceToRemove.index()) {
                // remove from persistent store
                if (dev.ceaseToExist()) {
                    // remove from all models, idx.row() is only correct for the current model
                    foreach (Phonon::AudioOutputDeviceModel *model, m_outputModel) {
                        QList<Phonon::AudioOutputDevice> data = model->modelData();
                        for (int row = 0; row < data.size(); ++row) {
                            if (data[row] == deviceToRemove) {
                                model->removeRows(row, 1);
                                break;
                            }
                        }
                    }
                    updateButtonsEnabled();
                    emit changed();
                }
            }
        }
        /*
    } else {
        Phonon::AudioCaptureDeviceModel *captureModel = qobject_cast<Phonon::AudioCaptureDeviceModel *>(model);
        if (captureModel && idx.isValid()) {
            Phonon::AudioCaptureDevice deviceToRemove = captureModel->modelData(idx);
            QList<Phonon::AudioDevice> deviceList = Phonon::AudioDeviceEnumerator::availableCaptureDevices();
            foreach (Phonon::AudioDevice dev, deviceList) {
                if (dev.index() == deviceToRemove.index()) {
                    // remove from persistent store
                    if (dev.ceaseToExist()) {
                        m_captureModel.removeRows(idx.row(), 1);
                        updateButtonsEnabled();
                        emit changed();
                    }
                }
            }
        }
        */
    }
}

void OutputDeviceChoice::updateButtonsEnabled()
{
    //kDebug() ;
    if (deviceList->model()) {
        //kDebug() << "model available";
        QModelIndex idx = deviceList->currentIndex();
        preferButton->setEnabled(idx.isValid() && idx.row() > 0);
        deferButton->setEnabled(idx.isValid() && idx.row() < deviceList->model()->rowCount() - 1);
        removeButton->setEnabled(idx.isValid() && !(idx.flags()  & Qt::ItemIsEnabled));
    } else {
        preferButton->setEnabled(false);
        deferButton->setEnabled(false);
        removeButton->setEnabled(false);
    }
}

#include "outputdevicechoice.moc"
// vim: sw=4 ts=4
<commit_msg>small cleanup<commit_after>/*  This file is part of the KDE project
    Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org>

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

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

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.

*/

#include "outputdevicechoice.h"

#include <QtCore/QList>
#include <QtCore/QSettings>
#include <QtGui/QHeaderView>
#include <QtGui/QPalette>

#include <phonon/backendcapabilities.h>
#include <phonon/objectdescription.h>
#include <phonon/phononnamespace.h>
#include "../libkaudiodevicelist/audiodeviceenumerator.h"
#include "../libkaudiodevicelist/audiodevice.h"

#include <klocale.h>
#include <kstandarddirs.h>
#include <kdebug.h>

#ifndef METATYPE_QLIST_INT_DEFINED
#define METATYPE_QLIST_INT_DEFINED
// Want this exactly once, see phonondefs_p.h kcm/outputdevicechoice.cpp
Q_DECLARE_METATYPE(QList<int>)
#endif

class QSettingsGroup
{
    public:
        QSettingsGroup(QSettings *settings, const QString &name)
            : m_s(settings),
            m_group(name + QLatin1Char('/'))
        {
        }

        template<typename T>
        inline T value(const QString &key, const T &def) const
        {
            return qvariant_cast<T>(value(key, QVariant::fromValue(def)));
        }

        QVariant value(const QString &key, const QVariant &def) const
        {
            return m_s->value(m_group + key, def);
        }

        template<typename T>
        inline void setValue(const QString &key, const T &value)
        {
            m_s->setValue(m_group + key, QVariant::fromValue(value));
        }

    private:
        QSettings *const m_s;
        QString m_group;
};

class CategoryItem : public QStandardItem {
    public:
        CategoryItem(Phonon::Category cat)
            : QStandardItem(Phonon::categoryToString(cat)),
            m_cat(cat)
        {
        }

        int type() const { return 1001; }
        Phonon::Category category() const { return m_cat; }

    private:
        Phonon::Category m_cat;
};

OutputDeviceChoice::OutputDeviceChoice(QWidget *parent)
    : QWidget(parent)
{
    setupUi(this);
    removeButton->setIcon(KIcon("list-remove"));
    deferButton->setIcon(KIcon("arrow-down"));
    preferButton->setIcon(KIcon("arrow-up"));
    //categoryTree->setDragEnabled(true);
    //categoryTree->setAcceptDrops(true);
    //categoryTree->setDropIndicatorShown(true);
    //categoryTree->setDragDropMode(QAbstractItemView::InternalMove);
//X     deviceList->setDragEnabled(true);
//X     deviceList->setAcceptDrops(true);
//X     deviceList->setDropIndicatorShown(true);
    deviceList->setDragDropMode(QAbstractItemView::InternalMove);
    const QColor bgColor = deviceList->viewport()->palette().color(deviceList->viewport()->backgroundRole());
    const QString stylesheet = QString("QListView {"
            "background-color: %1;"
            "background-image: url(%2);"
            "background-position: bottom left;"
            "background-attachment: fixed;"
            "background-repeat: no-repeat;"
            "}")
        .arg(bgColor.name())
        .arg(KStandardDirs::locate("data", "kcm_phonon/listview-background.png"));
    kDebug() << stylesheet;
    deviceList->setStyleSheet(stylesheet);
    deviceList->setAlternatingRowColors(false);
    QStandardItem *parentItem = m_categoryModel.invisibleRootItem();
    QStandardItem *outputItem = new QStandardItem(i18n("Audio Output"));
    outputItem->setEditable(false);
    outputItem->setSelectable(false);
    parentItem->appendRow(outputItem);
    /*
    m_captureItem = new QStandardItem(i18n("Audio Capture"));
    m_captureItem->setEditable(false);
    parentItem->appendRow(m_captureItem);
    */

    parentItem = outputItem;
    for (int i = 0; i <= Phonon::LastCategory; ++i) {
        m_outputModel[i] = new Phonon::AudioOutputDeviceModel;
        QStandardItem *item = new CategoryItem(static_cast<Phonon::Category>(i));
        item->setEditable(false);
        parentItem->appendRow(item);
    }
    //parentItem = m_captureItem;

    categoryTree->setModel(&m_categoryModel);
    if (categoryTree->header()) {
        categoryTree->header()->hide();
    }
    categoryTree->expandAll();

    connect(categoryTree->selectionModel(),
            SIGNAL(currentChanged(const QModelIndex &,const QModelIndex &)),
            SLOT(updateDeviceList()));

    for (int i = 0; i <= Phonon::LastCategory; ++i) {
        connect(m_outputModel[i], SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SIGNAL(changed()));
        connect(m_outputModel[i], SIGNAL(rowsRemoved(const QModelIndex &, int, int)), this, SIGNAL(changed()));
        connect(m_outputModel[i], SIGNAL(layoutChanged()), this, SIGNAL(changed()));
        connect(m_outputModel[i], SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this, SIGNAL(changed()));
    }
    /*
    connect(&m_captureModel, SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SIGNAL(changed()));
    connect(&m_captureModel, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), this, SIGNAL(changed()));
    connect(&m_captureModel, SIGNAL(layoutChanged()), this, SIGNAL(changed()));
    connect(&m_captureModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this, SIGNAL(changed()));
    */

    connect(Phonon::BackendCapabilities::notifier(), SIGNAL(availableAudioOutputDevicesChanged()), SLOT(updateAudioOutputDevices()));

    if (!categoryTree->currentIndex().isValid()) {
        categoryTree->setCurrentIndex(m_categoryModel.index(0, 0).child(0, 0));
    }
}

void OutputDeviceChoice::updateDeviceList()
{
    QStandardItem *currentItem = m_categoryModel.itemFromIndex(categoryTree->currentIndex());
    if (deviceList->selectionModel()) {
        disconnect(deviceList->selectionModel(),
                SIGNAL(currentRowChanged(const QModelIndex &,const QModelIndex &)),
                this, SLOT(updateButtonsEnabled()));
    }
    if (currentItem->type() == 1001) {
        CategoryItem *catItem = static_cast<CategoryItem *>(currentItem);
        deviceList->setModel(m_outputModel[catItem->category()]);
        /*
    } else if (currentItem == m_captureItem) {
        deviceList->setModel(&m_captureModel);
        */
    } else {
        deviceList->setModel(0);
    }
    updateButtonsEnabled();
    if (deviceList->selectionModel()) {
        connect(deviceList->selectionModel(),
                SIGNAL(currentRowChanged(const QModelIndex &,const QModelIndex &)),
                this, SLOT(updateButtonsEnabled()));
    }
}

void OutputDeviceChoice::updateAudioOutputDevices()
{
    QList<Phonon::AudioOutputDevice> list = Phonon::BackendCapabilities::availableAudioOutputDevices();
    QHash<int, Phonon::AudioOutputDevice> hash;
    foreach (Phonon::AudioOutputDevice dev, list) {
        hash.insert(dev.index(), dev);
    }
    for (int i = 0; i <= Phonon::LastCategory; ++i) {
        Phonon::AudioOutputDeviceModel *model = m_outputModel.value(i);
        Q_ASSERT(model);

        QHash<int, Phonon::AudioOutputDevice> hashCopy(hash);
        QList<Phonon::AudioOutputDevice> orderedList;
        if (model->rowCount() > 0) {
            QList<int> order = model->tupleIndexOrder();
            foreach (int idx, order) {
                if (hashCopy.contains(idx)) {
                    orderedList << hashCopy.take(idx);
                }
            }
            if (hashCopy.size() > 1) {
                // keep the order of the original list
                foreach (const Phonon::AudioOutputDevice &dev, list) {
                    if (hashCopy.contains(dev.index())) {
                        orderedList << hashCopy.take(dev.index());
                    }
                }
            } else if (hashCopy.size() == 1) {
                orderedList += hashCopy.values();
            }
            model->setModelData(orderedList);
        } else {
            model->setModelData(list);
        }
    }
}

void OutputDeviceChoice::load()
{
    QSettings phononConfig(QLatin1String("kde.org"), QLatin1String("libphonon"));
    QSettingsGroup outputDeviceGroup(&phononConfig, QLatin1String("AudioOutputDevice"));
    QSettingsGroup captureDeviceGroup(&phononConfig, QLatin1String("AudioCaptureDevice"));

    QList<Phonon::AudioOutputDevice> list = Phonon::BackendCapabilities::availableAudioOutputDevices();
    QHash<int, Phonon::AudioOutputDevice> hash;
    foreach (Phonon::AudioOutputDevice dev, list) {
        hash.insert(dev.index(), dev);
    }
    for (int i = 0; i <= Phonon::LastCategory; ++i) {
        QHash<int, Phonon::AudioOutputDevice> hashCopy(hash);
        QList<int> order = outputDeviceGroup.value(QLatin1String("Category") + QString::number(i), QList<int>());
        QList<Phonon::AudioOutputDevice> orderedList;
        foreach (int idx, order) {
            if (hashCopy.contains(idx)) {
                orderedList << hashCopy.take(idx);
            }
        }
        if (hashCopy.size() > 1) {
            // keep the order of the original list
            foreach (const Phonon::AudioOutputDevice &dev, list) {
                if (hashCopy.contains(dev.index())) {
                    orderedList << hashCopy.take(dev.index());
                }
            }
        } else if (hashCopy.size() == 1) {
            orderedList += hashCopy.values();
        }
        m_outputModel[i]->setModelData(orderedList);
    }

    /*
    QList<Phonon::AudioCaptureDevice> list2 = Phonon::BackendCapabilities::availableAudioCaptureDevices();
    QList<int> order = captureDeviceGroup.value(QLatin1String("DeviceOrder"), QList<int>());
    QList<Phonon::AudioCaptureDevice> orderedList;
    foreach (int idx, order) {
        for (int i = 0; i < list2.size(); ++i) {
            if (list2.at(i).index() == idx) {
                orderedList << list2.takeAt(i);
                break; // out of the inner for loop to get the next idx
            }
        }
    }
    foreach (Phonon::AudioCaptureDevice dev, list2) {
        orderedList << dev;
    }
    m_captureModel.setModelData(orderedList);
    */
}

void OutputDeviceChoice::save()
{
    QSettings config(QLatin1String("kde.org"), QLatin1String("libphonon"));
    {
        QSettingsGroup globalGroup(&config, QLatin1String("AudioOutputDevice"));
        for (int i = 0; i <= Phonon::LastCategory; ++i) {
            if (m_outputModel.value(i)) {
                globalGroup.setValue(QLatin1String("Category") + QString::number(i), m_outputModel.value(i)->tupleIndexOrder());
            }
        }
    }
    /*
    {
        QSettingsGroup globalGroup(&config, QLatin1String("AudioCaptureDevice"));
        globalGroup.setValue(QLatin1String("DeviceOrder"), m_captureModel.tupleIndexOrder());
    }
    */
}

void OutputDeviceChoice::defaults()
{
    QList<Phonon::AudioOutputDevice> list = Phonon::BackendCapabilities::availableAudioOutputDevices();
    for (int i = 0; i <= Phonon::LastCategory; ++i) {
        m_outputModel[i]->setModelData(list);
    }

    /*
    QList<Phonon::AudioCaptureDevice> list2 = Phonon::BackendCapabilities::availableAudioCaptureDevices();
    m_captureModel.setModelData(list2);
    */
}

void OutputDeviceChoice::on_preferButton_clicked()
{
    QAbstractItemModel *model = deviceList->model();
    Phonon::AudioOutputDeviceModel *deviceModel = qobject_cast<Phonon::AudioOutputDeviceModel *>(model);
    if (deviceModel) {
        deviceModel->moveUp(deviceList->currentIndex());
        updateButtonsEnabled();
        emit changed();
    }
}

void OutputDeviceChoice::on_deferButton_clicked()
{
    QAbstractItemModel *model = deviceList->model();
    Phonon::AudioOutputDeviceModel *deviceModel = qobject_cast<Phonon::AudioOutputDeviceModel *>(model);
    if (deviceModel) {
        deviceModel->moveDown(deviceList->currentIndex());
        updateButtonsEnabled();
        emit changed();
    }
}

void OutputDeviceChoice::on_removeButton_clicked()
{
    QModelIndex idx = deviceList->currentIndex();

    QAbstractItemModel *model = deviceList->model();
    Phonon::AudioOutputDeviceModel *playbackModel = qobject_cast<Phonon::AudioOutputDeviceModel *>(model);
    if (playbackModel && idx.isValid()) {
        Phonon::AudioOutputDevice deviceToRemove = playbackModel->modelData(idx);
        QList<Phonon::AudioDevice> deviceList = Phonon::AudioDeviceEnumerator::availablePlaybackDevices();
        foreach (Phonon::AudioDevice dev, deviceList) {
            if (dev.index() == deviceToRemove.index()) {
                // remove from persistent store
                if (dev.ceaseToExist()) {
                    // remove from all models, idx.row() is only correct for the current model
                    foreach (Phonon::AudioOutputDeviceModel *model, m_outputModel) {
                        QList<Phonon::AudioOutputDevice> data = model->modelData();
                        for (int row = 0; row < data.size(); ++row) {
                            if (data[row] == deviceToRemove) {
                                model->removeRows(row, 1);
                                break;
                            }
                        }
                    }
                    updateButtonsEnabled();
                    emit changed();
                }
            }
        }
        /*
    } else {
        Phonon::AudioCaptureDeviceModel *captureModel = qobject_cast<Phonon::AudioCaptureDeviceModel *>(model);
        if (captureModel && idx.isValid()) {
            Phonon::AudioCaptureDevice deviceToRemove = captureModel->modelData(idx);
            QList<Phonon::AudioDevice> deviceList = Phonon::AudioDeviceEnumerator::availableCaptureDevices();
            foreach (Phonon::AudioDevice dev, deviceList) {
                if (dev.index() == deviceToRemove.index()) {
                    // remove from persistent store
                    if (dev.ceaseToExist()) {
                        m_captureModel.removeRows(idx.row(), 1);
                        updateButtonsEnabled();
                        emit changed();
                    }
                }
            }
        }
        */
    }
}

void OutputDeviceChoice::updateButtonsEnabled()
{
    //kDebug() ;
    if (deviceList->model()) {
        //kDebug() << "model available";
        QModelIndex idx = deviceList->currentIndex();
        preferButton->setEnabled(idx.isValid() && idx.row() > 0);
        deferButton->setEnabled(idx.isValid() && idx.row() < deviceList->model()->rowCount() - 1);
        removeButton->setEnabled(idx.isValid() && !(idx.flags()  & Qt::ItemIsEnabled));
    } else {
        preferButton->setEnabled(false);
        deferButton->setEnabled(false);
        removeButton->setEnabled(false);
    }
}

#include "outputdevicechoice.moc"
// vim: sw=4 ts=4
<|endoftext|>