Mercurial > hg > dmlib
view edmain.cpp @ 510:43ea59887c69
Start work on making C64 formats encoding possible by changing DMDecodeOps
to DMEncDecOps and adding fields and op enums for custom encode functions, renaming,
etc. Split generic op sanity checking into a separate function in
preparation for its use in generic encoding function.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Mon, 19 Nov 2012 15:06:01 +0200 |
parents | d34922e6a244 |
children | 935b91d0f508 |
line wrap: on
line source
// // Demo Editor -- Main program // (C) Copyright 2012 Matti 'ccr' Hämäläinen <ccr@tnsp.org> // #include <SDL.h> #include "dmengine.h" #include "edmain.h" #include <QSettings> #include <QGLWidget> int main(int argc, char *argv[]) { dmVerbosity = 5; QApplication app(argc, argv); app.setOrganizationName("TNSP"); app.setOrganizationDomain("tnsp.org"); app.setApplicationName(PROGRAM_NAME); app.setApplicationVersion(PROGRAM_VERSION); DemoEditor mainWin; mainWin.show(); return app.exec(); } void engineAudioCallback(void *userdata, Uint8 * stream, int len) { DMEngineData *engine = (DMEngineData *) userdata; if (engine->paused) { memset(stream, 0, len); } else #ifdef DM_USE_JSS { if (engine->dev != NULL) jvmRenderAudio(engine->dev, stream, len / jvmGetSampleSize(engine->dev)); } #endif #ifdef DM_USE_TREMOR if (engine->audioPos + len >= engine->audioRes->rdataSize) { engine->exitFlag = true; } else { memcpy(stream, (Uint8 *) engine->audioRes->rdata + engine->audioPos, len); engine->audioPos += len; } #endif } int DemoEditor::reopenResources() { int err; if ((err = dmres_init(&engine.resources, engine.optPackFilename, engine.optDataPath, engine.optResFlags, engineClassifier)) != DMERR_OK) { dmError("Could not initialize resource manager: %d, %s.\n", err, dmErrorStr(err)); } return err; } int DemoEditor::loadResources() { int err, loaded, total; err = dmres_preload(engine.resources, true, &loaded, &total); while ((err = dmres_preload(engine.resources, false, &loaded, &total)) == DMERR_PROGRESS) { // Show a nice progress bar while loading if (total > 0 && (loaded % 2) == 0) { /* if ((err = engineShowProgress(loaded, total)) != DMERR_OK) return err; */ } } return DMERR_OK; } DemoEditor::DemoEditor() { int err; resize(1024, 768); setWindowTitle(QCoreApplication::applicationName()); memset(&engine, 0, sizeof(engine)); initSDL = FALSE; currTimeline = NULL; // Pre-initialization if ((err = demoPreInit(&engine)) != DMERR_OK) goto error_exit; // Initialize SDL components dmPrint(1, "Initializing libSDL.\n"); if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) != 0) { dmError("Could not initialize SDL: %s\n", SDL_GetError()); goto error_exit; } initSDL = true; // Initialize audio parts if (engine.optAfmt.freq == 0 && engine.optAfmt.channels == 0) { // Defaults, if none seem to be set engine.optAfmt.freq = 44100; engine.optAfmt.format = AUDIO_S16SYS; engine.optAfmt.channels = 2; engine.optAfmt.samples = engine.optAfmt.freq / 16; } #ifdef DM_USE_JSS jssInit(); switch (engine.optAfmt.format) { case AUDIO_S16SYS: engine.jss_format = JSS_AUDIO_S16; break; case AUDIO_U16SYS: engine.jss_format = JSS_AUDIO_U16; break; case AUDIO_S8: engine.jss_format = JSS_AUDIO_S8; break; case AUDIO_U8: engine.jss_format = JSS_AUDIO_U8; break; } dmPrint(1, "Initializing miniJSS mixer with fmt=%d, chn=%d, freq=%d\n", engine.jss_format, engine.optAfmt.channels, engine.optAfmt.freq); if ((engine.dev = jvmInit(engine.jss_format, engine.optAfmt.channels, engine.optAfmt.freq, JMIX_AUTO)) == NULL) { dmError("jvmInit() returned NULL, voi perkele.\n"); goto error_exit; } if ((engine.plr = jmpInit(engine.dev)) == NULL) { dmError("jmpInit() returned NULL\n"); goto error_exit; } #endif // Initialize SDL audio dmPrint(1, "Trying to init SDL audio with: fmt=%d, chn=%d, freq=%d\n", engine.optAfmt.format, engine.optAfmt.channels, engine.optAfmt.freq); engine.optAfmt.callback = engineAudioCallback; if (SDL_OpenAudio(&engine.optAfmt, NULL) < 0) { dmError("Couldn't open SDL audio: %s\n", SDL_GetError()); goto error_exit; } // Initialize SDL video if (engine.demoInitPreVideo != NULL && (err = engine.demoInitPreVideo(&engine)) != DMERR_OK) { dmError("demoInitPreVideo() failed, %d: %s\n", err, dmErrorStr(err)); goto error_exit; } dmPrint(1, "Initializing SDL video %d x %d x %dbpp, flags=0x%08x\n", engine.optScrWidth, engine.optScrHeight, engine.optBitDepth, engine.optVFlags); engine.screen = SDL_CreateRGBSurface(SDL_SWSURFACE, engine.optScrWidth, engine.optScrHeight, engine.optBitDepth, 0, 0, 0, 0); if (engine.screen == NULL) { dmError("Could not allocate video backbuffer surface.\n"); goto error_exit; } if (engine.demoInitPostVideo != NULL && (err = engine.demoInitPostVideo(&engine)) != DMERR_OK) { dmError("demoInitPostVideo() failed, %d: %s\n", err, dmErrorStr(err)); goto error_exit; } error_exit: // Setup GUI elements createMainGUI(); createNewFile(); timelineView->setTimeline(currTimeline); settingsRestore(); initEffectsAndResources(); statusMsg("Application started."); } DemoEditor::~DemoEditor() { statusMsg("Shutting down."); settingsSave(); delete demoView; historyReset(); if (engine.screen) SDL_FreeSurface(engine.screen); SDL_LockAudio(); SDL_PauseAudio(1); #ifdef DM_USE_JSS jmpClose(engine.plr); jvmClose(engine.dev); jssClose(); #endif SDL_UnlockAudio(); shutdownEffectsAndResources(); if (initSDL) SDL_Quit(); } int DemoEditor::getTimelineDuration() { return timelineAudioTrack->getDuration(); } void DemoEditor::updateResourceView() { } void DemoEditor::updateTimelineView() { demoView->setEngineData(&engine); if (engine.audioRes != NULL) { timelineAudioTrack->setWaveform( engine.audioRes->rdata, engine.audioRes->rdataSize, engine.optAfmt.format, engine.optAfmt.channels, engine.optAfmt.freq); } timelineAudioTrack->setOffset(currViewOffset); timelineAudioTrack->setScale(currViewScale); timelineView->setTime(currFrameTime); timelineView->setOffset(currViewOffset); timelineView->setScale(currViewScale); timelineScrollBar->setRange(0, getTimelineDuration()); timelineScrollBar->setValue(currViewOffset); } void DemoEditor::actionTimelineScrollChanged(int value) { currViewOffset = value; updateTimelineView(); } void DemoEditor::actionOffsetChanged(float value) { currViewOffset = value; updateTimelineView(); } void DemoEditor::actionTimeChanged(float value) { currFrameTime = value; updateTimelineView(); } void DemoEditor::actionTimelineChanged() { updateMenuStates(); update(); } int DemoEditor::initEffectsAndResources() { int err; currViewOffset = 0; currFrameTime = 0; currViewScale = 1.0f; // Initialize resource subsystem statusMsg("Initializing resources subsystem."); if ((err = reopenResources()) != DMERR_OK) return err; // Load resources statusMsg("Loading resources, please wait..."); if ((err = loadResources()) != DMERR_OK) { dmError("Error loading resources, %d: %s.\n", err, dmErrorStr(err)); return err; } // Final initializations statusMsg("Initializing custom demo data."); if ((err = engine.demoInit(&engine)) != DMERR_OK) { dmError("Failure in demoInit(), %d: %s\n", err, dmErrorStr(err)); return err; } // Initialize effects statusMsg("Initializing effects ..."); if ((err = engineInitializeEffects(&engine)) != DMERR_OK) { dmError("Effects initialization failed, %d: %s\n", err, dmErrorStr(err)); return err; } // Etc. rehash(); return DMERR_OK; } void DemoEditor::shutdownEffectsAndResources() { delete currTimeline; dmFreePreparedTimelineData(engine.ptl); engineShutdownEffects(&engine); dmres_close(engine.resources); if (engine.demoShutdown != NULL) engine.demoShutdown(&engine); } void DemoEditor::rehash() { timelineView->setTimeline(currTimeline); updateResourceView(); updateTimelineView(); updateMenuStates(); update(); } void DemoEditor::createNewFile() { delete currTimeline; currTimeline = new EDTimelineObject(); DMTimelineTrack *tr; dmTimelineAddTrack(currTimeline->tl, &tr, "Penis"); DMTimelineEvent *ev; dmTimelineTrackAddEvent(tr, 500, 100, &ev); dmTimelineEventSetEffectByIndex(ev, 0); historyReset(); updateMenuStates(); update(); } void DemoEditor::readFromFile(QString filename) { EDTimelineObject *tmp = new EDTimelineObject(); int ret = tmp->load(filename); if (ret != DMERR_OK) { showFileErrorDialog("Loading demo blob file "+ filename, ret); delete tmp; } else { delete currTimeline; currTimeline = tmp; rehash(); } } void DemoEditor::saveToFile(QString filename) { int ret = currTimeline->save(filename); if (ret != DMERR_OK) { showFileErrorDialog("Saving demo blob file "+ filename, ret); } updateMenuStates(); } void DemoEditor::settingsRestore() { QSettings s; restoreGeometry(s.value("windowGeometry").toByteArray()); restoreState(s.value("windowState").toByteArray()); } void DemoEditor::settingsSave() { QSettings s; s.setValue("windowGeometry", saveGeometry()); s.setValue("windowState", saveState()); } // // Edit history functionality // void DemoEditor::historyReset() { if (currTimeline != NULL) currTimeline->scrub(); undoHistoryPos = -1; undoHistoryMax = DOC_UNDO_MAX; undoHistory.clear(); } void DemoEditor::historyPush(QString description) { if (currTimeline == NULL) return; if (!undoHistory.isEmpty() && undoHistory.last()->state() == "-") { delete undoHistory.takeLast(); } while (undoHistory.size() >= undoHistoryMax) { delete undoHistory.takeFirst(); } EDTimelineObject *copy = new EDTimelineObject(currTimeline); copy->setState(description); undoHistory.append(copy); } void DemoEditor::historyTop() { if (currTimeline == NULL) return; EDTimelineObject *copy = new EDTimelineObject(currTimeline); copy->setState("-"); undoHistory.append(copy); undoHistoryPos = undoHistory.size() - 1; currTimeline->touch(); updateTimelineView(); updateMenuStates(); update(); } void DemoEditor::historyPop() { if (!undoHistory.isEmpty()) { delete undoHistory.takeLast(); } } void DemoEditor::performRedo() { if (undoHistoryPos >= 0 && undoHistoryPos < undoHistory.size() - 1) { undoHistoryPos++; delete currTimeline; currTimeline = new EDTimelineObject(undoHistory.at(undoHistoryPos)); currTimeline->touch(); updateTimelineView(); updateMenuStates(); update(); } } void DemoEditor::performUndo() { if (undoHistoryPos > 0 && undoHistory.size() > 1) { undoHistoryPos--; delete currTimeline; currTimeline = new EDTimelineObject(undoHistory.at(undoHistoryPos)); currTimeline->touch(); updateTimelineView(); updateMenuStates(); update(); } }