Annihilate nc_err_e and all infrastructure #948

This commit is contained in:
nick black 2020-08-24 01:23:35 -04:00 committed by Nick Black
parent ea681ed4ec
commit 4dd1d6a4c8
43 changed files with 200 additions and 338 deletions

View File

@ -1,6 +1,12 @@
This document attempts to list user-visible changes and any major internal This document attempts to list user-visible changes and any major internal
rearrangements of Notcurses. 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) * 1.6.17 (2020-08-22)
* `ncdirect_flush()` now takes a `const struct ncdirect*`. * `ncdirect_flush()` now takes a `const struct ncdirect*`.
* A `const char* title` field has been added to `ncplot_options`. If not * A `const char* title` field has been added to `ncplot_options`. If not

View File

@ -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 // Display an image using the specified blitter and scaling. The image may
// be arbitrarily many rows -- the output will scroll -- but will only occupy // be arbitrarily many rows -- the output will scroll -- but will only occupy
// the column of the cursor, and those to the right. // the column of the cursor, and those to the right.
nc_err_e ncdirect_render_image(struct ncdirect* nc, const char* filename, int ncdirect_render_image(struct ncdirect* nc, const char* filename,
ncblitter_e blitter, ncscale_e scale); ncblitter_e blitter, ncscale_e scale);
``` ```
Several of the Notcurses capability predicates have `ncdirect` analogues: 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 // Rotate the visual 'rads' radians. Only M_PI/2 and -M_PI/2 are
// supported at the moment, but this will change FIXME. // 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 // Resize the visual so that it is 'rows' X 'columns'. This is a lossy
// transformation, unless the size is unchanged. // 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'. // 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); 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 // 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 // 300FPS, and a 'timescale' of 10 will result in 3FPS. It is an error to
// supply 'timescale' less than or equal to 0. // supply 'timescale' less than or equal to 0.
int ncvisual_stream(struct notcurses* nc, struct ncvisual* ncv, int ncvisual_stream(struct notcurses* nc, struct ncvisual* ncv, float timescale,
nc_err_e* ncerr, float timescale, streamcb streamer, streamcb streamer, const struct ncvisual_options* vopts,
const struct ncvisual_options* vopts, void* curry); void* curry);
``` ```
### QR codes ### QR codes
@ -2746,12 +2746,12 @@ have only one frame), until it returns `NCERR_EOF`:
```c ```c
// Open a visual at 'file', extracting a codec and parameters. // 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, // extract the next frame from an ncvisual. returns NCERR_EOF on end of file,
// and NCERR_SUCCESS on success, otherwise some other NCERR. // and NCERR_SUCCESS on success, otherwise some other NCERR.
nc_err_e ncvisual_decode(struct ncvisual* nc); int ncvisual_decode(struct ncvisual* nc);
``` ```
### Pixels ### Pixels

View File

@ -45,7 +45,6 @@
<a href="notcurses_cell.3.html">notcurses_cell</a>—operations on <tt>cell</tt> objects<br/> <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_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_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_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_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/> <a href="notcurses_init.3.html">notcurses_init</a>—initialization<br/>

View File

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

View File

@ -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);** **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 # DESCRIPTION

View File

@ -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)**

View File

@ -50,7 +50,7 @@ typedef int (*streamcb)(struct notcurses*, struct ncvisual*, void*);
**bool notcurses_cansixel(const struct notcurses* nc);** **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);** **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);** **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);** **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_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);** **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** **ncvisual_from_file** returns an **ncvisual** object on success, or **NULL**
on failure. Success indicates that the specified **file** was opened, and 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 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. that the entire file is properly-formed.
**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** **ncvisual_decode** returns 0 on success, or 1 on end of file, or -1 on
in the event of an error. It is only necessary for multimedia-based visuals. 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 **ncvisual_from_plane** returns **NULL** if the **ncvisual** cannot be created
and bound. This is usually due to illegal content in the source **ncplane**. and bound. This is usually due to illegal content in the source **ncplane**.

View File

@ -138,7 +138,7 @@ namespace ncpp
return error_guard (ncdirect_cursor_disable (direct), -1); 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); return ncdirect_render_image (direct, file, align, blitter, scale);
} }

View File

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

View File

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

View File

@ -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

View File

@ -14,7 +14,6 @@
#include <limits.h> #include <limits.h>
#include <stdbool.h> #include <stdbool.h>
#include <notcurses/nckeys.h> #include <notcurses/nckeys.h>
#include <notcurses/ncerrs.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { 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 // Open a visual at 'file', extract a codec and parameters, decode the first
// image to memory. // 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 // 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. // 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. // can be neither decoded nor rendered any further.
API void ncvisual_destroy(struct ncvisual* ncv); API void ncvisual_destroy(struct ncvisual* ncv);
// extract the next frame from an ncvisual. returns NCERR_EOF on end of file, // extract the next frame from an ncvisual. returns 1 on end of file, 0 on
// and NCERR_SUCCESS on success, otherwise some other NCERR. // success, and -1 on failure.
API nc_err_e ncvisual_decode(struct ncvisual* nc); API int ncvisual_decode(struct ncvisual* nc);
// Rotate the visual 'rads' radians. Only M_PI/2 and -M_PI/2 are // Rotate the visual 'rads' radians. Only M_PI/2 and -M_PI/2 are
// supported at the moment, but this will change FIXME. // 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 // Resize the visual so that it is 'rows' X 'columns'. This is a lossy
// transformation, unless the size is unchanged. // 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'. // 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); 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 // 300FPS, and a 'timescale' of 10 will result in 3FPS. It is an error to
// supply 'timescale' less than or equal to 0. // supply 'timescale' less than or equal to 0.
API int ncvisual_stream(struct notcurses* nc, struct ncvisual* ncv, 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); const struct ncvisual_options* vopts, void* curry);
// Blit a flat array 'data' of RGBA 32-bit values to the ncplane 'vopts->n', // Blit a flat array 'data' of RGBA 32-bit values to the ncplane 'vopts->n',

View File

@ -184,13 +184,6 @@ typedef struct palette256 {
palette256* palette256_new(struct notcurses* nc); palette256* palette256_new(struct notcurses* nc);
int palette256_use(struct notcurses* nc, const palette256* p); int palette256_use(struct notcurses* nc, const palette256* p);
void palette256_free(palette256* p); void palette256_free(palette256* p);
typedef enum {
NCERR_SUCCESS,
NCERR_NOMEM,
NCERR_EOF,
NCERR_DECODE,
NCERR_UNIMPLEMENTED,
} nc_err_e;
typedef enum { typedef enum {
NCSCALE_NONE, NCSCALE_NONE,
NCSCALE_SCALE, NCSCALE_SCALE,
@ -198,13 +191,13 @@ typedef enum {
} ncscale_e; } ncscale_e;
int notcurses_lex_scalemode(const char* op, ncscale_e* scalemode); int notcurses_lex_scalemode(const char* op, ncscale_e* scalemode);
const char* notcurses_str_scalemode(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_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_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); 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); 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); 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_rotate(struct ncvisual* n, double rads);
int ncvisual_resize(struct ncvisual* n, int rows, int cols); int ncvisual_resize(struct ncvisual* n, int rows, int cols);
int ncvisual_polyfill_yx(struct ncvisual* n, int y, int x, uint32_t rgba); 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_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); 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*); 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 ncvisual_options {
struct ncplane* n; struct ncplane* n;
ncscale_e scaling; 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); 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_canopen_images(const struct ncdirect* n);
bool ncdirect_canutf8(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); struct ncplane* ncplane_parent(struct ncplane* n);
const struct ncplane* ncplane_parent_const(const struct ncplane* n); const struct ncplane* ncplane_parent_const(const struct ncplane* n);
""") """)

View File

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

View File

@ -26,13 +26,12 @@ const char eagle1[] =
static struct ncplane* static struct ncplane*
zoom_map(struct notcurses* nc, const char* map, int* ret){ zoom_map(struct notcurses* nc, const char* map, int* ret){
*ret = -1; *ret = -1;
nc_err_e ncerr;
// determine size that will be represented on screen at once, and how // 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 // 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 // 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 // less and less. eventually, reach our natural NCSCALE_NONE size and begin
// scrolling through the map, whooooooooosh. // scrolling through the map, whooooooooosh.
struct ncvisual* ncv = ncvisual_from_file(map, &ncerr); struct ncvisual* ncv = ncvisual_from_file(map);
if(ncv == NULL){ if(ncv == NULL){
return NULL; return NULL;
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -79,8 +79,7 @@ int xray_demo(struct notcurses* nc){
return -1; return -1;
} }
char* path = find_data("notcursesI.avi"); char* path = find_data("notcursesI.avi");
nc_err_e err; struct ncvisual* ncv = ncvisual_from_file(path);
struct ncvisual* ncv = ncvisual_from_file(path, &err);
free(path); free(path);
if(ncv == NULL){ if(ncv == NULL){
return -1; return -1;
@ -96,7 +95,7 @@ int xray_demo(struct notcurses* nc){
.scaling = NCSCALE_STRETCH, .scaling = NCSCALE_STRETCH,
.blitter = NCBLIT_2x1, .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); ncvisual_destroy(ncv);
ncplane_destroy(n); ncplane_destroy(n);
ncplane_destroy(newpanel); ncplane_destroy(newpanel);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 // Resize the provided ncviusal to the specified 'rows' x 'cols', but do not
// change the internals of the ncvisual. Uses oframe. // change the internals of the ncvisual. Uses oframe.
nc_err_e ncvisual_blit(struct ncvisual* ncv, int rows, int cols, int ncvisual_blit(struct ncvisual* ncv, int rows, int cols,
ncplane* n, const struct blitset* bset, ncplane* n, const struct blitset* bset,
int placey, int placex, int begy, int begx, int placey, int placex, int begy, int begx,
int leny, int lenx, bool blendcolors); int leny, int lenx, bool blendcolors);
void nclog(const char* fmt, ...); void nclog(const char* fmt, ...);

View File

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

View File

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

View File

@ -10,14 +10,13 @@
#ifdef USE_OIIO #ifdef USE_OIIO
#include "oiio.h" #include "oiio.h"
#else #else
#include "notcurses/ncerrs.h"
typedef struct ncvisual_details { typedef struct ncvisual_details {
} 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; (void)deets;
return NCERR_SUCCESS; return 0;
} }
static inline auto static inline auto

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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