Blob Blame Raw


#if (!(defined(x64) || defined(__LP64__) || defined(LINUX)))

//Toonz stuff
#include "tiio.h"
#include "timage_io.h"
#include "tlevel_io.h"
#include "trasterimage.h"
#include "traster.h"
#include "tstream.h"
#include "movsettings.h"
#include "tproperty.h"
#include "tsound.h"

#ifdef WIN32
#include "../image/mov/tiio_mov.h"
#elif MACOSX
#include "../image/mov/tiio_movM.h"
#include <ApplicationServices/ApplicationServices.h>
#endif

//Qt stuff
#include <QString>
#include <QHash>
#include <QSharedMemory>
#include <QDebug>

#include <QLocalSocket>
#include <QDataStream>

//tipc includes
#include "tipc.h"
#include "tipcmsg.h"
#include "tipcsrv.h"
#include "t32bitsrv_wrap.h"

#include "t32movmsg.h"

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

//  Diagnostics stuff

//#define TIPC_DEBUG

#ifdef TIPC_DEBUG
#define tipc_debug(expr) expr
#else
#define tipc_debug(expr)
#endif

#ifdef TIPC_DEBUG
#include <QTime>
#endif

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

//  Local namespace stuff

namespace
{
QHash<unsigned int, TLevelReaderP> readers;
QHash<unsigned int, TLevelWriterP> writers;
}

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

using namespace tipc;

namespace mov_io
{

void addParsers(tipc::Server *srv)
{
	srv->addParser(new IsQTInstalledParser);
	srv->addParser(new DefaultMovPropsParser);
	srv->addParser(new OpenMovSettingsPopupParser);
	srv->addParser(new InitLWMovParser);
	srv->addParser(new LWSetFrameRateParser);
	srv->addParser(new LWImageWriteParser);
	srv->addParser(new LWSaveSoundTrackParser);
	srv->addParser(new CloseLWMovParser);
	srv->addParser(new InitLRMovParser);
	srv->addParser(new LRLoadInfoParser);
	srv->addParser(new LREnableRandomAccessReadParser);
	srv->addParser(new LRImageReadParser);
	srv->addParser(new LRImageReadSHMParser);
	srv->addParser(new CloseLRMovParser);

#ifdef WIN32
	srv->addParser(new LRSetYMirrorParser);
	srv->addParser(new LRSetLoadTimecodeParser);
	srv->addParser(new LRTimecodeParser);
#endif
}

//************************************************************************
//    IsQTInstalled Parser
//************************************************************************

void IsQTInstalledParser::operator()(Message &msg)
{
	bool ret = Tiio::isQuicktimeInstalled();
	msg << clr << QString((ret) ? "yes" : "no");
}

//************************************************************************
//    DefaultMovProps Parser
//************************************************************************

void DefaultMovPropsParser::operator()(Message &msg)
{
	//Ensure the file path was passed - and retrieve it
	QString reply;
	msg >> reply >> clr;
	if (reply.isEmpty())
		goto err;

#ifdef WIN32
	//Ensure that QuickTime is correctly running
	if (InitializeQTML(0) != noErr)
		goto err;
#endif

	//Success - retrieve the props
	{
		TPropertyGroup movProps;
		{
			//Low-level QuickTime stuff
			ComponentInstance ci = OpenDefaultComponent(StandardCompressionType, StandardCompressionSubType);
			QTAtomContainer settings;

			if (SCGetSettingsAsAtomContainer(ci, &settings) != noErr)
				assert(false);

			fromAtomsToProperties(settings, movProps);
		}

		//Write the retrieved properties
		TFilePath tfp(reply.toStdWString());
		TOStream os(tfp);

		movProps.saveData(os);

		msg << QString("ok");
	}

	return;

err:

	msg << QString("err");
}

//************************************************************************
//    OpenMovSettingsPopup Parser
//************************************************************************

void OpenMovSettingsPopupParser::operator()(Message &msg)
{
	//Open the properties file
	QString fp;
	msg >> fp >> clr;

	//Retrieve the properties
	TPropertyGroup *props = new TPropertyGroup;
	TFilePath tfp(fp.toStdWString());
	{
		TIStream is(tfp);
		props->loadData(is);
	}

#ifdef MACOSX

	ProcessSerialNumber psn = {0, kCurrentProcess};
	TransformProcessType(&psn, kProcessTransformToForegroundApplication);
	SetFrontProcess(&psn);

#endif

	openMovSettingsPopup(props, true);

	{
		TOStream os(tfp); //Should NOT append
		props->saveData(os);
	}

	delete props;

	msg << QString("ok");
}

//************************************************************************
//    InitLWMov Parser
//************************************************************************

void InitLWMovParser::operator()(Message &msg)
{
	unsigned int id;
	QString fp, propsFp;
	msg >> id >> fp >> propsFp >> clr;

	TFilePath tfp(fp.toStdWString()), propsTFp(propsFp.toStdWString());

	try {
		TPropertyGroup *props = 0;
		if (!propsTFp.isEmpty()) {
			props = new TPropertyGroup;

			TIStream is(propsTFp);
			props->loadData(is);
		}

		writers.insert(id, TLevelWriterP(tfp, props));

		msg << QString("ok");
	} catch (...) {
		msg << QString("err");
	}
}

//************************************************************************
//    LWsetFrameRate Parser
//************************************************************************

void LWSetFrameRateParser::operator()(Message &msg)
{
	unsigned int id;
	double fps;

	msg >> id >> fps >> clr;

	writers.find(id).value()->setFrameRate(fps);

	msg << QString("ok");
}

//************************************************************************
//    LWImageWrite Parser
//************************************************************************

void LWImageWriteParser::operator()(Message &msg)
{
	unsigned int id;
	int frameIdx, lx, ly;

	msg >> id >> frameIdx >> lx >> ly;

	//Read the data through a shared memory segment
	TRaster32P ras(lx, ly);
	t32bitsrv::RasterExchanger<TPixel32> exch(ras);
	tipc::readShMemBuffer(*stream(), msg, &exch);

	//Save the image
	try {
		TImageWriterP iw(writers.find(id).value()->getFrameWriter(frameIdx + 1));
		iw->save(TRasterImageP(ras));

		msg << QString("ok");
	} catch (...) {
		msg << QString("err");
	}
}

//************************************************************************
//    LWSaveSoundTrack Parser
//************************************************************************

void LWSaveSoundTrackParser::operator()(Message &msg)
{
	unsigned int id;
	QString shMemId;

	TUINT32 sampleRate;
	TINT32 sCount;
	int bps, chanCount;
	bool signedSample;

	msg >> id >> sampleRate >> bps >> chanCount >> sCount >> signedSample;

	//Retrieve the soundtrack buffer
	TSoundTrackP st = TSoundTrack::create(sampleRate, bps, chanCount, sCount, signedSample);
	t32bitsrv::BufferExchanger exch((UCHAR *)st->getRawData());
	tipc::readShMemBuffer(*stream(), msg, &exch);

	//Write the soundtrack
	try {
		writers.find(id).value()->saveSoundTrack(st.getPointer());
		msg << QString("ok");
	} catch (...) {
		msg << QString("err");
	}
}

//************************************************************************
//    CloseLWMov Parser
//************************************************************************

void CloseLWMovParser::operator()(Message &msg)
{
	unsigned int id;
	msg >> id >> clr;

	try {
		writers.take(id);
		msg << QString("ok");
	} catch (...) {
		msg << QString("err");
	}
}

//************************************************************************
//    InitLRMov Parser
//************************************************************************

void InitLRMovParser::operator()(Message &msg)
{
	unsigned int id;
	QString fp, propsFp;
	msg >> id >> fp >> clr;
	assert(!fp.isEmpty());

	TFilePath tfp(fp.toStdWString());

	try {
		TLevelReaderP lrm(tfp);

		//Extract some info to be returned
		const TImageInfo *info = lrm->getImageInfo();
		if (!info)
			throw TImageException(tfp, "Couldn't retrieve image properties");

		int lx = info->m_lx, ly = info->m_ly;
		double frameRate = info->m_frameRate;

		tipc_debug(qDebug() << "Inserted image" << QString::fromStdWString(tfp.getWideString()));
		readers.insert(id, lrm);

		msg << QString("ok") << lx << ly << frameRate;
	} catch (...) {
		msg << QString("err");
	}
}

//************************************************************************
//    LRLoadInfo Parser
//************************************************************************

void LRLoadInfoParser::operator()(Message &msg)
{
	//Read command data
	unsigned int id;
	QString shMemId;
	msg >> id >> shMemId >> clr;

	QHash<unsigned int, TLevelReaderP>::iterator it = readers.find(id);
	if (it == readers.end())
		goto err;

	//Read level infos
	{
		TLevelP level;
		try {
			level = it.value()->loadInfo();
		} catch (...) {
			goto err;
		}

		int frameCount = level->getFrameCount();
		if (!shMemId.isEmpty()) {
			//Create a shared memory segment to transfer the infos to
			tipc::DefaultMessageParser<SHMEM_REQUEST> msgParser;
			Message shMsg;

			shMsg << shMemId << frameCount * (int)sizeof(int) << reset;
			msgParser(shMsg);

			QString str;
			shMsg >> reset >> str;
			if (str != QString("ok"))
				goto err;

			//Copy level data to the shared memory segment
			{
				QSharedMemory shmem(shMemId);
				shmem.attach();
				shmem.lock();

				TLevel::Table *table = level->getTable();

				TLevel::Table::const_iterator jt;
				int *f = (int *)shmem.data();
				for (jt = table->begin(); jt != table->end(); ++jt, ++f)
					*f = jt->first.getNumber();

				shmem.unlock();
				shmem.detach();
			}
		}

		msg << QString("ok") << frameCount;
	}

	return;

err:

	msg << QString("err");
}

//************************************************************************
//    LREnableRandomAccessRead Parser
//************************************************************************

void LREnableRandomAccessReadParser::operator()(Message &msg)
{
	unsigned int id;
	QString str;
	msg >> id >> str >> clr;
	bool enable = (str == "true");

	QHash<unsigned int, TLevelReaderP>::iterator it = readers.find(id);
	if (it == readers.end()) {
		msg << QString("err");
		return;
	}

	it.value()->enableRandomAccessRead(enable);

	msg << QString("ok");
}

//************************************************************************
//    LRSetYMirror Parser
//************************************************************************

#ifdef WIN32

void LRSetYMirrorParser::operator()(Message &msg)
{
	unsigned int id;
	QString str;
	msg >> id >> str >> clr;
	bool enable = (str == "true");

	QHash<unsigned int, TLevelReaderP>::iterator it = readers.find(id);
	if (it == readers.end()) {
		msg << QString("err");
		return;
	}

	static_cast<TLevelReaderMov *>(it.value().getPointer())->setYMirror(enable);

	msg << QString("ok");
}

//************************************************************************
//    LRSetLoadTimecode Parser
//************************************************************************

void LRSetLoadTimecodeParser::operator()(Message &msg)
{
	unsigned int id;
	QString str;
	msg >> id >> str >> clr;
	bool enable = (str == "true");

	QHash<unsigned int, TLevelReaderP>::iterator it = readers.find(id);
	if (it == readers.end()) {
		msg << QString("err");
		return;
	}

	static_cast<TLevelReaderMov *>(it.value().getPointer())->setLoadTimecode(enable);

	msg << QString("ok");
}

//************************************************************************
//    LRTimecode Parser
//************************************************************************

void LRTimecodeParser::operator()(Message &msg)
{
	unsigned int id;
	int frameIdx;
	QString str;
	msg >> id >> frameIdx >> clr;

	QHash<unsigned int, TLevelReaderP>::iterator it = readers.find(id);
	if (it == readers.end()) {
		msg << QString("err");
		return;
	}

	UCHAR hh, mm, ss, ff;
	static_cast<TLevelReaderMov *>(it.value().getPointer())->timecode(frameIdx, hh, mm, ss, ff);

	msg << QString("ok") << hh << mm << ss << ff;
}

#endif

//************************************************************************
//    LRImageRead Parser
//************************************************************************

void LRImageReadParser::operator()(Message &msg)
{
	tipc_debug(
		QTime fTime; QTime irTime; QTime shTime;
		fTime.start(););

	{
		unsigned int id;
		int lx, ly, pixSize, frameIdx, x, y, shrinkX, shrinkY;

		msg >> id >> lx >> ly >> pixSize >> frameIdx >> x >> y >> shrinkX >> shrinkY >> clr;

		if (pixSize != 4)
			goto err;

		QHash<unsigned int, TLevelReaderP>::iterator it = readers.find(id);
		if (it == readers.end())
			goto err;

		tipc_debug(irTime.start());

		//Load the raster
		TRaster32P ras(lx, ly);
		try {
			TImageReaderP ir(it.value()->getFrameReader(frameIdx + 1));
			ir->load(ras, TPoint(x, y), shrinkX, shrinkY);
		} catch (...) {
			goto err;
		}

		tipc_debug(qDebug() << "load time:" << irTime.elapsed());
		tipc_debug(shTime.start());

		t32bitsrv::RasterExchanger<TPixel32> exch(ras);
		if (!tipc::writeShMemBuffer(*stream(), msg << clr, lx * ly * sizeof(TPixel32), &exch))
			goto err;

		tipc_debug(qDebug() << "exchange time:" << shTime.elapsed());
		tipc_debug(qDebug() << "TLevelReaderMov::loadImage time:" << fTime.elapsed());
	}

	return;

err:

	msg << QString("err");
}

//************************************************************************
//    LRImageReadSHM Parser
//************************************************************************

void LRImageReadSHMParser::operator()(Message &msg)
{
	tipc_debug(
		QTime fTime; QTime irTime;
		fTime.start(););

	unsigned int id;
	int lx, ly, frameIdx;
	QString shMemId;

	msg >> id >> lx >> ly >> frameIdx >> shMemId >> clr;

	tipc_debug(qDebug() << "LoadImageSHM data:" << id << lx << ly << frameIdx << shMemId);

	QHash<unsigned int, TLevelReaderP>::iterator it = readers.find(id);
	if (it == readers.end())
		goto err;

	//Attach the shared memory segment the raster
	{
		QSharedMemory shm(shMemId);
		shm.attach();
		if (!shm.isAttached())
			goto err;

		//Load the raster
		TRaster32P ras(lx, ly, lx, (TPixel32 *)shm.data());
		try {
			tipc_debug(qDebug() << "loading image...");
			tipc_debug(irTime.start());

			shm.lock();
			TImageReaderP ir(it.value()->getFrameReader(frameIdx + 1));
			ir->load(ras, TPoint(), 1, 1);
			shm.unlock();

			tipc_debug(qDebug() << "load time:" << irTime.elapsed());
		} catch (TImageException e) {
			shm.unlock();
			tipc_debug(qDebug() << "Image Read Error:" << QString::fromStdWString(e.getMessage()));
			goto err;
		} catch (...) {
			shm.unlock();
			tipc_debug(qDebug() << "Unknown Image Read Error");
			goto err;
		}
	}

	msg << QString("ok");

#ifdef WIN32

	UCHAR hh, mm, ss, ff;
	TLevelReaderMov *lrm = static_cast<TLevelReaderMov *>(it.value().getPointer());
	lrm->loadedTimecode(hh, mm, ss, ff);

	tipc_debug(qDebug() << "TLevelReaderMov::loadImage time:" << fTime.elapsed());
	msg << hh << mm << ss << ff;

#endif

	return;

err:

	msg << QString("err");
}

//************************************************************************
//    CloseLRMov Parser
//************************************************************************

void CloseLRMovParser::operator()(Message &msg)
{
	unsigned int id;
	msg >> id >> clr;

	readers.take(id);
	msg << QString("ok");
}

} //namespace mov_io

#endif // !x64 && !__LP64__