Annihilate nc_err_e and all infrastructure #948

pull/954/head
nick black 4 years ago committed by Nick Black
parent ea681ed4ec
commit 4dd1d6a4c8

@ -1,6 +1,12 @@
This document attempts to list user-visible changes and any major internal
rearrangements of Notcurses.
* 1.6.18 (not yet released)
* `nc_err_e` has been taken behind the shed and shot in the face. All
functions which once returned `nc_err_e` now return a bimodal `int`. Those
functions which accepted a value-result `nc_err_e*` no longer take this
argument.
* 1.6.17 (2020-08-22)
* `ncdirect_flush()` now takes a `const struct ncdirect*`.
* A `const char* title` field has been added to `ncplot_options`. If not

@ -378,8 +378,8 @@ int ncdirect_double_box(struct ncdirect* n, uint64_t ul, uint64_t ur,
// Display an image using the specified blitter and scaling. The image may
// be arbitrarily many rows -- the output will scroll -- but will only occupy
// the column of the cursor, and those to the right.
nc_err_e ncdirect_render_image(struct ncdirect* nc, const char* filename,
ncblitter_e blitter, ncscale_e scale);
int ncdirect_render_image(struct ncdirect* nc, const char* filename,
ncblitter_e blitter, ncscale_e scale);
```
Several of the Notcurses capability predicates have `ncdirect` analogues:
@ -2587,11 +2587,11 @@ int ncvisual_geom(const struct notcurses* nc, const struct ncvisual* n,
// Rotate the visual 'rads' radians. Only M_PI/2 and -M_PI/2 are
// supported at the moment, but this will change FIXME.
nc_err_e ncvisual_rotate(struct ncvisual* n, double rads);
int ncvisual_rotate(struct ncvisual* n, double rads);
// Resize the visual so that it is 'rows' X 'columns'. This is a lossy
// transformation, unless the size is unchanged.
nc_err_e ncvisual_resize(struct ncvisual* n, int rows, int cols);
int ncvisual_resize(struct ncvisual* n, int rows, int cols);
// Polyfill at the specified location within the ncvisual 'n', using 'rgba'.
int ncvisual_polyfill_yx(struct ncvisual* n, int y, int x, uint32_t rgba);
@ -2715,9 +2715,9 @@ ncvisual_simple_streamer(struct ncplane* n, struct ncvisual* ncv,
// visual naturally running at 30FPS, a 'timescale' of 0.1 will result in
// 300FPS, and a 'timescale' of 10 will result in 3FPS. It is an error to
// supply 'timescale' less than or equal to 0.
int ncvisual_stream(struct notcurses* nc, struct ncvisual* ncv,
nc_err_e* ncerr, float timescale, streamcb streamer,
const struct ncvisual_options* vopts, void* curry);
int ncvisual_stream(struct notcurses* nc, struct ncvisual* ncv, float timescale,
streamcb streamer, const struct ncvisual_options* vopts,
void* curry);
```
### QR codes
@ -2746,12 +2746,12 @@ have only one frame), until it returns `NCERR_EOF`:
```c
// Open a visual at 'file', extracting a codec and parameters.
struct ncvisual* ncvisual_from_file(const char* file, nc_err_e* ncerr);
struct ncvisual* ncvisual_from_file(const char* file);
// extract the next frame from an ncvisual. returns NCERR_EOF on end of file,
// and NCERR_SUCCESS on success, otherwise some other NCERR.
nc_err_e ncvisual_decode(struct ncvisual* nc);
int ncvisual_decode(struct ncvisual* nc);
```
### Pixels

@ -45,7 +45,6 @@
<a href="notcurses_cell.3.html">notcurses_cell</a>—operations on <tt>cell</tt> objects<br/>
<a href="notcurses_channels.3.html">notcurses_channels</a>—operations on the <tt>channel</tt> type<br/>
<a href="notcurses_directmode.3.html">notcurses_directmode</a>—minimal notcurses instances for styling text<br/>
<a href="notcurses_error.3.html">notcurses_error</a>—granular Notcurses error reporting<br/>
<a href="notcurses_fade.3.html">notcurses_fade</a>—fading and pulsing for <tt>ncplane</tt>s<br/>
<a href="notcurses_fds.3.html">notcurses_fds</a>—dumping file descriptors/subprocesses to <tt>ncplane</tt>s<br/>
<a href="notcurses_init.3.html">notcurses_init</a>—initialization<br/>

@ -141,7 +141,6 @@ previous action.
**notcurses_cell(3)**,
**notcurses_channels(3)**,
**notcurses_directmode(3)**,
**notcurses_error(3)**,
**notcurses_fade(3)**,
**notcurses_fds(3)**,
**notcurses_init(3)**,

@ -70,7 +70,7 @@ ncdirect_init - minimal notcurses instances for styling text
**int ncdirect_double_box(struct ncdirect* n, uint64_t ul, uint64_t ur, uint64_t ll, uint64_t lr, int ylen, int xlen, unsigned ctlword);**
**nc_err_e ncdirect_render_image(struct ncdirect* n, const char* filename, ncblitter_e blitter, ncscale_e scale);**
**int ncdirect_render_image(struct ncdirect* n, const char* filename, ncblitter_e blitter, ncscale_e scale);**
# DESCRIPTION

@ -1,37 +0,0 @@
% notcurses_error(3)
% nick black <nickblack@linux.com>
% v1.6.17
# NAME
notcurses_error - granular Notcurses error reporting
# SYNOPSIS
**#include <notcurses/ncerrs.h>**
```c
typedef enum {
NCERR_SUCCESS = 0,
NCERR_NOMEM = ENOMEM,
NCERR_EOF = 0x20464f45, // matches AVERROR_EOF
} nc_err_e;
```
# DESCRIPTION
Various functions in Notcurses return granular information about the cause of
an error. When done, this information is returned through an **nc_err_e**.
# NOTES
The goal is to abstract the union of errors returned by supported operating
systems and the libraries on which Notcurses depends. Thus **nc_err_e** is
a union of members of POSIX and FFmpeg.
# RETURN VALUES
# SEE ALSO
**errno(3)**,
**notcurses(3)**

@ -50,7 +50,7 @@ typedef int (*streamcb)(struct notcurses*, struct ncvisual*, void*);
**bool notcurses_cansixel(const struct notcurses* nc);**
**struct ncvisual* ncvisual_from_file(const char* file, nc_err_e* err);**
**struct ncvisual* ncvisual_from_file(const char* file);**
**struct ncvisual* ncvisual_from_rgba(const void* rgba, int rows, int rowstride, int cols);**
@ -62,13 +62,13 @@ typedef int (*streamcb)(struct notcurses*, struct ncvisual*, void*);
**void ncvisual_destroy(struct ncvisual* ncv);**
**nc_err_e ncvisual_decode(struct ncvisual* nc);**
**int ncvisual_decode(struct ncvisual* nc);**
**struct ncplane* ncvisual_render(struct notcurses* nc, struct ncvisual* ncv, const struct ncvisual_options* vopts);**
**int ncvisual_simple_streamer(struct ncplane* n, struct ncvisual* ncv, const struct timespec* disptime, void* curry);**
**int ncvisual_stream(struct notcurses* nc, struct ncvisual* ncv, nc_err_e* err, float timescale, streamcb streamer, const struct ncvisual_options* vopts, void* curry);**
**int ncvisual_stream(struct notcurses* nc, struct ncvisual* ncv, float timescale, streamcb streamer, const struct ncvisual_options* vopts, void* curry);**
**int ncvisual_rotate(struct ncvisual* n, double rads);**
@ -160,10 +160,11 @@ built with insufficient multimedia support.
**ncvisual_from_file** returns an **ncvisual** object on success, or **NULL**
on failure. Success indicates that the specified **file** was opened, and
enough data was read to make a firm codec identification. It does not imply
that the entire file is properly-formed. On failure, **err** will be updated.
**ncvisual_decode** returns **NCERR_SUCCESS** on success, or **NCERR_EOF** on
end of file, or some other **nc_err_e** on failure. It likewise updates **err**
in the event of an error. It is only necessary for multimedia-based visuals.
that the entire file is properly-formed.
**ncvisual_decode** returns 0 on success, or 1 on end of file, or -1 on
failure. It is only necessary for multimedia-based visuals. It advances one
frame for each call.
**ncvisual_from_plane** returns **NULL** if the **ncvisual** cannot be created
and bound. This is usually due to illegal content in the source **ncplane**.

@ -138,7 +138,7 @@ namespace ncpp
return error_guard (ncdirect_cursor_disable (direct), -1);
}
nc_err_e render_image (const char* file, ncalign_e align, ncblitter_e blitter, ncscale_e scale) const noexcept
int render_image (const char* file, ncalign_e align, ncblitter_e blitter, ncscale_e scale) const noexcept
{
return ncdirect_render_image (direct, file, align, blitter, scale);
}

@ -16,10 +16,10 @@ namespace ncpp
class NCPP_API_EXPORT Visual : public Root
{
public:
explicit Visual (const char *file, nc_err_e *ncerr)
explicit Visual (const char *file)
: Root (NotCurses::get_instance ())
{
visual = ncvisual_from_file (file, ncerr);
visual = ncvisual_from_file (file);
if (visual == nullptr)
throw init_error ("Notcurses failed to create a new visual");
}
@ -56,7 +56,7 @@ namespace ncpp
return visual;
}
nc_err_e decode () const noexcept
int decode () const noexcept
{
return ncvisual_decode (visual);
}
@ -66,9 +66,9 @@ namespace ncpp
return error_guard<ncplane*, ncplane*> (ncvisual_render (get_notcurses (), visual, vopts), nullptr);
}
int stream (const ncvisual_options* vopts, nc_err_e* ncerr, float timescale, streamcb streamer, void *curry = nullptr) const NOEXCEPT_MAYBE
int stream (const ncvisual_options* vopts, float timescale, streamcb streamer, void *curry = nullptr) const NOEXCEPT_MAYBE
{
return error_guard<int> (ncvisual_stream (get_notcurses (), visual, ncerr, timescale, streamer, vopts, curry), -1);
return error_guard<int> (ncvisual_stream (get_notcurses (), visual, timescale, streamer, vopts, curry), -1);
}
char* subtitle () const noexcept
@ -78,8 +78,7 @@ namespace ncpp
bool rotate (double rads) const NOEXCEPT_MAYBE
{
nc_err_e ret = ncvisual_rotate (visual, rads);
return error_guard_cond (ret, ret != NCERR_SUCCESS);
return error_guard (ncvisual_rotate (visual, rads), -1);
}
bool simple_streamer (ncvisual_options* vopts, const timespec* tspec, void* curry = nullptr) const NOEXCEPT_MAYBE
@ -111,12 +110,12 @@ namespace ncpp
}
private:
void common_init (ncplane *plane, const char *file, nc_err_e* ncerr)
void common_init (ncplane *plane, const char *file)
{
if (plane == nullptr)
throw invalid_argument ("'plane' must be a valid pointer");
visual = ncvisual_from_file (file, ncerr);
visual = ncvisual_from_file (file);
if (visual == nullptr)
throw init_error ("Notcurses failed to create a new visual");
}

@ -94,9 +94,9 @@ API int ncdirect_printf_aligned(struct ncdirect* n, int y, ncalign_e align,
// Display an image using the specified blitter and scaling. The image may
// be arbitrarily many rows -- the output will scroll -- but will only occupy
// the column of the cursor, and those to the right.
API nc_err_e ncdirect_render_image(struct ncdirect* n, const char* filename,
ncalign_e align, ncblitter_e blitter,
ncscale_e scale);
API int ncdirect_render_image(struct ncdirect* n, const char* filename,
ncalign_e align, ncblitter_e blitter,
ncscale_e scale);
// Clear the screen.
API int ncdirect_clear(struct ncdirect* nc);

@ -1,42 +0,0 @@
#ifndef NOTCURSES_NCERRS
#define NOTCURSES_NCERRS
#ifdef __cplusplus
extern "C" {
#endif
#include <errno.h>
#include <string.h>
// Error values for more granular problem indication. We map to POSIX error
// codes when possible. We need at least the union of POSIX (errno) and FFMpeg
// (AVERROR) codes that we might see.
typedef enum {
NCERR_SUCCESS = 0,
NCERR_NOMEM = ENOMEM,
NCERR_EOF = 0x20464f45, // matches AVERROR_EOF
NCERR_DECODE,
NCERR_SYSTEM,
NCERR_INVALID_ARG,
NCERR_UNIMPLEMENTED,
} nc_err_e;
static inline const char*
nc_strerror(nc_err_e ncerr){
switch(ncerr){
case NCERR_SUCCESS: return "success";
case NCERR_NOMEM: return strerror(ENOMEM);
case NCERR_EOF: return "end of file";
case NCERR_DECODE: return "error decoding";
case NCERR_SYSTEM: return "system error";
case NCERR_INVALID_ARG: return "invalid argument";
case NCERR_UNIMPLEMENTED: return "feature not available";
};
return "unknown error";
}
#ifdef __cplusplus
} // extern "C"
#endif
#endif

@ -14,7 +14,6 @@
#include <limits.h>
#include <stdbool.h>
#include <notcurses/nckeys.h>
#include <notcurses/ncerrs.h>
#ifdef __cplusplus
extern "C" {
@ -2175,7 +2174,7 @@ ncplane_double_box_sized(struct ncplane* n, uint32_t styles, uint64_t channels,
// Open a visual at 'file', extract a codec and parameters, decode the first
// image to memory.
API struct ncvisual* ncvisual_from_file(const char* file, nc_err_e* ncerr);
API struct ncvisual* ncvisual_from_file(const char* file);
// Prepare an ncvisual, and its underlying plane, based off RGBA content in
// memory at 'rgba'. 'rgba' must be a flat array of 32-bit 8bpc RGBA pixels.
@ -2248,17 +2247,17 @@ API int ncvisual_geom(const struct notcurses* nc, const struct ncvisual* n,
// can be neither decoded nor rendered any further.
API void ncvisual_destroy(struct ncvisual* ncv);
// extract the next frame from an ncvisual. returns NCERR_EOF on end of file,
// and NCERR_SUCCESS on success, otherwise some other NCERR.
API nc_err_e ncvisual_decode(struct ncvisual* nc);
// extract the next frame from an ncvisual. returns 1 on end of file, 0 on
// success, and -1 on failure.
API int ncvisual_decode(struct ncvisual* nc);
// Rotate the visual 'rads' radians. Only M_PI/2 and -M_PI/2 are
// supported at the moment, but this will change FIXME.
API nc_err_e ncvisual_rotate(struct ncvisual* n, double rads);
API int ncvisual_rotate(struct ncvisual* n, double rads);
// Resize the visual so that it is 'rows' X 'columns'. This is a lossy
// transformation, unless the size is unchanged.
API nc_err_e ncvisual_resize(struct ncvisual* n, int rows, int cols);
API int ncvisual_resize(struct ncvisual* n, int rows, int cols);
// Polyfill at the specified location within the ncvisual 'n', using 'rgba'.
API int ncvisual_polyfill_yx(struct ncvisual* n, int y, int x, uint32_t rgba);
@ -2305,7 +2304,7 @@ API int ncvisual_simple_streamer(struct ncvisual* ncv, struct ncvisual_options*
// 300FPS, and a 'timescale' of 10 will result in 3FPS. It is an error to
// supply 'timescale' less than or equal to 0.
API int ncvisual_stream(struct notcurses* nc, struct ncvisual* ncv,
nc_err_e* ncerr, float timescale, streamcb streamer,
float timescale, streamcb streamer,
const struct ncvisual_options* vopts, void* curry);
// Blit a flat array 'data' of RGBA 32-bit values to the ncplane 'vopts->n',

@ -184,13 +184,6 @@ typedef struct palette256 {
palette256* palette256_new(struct notcurses* nc);
int palette256_use(struct notcurses* nc, const palette256* p);
void palette256_free(palette256* p);
typedef enum {
NCERR_SUCCESS,
NCERR_NOMEM,
NCERR_EOF,
NCERR_DECODE,
NCERR_UNIMPLEMENTED,
} nc_err_e;
typedef enum {
NCSCALE_NONE,
NCSCALE_SCALE,
@ -198,13 +191,13 @@ typedef enum {
} ncscale_e;
int notcurses_lex_scalemode(const char* op, ncscale_e* scalemode);
const char* notcurses_str_scalemode(ncscale_e scalemode);
struct ncvisual* ncvisual_from_file(const char* file, nc_err_e* ncerr);
struct ncvisual* ncvisual_from_file(const char* file);
struct ncvisual* ncvisual_from_rgba(const void* rgba, int rows, int rowstride, int cols);
struct ncvisual* ncvisual_from_bgra(const void* rgba, int rows, int rowstride, int cols);
struct ncvisual* ncvisual_from_plane(const struct ncplane* n, ncblitter_e blit, int begy, int begx, int leny, int lenx);
int ncvisual_geom(const struct notcurses* nc, const struct ncvisual* n, const struct ncvisual_options* vopts, int* y, int* x, int* toy, int* tox);
void ncvisual_destroy(struct ncvisual* ncv);
nc_err_e ncvisual_decode(struct ncvisual* nc);
int ncvisual_decode(struct ncvisual* nc);
int ncvisual_rotate(struct ncvisual* n, double rads);
int ncvisual_resize(struct ncvisual* n, int rows, int cols);
int ncvisual_polyfill_yx(struct ncvisual* n, int y, int x, uint32_t rgba);
@ -213,7 +206,7 @@ char* ncvisual_subtitle(const struct ncvisual* ncv);
int ncvisual_at_yx(const struct ncvisual* n, int y, int x, uint32_t* pixel);
int ncvisual_set_yx(const struct ncvisual* n, int y, int x, uint32_t pixel);
typedef int (*streamcb)(struct ncvisual*, struct ncvisual_options*, const struct timespec*, void*);
int ncvisual_stream(struct notcurses* nc, struct ncvisual* ncv, nc_err_e* ncerr, float timescale, streamcb streamer, const struct ncvisual_options* vopts, void* curry);
int ncvisual_stream(struct notcurses* nc, struct ncvisual* ncv, float timescale, streamcb streamer, const struct ncvisual_options* vopts, void* curry);
struct ncvisual_options {
struct ncplane* n;
ncscale_e scaling;
@ -435,7 +428,7 @@ int ncdirect_rounded_box(struct ncdirect* n, uint64_t ul, uint64_t ur, uint64_t
int ncdirect_double_box(struct ncdirect* n, uint64_t ul, uint64_t ur, uint64_t ll, uint64_t lr, int ylen, int xlen, unsigned ctlword);
bool ncdirect_canopen_images(const struct ncdirect* n);
bool ncdirect_canutf8(const struct ncdirect* n);
nc_err_e ncdirect_render_image(struct ncdirect* n, const char* filename, ncalign_e align, ncblitter_e blitter, ncscale_e scale);
int ncdirect_render_image(struct ncdirect* n, const char* filename, ncalign_e align, ncblitter_e blitter, ncscale_e scale);
struct ncplane* ncplane_parent(struct ncplane* n);
const struct ncplane* ncplane_parent_const(const struct ncplane* n);
""")

@ -16,11 +16,10 @@ chunli_draw(struct notcurses* nc, const char* ext, int count, const cell* b){
struct timespec iterdelay;
timespec_div(&demodelay, 10, &iterdelay);
for(int i = 0 ; i < count ; ++i){
nc_err_e err;
notcurses_refresh(nc, &dimy, &dimx);
snprintf(file, sizeof(file), "chunli%d.%s", i + 1, ext);
chuns[i].path = find_data(file);
chuns[i].ncv = ncvisual_from_file(chuns[i].path, &err);
chuns[i].ncv = ncvisual_from_file(chuns[i].path);
if(chuns[i].ncv == NULL){
return -1;
}
@ -62,8 +61,7 @@ int chunli_demo(struct notcurses* nc){
for(int i = 1 ; i < 100 ; ++i){
snprintf(file, sizeof(file), "chunli%02d.png", i);
char* path = find_data(file);
nc_err_e err;
struct ncvisual* ncv = ncvisual_from_file(path, &err);
struct ncvisual* ncv = ncvisual_from_file(path);
if(ncv == NULL){
free(path);
break;

@ -26,13 +26,12 @@ const char eagle1[] =
static struct ncplane*
zoom_map(struct notcurses* nc, const char* map, int* ret){
*ret = -1;
nc_err_e ncerr;
// determine size that will be represented on screen at once, and how
// large that section has been rendered in the outzoomed map. take the map
// and begin opening it on larger and larger planes that fit on the screen
// less and less. eventually, reach our natural NCSCALE_NONE size and begin
// scrolling through the map, whooooooooosh.
struct ncvisual* ncv = ncvisual_from_file(map, &ncerr);
struct ncvisual* ncv = ncvisual_from_file(map);
if(ncv == NULL){
return NULL;
}

@ -177,9 +177,8 @@ int fallin_demo(struct notcurses* nc){
ncplane_erase(stdn);
#ifdef USE_MULTIMEDIA
#ifndef DFSG_BUILD
nc_err_e err = NCERR_SUCCESS;
char* path = find_data("lamepatents.jpg");
struct ncvisual* ncv = ncvisual_from_file(path, &err);
struct ncvisual* ncv = ncvisual_from_file(path);
free(path);
if(ncv == NULL){
goto err;
@ -193,7 +192,7 @@ int fallin_demo(struct notcurses* nc){
ncvisual_destroy(ncv);
goto err;
}
assert(ncvisual_decode(ncv) == NCERR_EOF);
assert(ncvisual_decode(ncv) == 1);
ncvisual_destroy(ncv);
#endif
#endif

@ -147,9 +147,8 @@ int luigi_demo(struct notcurses* nc){
return 0;
}
int rows, cols;
nc_err_e ncerr = NCERR_SUCCESS;
char* map = find_data("megaman2.bmp");
struct ncvisual* nv = ncvisual_from_file(map, &ncerr);
struct ncvisual* nv = ncvisual_from_file(map);
free(map);
if(nv == NULL){
return -1;
@ -161,7 +160,7 @@ int luigi_demo(struct notcurses* nc){
if(ncvisual_render(nc, nv, &vopts) == NULL){
return -1;
}
assert(NCERR_EOF == ncvisual_decode(nv));
assert(1 == ncvisual_decode(nv));
// he should be walking on the platform ~4/5 of the way down
const int height = 32;
int yoff = rows * 4 / 5 - height + 1; // tuned
@ -187,7 +186,7 @@ int luigi_demo(struct notcurses* nc){
if(fname == NULL){
return -1;
}
wmncv = ncvisual_from_file(fname, &ncerr);
wmncv = ncvisual_from_file(fname);
free(fname);
if(wmncv == NULL){
return -1;

@ -80,8 +80,7 @@ rotate_visual(struct notcurses* nc, struct ncplane* n, int dy, int dx){
if(notcurses_canopen_images(nc)){
char* path = find_data("normal.png");
if(path){
nc_err_e err;
nncv = ncvisual_from_file(path, &err);
nncv = ncvisual_from_file(path);
if(nncv){
struct ncvisual_options nvopts = {
.n = notcurses_stdplane(nc),

@ -46,9 +46,8 @@ changes_fadeout(struct notcurses* nc, struct ncplane* ncp,
static void*
videothread(void* vnc){
struct notcurses* nc = vnc;
nc_err_e err;
char* path = find_data("samoa.avi");
struct ncvisual* ncv = ncvisual_from_file(path, &err);
struct ncvisual* ncv = ncvisual_from_file(path);
free(path);
if(ncv == NULL){
return NULL;
@ -97,7 +96,7 @@ videothread(void* vnc){
ncplane_set_bg_rgb(apiap, 0, 0, 0);
ncplane_putstr_aligned(apiap, 0, NCALIGN_CENTER,
"Apia 🡺 Atlanta. Samoa, tula'i ma sisi ia lau fu'a, lou pale lea!");
int canceled = ncvisual_stream(nc, ncv, &err, delaymultiplier, perframe, &ovopts, &three);
int canceled = ncvisual_stream(nc, ncv, delaymultiplier, perframe, &ovopts, &three);
ncvisual_destroy(ncv);
ncplane_destroy(apiap);
if(canceled == 1){
@ -181,9 +180,8 @@ int outro(struct notcurses* nc){
struct ncvisual* chncv = NULL;
memset(&vopts, 0, sizeof(vopts));
if(notcurses_canopen_images(nc)){
nc_err_e err = 0;
char* path = find_data("changes.jpg");
chncv = ncvisual_from_file(path, &err);
chncv = ncvisual_from_file(path);
free(path);
if(chncv == NULL){
return -1;

@ -3,10 +3,9 @@
static int
view_video_demo(struct notcurses* nc){
struct ncplane* ncp = notcurses_stdplane(nc);
nc_err_e err;
struct ncvisual* ncv;
char* fm6 = find_data("fm6.mkv");
ncv = ncvisual_from_file(fm6, &err);
ncv = ncvisual_from_file(fm6);
if(!ncv){
free(fm6);
return -1;
@ -17,7 +16,7 @@ view_video_demo(struct notcurses* nc){
.n = ncp,
.y = 1,
};
int ret = ncvisual_stream(nc, ncv, &err, 0.5 * delaymultiplier,
int ret = ncvisual_stream(nc, ncv, 0.5 * delaymultiplier,
demo_simple_streamer, &vopts, NULL);
ncvisual_destroy(ncv);
return ret;
@ -68,9 +67,8 @@ view_images(struct notcurses* nc, struct ncplane* nstd, int dimy, int dimx){
if(dsplane == NULL){
return -1;
}
nc_err_e err = NCERR_SUCCESS;
char* pic = find_data("dsscaw-purp.png");
struct ncvisual* ncv2 = ncvisual_from_file(pic, &err);
struct ncvisual* ncv2 = ncvisual_from_file(pic);
if(ncv2 == NULL){
free(pic);
ncplane_destroy(dsplane);
@ -97,7 +95,7 @@ view_images(struct notcurses* nc, struct ncplane* nstd, int dimy, int dimx){
// now we open PurpleDrank on the standard plane, and hide DSSAW
ncplane_move_bottom(dsplane);
pic = find_data("PurpleDrank.jpg");
struct ncvisual* ncv = ncvisual_from_file(pic, &err);
struct ncvisual* ncv = ncvisual_from_file(pic);
if(ncv == NULL){
ncplane_destroy(dsplane);
free(pic);

@ -79,8 +79,7 @@ int xray_demo(struct notcurses* nc){
return -1;
}
char* path = find_data("notcursesI.avi");
nc_err_e err;
struct ncvisual* ncv = ncvisual_from_file(path, &err);
struct ncvisual* ncv = ncvisual_from_file(path);
free(path);
if(ncv == NULL){
return -1;
@ -96,7 +95,7 @@ int xray_demo(struct notcurses* nc){
.scaling = NCSCALE_STRETCH,
.blitter = NCBLIT_2x1,
};
int ret = ncvisual_stream(nc, ncv, &err, 0.5 * delaymultiplier, perframecb, &vopts, newpanel);
int ret = ncvisual_stream(nc, ncv, 0.5 * delaymultiplier, perframecb, &vopts, newpanel);
ncvisual_destroy(ncv);
ncplane_destroy(n);
ncplane_destroy(newpanel);

@ -7,8 +7,7 @@ int yield_demo(struct notcurses* nc){
int dimy, dimx;
struct ncplane* std = notcurses_stddim_yx(nc, &dimy, &dimx);
char* pic = find_data("worldmap.png");
nc_err_e err;
struct ncvisual* wmv = ncvisual_from_file(pic, &err);
struct ncvisual* wmv = ncvisual_from_file(pic);
free(pic);
if(wmv == NULL){
return -1;

@ -5,9 +5,8 @@ static int
draw_background(struct notcurses* nc){
if(notcurses_canopen_images(nc)){
struct ncplane* n = notcurses_stdplane(nc);
nc_err_e err;
char* path = find_data("changes.jpg");
struct ncvisual* ncv = ncvisual_from_file(path, &err);
struct ncvisual* ncv = ncvisual_from_file(path);
free(path);
if(!ncv){
return -1;

@ -1,8 +1,9 @@
#include <pwd.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <locale.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/types.h>
#ifdef __linux__
@ -420,9 +421,8 @@ display_thread(void* vmarshal){
drawpalette(m->nc);
if(m->dinfo){
if(m->dinfo->logofile){
if(ncdirect_render_image(m->nc, m->dinfo->logofile,
NCALIGN_CENTER, NCBLIT_2x2,
NCSCALE_SCALE) != NCERR_SUCCESS){
if(ncdirect_render_image(m->nc, m->dinfo->logofile, NCALIGN_CENTER,
NCBLIT_2x2, NCSCALE_SCALE)){
return NULL;
}
}

@ -307,24 +307,23 @@ ncdirect_dump_plane(ncdirect* n, const ncplane* np, int xoff){
return 0;
}
nc_err_e ncdirect_render_image(ncdirect* n, const char* file, ncalign_e align,
ncblitter_e blitter, ncscale_e scale){
nc_err_e ret;
struct ncvisual* ncv = ncvisual_from_file(file, &ret);
int ncdirect_render_image(ncdirect* n, const char* file, ncalign_e align,
ncblitter_e blitter, ncscale_e scale){
struct ncvisual* ncv = ncvisual_from_file(file);
if(ncv == nullptr){
return ret;
return -1;
}
//fprintf(stderr, "OUR DATA: %p rows/cols: %d/%d\n", ncv->data, ncv->rows, ncv->cols);
int leny = ncv->rows; // we allow it to freely scroll
int lenx = ncv->cols;
if(leny == 0 || lenx == 0){
ncvisual_destroy(ncv);
return NCERR_DECODE;
return -1;
}
//fprintf(stderr, "render %d/%d to %d+%dx%d scaling: %d\n", ncv->rows, ncv->cols, leny, lenx, scale);
auto bset = rgba_blitter_low(n->utf8, scale, true, blitter);
if(!bset){
return NCERR_INVALID_ARG;
return -1;
}
int disprows, dispcols;
if(scale != NCSCALE_NONE){
@ -345,18 +344,18 @@ nc_err_e ncdirect_render_image(ncdirect* n, const char* file, ncalign_e align,
dispcols / encoding_x_scale(bset),
0, 0, nullptr, nullptr);
if(faken == nullptr){
return NCERR_NOMEM;
return -1;
}
if(ncvisual_blit(ncv, disprows, dispcols, faken, bset,
0, 0, 0, 0, leny, lenx, false)){
ncvisual_destroy(ncv);
free_plane(faken);
return NCERR_SYSTEM;
return -1;
}
ncvisual_destroy(ncv);
int xoff = ncdirect_align(n, align, lenx / encoding_x_scale(bset));
if(ncdirect_dump_plane(n, faken, xoff)){
return NCERR_SYSTEM;
return -1;
}
while(fflush(stdout) == EOF && errno == EAGAIN){
;
@ -364,7 +363,7 @@ nc_err_e ncdirect_render_image(ncdirect* n, const char* file, ncalign_e align,
free_plane(faken);
ncdirect_fg_default(n);
ncdirect_bg_default(n);
return NCERR_SUCCESS;
return 0;
}
int ncdirect_fg_palindex(ncdirect* nc, int pidx){

@ -97,19 +97,19 @@ auto ncvisual_subtitle(const ncvisual* ncv) -> char* {
return nullptr;
}
static nc_err_e
static int
averr2ncerr(int averr){
if(averr == AVERROR_EOF){
return NCERR_EOF;
return 1;
}
// FIXME need to map averror codes to ncerrors
//fprintf(stderr, "AVERR: %d/%x %d/%x\n", averr, averr, -averr, -averr);
return NCERR_DECODE;
return -1;
}
nc_err_e ncvisual_decode(ncvisual* nc){
int ncvisual_decode(ncvisual* nc){
if(nc->details.fmtctx == nullptr){ // not a file-backed ncvisual
return NCERR_DECODE;
return -1;
}
bool have_frame = false;
bool unref = false;
@ -165,16 +165,16 @@ nc_err_e ncvisual_decode(ncvisual* nc){
nc->rows = nc->details.frame->height;
//fprintf(stderr, "good decode! %d/%d %d %p\n", nc->details.frame->height, nc->details.frame->width, nc->rowstride, f->data);
ncvisual_set_data(nc, reinterpret_cast<uint32_t*>(f->data[0]), false);
return NCERR_SUCCESS;
return 0;
}
// resize frame to oframe, converting to RGBA (if necessary) along the way
nc_err_e ncvisual_resize(ncvisual* nc, int rows, int cols) {
int ncvisual_resize(ncvisual* nc, int rows, int cols) {
const int targformat = AV_PIX_FMT_RGBA;
AVFrame* inf = nc->details.oframe ? nc->details.oframe : nc->details.frame;
//fprintf(stderr, "got format: %d (%d/%d) want format: %d (%d/%d)\n", inf->format, nc->rows, nc->cols, targformat, rows, cols);
if(inf->format == targformat && nc->rows == rows && nc->cols == cols){
return NCERR_SUCCESS;
return 0;
}
auto swsctx = sws_getContext(inf->width,
inf->height,
@ -184,13 +184,13 @@ nc_err_e ncvisual_resize(ncvisual* nc, int rows, int cols) {
SWS_LANCZOS, nullptr, nullptr, nullptr);
if(swsctx == nullptr){
//fprintf(stderr, "Error retrieving swsctx\n");
return NCERR_NOMEM;
return -1;
}
AVFrame* sframe;
if((sframe = av_frame_alloc()) == nullptr){
// fprintf(stderr, "Couldn't allocate frame for %s\n", filename);
sws_freeContext(swsctx);
return NCERR_NOMEM; // no need to free swsctx
return -1; // no need to free swsctx
}
memcpy(sframe, inf, sizeof(*sframe));
sframe->format = targformat;
@ -205,7 +205,7 @@ nc_err_e ncvisual_resize(ncvisual* nc, int rows, int cols) {
//fprintf(stderr, "Error allocating visual data (%d)\n", size);
av_freep(&sframe);
sws_freeContext(swsctx);
return NCERR_NOMEM;
return -1;
}
int height = sws_scale(swsctx, inf->data,
inf->linesize, 0,
@ -216,7 +216,7 @@ nc_err_e ncvisual_resize(ncvisual* nc, int rows, int cols) {
//fprintf(stderr, "Error applying scaling (%s)\n", av_err2str(height));
av_freep(sframe->data);
av_freep(&sframe);
return NCERR_DECODE;
return -1;
}
const AVFrame* f = sframe;
int bpp = av_get_bits_per_pixel(av_pix_fmt_desc_get(static_cast<AVPixelFormat>(f->format)));
@ -224,7 +224,7 @@ nc_err_e ncvisual_resize(ncvisual* nc, int rows, int cols) {
//fprintf(stderr, "Bad bits-per-pixel (wanted 32, got %d)\n", bpp);
av_freep(sframe->data);
av_freep(&sframe);
return NCERR_DECODE;
return -1;
}
nc->rowstride = sframe->linesize[0];
nc->rows = rows;
@ -237,29 +237,25 @@ nc_err_e ncvisual_resize(ncvisual* nc, int rows, int cols) {
nc->details.oframe = sframe;
//fprintf(stderr, "SIZE SCALED: %d %d (%u)\n", nc->details.oframe->height, nc->details.oframe->width, nc->details.oframe->linesize[0]);
return NCERR_SUCCESS;
return 0;
}
ncvisual* ncvisual_from_file(const char* filename, nc_err_e* ncerr) {
ncvisual* ncvisual_from_file(const char* filename) {
AVStream* st;
*ncerr = NCERR_SUCCESS;
ncvisual* ncv = ncvisual_create();
if(ncv == nullptr){
// fprintf(stderr, "Couldn't create %s (%s)\n", filename, strerror(errno));
*ncerr = NCERR_NOMEM;
return nullptr;
}
//fprintf(stderr, "FRAME FRAME: %p\n", ncv->details.frame);
int averr = avformat_open_input(&ncv->details.fmtctx, filename, nullptr, nullptr);
if(averr < 0){
//fprintf(stderr, "Couldn't open %s (%d)\n", filename, averr);
*ncerr = averr2ncerr(averr);
goto err;
}
averr = avformat_find_stream_info(ncv->details.fmtctx, nullptr);
if(averr < 0){
//fprintf(stderr, "Error extracting stream info from %s (%d)\n", filename, averr);
*ncerr = averr2ncerr(averr);
goto err;
}
//av_dump_format(ncv->details.fmtctx, 0, filename, false);
@ -267,13 +263,11 @@ ncvisual* ncvisual_from_file(const char* filename, nc_err_e* ncerr) {
ncv->details.sub_stream_index = averr;
if((ncv->details.subtcodecctx = avcodec_alloc_context3(ncv->details.subtcodec)) == nullptr){
//fprintf(stderr, "Couldn't allocate decoder for %s\n", filename);
*ncerr = NCERR_NOMEM;
goto err;
}
// FIXME do we need avcodec_parameters_to_context() here?
if((averr = avcodec_open2(ncv->details.subtcodecctx, ncv->details.subtcodec, nullptr)) < 0){
//fprintf(stderr, "Couldn't open codec for %s (%s)\n", filename, av_err2str(*averr));
*ncerr = averr2ncerr(averr);
goto err;
}
}else{
@ -282,24 +276,20 @@ ncvisual* ncvisual_from_file(const char* filename, nc_err_e* ncerr) {
//fprintf(stderr, "FRAME FRAME: %p\n", ncv->details.frame);
if((ncv->details.packet = av_packet_alloc()) == nullptr){
// fprintf(stderr, "Couldn't allocate packet for %s\n", filename);
*ncerr = NCERR_NOMEM;
goto err;
}
if((averr = av_find_best_stream(ncv->details.fmtctx, AVMEDIA_TYPE_VIDEO, -1, -1, &ncv->details.codec, 0)) < 0){
// fprintf(stderr, "Couldn't find visuals in %s (%s)\n", filename, av_err2str(*averr));
*ncerr = averr2ncerr(averr);
goto err;
}
ncv->details.stream_index = averr;
if(ncv->details.codec == nullptr){
//fprintf(stderr, "Couldn't find decoder for %s\n", filename);
*ncerr = NCERR_DECODE;
goto err;
}
st = ncv->details.fmtctx->streams[ncv->details.stream_index];
if((ncv->details.codecctx = avcodec_alloc_context3(ncv->details.codec)) == nullptr){
//fprintf(stderr, "Couldn't allocate decoder for %s\n", filename);
*ncerr = NCERR_NOMEM;
goto err;
}
if(avcodec_parameters_to_context(ncv->details.codecctx, st->codecpar) < 0){
@ -307,12 +297,10 @@ ncvisual* ncvisual_from_file(const char* filename, nc_err_e* ncerr) {
}
if((averr = avcodec_open2(ncv->details.codecctx, ncv->details.codec, nullptr)) < 0){
//fprintf(stderr, "Couldn't open codec for %s (%s)\n", filename, av_err2str(*averr));
*ncerr = averr2ncerr(averr);
goto err;
}
/*if((ncv->cparams = avcodec_parameters_alloc()) == nullptr){
//fprintf(stderr, "Couldn't allocate codec params for %s\n", filename);
*averr = NCERR_NOMEM;
goto err;
}
if((*averr = avcodec_parameters_from_context(ncv->cparams, ncv->details.codecctx)) < 0){
@ -323,7 +311,7 @@ ncvisual* ncvisual_from_file(const char* filename, nc_err_e* ncerr) {
// frame is set up in prep_details(), so that format can be set there, as
// is necessary when it is prepared from inputs other than files. oframe
// is set up whenever we convert to RGBA.
if((*ncerr = ncvisual_decode(ncv)) != NCERR_SUCCESS){
if(ncvisual_decode(ncv)){
goto err;
}
return ncv;
@ -337,10 +325,9 @@ err:
// frames carry a presentation time relative to the beginning, so we get an
// initial timestamp, and check each frame against the elapsed time to sync
// up playback.
int ncvisual_stream(notcurses* nc, ncvisual* ncv, nc_err_e* ncerr,
float timescale, streamcb streamer,
const struct ncvisual_options* vopts, void* curry) {
*ncerr = NCERR_SUCCESS;
int ncvisual_stream(notcurses* nc, ncvisual* ncv, float timescale,
streamcb streamer, const struct ncvisual_options* vopts,
void* curry) {
int frame = 1;
struct timespec begin; // time we started
clock_gettime(CLOCK_MONOTONIC, &begin);
@ -352,6 +339,7 @@ int ncvisual_stream(notcurses* nc, ncvisual* ncv, nc_err_e* ncerr,
ncplane* newn = NULL;
ncvisual_options activevopts;
memcpy(&activevopts, vopts, sizeof(*vopts));
int ncerr;
do{
// codecctx seems to be off by a factor of 2 regularly. instead, go with
// the time_base from the avformatctx.
@ -396,20 +384,20 @@ int ncvisual_stream(notcurses* nc, ncvisual* ncv, nc_err_e* ncerr,
}
return r;
}
}while((*ncerr = ncvisual_decode(ncv)) == NCERR_SUCCESS);
}while((ncerr = ncvisual_decode(ncv)) == 0);
if(activevopts.n != vopts->n){
ncplane_destroy(activevopts.n);
}
if(*ncerr == NCERR_EOF){
return 0;
if(ncerr == 1){ // 1 indicates reaching EOF
ncerr = 0;
}
return -1;
return ncerr;
}
nc_err_e ncvisual_blit(ncvisual* ncv, int rows, int cols, ncplane* n,
const struct blitset* bset, int placey, int placex,
int begy, int begx, int leny, int lenx,
bool blendcolors) {
int ncvisual_blit(ncvisual* ncv, int rows, int cols, ncplane* n,
const struct blitset* bset, int placey, int placex,
int begy, int begx, int leny, int lenx,
bool blendcolors) {
const AVFrame* inframe = ncv->details.oframe ? ncv->details.oframe : ncv->details.frame;
//fprintf(stderr, "inframe: %p oframe: %p frame: %p\n", inframe, ncv->details.oframe, ncv->details.frame);
void* data = nullptr;
@ -422,7 +410,7 @@ nc_err_e ncvisual_blit(ncvisual* ncv, int rows, int cols, ncplane* n,
sframe = av_frame_alloc();
if(sframe == nullptr){
//fprintf(stderr, "Couldn't allocate output frame for scaled frame\n");
return NCERR_NOMEM;
return -1;
}
//fprintf(stderr, "WHN NCV: %d/%d\n", inframe->width, inframe->height);
ncv->details.swsctx = sws_getCachedContext(ncv->details.swsctx,
@ -433,7 +421,7 @@ nc_err_e ncvisual_blit(ncvisual* ncv, int rows, int cols, ncplane* n,
SWS_LANCZOS, nullptr, nullptr, nullptr);
if(ncv->details.swsctx == nullptr){
//fprintf(stderr, "Error retrieving details.swsctx\n");
return NCERR_NOMEM;
return -1;
}
memcpy(sframe, inframe, sizeof(*inframe));
sframe->format = targformat;
@ -445,14 +433,14 @@ nc_err_e ncvisual_blit(ncvisual* ncv, int rows, int cols, ncplane* n,
IMGALLOCALIGN);
if(size < 0){
//fprintf(stderr, "Error allocating visual data (%d X %d)\n", sframe->height, sframe->width);
return NCERR_NOMEM;
return -1;
}
int height = sws_scale(ncv->details.swsctx, (const uint8_t* const*)inframe->data,
inframe->linesize, 0, inframe->height, sframe->data,
sframe->linesize);
if(height < 0){
//fprintf(stderr, "Error applying scaling (%d X %d)\n", inframe->height, inframe->width);
return NCERR_DECODE;
return -1;
}
stride = sframe->linesize[0]; // FIXME check for others?
data = sframe->data[0];
@ -469,13 +457,13 @@ nc_err_e ncvisual_blit(ncvisual* ncv, int rows, int cols, ncplane* n,
av_freep(sframe->data);
av_freep(&sframe);
}
return NCERR_DECODE;
return -1;
}
if(sframe){
av_freep(sframe->data);
av_freep(&sframe);
}
return NCERR_SUCCESS;
return 0;
}
auto ncvisual_details_seed(ncvisual* ncv) -> void {

@ -6,7 +6,6 @@
extern "C" {
#include "notcurses/ncerrs.h"
#include <libavutil/error.h>
#include <libavutil/frame.h>
#include <libavutil/pixdesc.h>
@ -45,14 +44,14 @@ typedef struct ncvisual_details {
} ncvisual_details;
static inline auto
ncvisual_details_init(ncvisual_details* deets) -> nc_err_e {
ncvisual_details_init(ncvisual_details* deets) -> int {
memset(deets, 0, sizeof(*deets));
deets->stream_index = -1;
deets->sub_stream_index = -1;
if((deets->frame = av_frame_alloc()) == nullptr){
return NCERR_NOMEM;
return -1;
}
return NCERR_SUCCESS;
return 0;
}
static inline auto

@ -759,10 +759,10 @@ char* ncplane_vprintf_prep(const char* format, va_list ap);
// Resize the provided ncviusal to the specified 'rows' x 'cols', but do not
// change the internals of the ncvisual. Uses oframe.
nc_err_e ncvisual_blit(struct ncvisual* ncv, int rows, int cols,
ncplane* n, const struct blitset* bset,
int placey, int placex, int begy, int begx,
int leny, int lenx, bool blendcolors);
int ncvisual_blit(struct ncvisual* ncv, int rows, int cols,
ncplane* n, const struct blitset* bset,
int placey, int placex, int begy, int begx,
int leny, int lenx, bool blendcolors);
void nclog(const char* fmt, ...);

@ -12,45 +12,42 @@ bool notcurses_canopen_videos(const notcurses* nc __attribute__ ((unused))) {
return false; // too slow for reliable use at the moment
}
ncvisual* ncvisual_from_file(const char* filename, nc_err_e* err) {
*err = NCERR_SUCCESS;
ncvisual* ncvisual_from_file(const char* filename) {
ncvisual* ncv = ncvisual_create();
if(ncv == nullptr){
*err = NCERR_NOMEM;
return nullptr;
}
ncv->details.image = OIIO::ImageInput::open(filename);
if(!ncv->details.image){
// fprintf(stderr, "Couldn't create %s (%s)\n", filename, strerror(errno));
*err = NCERR_DECODE;
ncvisual_destroy(ncv);
return nullptr;
}
/*const auto &spec = ncv->details.image->spec_dimensions(0);
std::cout << "Opened " << filename << ": " << spec.height << "x" <<
spec.width << "@" << spec.nchannels << " (" << spec.format << ")" << std::endl;*/
if((*err = ncvisual_decode(ncv)) != NCERR_SUCCESS){
if(ncvisual_decode(ncv)){
ncvisual_destroy(ncv);
return nullptr;
}
return ncv;
}
nc_err_e ncvisual_decode(ncvisual* nc) {
int ncvisual_decode(ncvisual* nc) {
//fprintf(stderr, "current subimage: %d frame: %p\n", nc->details.image->current_subimage(), nc->details.frame.get());
const auto &spec = nc->details.image->spec_dimensions(nc->details.framenum);
if(nc->details.frame){
//fprintf(stderr, "seeking subimage: %d\n", nc->details.image->current_subimage() + 1);
OIIO::ImageSpec newspec;
if(!nc->details.image->seek_subimage(nc->details.image->current_subimage() + 1, 0, newspec)){
return NCERR_EOF;
return 1;
}
// FIXME check newspec vis-a-vis image->spec()?
}
//fprintf(stderr, "SUBIMAGE: %d\n", nc->details.image->current_subimage());
auto pixels = spec.width * spec.height;// * spec.nchannels;
if(spec.nchannels < 3 || spec.nchannels > 4){
return NCERR_DECODE; // FIXME get some to test with
return -1; // FIXME get some to test with
}
nc->details.frame = std::make_unique<uint32_t[]>(pixels);
if(spec.nchannels == 3){ // FIXME replace with channel shuffle
@ -58,7 +55,7 @@ nc_err_e ncvisual_decode(ncvisual* nc) {
}
//fprintf(stderr, "READING: %d %ju\n", nc->details.image->current_subimage(), nc->details.framenum);
if(!nc->details.image->read_image(nc->details.framenum++, 0, 0, spec.nchannels, OIIO::TypeDesc(OIIO::TypeDesc::UINT8, 4), nc->details.frame.get(), 4)){
return NCERR_DECODE;
return -1;
}
//fprintf(stderr, "READ: %d %ju\n", nc->details.image->current_subimage(), nc->details.framenum);
/*for(int i = 0 ; i < pixels ; ++i){
@ -79,11 +76,11 @@ nc_err_e ncvisual_decode(ncvisual* nc) {
//fprintf(stderr, "SUBS: %d\n", nc->details.ibuf->nsubimages());
ncvisual_set_data(nc, static_cast<uint32_t*>(nc->details.ibuf->localpixels()), false);
//fprintf(stderr, "POST-DECODE DATA: %d %d %p %p\n", nc->rows, nc->cols, nc->data, nc->details.ibuf->localpixels());
return NCERR_SUCCESS;
return 0;
}
// resize, converting to RGBA (if necessary) along the way
nc_err_e ncvisual_resize(ncvisual* nc, int rows, int cols) {
int ncvisual_resize(ncvisual* nc, int rows, int cols) {
//fprintf(stderr, "%d/%d -> %d/%d on the resize\n", ncv->rows, ncv->cols, rows, cols);
auto ibuf = std::make_unique<OIIO::ImageBuf>();
if(nc->details.ibuf && (nc->cols != cols || nc->rows != rows)){ // scale it
@ -93,7 +90,7 @@ nc_err_e ncvisual_resize(ncvisual* nc, int rows, int cols) {
ibuf->reset(sp, OIIO::InitializePixels::Yes);
OIIO::ROI roi(0, cols, 0, rows, 0, 1, 0, 4);
if(!OIIO::ImageBufAlgo::resize(*ibuf, *nc->details.ibuf, "", 0, roi)){
return NCERR_DECODE;
return -1;
}
nc->cols = cols;
nc->rows = rows;
@ -102,13 +99,13 @@ nc_err_e ncvisual_resize(ncvisual* nc, int rows, int cols) {
//fprintf(stderr, "HAVE SOME NEW DATA: %p\n", ibuf->localpixels());
nc->details.ibuf = std::move(ibuf);
}
return NCERR_SUCCESS;
return 0;
}
nc_err_e ncvisual_blit(struct ncvisual* ncv, int rows, int cols,
ncplane* n, const struct blitset* bset,
int placey, int placex, int begy, int begx,
int leny, int lenx, bool blendcolors) {
int ncvisual_blit(struct ncvisual* ncv, int rows, int cols,
ncplane* n, const struct blitset* bset,
int placey, int placex, int begy, int begx,
int leny, int lenx, bool blendcolors) {
//fprintf(stderr, "%d/%d -> %d/%d on the resize\n", ncv->rows, ncv->cols, rows, cols);
void* data = nullptr;
int stride = 0;
@ -120,7 +117,7 @@ nc_err_e ncvisual_blit(struct ncvisual* ncv, int rows, int cols,
ibuf->reset(sp, OIIO::InitializePixels::Yes);
OIIO::ROI roi(0, cols, 0, rows, 0, 1, 0, 4);
if(!OIIO::ImageBufAlgo::resize(*ibuf, *ncv->details.ibuf, "", 0, roi)){
return NCERR_DECODE;
return -1;
}
stride = cols * 4;
data = ibuf->localpixels();
@ -131,21 +128,21 @@ nc_err_e ncvisual_blit(struct ncvisual* ncv, int rows, int cols,
}
if(rgba_blit_dispatch(n, bset, placey, placex, stride, data, begy, begx,
leny, lenx, blendcolors) <= 0){
return NCERR_DECODE;
return -1;
}
return NCERR_SUCCESS;
return 0;
}
auto ncvisual_stream(notcurses* nc, ncvisual* ncv, nc_err_e* ncerr, float timescale,
auto ncvisual_stream(notcurses* nc, ncvisual* ncv, float timescale,
streamcb streamer, const struct ncvisual_options* vopts, void* curry) -> int {
(void)timescale; // FIXME
*ncerr = NCERR_SUCCESS;
int frame = 1;
struct timespec begin; // time we started
clock_gettime(CLOCK_MONOTONIC, &begin);
ncplane* newn = nullptr;
ncvisual_options activevopts;
memcpy(&activevopts, vopts, sizeof(*vopts));
int ncerr;
do{
if((newn = ncvisual_render(nc, ncv, &activevopts)) == NULL){
if(activevopts.n != vopts->n){
@ -173,11 +170,11 @@ auto ncvisual_stream(notcurses* nc, ncvisual* ncv, nc_err_e* ncerr, float timesc
return r;
}
++frame;
}while((*ncerr = ncvisual_decode(ncv)) == NCERR_SUCCESS);
}while((ncerr = ncvisual_decode(ncv)) == 0);
if(activevopts.n != vopts->n){
ncplane_destroy(activevopts.n);
}
if(*ncerr == NCERR_EOF){
if(ncerr == 1){
return 0;
}
return -1;

@ -19,12 +19,12 @@ typedef struct ncvisual_details {
} ncvisual_details;
static inline auto
ncvisual_details_init(ncvisual_details *deets) -> nc_err_e {
ncvisual_details_init(ncvisual_details *deets) -> int {
deets->image = nullptr;
deets->frame = nullptr;
deets->ibuf = nullptr;
deets->framenum = 0;
return NCERR_SUCCESS;
return 0;
}
static inline auto

@ -10,14 +10,13 @@
#ifdef USE_OIIO
#include "oiio.h"
#else
#include "notcurses/ncerrs.h"
typedef struct ncvisual_details {
} ncvisual_details;
static inline auto ncvisual_details_init(ncvisual_details* deets) -> nc_err_e {
static inline auto ncvisual_details_init(ncvisual_details* deets) -> int {
(void)deets;
return NCERR_SUCCESS;
return 0;
}
static inline auto

@ -249,16 +249,16 @@ rotate_bounding_box(double stheta, double ctheta, int* leny, int* lenx,
return *leny * *lenx;
}
auto ncvisual_rotate(ncvisual* ncv, double rads) -> nc_err_e {
auto ncvisual_rotate(ncvisual* ncv, double rads) -> int {
// done to force conversion into RGBA
nc_err_e err = ncvisual_resize(ncv, ncv->rows, ncv->cols);
if(err != NCERR_SUCCESS){
int err = ncvisual_resize(ncv, ncv->rows, ncv->cols);
if(err){
return err;
}
assert(ncv->rowstride / 4 >= ncv->cols);
rads = -rads; // we're a left-handed Cartesian
if(ncv->data == nullptr){
return NCERR_DECODE;
return -1;
}
int centy, centx;
ncvisual_center(ncv, &centy, &centx); // pixel center (center of 'data')
@ -273,12 +273,12 @@ auto ncvisual_rotate(ncvisual* ncv, double rads) -> nc_err_e {
int bboffy = 0;
int bboffx = 0;
if(ncvisual_bounding_box(ncv, &bby, &bbx, &bboffy, &bboffx) <= 0){
return NCERR_DECODE;
return -1;
}
int bbarea;
bbarea = rotate_bounding_box(stheta, ctheta, &bby, &bbx, &bboffy, &bboffx);
if(bbarea <= 0){
return NCERR_DECODE;
return -1;
}
int bbcentx = bbx, bbcenty = bby;
center_box(&bbcenty, &bbcentx);
@ -286,7 +286,7 @@ auto ncvisual_rotate(ncvisual* ncv, double rads) -> nc_err_e {
assert(ncv->rowstride / 4 >= ncv->cols);
auto data = static_cast<uint32_t*>(malloc(bbarea * 4));
if(data == nullptr){
return NCERR_NOMEM;
return -1;
}
memset(data, 0, bbarea * 4);
//fprintf(stderr, "bbarea: %d bby: %d bbx: %d centy: %d centx: %d bbcenty: %d bbcentx: %d\n", bbarea, bby, bbx, centy, centx, bbcenty, bbcentx);
@ -309,7 +309,7 @@ auto ncvisual_rotate(ncvisual* ncv, double rads) -> nc_err_e {
ncv->rows = bby;
ncv->rowstride = bbx * 4;
ncvisual_details_seed(ncv);
return NCERR_SUCCESS;
return 0;
}
auto ncvisual_from_rgba(const void* rgba, int rows, int rowstride,
@ -556,9 +556,8 @@ auto ncvisual_polyfill_yx(ncvisual* n, int y, int x, uint32_t rgba) -> int {
#ifndef USE_OIIO // built without ffmpeg or oiio
#ifndef USE_FFMPEG
auto ncvisual_from_file(const char* filename, nc_err_e* err) -> ncvisual* {
auto ncvisual_from_file(const char* filename) -> ncvisual* {
(void)filename;
*err = NCERR_UNIMPLEMENTED;
return nullptr;
}
@ -570,21 +569,20 @@ auto notcurses_canopen_videos(const notcurses* nc __attribute__ ((unused))) -> b
return false;
}
auto ncvisual_decode(ncvisual* nc) -> nc_err_e {
auto ncvisual_decode(ncvisual* nc) -> int {
(void)nc;
return NCERR_UNIMPLEMENTED;
return -1;
}
auto ncvisual_stream(notcurses* nc, ncvisual* ncv, nc_err_e* ncerr,
float timescale, streamcb streamer,
const ncvisual_options* vopts, void* curry) -> int {
auto ncvisual_stream(notcurses* nc, ncvisual* ncv, float timescale,
streamcb streamer, const ncvisual_options* vopts,
void* curry) -> int {
(void)nc;
(void)ncv;
(void)timescale;
(void)streamer;
(void)vopts;
(void)curry;
*ncerr = NCERR_UNIMPLEMENTED;
return -1;
}
@ -601,28 +599,28 @@ auto ncvisual_init(int loglevel) -> int {
auto ncvisual_blit(ncvisual* ncv, int rows, int cols, ncplane* n,
const struct blitset* bset, int placey, int placex,
int begy, int begx, int leny, int lenx,
bool blendcolors) -> nc_err_e {
bool blendcolors) -> int {
(void)rows;
(void)cols;
if(rgba_blit_dispatch(n, bset, placey, placex, ncv->rowstride, ncv->data,
begy, begx, leny, lenx, blendcolors) <= 0){
return NCERR_DECODE;
return -1;
}
return NCERR_SUCCESS;
return 0;
}
auto ncvisual_details_seed(struct ncvisual* ncv) -> void {
(void)ncv;
}
auto ncvisual_resize(ncvisual* nc, int rows, int cols) -> nc_err_e {
auto ncvisual_resize(ncvisual* nc, int rows, int cols) -> int {
// we'd need to verify that it's RGBA as well, except that if we've got no
// multimedia engine, we've only got memory-assembled ncvisuals, which are
// RGBA-native. so we ought be good, but this is undeniably sloppy...
if(nc->rows == rows && nc->cols == cols){
return NCERR_SUCCESS;
return 0;
}
return NCERR_UNIMPLEMENTED;
return -1;
}
#endif

@ -38,8 +38,7 @@ int main(int argc, char** argv){
for(int i = 1 ; i < argc ; ++i){
ncplane_erase(std);
const char* fname = argv[i];
nc_err_e err;
struct ncvisual* ncv = ncvisual_from_file(fname, &err);
struct ncvisual* ncv = ncvisual_from_file(fname);
if(ncv == NULL){
goto err;
}

@ -81,8 +81,7 @@ int main(void){
struct ncplane* n = notcurses_stdplane(nc);
if(notcurses_canopen_images(nc)){
nc_err_e err;
struct ncvisual* ncv = ncvisual_from_file("../data/covid19.jpg", &err);
struct ncvisual* ncv = ncvisual_from_file("../data/covid19.jpg");
if(!ncv){
goto err;
}

@ -23,12 +23,11 @@ int main(int argc, char** argv){
}
struct ncvisual_options vopts{};
bool failed = false;
nc_err_e ncerr;
int dimy, dimx;
int scaley, scalex;
int top = 0;
int bot;
auto ncv = ncvisual_from_file(file, &ncerr);
auto ncv = ncvisual_from_file(file);
if(!ncv){
goto err;
}

@ -65,7 +65,7 @@ rotate_grad(struct notcurses* nc){
ncplane_erase(n);
for(int i = 0 ; i < 4 ; ++i){
int vy, vx, scaley, scalex;
if(NCERR_SUCCESS != ncvisual_rotate(v, M_PI / 2)){
if(ncvisual_rotate(v, M_PI / 2)){
return -1;
}
ncvisual_geom(nc, v, &vopts, &vy, &vx, &scaley, &scalex);
@ -85,7 +85,7 @@ rotate_grad(struct notcurses* nc){
ncvisual_geom(nc, v, &vopts, &vy, &vx, &scaley, &scalex);
vopts.x = (dimx - (vx / scalex)) / 2;
vopts.y = (dimy - (vy / scaley)) / 2;
if(NCERR_SUCCESS != ncvisual_rotate(v, M_PI / 4)){
if(ncvisual_rotate(v, M_PI / 4)){
return -1;
}
ncplane_erase(n);
@ -195,7 +195,7 @@ rotate(struct notcurses* nc){
clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);;
for(int i = 0 ; i < 4 ; ++i){
if(NCERR_SUCCESS != ncvisual_rotate(v, M_PI / 2)){
if(ncvisual_rotate(v, M_PI / 2)){
return -1;
}
ncplane_erase(n);
@ -205,7 +205,7 @@ rotate(struct notcurses* nc){
}
for(int i = 0 ; i < 8 ; ++i){
if(NCERR_SUCCESS != ncvisual_rotate(v, M_PI / 4)){
if(ncvisual_rotate(v, M_PI / 4)){
return -1;
}
ncplane_erase(n);

@ -82,8 +82,7 @@ int main(void){
struct ncplane* n = notcurses_stdplane(nc);
if(notcurses_canopen_images(nc)){
nc_err_e err;
struct ncvisual* ncv = ncvisual_from_file("../data/changes.jpg", &err);
struct ncvisual* ncv = ncvisual_from_file("../data/changes.jpg");
if(!ncv){
goto err;
}

@ -34,8 +34,7 @@ int main(int argc, char** argv){
}
struct ncvisual_options vopts{};
bool failed = false;
nc_err_e ncerr;
auto ncv = ncvisual_from_file(file, &ncerr);
auto ncv = ncvisual_from_file(file);
if(!ncv){
goto err;
}

@ -17,15 +17,15 @@ int main(void){
return EXIT_FAILURE;
}
if(ncdirect_render_image(n, "../data/normal.png", NCALIGN_LEFT,
NCBLIT_DEFAULT, NCSCALE_STRETCH) != NCERR_SUCCESS){
NCBLIT_DEFAULT, NCSCALE_STRETCH)){
return EXIT_FAILURE;
}
if(ncdirect_render_image(n, "../data/normal.png", NCALIGN_CENTER,
NCBLIT_DEFAULT, NCSCALE_STRETCH) != NCERR_SUCCESS){
NCBLIT_DEFAULT, NCSCALE_STRETCH)){
return EXIT_FAILURE;
}
if(ncdirect_render_image(n, "../data/normal.png", NCALIGN_RIGHT,
NCBLIT_DEFAULT, NCSCALE_STRETCH) != NCERR_SUCCESS){
NCBLIT_DEFAULT, NCSCALE_STRETCH)){
return EXIT_FAILURE;
}
sleep(1);
@ -33,15 +33,15 @@ int main(void){
return EXIT_FAILURE;
}
if(ncdirect_render_image(n, "../data/changes.jpg", NCALIGN_LEFT,
NCBLIT_DEFAULT, NCSCALE_SCALE) != NCERR_SUCCESS){
NCBLIT_DEFAULT, NCSCALE_SCALE)){
return EXIT_FAILURE;
}
if(ncdirect_render_image(n, "../data/changes.jpg", NCALIGN_CENTER,
NCBLIT_DEFAULT, NCSCALE_SCALE) != NCERR_SUCCESS){
NCBLIT_DEFAULT, NCSCALE_SCALE)){
return EXIT_FAILURE;
}
if(ncdirect_render_image(n, "../data/changes.jpg", NCALIGN_RIGHT,
NCBLIT_DEFAULT, NCSCALE_SCALE) != NCERR_SUCCESS){
NCBLIT_DEFAULT, NCSCALE_SCALE)){
return EXIT_FAILURE;
}
sleep(1);
@ -49,11 +49,11 @@ int main(void){
return EXIT_FAILURE;
}
if(ncdirect_render_image(n, "../data/warmech.bmp", NCALIGN_RIGHT,
NCBLIT_DEFAULT, NCSCALE_NONE) != NCERR_SUCCESS){
NCBLIT_DEFAULT, NCSCALE_NONE)){
return EXIT_FAILURE;
}
if(ncdirect_render_image(n, "../data/warmech.bmp", NCALIGN_LEFT,
NCBLIT_DEFAULT, NCSCALE_NONE) != NCERR_SUCCESS){
NCBLIT_DEFAULT, NCSCALE_NONE)){
return EXIT_FAILURE;
}
if(ncdirect_stop(n)){

@ -1,6 +1,5 @@
void DrawBackground(const std::string& s) { // drawn to the standard plane
nc_err_e err;
backg_ = std::make_unique<ncpp::Visual>(s.c_str(), &err);
backg_ = std::make_unique<ncpp::Visual>(s.c_str());
backg_->decode();
ncvisual_options opts{};
opts.scaling = NCSCALE_STRETCH;

@ -216,10 +216,9 @@ auto main(int argc, char** argv) -> int {
std::unique_ptr<Plane> stdn(nc.get_stdplane(&dimy, &dimx));
for(auto i = nonopt ; i < argc ; ++i){
int frames = 0;
nc_err_e err;
std::unique_ptr<Visual> ncv;
try{
ncv = std::make_unique<Visual>(argv[i], &err);
ncv = std::make_unique<Visual>(argv[i]);
}catch(std::exception& e){
// FIXME want to stop nc first :/ can't due to stdn, ugh
std::cerr << argv[i] << ": " << e.what() << "\n";
@ -231,11 +230,11 @@ auto main(int argc, char** argv) -> int {
vopts.n = *stdn;
vopts.scaling = scalemode;
vopts.blitter = blitter;
int r = ncv->stream(&vopts, &err, timescale, perframe, &frames);
int r = ncv->stream(&vopts, timescale, perframe, &frames);
free(stdn->get_userptr());
stdn->set_userptr(nullptr);
if(r < 0){ // positive is intentional abort
std::cerr << "Error decoding " << argv[i] << ": " << nc_strerror(err) << std::endl;
std::cerr << "Error decoding " << argv[i] << std::endl;
failed = true;
break;
}else if(r == 0){

@ -65,10 +65,8 @@ TEST_CASE("Ncpp"
SUBCASE("VisualFromFile") {
NotCurses nc{ nopts };
if(nc.can_open_images()){
nc_err_e err;
{
Visual v = Visual(find_data("changes.jpg"), &err);
CHECK(NCERR_SUCCESS == err);
Visual v = Visual(find_data("changes.jpg"));
}
}
CHECK(nc.stop());

@ -22,12 +22,10 @@ TEST_CASE("Visual") {
}
SUBCASE("LoadImageCreatePlane") {
nc_err_e ncerr = NCERR_SUCCESS;
int dimy, dimx;
ncplane_dim_yx(ncp_, &dimy, &dimx);
auto ncv = ncvisual_from_file(find_data("changes.jpg"), &ncerr);
auto ncv = ncvisual_from_file(find_data("changes.jpg"));
REQUIRE(ncv);
REQUIRE(NCERR_SUCCESS == ncerr);
/*CHECK(dimy * 2 == frame->height);
CHECK(dimx == frame->width); FIXME */
struct ncvisual_options opts{};
@ -35,19 +33,16 @@ TEST_CASE("Visual") {
auto newn = ncvisual_render(nc_, ncv, &opts);
CHECK(newn);
CHECK(0 == notcurses_render(nc_));
ncerr = ncvisual_decode(ncv);
CHECK(NCERR_EOF == ncerr);
CHECK(1 == ncvisual_decode(ncv));
ncplane_destroy(newn);
ncvisual_destroy(ncv);
}
SUBCASE("LoadImage") {
nc_err_e ncerr = NCERR_SUCCESS;
int dimy, dimx;
ncplane_dim_yx(ncp_, &dimy, &dimx);
auto ncv = ncvisual_from_file(find_data("changes.jpg"), &ncerr);
auto ncv = ncvisual_from_file(find_data("changes.jpg"));
REQUIRE(ncv);
REQUIRE(NCERR_SUCCESS == ncerr);
/*CHECK(dimy * 2 == frame->height);
CHECK(dimx == frame->width); FIXME */
struct ncvisual_options opts{};
@ -55,18 +50,15 @@ TEST_CASE("Visual") {
opts.n = ncp_;
CHECK(ncvisual_render(nc_, ncv, &opts));
CHECK(0 == notcurses_render(nc_));
ncerr = ncvisual_decode(ncv);
CHECK(NCERR_EOF == ncerr);
CHECK(1 == ncvisual_decode(ncv));
ncvisual_destroy(ncv);
}
SUBCASE("PlaneDuplicate") {
nc_err_e ncerr = NCERR_SUCCESS;
int dimy, dimx;
ncplane_dim_yx(ncp_, &dimy, &dimx);
auto ncv = ncvisual_from_file(find_data("changes.jpg"), &ncerr);
auto ncv = ncvisual_from_file(find_data("changes.jpg"));
REQUIRE(ncv);
REQUIRE(NCERR_SUCCESS == ncerr);
/*CHECK(dimy * 2 == frame->height);
CHECK(dimx == frame->width); FIXME */
struct ncvisual_options opts{};
@ -89,18 +81,16 @@ TEST_CASE("Visual") {
SUBCASE("LoadVideo") {
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(find_data("notcursesI.avi"), &ncerr);
auto ncv = ncvisual_from_file(find_data("notcursesI.avi"));
REQUIRE(ncv);
CHECK(NCERR_SUCCESS == ncerr);
for(;;){ // run at the highest speed we can
ncerr = ncvisual_decode(ncv);
if(NCERR_EOF == ncerr){
int ret = ncvisual_decode(ncv);
if(1 == ret){
break;
}
CHECK(NCERR_SUCCESS == ncerr);
CHECK(0 == ret);
/*CHECK(dimy * 2 == frame->height);
CHECK(dimx == frame->width); FIXME */
struct ncvisual_options opts{};
@ -115,14 +105,11 @@ TEST_CASE("Visual") {
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(find_data("notcursesI.avi"), &ncerr);
auto ncv = ncvisual_from_file(find_data("notcursesI.avi"));
REQUIRE(ncv);
CHECK(NCERR_SUCCESS == ncerr);
ncerr = ncvisual_decode(ncv);
CHECK(NCERR_SUCCESS == ncerr);
CHECK(0 == ncvisual_decode(ncv));
/*CHECK(dimy * 2 == frame->height);
CHECK(dimx == frame->width); FIXME */
struct ncvisual_options opts{};

Loading…
Cancel
Save