From c70bc7b2a4e773dec470c71b3f57c497d8b29352 Mon Sep 17 00:00:00 2001 From: nick black Date: Mon, 2 Dec 2019 06:18:17 -0500 Subject: [PATCH] slider-demo: work atop a background --- CMakeLists.txt | 25 ++++++++++++ src/demo/sliding.c | 14 +++++++ src/lib/notcurses.c | 3 ++ src/panelvideo/pv.cpp | 91 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 133 insertions(+) create mode 100644 src/panelvideo/pv.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 02dd6b482..baee4cebb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -86,6 +86,30 @@ target_compile_options(notcurses-input -Wall -Wextra -W -Wshadow ) +file(GLOB PVSRCS CONFIGURE_DEPENDS src/panelvideo/*.cpp) +add_executable(notcurses-panelvideo ${PVSRCS}) +target_include_directories(notcurses-panelvideo + PRIVATE + include + "${PROJECT_BINARY_DIR}/include" + "${AVUTIL_INCLUDE_DIR}" +) +target_link_directories(notcurses-panelvideo + PRIVATE + "${AVUTIL_LIBRARY_DIRS}" +) +target_link_libraries(notcurses-panelvideo + PRIVATE + notcurses + PRIVATE + "${AVUTIL_LIBRARIES}" + Threads::Threads +) +target_compile_options(notcurses-panelvideo + PRIVATE + -Wall -Wextra -W -Wshadow +) + file(GLOB VIEWSRCS CONFIGURE_DEPENDS src/view/*.cpp) add_executable(notcurses-view ${VIEWSRCS}) target_include_directories(notcurses-view @@ -164,6 +188,7 @@ install(FILES install(TARGETS notcurses-demo DESTINATION bin) install(TARGETS notcurses-view DESTINATION bin) +install(TARGETS notcurses-panelvideo DESTINATION bin) install(TARGETS notcurses-input DESTINATION bin) install(TARGETS notcurses LIBRARY diff --git a/src/demo/sliding.c b/src/demo/sliding.c index d97778bd4..d960b3ad2 100644 --- a/src/demo/sliding.c +++ b/src/demo/sliding.c @@ -30,6 +30,7 @@ move_square(struct notcurses* nc, struct ncplane* chunk, int* holey, int* holex) int targx = newholex; deltay = deltay < 0 ? -1 : deltay == 0 ? 0 : 1; deltax = deltax < 0 ? -1 : deltax == 0 ? 0 : 1; + // FIXME do an adaptive time, like our fades, so we whip along under load for(i = 0 ; i < units ; ++i){ targy += deltay; targx += deltax; @@ -177,6 +178,19 @@ int sliding_puzzle_demo(struct notcurses* nc){ int wastex = ((maxx - 2) % CHUNKS_HORZ) / 2; struct ncplane* n = notcurses_stdplane(nc); ncplane_erase(n); + int averr = 0; + struct ncvisual* ncv = ncplane_visual_open(n, "../tests/changes.jpg", &averr); + if(ncv == NULL){ + return -1; + } + if(ncvisual_decode(ncv, &averr) == NULL){ + ncvisual_destroy(ncv); + return -1; + } + if(ncvisual_render(ncv)){ + ncvisual_destroy(ncv); + return -1; + } const int chunkcount = CHUNKS_VERT * CHUNKS_HORZ; struct ncplane** chunks = malloc(sizeof(*chunks) * chunkcount); if(chunks == NULL){ diff --git a/src/lib/notcurses.c b/src/lib/notcurses.c index d9a9f19e7..9bd39f335 100644 --- a/src/lib/notcurses.c +++ b/src/lib/notcurses.c @@ -1107,6 +1107,9 @@ int notcurses_render(notcurses* nc){ unsigned r, g, b, br, bg, bb; ncplane* p = nc->top; const cell* c = visible_cell(y, x, &p); + if(c == NULL){ + continue; // shrug? + } // we allow these to be set distinctly, but terminfo only supports using // them both via the 'op' capability. unless we want to generate the 'op' // escapes ourselves, if either is set to default, we first send op, and diff --git a/src/panelvideo/pv.cpp b/src/panelvideo/pv.cpp new file mode 100644 index 000000000..e005f0c0a --- /dev/null +++ b/src/panelvideo/pv.cpp @@ -0,0 +1,91 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "notcurses.h" + +static void usage(std::ostream& os, const char* name, int exitcode) + __attribute__ ((noreturn)); + +void usage(std::ostream& o, const char* name, int exitcode){ + o << "usage: " << name << " files" << '\n'; + exit(exitcode); +} + +static struct marshal { + struct notcurses* nc; + struct ncvisual* ncv; + int averr; +} m; + +int ncview(struct notcurses* nc, struct ncvisual* ncv, int* averr){ + if(ncvisual_stream(nc, ncv, averr)){ + return -1; + } + return 0; +} + +void* ncviewthread(void* v){ + ncview(m.nc, m.ncv, &m.averr); + return NULL; +} + +int main(int argc, char** argv){ + setlocale(LC_ALL, ""); + if(argc == 1){ + usage(std::cerr, argv[0], EXIT_FAILURE); + } + notcurses_options opts{}; + opts.outfp = stdout; + auto nc = notcurses_init(&opts); + if(nc == nullptr){ + return EXIT_FAILURE; + } + int dimy, dimx; + notcurses_term_dim_yx(nc, &dimy, &dimx); + auto ncp = notcurses_newplane(nc, dimy - 1, dimx, 1, 0, nullptr); + if(ncp == nullptr){ + notcurses_stop(nc); + return EXIT_FAILURE; + } + for(int i = 1 ; i < argc ; ++i){ + std::array errbuf; + int averr; + auto ncv = ncplane_visual_open(ncp, argv[i], &averr); + if(ncv == nullptr){ + av_make_error_string(errbuf.data(), errbuf.size(), averr); + notcurses_stop(nc); + std::cerr << "Error opening " << argv[i] << ": " << errbuf.data() << std::endl; + return EXIT_FAILURE; + } + pthread_t tid; + m.nc = nc; + m.ncv = ncv; + m.averr = 0; + int efd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); + if(efd < 0){ + fprintf(stderr, "Error creating eventfd (%s)\n", strerror(errno)); + return -1; + } + panelreel_options popts{}; + struct panelreel* pr = panelreel_create(ncp, &popts, efd); + if(pr == nullptr){ + return EXIT_FAILURE; + } + notcurses_render(nc); + pthread_create(&tid, NULL, ncviewthread, NULL); + ncspecial_key special; + cell c = CELL_TRIVIAL_INITIALIZER; + notcurses_getc_blocking(nc, &c, &special); + cell_release(ncp, &c); + // ncvisual_destroy(ncv); + } + if(notcurses_stop(nc)){ + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +}