A basic graphics package for the LPC4088 Display Module.
Dependents: lpc4088_displaymodule_demo_sphere sampleGUI sampleEmptyGUI lpc4088_displaymodule_fs_aid ... more
Fork of DMBasicGUI by
SlideShow.cpp
00001 /* 00002 * Copyright 2014 Embedded Artists AB 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include "SlideShow.h" 00018 #include "Image.h" 00019 #include "mbed_debug.h" 00020 #include "DMBoard.h" 00021 00022 /****************************************************************************** 00023 * Defines and typedefs 00024 *****************************************************************************/ 00025 00026 #define SLIDESHOW_DBG 0 00027 00028 #define NO_SLOT -12 /* Some constant to indicate that no slot is in use */ 00029 00030 /* Helper macros for the Fade transition */ 00031 #define FADE_XRED(__in) (((__in)>>11)&0x1f) 00032 #define FADE_XGREEN(__in) (((__in)>>5)&0x3f) 00033 #define FADE_XBLUE(__in) ((__in)&0x1f) 00034 #define FADE_COMBINE(__old, __new, __mul) \ 00035 ( ((((FADE_XRED(__old)*(8-(__mul)))+(FADE_XRED(__new)*(__mul)))>>3)<<11) \ 00036 | ((((FADE_XGREEN(__old)*(8-(__mul)))+(FADE_XGREEN(__new)*(__mul)))>>3)<<5) \ 00037 | (((FADE_XBLUE(__old)*(8-(__mul)))+(FADE_XBLUE(__new)*(__mul)))>>3) ) 00038 00039 00040 /****************************************************************************** 00041 * Global variables 00042 *****************************************************************************/ 00043 00044 extern volatile uint32_t msTicks; 00045 00046 /****************************************************************************** 00047 * Private Functions 00048 *****************************************************************************/ 00049 00050 void SlideShow::Command::print() 00051 { 00052 switch(type) 00053 { 00054 case Clear: 00055 printf("CMD: Clear screen\n"); 00056 break; 00057 case Goto: 00058 printf("CMD: Goto command %d\n", information); 00059 break; 00060 case LoadImage: 00061 printf("CMD: Load file %s into [%d]\n", fname, information); 00062 break; 00063 case Show: 00064 printf("CMD: Show image [%d] with %s transition\n", information, transition->typeString()); 00065 break; 00066 case Wait: 00067 printf("CMD: Wait %d ms\n", information); 00068 break; 00069 case Callout: 00070 printf("CMD: Callout %d\n", information); 00071 break; 00072 default: 00073 printf("Unknown command\n"); 00074 } 00075 } 00076 00077 SlideShow::SlideShowError SlideShow::Command::handle(SlideShow* ss, int* seqIdx, int* lastTime) 00078 { 00079 SlideShowError result = Ok; 00080 00081 //printf("[%03d] ", *seqIdx); print(); 00082 switch (type) 00083 { 00084 case Clear: 00085 // Use the 3rd back buffer as a fake image for the transition 00086 Image::ImageData_t d; 00087 d.height = ss->screenHeight; 00088 d.width = ss->screenWidth; 00089 d.pixels = &ss->ImageBackBuffer[ss->screenPixels*2]; 00090 d.pointerToFree = NULL; 00091 memset(d.pixels, information, ss->screenBytes); 00092 if (ss->CurrentSlot == NO_SLOT) { 00093 result = transition->execute(ss, NULL, &d); 00094 } else { 00095 result = transition->execute(ss, &(ss->PreparedImages[ss->CurrentSlot]), &d); 00096 } 00097 *lastTime = msTicks; 00098 *seqIdx+=1; 00099 break; 00100 00101 case Goto: 00102 *seqIdx = information; 00103 break; 00104 00105 case LoadImage: 00106 if ((result = ss->loadImage(fname, information)) != Ok) 00107 { 00108 printf("Failed to load image. Aborting...\n"); 00109 break; 00110 } 00111 *seqIdx+=1; 00112 break; 00113 00114 case Show: 00115 if (ss->CurrentSlot == NO_SLOT) { 00116 result = transition->execute(ss, NULL, &(ss->PreparedImages[information])); 00117 } else { 00118 result = transition->execute(ss, &(ss->PreparedImages[ss->CurrentSlot]), &(ss->PreparedImages[information])); 00119 } 00120 if (result != Ok) { 00121 printf("Failed to show image. Aborting...\n"); 00122 break; 00123 } 00124 ss->CurrentSlot = information; 00125 *lastTime = msTicks; 00126 *seqIdx+=1; 00127 break; 00128 00129 case Wait: 00130 ss->delay(*lastTime, information); 00131 *lastTime = msTicks; 00132 *seqIdx+=1; 00133 break; 00134 00135 case Callout: 00136 if (ss->callout != NULL) { 00137 result = ss->callout(ss->calloutId, ss, information); 00138 } else { 00139 // Silently accept that no callout listener is registered 00140 } 00141 *seqIdx+=1; 00142 break; 00143 00144 default: 00145 printf("Found unknown command at index %d\n", *seqIdx); 00146 result = InvalidScript; 00147 } 00148 return result; 00149 } 00150 00151 SlideShow::SlideShowError SlideShow::Transition::execute(SlideShow* ss, Image::ImageData_t* CurrentImage, Image::ImageData_t* NewImage) 00152 { 00153 SlideShowError result = Ok; 00154 00155 do { 00156 00157 // TODO: This would be a good place to handle rendering of differently sized images, 00158 // could unregister+register if NewImage is different from CurrentImage 00159 00160 // Register with the Renderer if needed. 00161 if (ss->rendHnd == 0) { 00162 if (ss->rend == NULL) { 00163 printf("No registered renderer\n"); 00164 result = RuntimeError; 00165 break; 00166 } 00167 00168 // time to register with the renderer 00169 ss->rendHnd = ss->rend->registerUser(ss->layer, ss->drawXoff, ss->drawYoff, 00170 NewImage->width, NewImage->height); 00171 if (ss->rendHnd == 0) { 00172 printf("Failed to register with renderer\n"); 00173 result = RuntimeError; 00174 break; 00175 } 00176 } 00177 00178 switch (t) { 00179 case None: 00180 { 00181 ss->rend->setFramebuffer(ss->rendHnd, NewImage->pixels); 00182 } 00183 break; 00184 00185 case LeftRight: // TODO: Note that this transition is only implemented for fullscreen mode 00186 { 00187 // Create a buffer with the old image 00188 if (CurrentImage == NULL) { 00189 memset(ss->ImageBackBuffer, 0, ss->screenBytes); 00190 } else { 00191 memcpy(ss->ImageBackBuffer, CurrentImage->pixels, ss->screenBytes); 00192 } 00193 int end = ss->screenWidth - LeftRight_PixelsToSkip; 00194 for (int x = 0; x < end; x += LeftRight_PixelsToSkip) 00195 { 00196 int off = 0; 00197 for (int y = 0; y < ss->screenHeight; y++) 00198 { 00199 memcpy(ss->ImageBackBuffer + (off+x), NewImage->pixels + (off+x), 00200 LeftRight_PixelsToSkip*sizeof(uint16_t)); 00201 off += ss->screenWidth; 00202 } 00203 00204 // Show the updated image 00205 ss->rend->setFramebuffer(ss->rendHnd, ss->ImageBackBuffer); 00206 00207 // Sleep and do over again 00208 ThisThread::sleep_for(LeftRight_DelayMs); 00209 } 00210 00211 // Show final image 00212 ss->rend->setFramebuffer(ss->rendHnd, NewImage->pixels); 00213 } 00214 break; 00215 00216 case DownUp: 00217 { 00218 int imgNumPixels = NewImage->width * NewImage->height; 00219 00220 // Create a buffer with the two images after each other, NewImage below 00221 if (CurrentImage == NULL) { 00222 memset(ss->ImageBackBuffer, 0, imgNumPixels*2); 00223 } else { 00224 memcpy(ss->ImageBackBuffer, CurrentImage->pixels, imgNumPixels*2); 00225 } 00226 memcpy(ss->ImageBackBuffer + imgNumPixels, NewImage->pixels, imgNumPixels*2); 00227 00228 // We will be using a back buffer 00229 for (int i = DownUp_LineSkip/2; i < (NewImage->height - 1); i+=DownUp_LineSkip) 00230 { 00231 // Show image by advancing what is shown one line at a time 00232 ss->rend->setFramebuffer(ss->rendHnd, ss->ImageBackBuffer + i * NewImage->width); 00233 00234 // Sleep and do over again 00235 ThisThread::sleep_for(DownUp_DelayMs); 00236 } 00237 00238 // show final image 00239 ss->rend->setFramebuffer(ss->rendHnd, NewImage->pixels); 00240 } 00241 break; 00242 00243 case TopDown: 00244 { 00245 int imgNumPixels = NewImage->width * NewImage->height; 00246 00247 // Create a buffer with the two images after each other, NewImage above 00248 if (CurrentImage == NULL) { 00249 memset(ss->ImageBackBuffer + imgNumPixels, 0, imgNumPixels*2); 00250 } else { 00251 memcpy(ss->ImageBackBuffer + imgNumPixels, CurrentImage->pixels, imgNumPixels*2); 00252 } 00253 memcpy(ss->ImageBackBuffer, NewImage->pixels, imgNumPixels*2); 00254 00255 // We will be using a back buffer 00256 for (int i = NewImage->height - TopDown_LineSkip/2; i > 0; i-=TopDown_LineSkip) 00257 { 00258 // Show image by advancing what is shown one line at a time 00259 ss->rend->setFramebuffer(ss->rendHnd, ss->ImageBackBuffer + i*NewImage->width); 00260 00261 // Sleep and do over again 00262 ThisThread::sleep_for(TopDown_DelayMs); 00263 } 00264 00265 // show final image 00266 ss->rend->setFramebuffer(ss->rendHnd, NewImage->pixels); 00267 } 00268 break; 00269 00270 case Blinds: 00271 { 00272 int i; 00273 int blockNumPixels = Blinds_LinesPerBlock * ss->screenWidth; 00274 int blockNumBytes = blockNumPixels * sizeof(uint16_t); 00275 image_t beamBlock = ss->ImageBackBuffer + ss->screenPixels; 00276 image_t bkgBlock = beamBlock + blockNumPixels; 00277 00278 // Create a buffer with the old image 00279 if (CurrentImage == NULL) { 00280 memset(ss->ImageBackBuffer, 0, ss->screenBytes); 00281 } else { 00282 memcpy(ss->ImageBackBuffer, CurrentImage->pixels, ss->screenBytes); 00283 } 00284 00285 // Create the two coloured blocks 00286 memset(beamBlock, Blinds_BeamColor, blockNumBytes); 00287 memset(bkgBlock, Blinds_BackColor, blockNumBytes); 00288 00289 for (i = 0; i < ss->screenPixels; i += blockNumPixels) 00290 { 00291 // Draw the moving beam, erasing the old image 00292 memcpy(ss->ImageBackBuffer+i, beamBlock, blockNumBytes); 00293 00294 // Fill upp behind the beam with background color 00295 if (i > 0) { 00296 memcpy(ss->ImageBackBuffer+i-blockNumPixels, bkgBlock, blockNumBytes); 00297 } 00298 00299 // Show the updated image 00300 ss->rend->setFramebuffer(ss->rendHnd, ss->ImageBackBuffer); 00301 00302 // Sleep and do over again 00303 ThisThread::sleep_for(Blinds_DelayMs); 00304 } 00305 memcpy(ss->ImageBackBuffer+i-blockNumPixels, bkgBlock, blockNumBytes); 00306 ss->rend->setFramebuffer(ss->rendHnd, ss->ImageBackBuffer); 00307 ThisThread::sleep_for(Blinds_DelayMs); 00308 00309 for (i = 0; i < ss->screenPixels; i += blockNumPixels) 00310 { 00311 // Draw the moving beam, erasing the old image 00312 memcpy(ss->ImageBackBuffer+i, beamBlock, blockNumBytes); 00313 00314 // Fill upp behind the beam with the new image 00315 if (i > 0) { 00316 memcpy(ss->ImageBackBuffer+i-blockNumPixels, NewImage->pixels+i-blockNumPixels, blockNumBytes); 00317 } 00318 00319 // Show image by advancing what is shown one line at a time 00320 ss->rend->setFramebuffer(ss->rendHnd, ss->ImageBackBuffer); 00321 00322 // Sleep and do over again 00323 ThisThread::sleep_for(Blinds_DelayMs); 00324 } 00325 00326 // show final image 00327 ss->rend->setFramebuffer(ss->rendHnd, NewImage->pixels); 00328 } 00329 break; 00330 00331 case Fade: 00332 { 00333 // Create a buffer with the old image 00334 if (CurrentImage == NULL) { 00335 memset(ss->ImageBackBuffer, 0, ss->screenBytes * 2); // use an extra backbuffer 00336 } else { 00337 memcpy(ss->ImageBackBuffer, CurrentImage->pixels, ss->screenBytes); 00338 } 00339 00340 uint32_t firstY = 0; 00341 uint32_t lastY = NewImage->height; 00342 for (uint32_t y = 0, off=0; y < NewImage->height; y++) { 00343 for (uint32_t x = 0; x < NewImage->width; x++) { 00344 off++; 00345 if (NewImage->pixels[off] != ss->ImageBackBuffer[off]) { 00346 firstY = y; 00347 y = NewImage->height; 00348 break; 00349 } 00350 } 00351 } 00352 for (uint32_t y = NewImage->height-1, off=NewImage->height*NewImage->width-1; y > firstY; y--) { 00353 for (uint32_t x = 0; x < NewImage->width; x++) { 00354 off--; 00355 if (NewImage->pixels[off] != ss->ImageBackBuffer[off]) { 00356 lastY = y; 00357 y = firstY; // to break the outer loop as well 00358 break; 00359 } 00360 } 00361 } 00362 00363 // Gradually fade between the old and new images 00364 for (int pass = 1; pass < 8; pass++) 00365 { 00366 uint16_t* oldImg = CurrentImage==NULL ? &ss->ImageBackBuffer[ss->screenPixels] : &CurrentImage->pixels[firstY*NewImage->width]; 00367 uint16_t* newImg = &NewImage->pixels[firstY*NewImage->width]; 00368 uint16_t* dstImg = &ss->ImageBackBuffer[firstY*NewImage->width]; 00369 for (uint32_t y = firstY; y <= lastY; y++) 00370 { 00371 for (uint32_t x = 0; x < NewImage->width; x++) 00372 { 00373 if (*oldImg != *newImg) { 00374 *dstImg = FADE_COMBINE(*oldImg, *newImg, pass); 00375 } 00376 oldImg++; 00377 newImg++; 00378 dstImg++; 00379 } 00380 } 00381 // Show the updated image 00382 ss->rend->setFramebuffer(ss->rendHnd, ss->ImageBackBuffer); 00383 00384 // Sleep and do over again 00385 ThisThread::sleep_for(Fade_DelayMs); 00386 } 00387 00388 // show final image 00389 ss->rend->setFramebuffer(ss->rendHnd, NewImage->pixels); 00390 } 00391 break; 00392 00393 case Unknown: 00394 default: 00395 result = RuntimeError; 00396 } 00397 } while(0); 00398 00399 return result; 00400 } 00401 00402 SlideShow::SlideShowError SlideShow::loadFile(const char* path, uint8_t** pData, uint32_t* pSize) 00403 { 00404 FILE* f = NULL; 00405 uint32_t pos, size, num; 00406 SlideShowError result = Ok; 00407 00408 *pData = NULL; 00409 *pSize = 0; 00410 00411 if (fileMutex != NULL) { 00412 fileMutex->lock(); 00413 } 00414 do 00415 { 00416 f = fopen(path, "r"); 00417 if (f == NULL) { 00418 printf("Failed to open file %s for reading\n", path); 00419 result = FileError; 00420 break; 00421 } 00422 00423 // Determine file size 00424 pos = ftell(f); 00425 fseek(f, 0, SEEK_END); 00426 size = ftell(f); 00427 fseek(f, pos, SEEK_SET); 00428 00429 // Allocate memory to read into 00430 *pData = (unsigned char*)malloc(size); 00431 if (*pData == NULL) { 00432 printf("Failed to allocate %u bytes to load %s into\n", size, path); 00433 result = OutOfMemory; 00434 break; 00435 } 00436 00437 // Read entire file 00438 *pSize = size; 00439 pos = 0; 00440 do { 00441 num = fread(*pData + pos, 1, size, f); 00442 if (num > 0) { 00443 size -= num; 00444 pos += num; 00445 } 00446 } while ((num > 0) && (size > 0)); 00447 00448 if (size != 0) { 00449 printf("Failed to read entire %s, got %u of %u\n", path, pos, *pSize); 00450 result = FileError; 00451 break; 00452 } 00453 00454 // All OK 00455 00456 } while(0); 00457 00458 if (f != NULL) { 00459 fclose(f); 00460 } 00461 if (result != Ok) { 00462 if (*pData != NULL) { 00463 free(*pData); 00464 *pData = NULL; 00465 *pSize = 0; 00466 } 00467 } 00468 00469 if (fileMutex != NULL) { 00470 fileMutex->unlock(); 00471 } 00472 00473 return result; 00474 } 00475 00476 00477 // pBuf in, pOffset in/out, pLine out 00478 // returns 0 as long as a token is found 00479 int SlideShow::getNextLine(char* pBuf, int* pOffset, char** ppLine) 00480 { 00481 int pos = *pOffset; 00482 int result = -1; 00483 00484 // trim whitespace from start of line 00485 while ((pBuf[pos] == ' ') || (pBuf[pos] == '\t')) 00486 { 00487 pos++; 00488 } 00489 *ppLine = &(pBuf[pos]); 00490 00491 while (pBuf[pos] != '\0') 00492 { 00493 if ((pBuf[pos] == '\r') || (pBuf[pos] == '\n')) 00494 { 00495 // found the next end of line 00496 pBuf[pos++] = '\0'; 00497 result = 0; 00498 00499 // move past all end-of-line characters 00500 while ((pBuf[pos] == '\r') || (pBuf[pos] == '\n')) 00501 { 00502 pos++; 00503 } 00504 break; 00505 } 00506 pos++; 00507 } 00508 00509 *pOffset = pos; 00510 return result; 00511 } 00512 00513 // pLine in, ppPart1 out, ppPart2 out, ppPart3 out 00514 // returns number of found parts 00515 int SlideShow::splitLine(char* pLine, char** ppPart1, char** ppPart2, char** ppPart3) 00516 { 00517 int pos = 0; 00518 int found = 0; 00519 00520 *ppPart1 = NULL; 00521 *ppPart2 = NULL; 00522 *ppPart3 = NULL; 00523 00524 if (*pLine != '\0') 00525 { 00526 *ppPart1 = &(pLine[0]); 00527 found++; 00528 00529 while (pLine[pos] != '\0') 00530 { 00531 if (pLine[pos] == ' ') 00532 { 00533 // found the next token separator 00534 pLine[pos++] = '\0'; 00535 found++; 00536 00537 // move past all token separator characters 00538 while (pLine[pos] == ' ') 00539 { 00540 pos++; 00541 } 00542 00543 // start looking for end of next token 00544 if (found == 2) 00545 { 00546 *ppPart2 = &(pLine[pos]); 00547 } 00548 else if (found == 3) 00549 { 00550 *ppPart3 = &(pLine[pos]); 00551 } 00552 } 00553 pos++; 00554 } 00555 } 00556 00557 return found; 00558 } 00559 00560 // returns index of pLabel or -1 if it doesn't exist 00561 int SlideShow::findLabel(LabelInfo* pLabels, int numLabels, const char* pLabel) 00562 { 00563 int i; 00564 for (i = 0; i < numLabels; i++) 00565 { 00566 if (strcmp(pLabels[i].pLabel, pLabel) == 0) 00567 { 00568 return pLabels[i].index; 00569 } 00570 } 00571 return -1; 00572 } 00573 00574 void SlideShow::freeSequence(void) 00575 { 00576 if (allocatedSequenceItems > 0) { 00577 for (int i = 0; i < usedSequenceItems; i++) { 00578 delete Sequence[i]; 00579 } 00580 free(Sequence); 00581 Sequence = NULL; 00582 allocatedSequenceItems = 0; 00583 usedSequenceItems = 0; 00584 } 00585 } 00586 00587 SlideShow::SlideShowError SlideShow::expandSequence() 00588 { 00589 int newSize = allocatedSequenceItems + 20; 00590 Command** newPtr = (Command**)realloc(Sequence, newSize * sizeof(Command*)); 00591 if (newPtr != NULL) { 00592 Sequence = newPtr; 00593 allocatedSequenceItems = newSize; 00594 return Ok; 00595 } else { 00596 return OutOfMemory; 00597 } 00598 } 00599 00600 SlideShow::SlideShowError SlideShow::parseScript(char* pBuf) 00601 { 00602 char* pLine = NULL; 00603 int offset = 0; 00604 LabelInfo Labels[10] = {0}; 00605 int numLabels = 0; 00606 LabelInfo UnresolvedGotos[10] = {0}; 00607 int numUnresolvedGotos = 0; 00608 int i; 00609 SlideShowError result; 00610 00611 // cleanup old sequences 00612 freeSequence(); 00613 00614 // prepare the new one 00615 result = expandSequence(); 00616 if (result != Ok) { 00617 return result; 00618 } 00619 00620 // start parsing the new sequence 00621 while (getNextLine(pBuf, &offset, &pLine) == 0) 00622 { 00623 if (*pLine == '#') 00624 { 00625 // found a comment line 00626 } 00627 else 00628 { 00629 char* pCommand; 00630 char* pArg1; 00631 char* pArg2; 00632 int num = splitLine(pLine, &pCommand, &pArg1, &pArg2); 00633 00634 if ((num >= 1) && (num <= 3) && (strcmp(pCommand, "clear") == 0)) 00635 { 00636 if (num == 1) { 00637 Sequence[usedSequenceItems] = new Command(Command::Clear, 0xff, new Transition("none")); 00638 } else if (num == 2) { 00639 Sequence[usedSequenceItems] = new Command(Command::Clear, strtol(pArg1, NULL, 16), new Transition("none")); 00640 } else { 00641 Transition* t = new Transition(pArg2); 00642 if (t->type() == Transition::Unknown) { 00643 printf("Found invalid transition '%s'. Aborting...\n", pArg2); 00644 result = InvalidScript; 00645 break; 00646 } 00647 Sequence[usedSequenceItems] = new Command(Command::Clear, strtol(pArg1, NULL, 16), t); 00648 } 00649 } 00650 else if ((num == 3) && (strcmp(pCommand, "show") == 0)) 00651 { 00652 Transition* t = new Transition(pArg2); 00653 if (t->type() == Transition::Unknown) { 00654 printf("Found invalid transition '%s'. Aborting...\n", pArg2); 00655 result = InvalidScript; 00656 break; 00657 } 00658 Sequence[usedSequenceItems] = new Command(Command::Show, atoi(pArg1), t); 00659 } 00660 else if ((num == 2) && (strcmp(pCommand, "wait") == 0)) 00661 { 00662 Sequence[usedSequenceItems] = new Command(Command::Wait, atoi(pArg1)); 00663 } 00664 else if ((num == 2) && (strcmp(pCommand, "callout") == 0)) 00665 { 00666 Sequence[usedSequenceItems] = new Command(Command::Callout, atoi(pArg1)); 00667 } 00668 else if ((num == 2) && (strcmp(pCommand, "label") == 0)) 00669 { 00670 int index = findLabel(&(Labels[0]), numLabels, pArg1); 00671 if (index == -1) 00672 { 00673 // found a new label 00674 Labels[numLabels].index = usedSequenceItems; 00675 Labels[numLabels].pLabel = pArg1; 00676 numLabels++; 00677 00678 // A label doesn't occupy a slot in the sequence 00679 usedSequenceItems--; 00680 } 00681 else 00682 { 00683 // label already declared 00684 printf("Found a second declaration of label '%s'. Aborting...\n", pArg1); 00685 result = InvalidScript; 00686 break; 00687 } 00688 } 00689 else if ((num == 2) && (strcmp(pCommand, "goto") == 0)) 00690 { 00691 int index = findLabel(&(Labels[0]), numLabels, pArg1); 00692 if (index == -1) 00693 { 00694 // couldn't find the label we are looking for so we 00695 // wait for now 00696 UnresolvedGotos[numUnresolvedGotos].index = usedSequenceItems; 00697 UnresolvedGotos[numUnresolvedGotos].pLabel = pArg1; 00698 numUnresolvedGotos++; 00699 } 00700 00701 // Create the command 00702 Sequence[usedSequenceItems] = new Command(Command::Goto, index); 00703 } 00704 else if ((num == 3) && (strcmp(pCommand, "load") == 0)) 00705 { 00706 Sequence[usedSequenceItems] = new Command(Command::LoadImage, atoi(pArg2), NULL, pArg1, pathPrefix); 00707 if (Sequence[usedSequenceItems]->info() >= MaxNumPreparedImages) { 00708 printf("Attempting to load into invalid slot %d, have 0..%d. Aborting...\n", Sequence[usedSequenceItems]->info(), MaxNumPreparedImages); 00709 result = InvalidScript; 00710 break; 00711 } 00712 } 00713 else 00714 { 00715 // unknown command 00716 printf("Found unknown command '%s'. Aborting...\n", pCommand); 00717 result = InvalidScript; 00718 break; 00719 } 00720 00721 // start looking for next part in the sequence 00722 usedSequenceItems++; 00723 00724 // assure we don't pass memory limit 00725 if (usedSequenceItems >= allocatedSequenceItems) 00726 { 00727 result = expandSequence(); 00728 if (result != Ok) { 00729 printf("Failed to allocate memory to hold sequence. Aborting...\n"); 00730 break; 00731 } 00732 } 00733 } 00734 } 00735 00736 // Resolve any unresolved gotos. Happens when the label is on 00737 // a line with a higher line number than the goto statement. 00738 for (i = 0; i < numUnresolvedGotos && result==Ok; i++) 00739 { 00740 int index = findLabel(&(Labels[0]), numLabels, UnresolvedGotos[i].pLabel); 00741 if (index == -1) 00742 { 00743 printf("Unable to find label '%s' used in goto statement. Aborting...\n", UnresolvedGotos[i].pLabel); 00744 result = InvalidScript; 00745 } 00746 else 00747 { 00748 // Update the goto element with the correct index of the label 00749 Sequence[UnresolvedGotos[i].index]->updateInfo(index); 00750 } 00751 } 00752 00753 if (result==Ok && usedSequenceItems == 0) 00754 { 00755 printf("Found no sequence. Aborting...\n"); 00756 result = InvalidScript; 00757 } 00758 return result; 00759 } 00760 00761 SlideShow::SlideShowError SlideShow::loadImage(const char* pFileName, int slot) 00762 { 00763 SlideShowError result = Ok; 00764 00765 if (PreparedImages[slot].pointerToFree != NULL) { 00766 free(PreparedImages[slot].pointerToFree); 00767 PreparedImages[slot].pointerToFree = NULL; 00768 } 00769 00770 if (Image::decode(pFileName, Image::RES_16BIT, &(PreparedImages[slot]), fileMutex) != 0) { 00771 printf("Failed to decode file %s as image\n", pFileName); 00772 result = FileError; 00773 } 00774 00775 return result; 00776 } 00777 void SlideShow::delay(int lastTime, int millis) 00778 { 00779 int timeToWait = (lastTime + millis) - msTicks; 00780 if (timeToWait > 0) { 00781 ThisThread::sleep_for(timeToWait); 00782 } 00783 } 00784 00785 SlideShow::SlideShowError SlideShow::runScript() 00786 { 00787 SlideShowError result = Ok; 00788 int seqIndex = 0; 00789 int lastTime = 0; 00790 00791 while ((result == Ok) && (seqIndex < this->usedSequenceItems)) 00792 { 00793 result = Sequence[seqIndex]->handle(this, &seqIndex, &lastTime); 00794 00795 if (abortBeforeNextStep) { 00796 break; 00797 } 00798 } 00799 00800 // if (*pAbort) 00801 // { 00802 // return SLIDE_USER_ABORT; 00803 // } 00804 // else 00805 // { 00806 // return SLIDE_SCRIPT_END; 00807 // } 00808 return Ok; 00809 } 00810 00811 00812 /****************************************************************************** 00813 * Public Functions 00814 *****************************************************************************/ 00815 00816 SlideShow::SlideShow(Renderer* r, const char* pathPrefix, int xoff, int yoff, int layer, Mutex* fileMutex) 00817 { 00818 Display* disp = DMBoard::instance().display(); 00819 this->screenWidth = disp->width(); 00820 this->screenHeight = disp->height(); 00821 this->screenPixels = this->screenWidth * this->screenHeight; 00822 this->drawXoff = xoff; 00823 this->drawYoff = yoff; 00824 00825 // Assume screen->bpp == Bpp_16 00826 this->screenBytes = 2 * this->screenPixels; 00827 00828 this->ImageBackBuffer = NULL; 00829 this->Sequence = NULL; 00830 this->allocatedSequenceItems = 0; 00831 this->usedSequenceItems = 0; 00832 00833 this->pathPrefix = pathPrefix; 00834 00835 this->CurrentSlot = NO_SLOT; 00836 00837 memset(PreparedImages, 0, MaxNumPreparedImages * sizeof(Image::ImageData_t)); 00838 00839 this->fileMutex = fileMutex; 00840 00841 this->rend = r; 00842 this->rendHnd = 0; 00843 this->layer = layer; 00844 00845 this->callout = NULL; 00846 00847 this->abortBeforeNextStep = false; 00848 } 00849 00850 SlideShow::~SlideShow() 00851 { 00852 if (ImageBackBuffer != NULL) { 00853 free(ImageBackBuffer); 00854 ImageBackBuffer = NULL; 00855 } 00856 for (int i = 0; i < MaxNumPreparedImages; i++) { 00857 if (PreparedImages[i].pointerToFree != NULL) { 00858 free(PreparedImages[i].pointerToFree); 00859 } 00860 } 00861 00862 freeSequence(); 00863 00864 if ((rendHnd != 0) && (rend != NULL)) { 00865 rend->unregisterUser(rendHnd); 00866 } 00867 00868 //memset(PreparedImages, 0, MaxNumPreparedImages * sizeof(Image::ImageData_t)); 00869 } 00870 00871 SlideShow::SlideShowError SlideShow::prepare(const char* scriptFile) 00872 { 00873 uint8_t* pBuf = NULL; 00874 uint32_t size = 0; 00875 SlideShowError result = InvalidScript; 00876 00877 do 00878 { 00879 if (ImageBackBuffer == NULL) { 00880 // Back buffer will be able to hold three images 00881 ImageBackBuffer = (image_t)malloc(screenBytes * 3); 00882 if (ImageBackBuffer == NULL) { 00883 result = OutOfMemory; 00884 break; 00885 } 00886 } 00887 00888 // Read the contents of the file into a newly allocated buffer 00889 result = loadFile(scriptFile, &pBuf, &size); 00890 if (result != Ok) 00891 { 00892 break; 00893 } 00894 00895 //printf("Parsing buffer...\n"); 00896 00897 // Parse buffer to create the script sequence 00898 result = parseScript((char*)pBuf); 00899 00900 } while (0); 00901 00902 // Release resources 00903 if (pBuf != NULL) 00904 { 00905 free(pBuf); 00906 pBuf = NULL; 00907 } 00908 if (result != Ok) { 00909 freeSequence(); 00910 } 00911 00912 return result; 00913 } 00914 00915 SlideShow::SlideShowError SlideShow::run() 00916 { 00917 //printf("Executing script...\n"); 00918 this->abortBeforeNextStep = false; 00919 return runScript(); 00920 } 00921 00922 void SlideShow::setCalloutHandler(calloutFunc func, int calloutId) 00923 { 00924 this->callout = func; 00925 this->calloutId = calloutId; 00926 } 00927 00928 void SlideShow::releaseScreen(void) 00929 { 00930 if ((rendHnd != 0) && (rend != NULL)) { 00931 rend->unregisterUser(rendHnd); 00932 } 00933 rendHnd = 0; 00934 }
Generated on Tue Jul 12 2022 21:27:04 by 1.7.2