| |
| |
| #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__ |
| |