diff --git a/NEWS.md b/NEWS.md index 70072d276..fd855734b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -10,6 +10,8 @@ rearrangements of Notcurses. * `ncvisual_from_plane()`, `ncplane_move_below_unsafe()`, `ncplane_dup()`, and `ncplane_move_above_unsafe()` now accept `const` arguments where they did not before. + * `notcurses_canopen()` has been split into `notcurses_canopen_images()` and + `notcurses_canopen_videos()`. * 1.4.1 (2020-05-11) * No user-visible changes (fixed two unit tests). diff --git a/USAGE.md b/USAGE.md index fbc036ed9..94d4e8b99 100644 --- a/USAGE.md +++ b/USAGE.md @@ -225,8 +225,11 @@ int notcurses_palette_size(const struct notcurses* nc); // Can we fade? Fading requires either the "rgb" or "ccc" terminfo capability. bool notcurses_canfade(const struct notcurses* nc); -// Can we load images/videos? This requires being built against FFmpeg. -bool notcurses_canopen(const struct notcurses* nc); +// Can we load images? This requires being built against FFmpeg/OIIO. +bool notcurses_canopen_images(const struct notcurses* nc); + +// Can we load videos? This requires being built against FFmpeg. +bool notcurses_canopen_videos(const struct notcurses* nc); // Can we change colors in the hardware palette? Requires "ccc" and "initc". bool notcurses_canchangecolors(const struct notcurses* nc); diff --git a/include/ncpp/NotCurses.hh b/include/ncpp/NotCurses.hh index 0015014af..f5eb9a26c 100644 --- a/include/ncpp/NotCurses.hh +++ b/include/ncpp/NotCurses.hh @@ -101,9 +101,14 @@ namespace ncpp return notcurses_canfade (nc); } - bool can_open () const noexcept + bool can_open_images () const noexcept { - return notcurses_canopen (nc); + return notcurses_canopen_images (nc); + } + + bool can_open_videos () const noexcept + { + return notcurses_canopen_videos (nc); } bool can_change_color () const noexcept diff --git a/include/notcurses/notcurses.h b/include/notcurses/notcurses.h index ed166c0e2..55f3188cf 100644 --- a/include/notcurses/notcurses.h +++ b/include/notcurses/notcurses.h @@ -1028,8 +1028,11 @@ API bool notcurses_canfade(const struct notcurses* nc); // Can we set the "hardware" palette? Requires the "ccc" terminfo capability. API bool notcurses_canchangecolor(const struct notcurses* nc); -// Can we load images/videos? This requires being built against FFmpeg. -API bool notcurses_canopen(const struct notcurses* nc); +// Can we load images? This requires being built against FFmpeg/OIIO. +API bool notcurses_canopen_images(const struct notcurses* nc); + +// Can we load videos? This requires being built against FFmpeg. +API bool notcurses_canopen_videos(const struct notcurses* nc); // Is our encoding UTF-8? API bool notcurses_canutf8(const struct notcurses* nc); diff --git a/src/demo/chunli.c b/src/demo/chunli.c index 79204eb56..db3e32200 100644 --- a/src/demo/chunli.c +++ b/src/demo/chunli.c @@ -48,7 +48,7 @@ chunli_draw(struct notcurses* nc, const char* ext, int count, const cell* b){ // test of sprites from files int chunli_demo(struct notcurses* nc){ - if(!notcurses_canopen(nc)){ + if(!notcurses_canopen_images(nc)){ return 0; } struct timespec iterdelay; diff --git a/src/demo/eagle.c b/src/demo/eagle.c index fefc086c5..1dc5610b4 100644 --- a/src/demo/eagle.c +++ b/src/demo/eagle.c @@ -199,7 +199,7 @@ eagles(struct notcurses* nc){ // motherfucking eagles! int eagle_demo(struct notcurses* nc){ - if(!notcurses_canopen(nc)){ + if(!notcurses_canopen_images(nc)){ return 0; } char* map = find_data("eagles.png"); diff --git a/src/demo/luigi.c b/src/demo/luigi.c index 28e4cd430..5a651197f 100644 --- a/src/demo/luigi.c +++ b/src/demo/luigi.c @@ -143,7 +143,7 @@ draw_luigi(struct ncplane* n, const char* sprite){ } int luigi_demo(struct notcurses* nc){ - if(!notcurses_canopen(nc)){ + if(!notcurses_canopen_images(nc)){ return 0; } int rows, cols; diff --git a/src/demo/outro.c b/src/demo/outro.c index ee51cd833..a08672ad1 100644 --- a/src/demo/outro.c +++ b/src/demo/outro.c @@ -120,7 +120,7 @@ outro_message(struct notcurses* nc, int* rows, int* cols){ } int outro(struct notcurses* nc){ - if(!notcurses_canopen(nc)){ + if(!notcurses_canopen_images(nc)){ return 0; } int rows, cols; @@ -150,14 +150,16 @@ int outro(struct notcurses* nc){ y = ystart - 1; DEMO_RENDER(nc); ncplane_move_top(on); - pthread_t tid; - // will fade across 2 * demodelay - targy = 3; - pthread_create(&tid, NULL, fadethread, nc); - void* ret; - pthread_join(tid, &ret); - if(ret == PTHREAD_CANCELED){ - return 1; + if(notcurses_canopen_videos(nc)){ + pthread_t tid; + // will fade across 2 * demodelay + targy = 3; + pthread_create(&tid, NULL, fadethread, nc); + void* ret; + pthread_join(tid, &ret); + if(ret == PTHREAD_CANCELED){ + return 1; + } } ncplane_fadeout(on, &demodelay, demo_fader, NULL); ncplane_destroy(on); diff --git a/src/demo/view.c b/src/demo/view.c index 1bd35584f..3f126d9a5 100644 --- a/src/demo/view.c +++ b/src/demo/view.c @@ -65,7 +65,7 @@ legend(struct notcurses* nc, int dimy, int dimx){ } int view_demo(struct notcurses* nc){ - if(!notcurses_canopen(nc)){ + if(!notcurses_canopen_images(nc)){ return 0; } int dimy, dimx; @@ -135,7 +135,10 @@ int view_demo(struct notcurses* nc){ if(ncpl == NULL){ return -1; } - int ret = view_video_demo(nc); + int ret = 0; + if(notcurses_canopen_videos(nc)){ + ret |= view_video_demo(nc); + } ncplane_destroy(ncpl); return ret; } diff --git a/src/demo/xray.c b/src/demo/xray.c index a3837e65d..9f5113c8f 100644 --- a/src/demo/xray.c +++ b/src/demo/xray.c @@ -96,7 +96,7 @@ perframecb(struct notcurses* nc, struct ncvisual* ncv __attribute__ ((unused)), } int xray_demo(struct notcurses* nc){ - if(!notcurses_canopen(nc)){ + if(!notcurses_canopen_videos(nc)){ return 0; } int dimx, dimy; diff --git a/src/lib/visual.cpp b/src/lib/visual.cpp index da3489b47..76068543b 100644 --- a/src/lib/visual.cpp +++ b/src/lib/visual.cpp @@ -363,7 +363,11 @@ void ncvisual_destroy(ncvisual* ncv){ } } -bool notcurses_canopen(const notcurses* nc __attribute__ ((unused))){ +bool notcurses_canopen_images(const notcurses* nc __attribute__ ((unused))){ + return true; +} + +bool notcurses_canopen_videos(const notcurses* nc __attribute__ ((unused))){ return true; } @@ -785,7 +789,11 @@ int ncvisual_init(int loglevel){ } // extern "C" #else // built without ffmpeg #ifndef USE_OIIO // built without ffmpeg or oiio -bool notcurses_canopen(const notcurses* nc __attribute__ ((unused))){ +bool notcurses_canopen_images(const notcurses* nc __attribute__ ((unused))){ + return false; +} + +bool notcurses_canopen_videos(const notcurses* nc __attribute__ ((unused))){ return false; } @@ -840,10 +848,14 @@ void ncvisual_destroy(ncvisual* ncv){ } #else #ifdef USE_OIIO -bool notcurses_canopen(const notcurses* nc __attribute__ ((unused))){ +bool notcurses_canopen_images(const notcurses* nc __attribute__ ((unused))){ return true; } +bool notcurses_canopen_videos(const notcurses* nc __attribute__ ((unused))){ + return false; // too slow for reliable use at the moment +} + static ncvisual* ncvisual_open(const char* filename, nc_err_e* err){ *ncerr = NCERR_SUCCESS; diff --git a/src/poc/multiselect.c b/src/poc/multiselect.c index c5312438a..e12c7f20a 100644 --- a/src/poc/multiselect.c +++ b/src/poc/multiselect.c @@ -82,7 +82,7 @@ int main(void){ channels_set_bg_alpha(&sopts.bgchannels, CELL_ALPHA_BLEND); struct ncplane* n = notcurses_stdplane(nc); - if(notcurses_canopen(nc)){ + if(notcurses_canopen_images(nc)){ nc_err_e err; struct ncvisual* ncv = ncplane_visual_open(n, "../data/covid19.jpg", &err); if(!ncv){ diff --git a/src/poc/selector.c b/src/poc/selector.c index 6a480e158..d449b5cc2 100644 --- a/src/poc/selector.c +++ b/src/poc/selector.c @@ -83,7 +83,7 @@ int main(void){ channels_set_bg_alpha(&sopts.bgchannels, CELL_ALPHA_BLEND); struct ncplane* n = notcurses_stdplane(nc); - if(notcurses_canopen(nc)){ + if(notcurses_canopen_images(nc)){ nc_err_e err; struct ncvisual* ncv = ncplane_visual_open(n, "../data/changes.jpg", &err); if(!ncv){ diff --git a/src/view/view.cpp b/src/view/view.cpp index b41e2a101..aeb718b60 100644 --- a/src/view/view.cpp +++ b/src/view/view.cpp @@ -178,7 +178,7 @@ auto main(int argc, char** argv) -> int { NCScale stretchmode; auto nonopt = handle_opts(argc, argv, NotCurses::default_notcurses_options, ×cale, &stretchmode); NotCurses nc; - if(!nc.can_open()){ + if(!nc.can_open_images()){ nc.stop(); std::cerr << "Notcurses was compiled without multimedia support\n"; return EXIT_FAILURE; diff --git a/tests/visual.cpp b/tests/visual.cpp index a3cb91520..4b519a4ca 100644 --- a/tests/visual.cpp +++ b/tests/visual.cpp @@ -16,12 +16,13 @@ TEST_CASE("Visual") { REQUIRE(ncp_); #ifndef USE_MULTIMEDIA - SUBCASE("LibavDisabled"){ - REQUIRE(!notcurses_canopen(nc_)); + SUBCASE("VisualDisabled"){ + REQUIRE(!notcurses_canopen_images(nc_)); + REQUIRE(!notcurses_canopen_videos(nc_)); } #else - SUBCASE("LibavEnabled"){ - REQUIRE(notcurses_canopen(nc_)); + SUBCASE("ImagesEnabled"){ + REQUIRE(notcurses_canopen_images(nc_)); } SUBCASE("LoadImageCreatePlane") { @@ -87,40 +88,44 @@ TEST_CASE("Visual") { } SUBCASE("LoadVideo") { - nc_err_e ncerr = NCERR_SUCCESS; - int dimy, dimx; - ncplane_dim_yx(ncp_, &dimy, &dimx); - auto ncv = ncplane_visual_open(ncp_, find_data("notcursesI.avi"), &ncerr); - REQUIRE(ncv); - CHECK(NCERR_SUCCESS == ncerr); - for(;;){ // run at the highest speed we can - ncerr = ncvisual_decode(ncv); - if(NCERR_EOF == ncerr){ - break; + if(notcurses_canopen_videos(nc_)){ + nc_err_e ncerr = NCERR_SUCCESS; + int dimy, dimx; + ncplane_dim_yx(ncp_, &dimy, &dimx); + auto ncv = ncplane_visual_open(ncp_, find_data("notcursesI.avi"), &ncerr); + REQUIRE(ncv); + CHECK(NCERR_SUCCESS == ncerr); + for(;;){ // run at the highest speed we can + ncerr = ncvisual_decode(ncv); + if(NCERR_EOF == ncerr){ + break; + } + CHECK(NCERR_SUCCESS == ncerr); + /*CHECK(dimy * 2 == frame->height); + CHECK(dimx == frame->width); FIXME */ + CHECK(0 < ncvisual_render(ncv, 0, 0, -1, -1)); + CHECK(0 == notcurses_render(nc_)); } + ncvisual_destroy(ncv); + } + } + + SUBCASE("LoadVideoCreatePlane") { + if(notcurses_canopen_videos(nc_)){ + nc_err_e ncerr = NCERR_SUCCESS; + int dimy, dimx; + ncplane_dim_yx(ncp_, &dimy, &dimx); + auto ncv = ncvisual_from_file(nc_, find_data("notcursesI.avi"), &ncerr, 0, 0, NCSCALE_STRETCH); + REQUIRE(ncv); + CHECK(NCERR_SUCCESS == ncerr); + ncerr = ncvisual_decode(ncv); CHECK(NCERR_SUCCESS == ncerr); /*CHECK(dimy * 2 == frame->height); CHECK(dimx == frame->width); FIXME */ CHECK(0 < ncvisual_render(ncv, 0, 0, -1, -1)); CHECK(0 == notcurses_render(nc_)); + ncvisual_destroy(ncv); } - ncvisual_destroy(ncv); - } - - SUBCASE("LoadVideoCreatePlane") { - nc_err_e ncerr = NCERR_SUCCESS; - int dimy, dimx; - ncplane_dim_yx(ncp_, &dimy, &dimx); - auto ncv = ncvisual_from_file(nc_, find_data("notcursesI.avi"), &ncerr, 0, 0, NCSCALE_STRETCH); - REQUIRE(ncv); - CHECK(NCERR_SUCCESS == ncerr); - ncerr = ncvisual_decode(ncv); - CHECK(NCERR_SUCCESS == ncerr); - /*CHECK(dimy * 2 == frame->height); - CHECK(dimx == frame->width); FIXME */ - CHECK(0 < ncvisual_render(ncv, 0, 0, -1, -1)); - CHECK(0 == notcurses_render(nc_)); - ncvisual_destroy(ncv); } #endif