Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 70088f3
Showing
4 changed files
with
7,841 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
|
||
Copyright (c) 2019 Ryan C. Gordon. | ||
|
||
This software is provided 'as-is', without any express or implied warranty. | ||
In no event will the authors be held liable for any damages arising from | ||
the use of this software. | ||
|
||
Permission is granted to anyone to use this software for any purpose, | ||
including commercial applications, and to alter it and redistribute it | ||
freely, subject to the following restrictions: | ||
|
||
1. The origin of this software must not be misrepresented; you must not | ||
claim that you wrote the original software. If you use this software in a | ||
product, an acknowledgment in the product documentation would be | ||
appreciated but is not required. | ||
|
||
2. Altered source versions must be plainly marked as such, and must not be | ||
misrepresented as being the original software. | ||
|
||
3. This notice may not be removed or altered from any source distribution. | ||
|
||
Ryan C. Gordon <icculus@icculus.org> | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
#!/bin/bash | ||
|
||
gcc -Wall -Os -o marquee-displaydaemon marquee-displaydaemon.c `sdl2-config --cflags --libs` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,286 @@ | ||
/** | ||
* arcade1up-lcd-marquee; control an LCD in a Arcade1Up marquee. | ||
* | ||
* Please see the file LICENSE.txt in the source's root directory. | ||
* | ||
* This file written by Ryan C. Gordon. | ||
*/ | ||
|
||
#include <stdio.h> | ||
#include "SDL.h" | ||
|
||
|
||
//#define STBI_SSE2 1 | ||
|
||
#if (defined(__ARM_ARCH) && (__ARM_ARCH >= 8)) /* ARMv8 always has NEON. */ | ||
#error sdfsdf | ||
#define STBI_NEON 1 | ||
#endif | ||
|
||
//#define STB_IMAGE_STATIC | ||
#define STB_IMAGE_IMPLEMENTATION | ||
#define STBI_ASSERT(x) SDL_assert(x) | ||
#define STBI_MALLOC(x) SDL_malloc(x) | ||
#define STBI_REALLOC(x,y) SDL_realloc(x, y) | ||
#define STBI_FREE(x) SDL_free(x) | ||
#include "stb_image.h" | ||
|
||
static SDL_Window *window = NULL; | ||
static SDL_Renderer *renderer = NULL; | ||
static SDL_Texture *texture = NULL; | ||
static int texturew = 0; | ||
static int textureh = 0; | ||
static Uint32 fadems = 500; | ||
|
||
static void redraw_window(void) | ||
{ | ||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); | ||
SDL_RenderClear(renderer); | ||
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); | ||
if (texture) { // fading in | ||
SDL_RenderSetLogicalSize(renderer, texturew, textureh); | ||
SDL_SetTextureAlphaMod(texture, 255); | ||
SDL_RenderCopy(renderer, texture, NULL, NULL); | ||
} | ||
SDL_RenderPresent(renderer); | ||
} | ||
|
||
static void set_new_image(const char *fname) | ||
{ | ||
SDL_Texture *newtex = NULL; | ||
int w = 0; | ||
int h = 0; | ||
|
||
if (fname) { | ||
int n; | ||
stbi_uc *img = stbi_load(fname, &w, &h, &n, 4); | ||
if (!img) { | ||
fprintf(stderr, "WARNING: couldn't load image \"%s\"\n", fname); | ||
} else { | ||
newtex = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ABGR8888, | ||
SDL_TEXTUREACCESS_STATIC, w, h); | ||
if (!newtex) { | ||
fprintf(stderr, "WARNING: couldn't create texture for \"%s\"\n", fname); | ||
} else { | ||
SDL_UpdateTexture(newtex, NULL, img, w * 4); | ||
SDL_SetTextureBlendMode(newtex, SDL_BLENDMODE_BLEND); | ||
} | ||
stbi_image_free(img); | ||
} | ||
} | ||
|
||
const Uint32 startms = SDL_GetTicks(); | ||
const Uint32 timeout = startms + fadems; | ||
for (Uint32 now = startms; !SDL_TICKS_PASSED(now, timeout); now = SDL_GetTicks()) { | ||
const float unclamped_percent = ((float) (now - startms)) / ((float) fadems); | ||
const float percent = SDL_max(0.0f, SDL_min(unclamped_percent, 1.0f)); | ||
|
||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); | ||
SDL_RenderClear(renderer); | ||
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); | ||
|
||
if (texture) { // fading out | ||
SDL_RenderSetLogicalSize(renderer, texturew, textureh); | ||
SDL_SetTextureAlphaMod(texture, (Uint8) (255.0f * (1.0f - percent))); | ||
SDL_RenderCopy(renderer, texture, NULL, NULL); | ||
} | ||
|
||
if (newtex) { // fading in | ||
SDL_RenderSetLogicalSize(renderer, w, h); | ||
SDL_SetTextureAlphaMod(newtex, (Uint8) (255.0f * percent)); | ||
SDL_RenderCopy(renderer, newtex, NULL, NULL); | ||
} | ||
|
||
SDL_RenderPresent(renderer); | ||
SDL_Delay(10); | ||
} | ||
|
||
SDL_Texture *destroyme = texture; | ||
texture = newtex; | ||
texturew = w; | ||
textureh = h; | ||
|
||
// one last time, with no fade at all. | ||
redraw_window(); | ||
|
||
if (destroyme) { | ||
SDL_DestroyTexture(destroyme); | ||
} | ||
} | ||
|
||
static void deinitialize(void) | ||
{ | ||
if (texture) { | ||
SDL_DestroyTexture(texture); | ||
texture = NULL; | ||
} | ||
|
||
if (renderer) { | ||
SDL_DestroyRenderer(renderer); | ||
renderer = NULL; | ||
} | ||
|
||
if (window) { | ||
SDL_DestroyWindow(window); | ||
window = NULL; | ||
} | ||
|
||
SDL_Quit(); | ||
} | ||
|
||
static SDL_bool initialize(const int argc, char **argv) | ||
{ | ||
int displayidx = 1; // presumably a good default for our use case. | ||
const char *initial_image = NULL; | ||
Uint32 window_flags = SDL_WINDOW_FULLSCREEN_DESKTOP; | ||
int width = 800; | ||
int height = 480; | ||
|
||
for (int i = 1; i < argc; i++) { | ||
const char *arg = argv[i]; | ||
if (SDL_strcmp(arg, "--display") == 0) { | ||
displayidx = SDL_atoi(argv[++i]); | ||
} else if (SDL_strcmp(arg, "--width") == 0) { | ||
width = SDL_atoi(argv[++i]); | ||
} else if (SDL_strcmp(arg, "--height") == 0) { | ||
height = SDL_atoi(argv[++i]); | ||
} else if (SDL_strcmp(arg, "--fadems") == 0) { | ||
fadems = (Uint32) SDL_atoi(argv[++i]); | ||
} else if (SDL_strcmp(arg, "--windowed") == 0) { | ||
window_flags &= ~SDL_WINDOW_FULLSCREEN_DESKTOP; | ||
} else if (SDL_strcmp(arg, "--fullscreen") == 0) { | ||
window_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; | ||
} else if (SDL_strcmp(arg, "--startimage") == 0) { | ||
initial_image = argv[++i]; | ||
} else { | ||
fprintf(stderr, "WARNING: Ignoring unknown command line option \"%s\"\n", arg); | ||
} | ||
} | ||
|
||
if (SDL_Init(SDL_INIT_VIDEO) < 0) { | ||
fprintf(stderr, "ERROR! SDL_Init(SDL_INIT_VIDEO) failed: %s\n", SDL_GetError()); | ||
return SDL_FALSE; | ||
} | ||
|
||
const char *driver = SDL_GetCurrentVideoDriver(); | ||
if (SDL_strcmp(driver, "rpi") != 0) { | ||
fprintf(stderr, "\n\n" | ||
"WARNING: %s:\n" | ||
"WARNING: you aren't using SDL's \"rpi\" video target.\n" | ||
"WARNING: (you are using \"%s\" instead.)\n" | ||
"WARNING: This is probably _not_ what you wanted to do!\n\n\n", | ||
argv[0], driver); | ||
} | ||
|
||
const int numdpy = SDL_GetNumVideoDisplays(); | ||
if (numdpy <= displayidx) { | ||
const int replacement = numdpy - 1; | ||
fprintf(stderr, "\n\n" | ||
"WARNING: %s:\n" | ||
"WARNING: We want display index %d, but there are only %d displays.\n" | ||
"WARNING: Choosing index %d instead.\n" | ||
"WARNING: This is probably _not_ what you wanted to do!\n\n\n", | ||
argv[0], displayidx, numdpy, replacement); | ||
displayidx = replacement; | ||
} | ||
|
||
window = SDL_CreateWindow("Arcade1Up LCD Marquee", | ||
SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayidx), | ||
SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayidx), | ||
width, height, window_flags); | ||
if (!window) { | ||
fprintf(stderr, "ERROR! SDL_CreateWindow failed: %s\n", SDL_GetError()); | ||
return SDL_FALSE; | ||
} | ||
|
||
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); | ||
if (!renderer) { | ||
fprintf(stderr, "WARNING! SDL_CreateRenderer(accel|vsync) failed: %s\n", SDL_GetError()); | ||
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); | ||
if (!renderer) { | ||
fprintf(stderr, "WARNING! SDL_CreateRenderer(accel) failed: %s\n", SDL_GetError()); | ||
renderer = SDL_CreateRenderer(window, -1, 0); | ||
if (!renderer) { | ||
fprintf(stderr, "ERROR! SDL_CreateRenderer(0) failed: %s\n", SDL_GetError()); | ||
fprintf(stderr, "Giving up.\n"); | ||
return SDL_FALSE; | ||
} | ||
} | ||
} | ||
|
||
#if 1 | ||
SDL_RendererInfo info; | ||
SDL_zero(info); | ||
SDL_GetRendererInfo(renderer, &info); | ||
printf("SDL renderer target: %s\n", info.name); | ||
#endif | ||
|
||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); | ||
SDL_RenderClear(renderer); | ||
SDL_RenderPresent(renderer); | ||
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); | ||
|
||
SDL_Event e; | ||
while (SDL_PollEvent(&e)) { | ||
if (e.type == SDL_QUIT) | ||
return SDL_FALSE; | ||
} | ||
|
||
set_new_image(initial_image); | ||
|
||
return SDL_TRUE; | ||
} | ||
|
||
static SDL_bool iterate(void) | ||
{ | ||
SDL_bool redraw = SDL_FALSE; | ||
SDL_bool saw_event = SDL_FALSE; | ||
char *newimage = NULL; | ||
|
||
SDL_Event e; | ||
while (SDL_PollEvent(&e)) { | ||
saw_event = SDL_TRUE; | ||
if (e.type == SDL_QUIT) { | ||
fprintf(stderr, "Got SDL_QUIT event, quitting now...\n"); | ||
return SDL_FALSE; | ||
} else if (e.type == SDL_WINDOWEVENT) { | ||
if ( (e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) || | ||
(e.window.event == SDL_WINDOWEVENT_EXPOSED) ) { | ||
redraw = SDL_TRUE; | ||
} | ||
} else if (e.type == SDL_DROPFILE) { | ||
SDL_free(newimage); | ||
newimage = e.drop.file; | ||
} | ||
} | ||
|
||
if (!saw_event) { | ||
SDL_Delay(100); | ||
} else if (newimage) { | ||
set_new_image(newimage); | ||
SDL_free(newimage); | ||
} else if (redraw) { | ||
redraw_window(); | ||
} | ||
|
||
return SDL_TRUE; | ||
} | ||
|
||
|
||
int main(int argc, char **argv) | ||
{ | ||
if (!initialize(argc, argv)) { | ||
deinitialize(); | ||
return 1; | ||
} | ||
|
||
while (iterate()) { | ||
// spin. | ||
} | ||
|
||
deinitialize(); | ||
return 0; | ||
} | ||
|
||
// end of marquee-displaydaemon.c ... | ||
|
Oops, something went wrong.