Skip to content

Commit cd5cb22

Browse files
authored
Merge pull request #6 from compucat/alex-dev-2
Merge GDQ hacks (and NULLchecks) into main branch; plan to rewrite this more nicely in the future.
2 parents 02560d2 + 6062d25 commit cd5cb22

File tree

1 file changed

+87
-8
lines changed

1 file changed

+87
-8
lines changed

main.c

+87-8
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,15 @@
1111
#include <unistd.h>
1212
#include <ctype.h>
1313
#include <sysexits.h>
14+
#include <sys/stat.h>
15+
#include <errno.h>
1416

1517
#define BASE_PATH "./gifs/base.gif"
1618
#define STARTUP_PATH "./gifs/startup.gif"
1719
#define OTHER_PATH "./gifs/others/"
1820
#define BLINK_PATH "./gifs/blinks/"
21+
#define IMMEDIATE_ANIM_PATH "./gifs/PLAYMENOW/"
22+
#define OVERRIDE_FILE_PATH "./gifs/OVERRIDE/gif.gif"
1923
#define MAX_FILENAME_LENGTH 256
2024
#define MAX_PATH_LENGTH 4096
2125
#define MIN_DELAY_TIME 35 //Smallest delay time that is possible due to hardware limitations (1000ms/30fps=33.3'ms)
@@ -125,6 +129,19 @@ void readFile(const char* _path, int _count, char** _out);
125129
unsigned int ledMatrixTranslation(int _x, int _y);
126130
bool numberIsEven(int _number);
127131

132+
//delay(): Behaves like usleep(), but polls OVERRIDE_FILE_PATH in the meantime.
133+
//If that GIF exists, immediately show it.
134+
void delay(useconds_t usec) {
135+
for(useconds_t elapsed=0; elapsed<usec; elapsed+=10 * 1000) {
136+
usleep(10 * 1000);
137+
struct stat buf;
138+
//TODO: Properly check that this is indeed a GIF. Or does showExpressionFromFilepath handle that safely?
139+
while(!stat(OVERRIDE_FILE_PATH, &buf)) {
140+
showExpressionFromFilepath(OVERRIDE_FILE_PATH, false, false);
141+
}
142+
}
143+
}
144+
128145
//Development function toggles
129146
bool activateLEDModule = true;
130147
bool realTASBot = true;
@@ -183,6 +200,11 @@ int main(int _argc, char** _argv) {
183200
//Default palette
184201
paletteCount = 8;
185202
palette = malloc(sizeof(ws2811_led_t) * paletteCount);
203+
if (!palette) {
204+
fprintf(stderr, "[ERROR] Failed to allocate palette memory");
205+
clearLEDs();
206+
exit(EXIT_FAILURE);
207+
}
186208
palette[0] = 0xFF0000; // red
187209
palette[1] = 0xFF8000; // orange
188210
palette[2] = 0xFFFF00; // yellow
@@ -232,7 +254,7 @@ int main(int _argc, char** _argv) {
232254
showExpressionFromFilepath(BASE_PATH, false, false);
233255
}
234256

235-
usleep(getBlinkDelay() * 1000);
257+
delay(getBlinkDelay() * 1000);
236258
//blink for a random amount of times
237259
for (unsigned int blinks = getBlinkAmount(); blinks > 0; --blinks) {
238260
showBlinkExpression();
@@ -242,8 +264,31 @@ int main(int _argc, char** _argv) {
242264
if (verboseLogging) {
243265
printf("[INFO] Blink #%d for %d milliseconds \n", blinks, blinkTime);
244266
}
245-
usleep(blinkTime * 1000);
267+
delay(blinkTime * 1000);
268+
269+
//Check for immediate animation to play back.
270+
DIR *immediate_anim_dir = opendir(IMMEDIATE_ANIM_PATH);
271+
struct dirent *dir;
272+
if(immediate_anim_dir) { //Null is discarded as this directory is not always expected to exist.
273+
struct dirent *dir;
274+
do {
275+
dir = readdir(immediate_anim_dir);
276+
if(dir && strlen(dir->d_name) > 4 && !strcmp(dir->d_name + strlen(dir->d_name) - 4, ".gif")) {
277+
char pathinter[PATH_MAX+1];
278+
sprintf(pathinter, "%s/%s", IMMEDIATE_ANIM_PATH, dir->d_name);
279+
char path[PATH_MAX+1];
280+
realpath(pathinter, path);
281+
Animation* animation = readAnimation(path);
282+
playExpression(animation, false, false);
283+
remove(path);
284+
blinks++;
285+
break;
286+
}
287+
} while(dir);
288+
closedir(immediate_anim_dir);
289+
}
246290
}
291+
247292
}
248293

249294
//Clean up
@@ -546,7 +591,7 @@ Animation* readAnimation(char* _file) {
546591

547592
//Open _file
548593
int e;
549-
GifFileType* image = DGifOpenFileName(_file, &e);
594+
GifFileType* image = DGifOpenFileName(_file, &e);
550595
if (!image) {
551596
fprintf(stderr, "[ERROR] EGifOpenFileName() failed. Couldn't find or open _file: %d\n", e);
552597
return false;
@@ -555,7 +600,7 @@ Animation* readAnimation(char* _file) {
555600
//"Slurp" infos into struct
556601
if (DGifSlurp(image) == GIF_ERROR) {
557602
fprintf(stderr, "[ERROR] DGifSlurp() failed. Couldn't load infos about GIF: %d\n", image->Error);
558-
DGifCloseFile(image, &e);
603+
if (DGifCloseFile(image, &e) != GIF_OK) fprintf(stderr, "[WARNING] readAnimation: DGifCloseFile returned%d\n", e);
559604
return false;
560605
}
561606

@@ -572,7 +617,17 @@ Animation* readAnimation(char* _file) {
572617

573618
//Process frames
574619
animation = malloc(sizeof(Animation));
620+
if (!animation) {
621+
fprintf(stderr, "[ERROR] readAnimation: Failed to allocate Animation");
622+
clearLEDs();
623+
exit(EXIT_FAILURE);
624+
}
575625
AnimationFrame** animationFrames = malloc(sizeof(AnimationFrame*) * image->ImageCount);
626+
if (!animationFrames) {
627+
fprintf(stderr, "[ERROR] readAnimation: Failed to allocate AnimationFrames");
628+
clearLEDs();
629+
exit(EXIT_FAILURE);
630+
}
576631
animation->frames = animationFrames;
577632
animation->frameCount = image->ImageCount;
578633
animation->monochrome = true;
@@ -630,6 +685,11 @@ AnimationFrame* readFramePixels(const SavedImage* frame, ColorMapObject* _global
630685
: _globalMap; //choose either global or local color map
631686

632687
AnimationFrame* animationFrame = malloc(sizeof(AnimationFrame));
688+
if (!animationFrame) {
689+
fprintf(stderr, "[ERROR] readFramePixels: Failed to allocate animationFrame");
690+
clearLEDs();
691+
exit(EXIT_FAILURE);
692+
}
633693

634694
bool keepColor = false;
635695
for (int y = 0; y < desc.Height; ++y) {
@@ -697,6 +757,10 @@ ws2811_return_t initLEDs() {
697757

698758
//Setup color array
699759
pixel = malloc(sizeof(ws2811_led_t) * LED_WIDTH * LED_HEIGHT);
760+
if (!pixel) {
761+
fprintf(stderr, "[ERROR] initLEDs: Failed to allocate color array");
762+
exit(EXIT_FAILURE);
763+
}
700764

701765
//Initialize hardware
702766
ws2811_return_t r;
@@ -778,7 +842,8 @@ void showRandomExpression(char* _path, bool _useRandomColor, bool _repeatAnimati
778842
*/
779843
void showExpressionFromFilepath(char* _filePath, bool _useRandomColor, bool _repeatAnimations) {
780844
Animation* animation = readAnimation(_filePath);
781-
playExpression(animation, _useRandomColor, _repeatAnimations);
845+
if(!animation) fprintf(stderr, "[WARNING] showExpressionFromFilepath: animation is NULL, skipping\n");
846+
else playExpression(animation, _useRandomColor, _repeatAnimations);
782847
}
783848

784849
/**
@@ -913,7 +978,7 @@ void showFrame(AnimationFrame* _frame, ws2811_led_t _color) {
913978
void freeAnimation(Animation* _animation) {
914979
//dirty trick, close file here, after animation. That way DGifCloseFile() can't destroy the animation data
915980
int e = 0;
916-
DGifCloseFile(_animation->image, &e);
981+
if (DGifCloseFile(_animation->image, &e) != GIF_OK) fprintf(stderr, "[WARNING] freeAnimation: DGifCloseFile returned%d\n", e);
917982
if (verboseLogging) {
918983
printf("[INFO] Closed GIF with code %d\n", e);
919984
}
@@ -995,6 +1060,11 @@ void readPalette(char* _path) {
9951060

9961061
//Read palette into final palette array
9971062
ws2811_led_t* pal = malloc(sizeof(ws2811_led_t) * colorCount);
1063+
if (!pal) {
1064+
fprintf(stderr, "[ERROR] readPalette: Failed to allocate palette memory");
1065+
clearLEDs();
1066+
exit(EXIT_FAILURE);
1067+
}
9981068
for (int i = 0; i < colorCount; ++i) {
9991069
int color = strtocol(rawPal[i]);
10001070
if (color != -1) {
@@ -1005,6 +1075,7 @@ void readPalette(char* _path) {
10051075
} else {
10061076
printf("[WARNING] Skip color %s because of parsing error", rawPal[i]);
10071077
}
1078+
free(rawPal[i]);
10081079
}
10091080

10101081
paletteCount = colorCount;
@@ -1088,6 +1159,7 @@ bool checkIfDirectoryExist(char* _path) {
10881159
closedir(dir);
10891160
return true;
10901161
}
1162+
fprintf(stderr, "[WARNING]: directory %s does not exist. Errno is %d\n", _path, errno);
10911163
return false;
10921164
}
10931165

@@ -1119,7 +1191,12 @@ void readFile(const char* _path, int _count, char** _out) {
11191191
//Read line after line into give array
11201192
for (int i = 0; i < _count; i++) {
11211193
_out[i] = malloc(sizeof(unsigned int));
1122-
fscanf(ptr, "%s\n", _out[i]);
1194+
if (!_out[i]) {
1195+
fprintf(stderr, "[ERROR] readFile: Failed to allocate memory");
1196+
clearLEDs();
1197+
exit(EXIT_FAILURE);
1198+
}
1199+
if (fscanf(ptr, "%s\n", _out[i]) != 1) fprintf(stderr, "[ERROR] readFile: Failed to read line %d\n", i);
11231200
}
11241201

11251202
//Closing the file
@@ -1144,6 +1221,7 @@ int countFilesInDir(char* _path) {
11441221
closedir(d);
11451222
return counter;
11461223
}
1224+
fprintf(stderr, "[WARNING]: countFilesInDir() called on nonexistent directory %s. Errno is %d\n", _path, errno);
11471225
return -1;
11481226
}
11491227

@@ -1167,6 +1245,7 @@ bool getFileList(const char* _path, char* _list[]) {
11671245
closedir(d);
11681246
return true;
11691247
}
1248+
fprintf(stderr, "[WARNING]: getFileList() called on nonexistent directory %s. Errno is %d\n", _path, errno);
11701249
return false;
11711250
}
11721251

@@ -1223,4 +1302,4 @@ unsigned int ledMatrixTranslation(int _x, int _y) {
12231302
bool numberIsEven(int _number) {
12241303
return (_number % 2 == 0);
12251304
}
1226-
//endregion
1305+
//endregion

0 commit comments

Comments
 (0)