Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d276f753f7 | ||
|
|
c06000eef8 | ||
|
|
1bc1cd2305 | ||
|
|
a735a2abd7 | ||
|
|
112c1abe31 | ||
|
|
362b35b631 | ||
|
|
49cf0af294 | ||
|
|
1b26874710 | ||
|
|
8fe636da7a | ||
|
|
812f149585 | ||
|
|
635424c8f0 | ||
|
|
2319918721 | ||
|
|
9fabf85a44 | ||
|
|
54fd5d0979 | ||
|
|
d141d281ca | ||
|
|
ebc3d74b04 | ||
|
|
a63fab8921 | ||
|
|
4ee8d8d3f9 | ||
|
|
574a2484c1 | ||
|
|
f5b92bee5e | ||
|
|
ca3d7144db | ||
|
|
86e7c3defb | ||
|
|
0fe1385d80 | ||
|
|
f4e9371d0f | ||
|
|
909185d49e | ||
|
|
c18c324c6f |
No files matched your search
@@ -1142,6 +1142,9 @@ OPTIONS
|
||||
Allow hardware decoding for a given list of codecs only. The special value
|
||||
``all`` always allows all codecs.
|
||||
|
||||
You can get the list of allowed codecs with ``mpv --vd=help``. Remove the
|
||||
prefix, e.g. instead of ``lavc:h264`` use ``h264``.
|
||||
|
||||
By default this is set to ``h264,vc1,wmv3``.
|
||||
|
||||
This is usually only needed with broken GPUs, where a codec is reported
|
||||
@@ -2366,7 +2369,7 @@ OPTIONS
|
||||
Some ``--sws`` options are tunable. The description of the ``scale``
|
||||
video filter has further information.
|
||||
|
||||
``--term-osd, --no-term-osd``
|
||||
``--term-osd, --no-term-osd``, ``--term-osd=force``
|
||||
Display OSD messages on the console when no video output is available.
|
||||
Enabled by default.
|
||||
|
||||
@@ -2375,6 +2378,8 @@ OPTIONS
|
||||
console. The escape sequence should move the pointer to the beginning of
|
||||
the line used for the OSD and clear it (default: ``^[[A\r^[[K``).
|
||||
|
||||
``force`` enables terminal OSD even if a video window is created.
|
||||
|
||||
``--title=<string>``
|
||||
Set the window title. Properties are expanded on playback start.
|
||||
(See `Property Expansion`_.)
|
||||
|
||||
@@ -458,6 +458,12 @@ static void handle_stream(demuxer_t *demuxer, int i)
|
||||
memcpy(sh_sub->extradata, codec->extradata, codec->extradata_size);
|
||||
sh_sub->extradata_len = codec->extradata_size;
|
||||
}
|
||||
|
||||
// Hack for MicroDVD: if time_base matches the ffmpeg microdvd reader's
|
||||
// default FPS (23.976), assume the MicroDVD file did not declare a
|
||||
// FPS, and the MicroDVD file uses frame based timing.
|
||||
if (codec->time_base.num == 125 && codec->time_base.den == 2997)
|
||||
sh_sub->frame_based = true;
|
||||
break;
|
||||
}
|
||||
case AVMEDIA_TYPE_ATTACHMENT: {
|
||||
|
||||
+18
-9
@@ -723,7 +723,7 @@ static int demux_mkv_read_cues(demuxer_t *demuxer)
|
||||
stream_t *s = demuxer->stream;
|
||||
|
||||
if (opts->index_mode == 0 || opts->index_mode == 2) {
|
||||
ebml_read_skip(s, NULL);
|
||||
ebml_read_skip(demuxer->log, -1, s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1128,7 +1128,7 @@ static int read_header_element(struct demuxer *demuxer, uint32_t id,
|
||||
res = 2;
|
||||
}
|
||||
if (!at_filepos && id != EBML_ID_INVALID)
|
||||
ebml_read_skip(s, NULL);
|
||||
ebml_read_skip(demuxer->log, -1, s);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -2270,7 +2270,7 @@ static void index_block(demuxer_t *demuxer, struct block_info *block)
|
||||
}
|
||||
}
|
||||
|
||||
static int read_block(demuxer_t *demuxer, struct block_info *block)
|
||||
static int read_block(demuxer_t *demuxer, int64_t end, struct block_info *block)
|
||||
{
|
||||
mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;
|
||||
stream_t *s = demuxer->stream;
|
||||
@@ -2281,7 +2281,7 @@ static int read_block(demuxer_t *demuxer, struct block_info *block)
|
||||
|
||||
free_block(block);
|
||||
length = ebml_read_length(s, NULL);
|
||||
if (length > 500000000)
|
||||
if (length > 500000000 || stream_tell(s) + length > (uint64_t)end)
|
||||
goto exit;
|
||||
block->alloc = malloc(length + AV_LZO_INPUT_PADDING);
|
||||
if (!block->alloc)
|
||||
@@ -2442,7 +2442,7 @@ static int read_block_group(demuxer_t *demuxer, int64_t end,
|
||||
break;
|
||||
|
||||
case MATROSKA_ID_BLOCK:
|
||||
if (read_block(demuxer, block) < 0)
|
||||
if (read_block(demuxer, end, block) < 0)
|
||||
goto error;
|
||||
break;
|
||||
|
||||
@@ -2454,11 +2454,12 @@ static int read_block_group(demuxer_t *demuxer, int64_t end,
|
||||
block->keyframe = false;
|
||||
break;
|
||||
|
||||
case MATROSKA_ID_CLUSTER:
|
||||
case EBML_ID_INVALID:
|
||||
goto error;
|
||||
|
||||
default:
|
||||
if (ebml_read_skip_or_resync_cluster(demuxer->log, s, NULL) != 0)
|
||||
if (ebml_read_skip(demuxer->log, end, s) != 0)
|
||||
goto error;
|
||||
break;
|
||||
}
|
||||
@@ -2491,6 +2492,8 @@ static int read_next_block(demuxer_t *demuxer, struct block_info *block)
|
||||
case MATROSKA_ID_BLOCKGROUP: {
|
||||
int64_t end = ebml_read_length(s, NULL);
|
||||
end += stream_tell(s);
|
||||
if (end > mkv_d->cluster_end)
|
||||
goto find_next_cluster;
|
||||
int res = read_block_group(demuxer, end, block);
|
||||
if (res < 0)
|
||||
goto find_next_cluster;
|
||||
@@ -2501,7 +2504,7 @@ static int read_next_block(demuxer_t *demuxer, struct block_info *block)
|
||||
|
||||
case MATROSKA_ID_SIMPLEBLOCK: {
|
||||
*block = (struct block_info){ .simple = true };
|
||||
int res = read_block(demuxer, block);
|
||||
int res = read_block(demuxer, mkv_d->cluster_end, block);
|
||||
if (res < 0)
|
||||
goto find_next_cluster;
|
||||
if (res > 0)
|
||||
@@ -2517,7 +2520,7 @@ static int read_next_block(demuxer_t *demuxer, struct block_info *block)
|
||||
goto find_next_cluster;
|
||||
|
||||
default: ;
|
||||
if (ebml_read_skip_or_resync_cluster(demuxer->log, s, NULL) != 0)
|
||||
if (ebml_read_skip(demuxer->log, mkv_d->cluster_end, s) != 0)
|
||||
goto find_next_cluster;
|
||||
break;
|
||||
}
|
||||
@@ -2532,7 +2535,13 @@ static int read_next_block(demuxer_t *demuxer, struct block_info *block)
|
||||
break;
|
||||
if (s->eof)
|
||||
return -1;
|
||||
ebml_read_skip_or_resync_cluster(demuxer->log, s, NULL);
|
||||
// For the sake of robustness, consider even unknown level 1
|
||||
// elements the same as unknown/broken IDs.
|
||||
if (!ebml_is_mkv_level1_id(id) ||
|
||||
ebml_read_skip(demuxer->log, -1, s) != 0)
|
||||
{
|
||||
ebml_resync_cluster(demuxer->log, s);
|
||||
}
|
||||
}
|
||||
next_cluster:
|
||||
mkv_d->cluster_end = ebml_read_length(s, NULL);
|
||||
|
||||
+36
-36
@@ -41,6 +41,26 @@
|
||||
#define SIZE_MAX ((size_t)-1)
|
||||
#endif
|
||||
|
||||
// Whether the id is a known Matroska level 1 element (allowed as element on
|
||||
// global file level, after the level 0 MATROSKA_ID_SEGMENT).
|
||||
// This (intentionally) doesn't include "global" elements.
|
||||
bool ebml_is_mkv_level1_id(uint32_t id)
|
||||
{
|
||||
switch (id) {
|
||||
case MATROSKA_ID_SEEKHEAD:
|
||||
case MATROSKA_ID_INFO:
|
||||
case MATROSKA_ID_CLUSTER:
|
||||
case MATROSKA_ID_TRACKS:
|
||||
case MATROSKA_ID_CUES:
|
||||
case MATROSKA_ID_ATTACHMENTS:
|
||||
case MATROSKA_ID_CHAPTERS:
|
||||
case MATROSKA_ID_TAGS:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read: the element content data ID.
|
||||
* Return: the ID.
|
||||
@@ -252,21 +272,32 @@ char *ebml_read_utf8(stream_t *s, uint64_t *length)
|
||||
|
||||
/*
|
||||
* Skip the current element.
|
||||
* end: the end of the parent element or -1 (for robust error handling)
|
||||
*/
|
||||
int ebml_read_skip(stream_t *s, uint64_t *length)
|
||||
int ebml_read_skip(struct mp_log *log, int64_t end, stream_t *s)
|
||||
{
|
||||
uint64_t len;
|
||||
int l;
|
||||
|
||||
int64_t pos = stream_tell(s);
|
||||
|
||||
len = ebml_read_length(s, &l);
|
||||
if (len == EBML_UINT_INVALID)
|
||||
return 1;
|
||||
if (length)
|
||||
*length = len + l;
|
||||
goto invalid;
|
||||
|
||||
stream_skip(s, len);
|
||||
int64_t pos2 = stream_tell(s);
|
||||
if (len >= INT64_MAX - pos2 || (end > 0 && pos2 + len > end))
|
||||
goto invalid;
|
||||
|
||||
if (!stream_skip(s, len))
|
||||
goto invalid;
|
||||
|
||||
return 0;
|
||||
|
||||
invalid:
|
||||
mp_err(log, "Invalid EBML length at position %"PRId64"\n", pos);
|
||||
stream_seek(s, pos);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -291,37 +322,6 @@ int ebml_resync_cluster(struct mp_log *log, stream_t *s)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip the current element, or on error, call ebml_resync_cluster().
|
||||
*/
|
||||
int ebml_read_skip_or_resync_cluster(struct mp_log *log, stream_t *s,
|
||||
uint64_t *length)
|
||||
{
|
||||
uint64_t len;
|
||||
int l;
|
||||
|
||||
len = ebml_read_length(s, &l);
|
||||
if (len == EBML_UINT_INVALID)
|
||||
goto resync;
|
||||
|
||||
if (length)
|
||||
*length = len + l;
|
||||
|
||||
int64_t pos = stream_tell(s);
|
||||
|
||||
// When reading corrupted elements, len will often be a random high number,
|
||||
// and stream_skip() will fail when skipping past EOF.
|
||||
if (!stream_skip(s, len)) {
|
||||
stream_seek(s, pos);
|
||||
goto resync;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
resync:
|
||||
return ebml_resync_cluster(log, s) < 0 ? -1 : 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the next element, but only the header. The contents
|
||||
* are supposed to be sub-elements which can be read separately.
|
||||
|
||||
+2
-3
@@ -92,6 +92,7 @@ struct ebml_parse_ctx {
|
||||
#define EBML_FLOAT_INVALID -1000000000.0
|
||||
|
||||
|
||||
bool ebml_is_mkv_level1_id(uint32_t id);
|
||||
uint32_t ebml_read_id (stream_t *s, int *length);
|
||||
uint64_t ebml_read_vlen_uint (bstr *buffer);
|
||||
int64_t ebml_read_vlen_int (bstr *buffer);
|
||||
@@ -101,9 +102,7 @@ int64_t ebml_read_int (stream_t *s, uint64_t *length);
|
||||
double ebml_read_float (stream_t *s, uint64_t *length);
|
||||
char *ebml_read_ascii (stream_t *s, uint64_t *length);
|
||||
char *ebml_read_utf8 (stream_t *s, uint64_t *length);
|
||||
int ebml_read_skip (stream_t *s, uint64_t *length);
|
||||
int ebml_read_skip_or_resync_cluster(struct mp_log *log, stream_t *s,
|
||||
uint64_t *length);
|
||||
int ebml_read_skip(struct mp_log *log, int64_t end, stream_t *s);
|
||||
int ebml_resync_cluster(struct mp_log *log, stream_t *s);
|
||||
uint32_t ebml_read_master (stream_t *s, uint64_t *length);
|
||||
|
||||
|
||||
@@ -47,6 +47,8 @@
|
||||
#include "input/keycodes.h"
|
||||
#include "terminal.h"
|
||||
|
||||
static int use_terminal;
|
||||
|
||||
#if HAVE_TERMIOS
|
||||
static volatile struct termios tio_orig;
|
||||
static volatile int tio_orig_set;
|
||||
@@ -454,7 +456,7 @@ static volatile int getch2_enabled = 0;
|
||||
|
||||
static void do_activate_getch2(void)
|
||||
{
|
||||
if (getch2_active)
|
||||
if (getch2_active || !use_terminal)
|
||||
return;
|
||||
|
||||
#if HAVE_TERMINFO || HAVE_TERMCAP
|
||||
@@ -612,6 +614,8 @@ void terminal_setup_stdin_cmd_input(struct input_ctx *ictx)
|
||||
|
||||
int terminal_init(void)
|
||||
{
|
||||
load_termcap(NULL);
|
||||
use_terminal = isatty(1);
|
||||
if (use_terminal)
|
||||
load_termcap(NULL);
|
||||
return 0;
|
||||
}
|
||||
+7
-2
@@ -443,13 +443,16 @@ static struct track *add_stream_track(struct MPContext *mpctx,
|
||||
track->preloaded = !!stream->sub->track;
|
||||
|
||||
// Needed for DVD and Blu-ray.
|
||||
if (!track->lang) {
|
||||
struct stream *st = track->demuxer->stream;
|
||||
if (!track->lang && (st->uncached_type == STREAMTYPE_BLURAY ||
|
||||
st->uncached_type == STREAMTYPE_DVD))
|
||||
{
|
||||
struct stream_lang_req req = {
|
||||
.type = track->type,
|
||||
.id = map_id_from_demuxer(track->demuxer, track->type,
|
||||
track->demuxer_id)
|
||||
};
|
||||
stream_control(track->demuxer->stream, STREAM_CTRL_GET_LANG, &req);
|
||||
stream_control(st, STREAM_CTRL_GET_LANG, &req);
|
||||
if (req.name[0])
|
||||
track->lang = talloc_strdup(track, req.name);
|
||||
}
|
||||
@@ -472,6 +475,8 @@ static void add_dvd_tracks(struct MPContext *mpctx)
|
||||
struct demuxer *demuxer = mpctx->demuxer;
|
||||
struct stream *stream = demuxer->stream;
|
||||
struct stream_dvd_info_req info;
|
||||
if (stream->uncached_type != STREAMTYPE_DVD)
|
||||
return;
|
||||
if (stream_control(stream, STREAM_CTRL_GET_DVD_INFO, &info) > 0) {
|
||||
for (int n = 0; n < info.num_subs; n++) {
|
||||
struct track *track = talloc_ptrtype(NULL, track);
|
||||
|
||||
+6
-3
@@ -435,9 +435,12 @@ static void add_seek_osd_messages(struct MPContext *mpctx)
|
||||
set_osd_bar_chapters(mpctx, OSD_BAR_SEEK);
|
||||
}
|
||||
if (mpctx->add_osd_seek_info & OSD_SEEK_INFO_TEXT) {
|
||||
mp_osd_msg_t *msg = add_osd_msg(mpctx, OSD_MSG_TEXT, 1,
|
||||
mpctx->opts->osd_duration);
|
||||
msg->show_position = true;
|
||||
// Never in term-osd mode
|
||||
if (mpctx->video_out && mpctx->opts->term_osd != 1) {
|
||||
mp_osd_msg_t *msg = add_osd_msg(mpctx, OSD_MSG_TEXT, 1,
|
||||
mpctx->opts->osd_duration);
|
||||
msg->show_position = true;
|
||||
}
|
||||
}
|
||||
if (mpctx->add_osd_seek_info & OSD_SEEK_INFO_CHAPTER_TEXT) {
|
||||
char *chapter = chapter_display_name(mpctx, get_current_chapter(mpctx));
|
||||
|
||||
+3
-3
@@ -71,8 +71,8 @@ static const char av_desync_help_text[] =
|
||||
" This is due to vsync limiting the framerate.\n"
|
||||
"- Playing from a slow network source.\n"
|
||||
" Download the file instead.\n"
|
||||
"- Try to find out whether audio or video is causing this by experimenting\n"
|
||||
" with --no-video and --no-audio.\n"
|
||||
"- Try to find out whether audio/video/subs are causing this by experimenting\n"
|
||||
" with --no-video, --no-audio, or --no-sub.\n"
|
||||
"- If you swiched audio or video tracks, try seeking to force synchronization.\n"
|
||||
"If none of this helps you, file a bug report.\n\n";
|
||||
|
||||
@@ -924,7 +924,7 @@ static double get_wakeup_period(struct MPContext *mpctx)
|
||||
*/
|
||||
double sleeptime = WAKEUP_PERIOD;
|
||||
|
||||
#ifndef HAVE_POSIX_SELECT
|
||||
#if !HAVE_POSIX_SELECT
|
||||
// No proper file descriptor event handling; keep waking up to poll input
|
||||
sleeptime = MPMIN(sleeptime, 0.02);
|
||||
#endif
|
||||
|
||||
@@ -35,6 +35,7 @@ enum streamtype {
|
||||
STREAMTYPE_RADIO,
|
||||
STREAMTYPE_DVB,
|
||||
STREAMTYPE_DVD,
|
||||
STREAMTYPE_BLURAY,
|
||||
STREAMTYPE_PVR,
|
||||
STREAMTYPE_TV,
|
||||
STREAMTYPE_MF,
|
||||
|
||||
@@ -390,6 +390,7 @@ err_no_info:
|
||||
b->current_angle = angle;
|
||||
b->current_title = title;
|
||||
|
||||
s->type = STREAMTYPE_BLURAY;
|
||||
s->end_pos = title_size;
|
||||
s->sector_size = BLURAY_SECTOR_SIZE;
|
||||
s->flags = MP_STREAM_SEEK;
|
||||
|
||||
+1
-1
@@ -420,7 +420,7 @@ bool sub_read_all_packets(struct dec_sub *sub, struct sh_stream *sh)
|
||||
|
||||
// 23.976 FPS is used as default timebase for frame based formats
|
||||
if (sub->video_fps && sh->sub->frame_based)
|
||||
sub_speed *= sub->video_fps / 23.976;
|
||||
sub_speed *= 23.976 / sub->video_fps;
|
||||
|
||||
if (opts->sub_fps && sub->video_fps)
|
||||
sub_speed *= opts->sub_fps / sub->video_fps;
|
||||
|
||||
@@ -221,8 +221,6 @@ static void vo_cocoa_update_screen_info(struct vo *vo)
|
||||
aspect_save_screenres(vo, r.size.width, r.size.height);
|
||||
opts->screenwidth = r.size.width;
|
||||
opts->screenheight = r.size.height;
|
||||
vo->xinerama_x = r.origin.x;
|
||||
vo->xinerama_y = r.origin.y;
|
||||
}
|
||||
|
||||
static void resize_window(struct vo *vo)
|
||||
@@ -262,7 +260,7 @@ static void create_window(struct vo *vo, uint32_t d_width, uint32_t d_height,
|
||||
struct vo_cocoa_state *s = vo->cocoa;
|
||||
struct mp_vo_opts *opts = vo->opts;
|
||||
|
||||
const NSRect contentRect = NSMakeRect(0, 0, d_width, d_height);
|
||||
const NSRect contentRect = NSMakeRect(vo->dx, vo->dy, d_width, d_height);
|
||||
|
||||
int window_mask = 0;
|
||||
if (opts->border) {
|
||||
@@ -276,7 +274,8 @@ static void create_window(struct vo *vo, uint32_t d_width, uint32_t d_height,
|
||||
[[MpvVideoWindow alloc] initWithContentRect:contentRect
|
||||
styleMask:window_mask
|
||||
backing:NSBackingStoreBuffered
|
||||
defer:NO];
|
||||
defer:NO
|
||||
screen:s->current_screen];
|
||||
s->view = [[[MpvVideoView alloc] initWithFrame:contentRect] autorelease];
|
||||
|
||||
[s->view setWantsBestResolutionOpenGLSurface:YES];
|
||||
@@ -299,7 +298,6 @@ static void create_window(struct vo *vo, uint32_t d_width, uint32_t d_height,
|
||||
[s->window setDelegate:s->window];
|
||||
[s->window makeMainWindow];
|
||||
|
||||
[s->window setFrameOrigin:NSMakePoint(vo->dx, vo->dy)];
|
||||
[s->window makeKeyAndOrderFront:nil];
|
||||
[NSApp activateIgnoringOtherApps:YES];
|
||||
|
||||
|
||||
@@ -188,11 +188,12 @@ static void releaseGlContext_wayland(MPGLContext *ctx)
|
||||
struct vo_wayland_state *wl = ctx->vo->wayland;
|
||||
|
||||
gl->Finish();
|
||||
eglReleaseThread();
|
||||
wl_egl_window_destroy(wl->egl_context.egl_window);
|
||||
eglDestroySurface(wl->egl_context.egl.dpy, wl->egl_context.egl_surface);
|
||||
eglMakeCurrent(wl->egl_context.egl.dpy, NULL, NULL, EGL_NO_CONTEXT);
|
||||
eglDestroyContext(wl->egl_context.egl.dpy, wl->egl_context.egl.ctx);
|
||||
eglTerminate(wl->egl_context.egl.dpy);
|
||||
eglReleaseThread();
|
||||
wl_egl_window_destroy(wl->egl_context.egl_window);
|
||||
wl->egl_context.egl.ctx = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -539,7 +539,7 @@ static void draw_image(struct vo *vo, mp_image_t *mpi)
|
||||
struct buffer *buf = buffer_get_back(p);
|
||||
|
||||
if (!buf) {
|
||||
MP_WARN(p->wl, "can't draw, back buffer is busy\n");
|
||||
MP_VERBOSE(p->wl, "can't draw, back buffer is busy\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -570,7 +570,7 @@ static void flip_page(struct vo *vo)
|
||||
buffer_swap(p);
|
||||
|
||||
if (!p->redraw_callback) {
|
||||
MP_INFO(p->wl, "restart frame callback\n");
|
||||
MP_DBG(p->wl, "restart frame callback\n");
|
||||
frame_handle_redraw(p, NULL, 0);
|
||||
}
|
||||
}
|
||||
@@ -639,6 +639,9 @@ static int reconfig(struct vo *vo, struct mp_image_params *fmt, int flags)
|
||||
|
||||
vo_wayland_config(vo, vo->dwidth, vo->dheight, flags);
|
||||
|
||||
if (p->wl->window.events & VO_EVENT_RESIZE)
|
||||
resize(p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -648,6 +651,9 @@ static void uninit(struct vo *vo)
|
||||
for (int i = 0; i < MAX_BUFFERS; ++i)
|
||||
destroy_shm_buffer(&p->buffers[i]);
|
||||
|
||||
if (p->redraw_callback)
|
||||
wl_callback_destroy(p->redraw_callback);
|
||||
|
||||
talloc_free(p->original_image);
|
||||
|
||||
vo_wayland_uninit(vo);
|
||||
@@ -657,10 +663,8 @@ static int preinit(struct vo *vo)
|
||||
{
|
||||
struct priv *p = vo->priv;
|
||||
|
||||
if (!vo_wayland_init(vo)) {
|
||||
MP_ERR(p->wl, "could not initalise backend\n");
|
||||
if (!vo_wayland_init(vo))
|
||||
return -1;
|
||||
}
|
||||
|
||||
p->vo = vo;
|
||||
p->wl = vo->wayland;
|
||||
|
||||
+67
-26
@@ -144,7 +144,7 @@ static void display_handle_delete_id(void *data,
|
||||
MP_DBG(wl, "Object %u deleted\n", id);
|
||||
}
|
||||
|
||||
const struct wl_display_listener display_listener = {
|
||||
static const struct wl_display_listener display_listener = {
|
||||
display_handle_error,
|
||||
display_handle_delete_id
|
||||
};
|
||||
@@ -171,7 +171,7 @@ static void ssurface_handle_popup_done(void *data,
|
||||
{
|
||||
}
|
||||
|
||||
const struct wl_shell_surface_listener shell_surface_listener = {
|
||||
static const struct wl_shell_surface_listener shell_surface_listener = {
|
||||
ssurface_handle_ping,
|
||||
ssurface_handle_configure,
|
||||
ssurface_handle_popup_done
|
||||
@@ -220,7 +220,7 @@ static void output_handle_mode(void *data,
|
||||
output->flags = flags;
|
||||
}
|
||||
|
||||
const struct wl_output_listener output_listener = {
|
||||
static const struct wl_output_listener output_listener = {
|
||||
output_handle_geometry,
|
||||
output_handle_mode
|
||||
};
|
||||
@@ -329,7 +329,7 @@ static void keyboard_handle_modifiers(void *data,
|
||||
0, 0, group);
|
||||
}
|
||||
|
||||
const struct wl_keyboard_listener keyboard_listener = {
|
||||
static const struct wl_keyboard_listener keyboard_listener = {
|
||||
keyboard_handle_keymap,
|
||||
keyboard_handle_enter,
|
||||
keyboard_handle_leave,
|
||||
@@ -443,7 +443,6 @@ static void seat_handle_capabilities(void *data,
|
||||
|
||||
if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !wl->input.keyboard) {
|
||||
wl->input.keyboard = wl_seat_get_keyboard(seat);
|
||||
wl_keyboard_set_user_data(wl->input.keyboard, wl);
|
||||
wl_keyboard_add_listener(wl->input.keyboard, &keyboard_listener, wl);
|
||||
}
|
||||
else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && wl->input.keyboard) {
|
||||
@@ -452,7 +451,6 @@ static void seat_handle_capabilities(void *data,
|
||||
}
|
||||
if ((caps & WL_SEAT_CAPABILITY_POINTER) && !wl->input.pointer) {
|
||||
wl->input.pointer = wl_seat_get_pointer(seat);
|
||||
wl_pointer_set_user_data(wl->input.pointer, wl);
|
||||
wl_pointer_add_listener(wl->input.pointer, &pointer_listener, wl);
|
||||
}
|
||||
else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && wl->input.pointer) {
|
||||
@@ -466,13 +464,12 @@ static const struct wl_seat_listener seat_listener = {
|
||||
};
|
||||
|
||||
static void registry_handle_global (void *data,
|
||||
struct wl_registry *registry,
|
||||
struct wl_registry *reg,
|
||||
uint32_t id,
|
||||
const char *interface,
|
||||
uint32_t version)
|
||||
{
|
||||
struct vo_wayland_state *wl = data;
|
||||
struct wl_registry *reg = wl->display.registry;
|
||||
|
||||
if (strcmp(interface, "wl_compositor") == 0) {
|
||||
|
||||
@@ -578,6 +575,8 @@ static void shedule_resize(struct vo_wayland_state *wl,
|
||||
int32_t x, y;
|
||||
float temp_aspect = width / (float) MPMAX(height, 1);
|
||||
|
||||
MP_DBG(wl, "shedule resize: %dx%d\n", width, height);
|
||||
|
||||
if (width < minimum_size)
|
||||
width = minimum_size;
|
||||
|
||||
@@ -632,6 +631,9 @@ static void shedule_resize(struct vo_wayland_state *wl,
|
||||
|
||||
static bool create_display (struct vo_wayland_state *wl)
|
||||
{
|
||||
if (wl->vo->probing && !getenv("XDG_RUNTIME_DIR"))
|
||||
return false;
|
||||
|
||||
wl->display.display = wl_display_connect(NULL);
|
||||
|
||||
if (!wl->display.display) {
|
||||
@@ -644,7 +646,6 @@ static bool create_display (struct vo_wayland_state *wl)
|
||||
|
||||
wl_display_add_listener(wl->display.display, &display_listener, wl);
|
||||
|
||||
wl_list_init(&wl->display.output_list);
|
||||
wl->display.registry = wl_display_get_registry(wl->display.display);
|
||||
wl_registry_add_listener(wl->display.registry, ®istry_listener, wl);
|
||||
|
||||
@@ -657,15 +658,33 @@ static bool create_display (struct vo_wayland_state *wl)
|
||||
|
||||
static void destroy_display (struct vo_wayland_state *wl)
|
||||
{
|
||||
struct vo_wayland_output *output = NULL;
|
||||
struct vo_wayland_output *tmp = NULL;
|
||||
|
||||
wl_list_for_each_safe(output, tmp, &wl->display.output_list, link) {
|
||||
if (output && output->output) {
|
||||
wl_output_destroy(output->output);
|
||||
output->output = NULL;
|
||||
wl_list_remove(&output->link);
|
||||
}
|
||||
}
|
||||
|
||||
if (wl->display.shm)
|
||||
wl_shm_destroy(wl->display.shm);
|
||||
|
||||
if (wl->display.shell)
|
||||
wl_shell_destroy(wl->display.shell);
|
||||
|
||||
if (wl->display.compositor)
|
||||
wl_compositor_destroy(wl->display.compositor);
|
||||
|
||||
wl_registry_destroy(wl->display.registry);
|
||||
wl_display_flush(wl->display.display);
|
||||
wl_display_disconnect(wl->display.display);
|
||||
if (wl->display.registry)
|
||||
wl_registry_destroy(wl->display.registry);
|
||||
|
||||
if (wl->display.display) {
|
||||
wl_display_flush(wl->display.display);
|
||||
wl_display_disconnect(wl->display.display);
|
||||
}
|
||||
}
|
||||
|
||||
static bool create_window (struct vo_wayland_state *wl)
|
||||
@@ -690,8 +709,11 @@ static bool create_window (struct vo_wayland_state *wl)
|
||||
|
||||
static void destroy_window (struct vo_wayland_state *wl)
|
||||
{
|
||||
wl_shell_surface_destroy(wl->window.shell_surface);
|
||||
wl_surface_destroy(wl->window.surface);
|
||||
if (wl->window.shell_surface)
|
||||
wl_shell_surface_destroy(wl->window.shell_surface);
|
||||
|
||||
if (wl->window.surface)
|
||||
wl_surface_destroy(wl->window.surface);
|
||||
}
|
||||
|
||||
static bool create_cursor (struct vo_wayland_state *wl)
|
||||
@@ -740,9 +762,11 @@ static void destroy_input (struct vo_wayland_state *wl)
|
||||
wl_keyboard_destroy(wl->input.keyboard);
|
||||
xkb_map_unref(wl->input.xkb.keymap);
|
||||
xkb_state_unref(wl->input.xkb.state);
|
||||
xkb_context_unref(wl->input.xkb.context);
|
||||
}
|
||||
|
||||
if (wl->input.xkb.context)
|
||||
xkb_context_unref(wl->input.xkb.context);
|
||||
|
||||
if (wl->input.pointer)
|
||||
wl_pointer_destroy(wl->input.pointer);
|
||||
|
||||
@@ -760,11 +784,14 @@ int vo_wayland_init (struct vo *vo)
|
||||
wl->vo = vo;
|
||||
wl->log = mp_log_new(wl, vo->log, "wayland");
|
||||
|
||||
wl_list_init(&wl->display.output_list);
|
||||
|
||||
if (!create_input(wl)
|
||||
|| !create_display(wl)
|
||||
|| !create_window(wl)
|
||||
|| !create_cursor(wl))
|
||||
{
|
||||
vo_wayland_uninit(vo);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -786,13 +813,11 @@ void vo_wayland_uninit (struct vo *vo)
|
||||
|
||||
static void vo_wayland_ontop (struct vo *vo)
|
||||
{
|
||||
MP_DBG(vo->wayland, "going ontop\n");
|
||||
vo->opts->ontop = 0;
|
||||
vo->opts->fullscreen = 1;
|
||||
|
||||
/* use the already existing code to leave fullscreen mode and go into
|
||||
* toplevel mode */
|
||||
vo_wayland_fullscreen(vo);
|
||||
struct vo_wayland_state *wl = vo->wayland;
|
||||
MP_DBG(wl, "going ontop\n");
|
||||
vo->opts->ontop = 1;
|
||||
wl_shell_surface_set_toplevel(wl->window.shell_surface);
|
||||
shedule_resize(wl, 0, wl->window.width, wl->window.height);
|
||||
}
|
||||
|
||||
static void vo_wayland_border (struct vo *vo)
|
||||
@@ -918,6 +943,9 @@ static void vo_wayland_update_screeninfo (struct vo *vo)
|
||||
}
|
||||
}
|
||||
|
||||
wl->window.fs_width = opts->screenwidth;
|
||||
wl->window.fs_height = opts->screenheight;
|
||||
|
||||
aspect_save_screenres(vo, opts->screenwidth, opts->screenheight);
|
||||
}
|
||||
|
||||
@@ -979,13 +1007,26 @@ bool vo_wayland_config (struct vo *vo, uint32_t d_width,
|
||||
{
|
||||
struct vo_wayland_state *wl = vo->wayland;
|
||||
|
||||
wl->window.width = d_width;
|
||||
wl->window.height = d_height;
|
||||
wl->window.p_width = d_width;
|
||||
wl->window.p_height = d_height;
|
||||
wl->window.aspect = wl->window.width / (float) MPMAX(wl->window.height, 1);
|
||||
wl->window.aspect = d_width / (float) MPMAX(d_height, 1);
|
||||
|
||||
vo_wayland_fullscreen(vo);
|
||||
if (!(flags & VOFLAG_HIDDEN)) {
|
||||
if (!wl->window.is_init) {
|
||||
wl->window.width = d_width;
|
||||
wl->window.height = d_height;
|
||||
}
|
||||
|
||||
if (vo->opts->fullscreen) {
|
||||
if (wl->window.is_fullscreen)
|
||||
shedule_resize(wl, 0, wl->window.fs_width, wl->window.fs_height);
|
||||
else
|
||||
vo_wayland_fullscreen(vo);
|
||||
}
|
||||
else
|
||||
vo_wayland_ontop(vo);
|
||||
wl->window.is_init = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -80,7 +80,7 @@ struct vo_wayland_state {
|
||||
} display;
|
||||
|
||||
struct {
|
||||
int32_t width;
|
||||
int32_t width; // current size of the window
|
||||
int32_t height;
|
||||
int32_t p_width; // previous sizes for leaving fullscreen
|
||||
int32_t p_height;
|
||||
@@ -90,7 +90,10 @@ struct vo_wayland_state {
|
||||
int32_t sh_y;
|
||||
float aspect;
|
||||
|
||||
bool is_init; // true if the window has a valid size
|
||||
bool is_fullscreen; // don't keep aspect ratio in fullscreen mode
|
||||
int32_t fs_width; // fullscreen sizes
|
||||
int32_t fs_height;
|
||||
|
||||
struct wl_surface *surface;
|
||||
int32_t mouse_x; // mouse position inside the surface
|
||||
|
||||
@@ -52,10 +52,12 @@ def check_lua(ctx, dependency_identifier):
|
||||
lua_versions = [
|
||||
( '51', 'lua >= 5.1.0 lua < 5.2.0'),
|
||||
( '51deb', 'lua5.1 >= 5.1.0'), # debian
|
||||
( '51fbsd', 'lua-5.1 >= 5.1.0'), # FreeBSD
|
||||
( 'luajit', 'luajit >= 2.0.0' ),
|
||||
# assume all our dependencies (libquvi in particular) link with 5.1
|
||||
( '52', 'lua >= 5.2.0' ),
|
||||
( '52deb', 'lua5.2 >= 5.2.0'), # debian
|
||||
( '52fbsd', 'lua-5.2 >= 5.2.0'), # FreeBSD
|
||||
]
|
||||
|
||||
if ctx.options.LUA_VER:
|
||||
|
||||
@@ -766,7 +766,7 @@ def options(opt):
|
||||
group.add_option('--lua',
|
||||
type = 'string',
|
||||
dest = 'LUA_VER',
|
||||
help = "select Lua package which should be autodetected. Choices: 51 51deb 52 52deb luajit")
|
||||
help = "select Lua package which should be autodetected. Choices: 51 51deb 51fbsd 52 52deb 52fbsd luajit")
|
||||
|
||||
@conf
|
||||
def is_debug_build(ctx):
|
||||
|
||||
Reference in new issue
Block a user