#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 #endif // Qt stuff #include #include #include #include #include #include // 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 #endif //--------------------------------------------------- // Local namespace stuff namespace { QHash readers; QHash 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 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::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 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::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::iterator it = readers.find(id); if (it == readers.end()) { msg << QString("err"); return; } static_cast(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::iterator it = readers.find(id); if (it == readers.end()) { msg << QString("err"); return; } static_cast(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::iterator it = readers.find(id); if (it == readers.end()) { msg << QString("err"); return; } UCHAR hh, mm, ss, ff; static_cast(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::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 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::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(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__