Esempio n. 1
0
MpvWidget::MpvWidget(QWidget *parent, Qt::WindowFlags f)
    : QOpenGLWidget(parent, f)
{
    mpv = mpv::qt::Handle::FromRawHandle(mpv_create());
    if (!mpv)
        throw std::runtime_error("could not create mpv context");

    mpv_set_option_string(mpv, "terminal", "yes");
    mpv_set_option_string(mpv, "msg-level", "all=v");
    if (mpv_initialize(mpv) < 0)
        throw std::runtime_error("could not initialize mpv context");

    // Make use of the MPV_SUB_API_OPENGL_CB API.
    mpv::qt::set_option_variant(mpv, "vo", "opengl-cb");

    // Request hw decoding, just for testing.
    mpv::qt::set_option_variant(mpv, "hwdec", "auto");

    mpv_gl = (mpv_opengl_cb_context *)mpv_get_sub_api(mpv, MPV_SUB_API_OPENGL_CB);
    if (!mpv_gl)
        throw std::runtime_error("OpenGL not compiled in");
    mpv_opengl_cb_set_update_callback(mpv_gl, MpvWidget::on_update, (void *)this);
    connect(this, SIGNAL(frameSwapped()), SLOT(swapped()));

    mpv_observe_property(mpv, 0, "duration", MPV_FORMAT_DOUBLE);
    mpv_observe_property(mpv, 0, "time-pos", MPV_FORMAT_DOUBLE);
    mpv_set_wakeup_callback(mpv, wakeup, this);
}
Esempio n. 2
0
MpvHandler::MpvHandler(int64_t wid, QObject *parent):
    QObject(parent),
    baka(static_cast<BakaEngine*>(parent))
{
    // create mpv
    mpv = mpv_create();
    if(!mpv)
        throw "Could not create mpv object";

    // set mpv options
    mpv_set_option(mpv, "wid", MPV_FORMAT_INT64, &wid);
    mpv_set_option_string(mpv, "input-cursor", "no");   // no mouse handling
    mpv_set_option_string(mpv, "cursor-autohide", "no");// no cursor-autohide, we handle that
    mpv_set_option_string(mpv, "ytdl", "yes"); // youtube-dl support

    // get updates when these properties change
    mpv_observe_property(mpv, 0, "playback-time", MPV_FORMAT_DOUBLE);
    mpv_observe_property(mpv, 0, "volume", MPV_FORMAT_DOUBLE);
    mpv_observe_property(mpv, 0, "sid", MPV_FORMAT_INT64);
    mpv_observe_property(mpv, 0, "aid", MPV_FORMAT_INT64);
    mpv_observe_property(mpv, 0, "sub-visibility", MPV_FORMAT_FLAG);
    mpv_observe_property(mpv, 0, "mute", MPV_FORMAT_FLAG);
    mpv_observe_property(mpv, 0, "core-idle", MPV_FORMAT_FLAG);
    mpv_observe_property(mpv, 0, "paused-for-cache", MPV_FORMAT_FLAG);

    // setup callback event handling
    mpv_set_wakeup_callback(mpv, wakeup, this);
}
Esempio n. 3
0
DanmakuDelayGetter::DanmakuDelayGetter(QStringList &names, QStringList &urls,
                                       const QString &danmakuUrl, bool download, QObject *parent) :
    QObject(parent), names(names), urls(urls), danmakuUrl(danmakuUrl), download(download)
{
    mpv = mpv_create();
    if (!mpv)
    {
        qDebug("Fails to create mpv instance.");
        deleteLater();
        return;
    }
    mpv_set_option(mpv, "no-video", MPV_FORMAT_NONE, NULL);
    mpv_set_option(mpv, "pause", MPV_FORMAT_NONE, NULL);
    mpv_set_option_string(mpv, "ao", "null");
    mpv_set_option_string(mpv, "user-agent", generateUA(urls.first()));
    QString host = QUrl(urls.first()).host();
    if (referer_table.contains(host))
        mpv_set_option_string(mpv, "referrer", referer_table[host].constData());
    mpv_observe_property(mpv, 0, "duration", MPV_FORMAT_DOUBLE);
    mpv_set_wakeup_callback(mpv, postEvent, this);
    if (mpv_initialize(mpv) < 0)
    {
        qDebug("Fails to initialaze mpv instance.");
        deleteLater();
        return;
    }
    delay = 0;
    start();
}
static void
gt_player_backend_mpv_opengl_init(GtPlayerBackendMpvOpenGL* self)
{
    GtPlayerBackendMpvOpenGLPrivate* priv = gt_player_backend_mpv_opengl_get_instance_private(self);

    MESSAGE("Init");

    setlocale(LC_NUMERIC, "C");

    priv->widget = gtk_gl_area_new();
    priv->mpv = mpv_create();

    g_object_set(priv->widget, "expand", TRUE, NULL);

    gtk_widget_add_events(priv->widget, GDK_BUTTON_PRESS_MASK);

    check_mpv_error(mpv_set_option_string(priv->mpv, "audio-client-name", "GNOME Twitch"));
    check_mpv_error(mpv_set_option_string(priv->mpv, "title", ""));
    check_mpv_error(mpv_set_option_string(priv->mpv, "vo", "opengl-cb"));
    check_mpv_error(mpv_set_option_string(priv->mpv, "softvol", "yes"));
    check_mpv_error(mpv_set_option_string(priv->mpv, "softvol-max", "100"));
    check_mpv_error(mpv_observe_property(priv->mpv, 0, "volume", MPV_FORMAT_DOUBLE));
    check_mpv_error(mpv_observe_property(priv->mpv, 0, "cache-buffering-state", MPV_FORMAT_INT64));

    check_mpv_error(mpv_initialize(priv->mpv));

    mpv_set_wakeup_callback(priv->mpv, mpv_wakeup_cb, self);

    priv->mpv_opengl = mpv_get_sub_api(priv->mpv, MPV_SUB_API_OPENGL_CB);

    mpv_opengl_cb_set_update_callback(priv->mpv_opengl, (mpv_opengl_cb_update_fn) opengl_cb, self);

    g_signal_connect(priv->widget, "destroy", G_CALLBACK(widget_destroy_cb), self);
    g_signal_connect(priv->widget, "realize", G_CALLBACK(realise_oneshot_cb), self);
    g_signal_connect(priv->widget, "render", G_CALLBACK(render_cb), self);
}
Esempio n. 5
0
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent)
{
    QMenu *menu = menuBar()->addMenu(tr("&File"));
    QAction *on_open = new QAction(tr("&Open"), this);
    on_open->setShortcuts(QKeySequence::Open);
    on_open->setStatusTip(tr("Open a file"));
    connect(on_open, SIGNAL(triggered()), this, SLOT(on_file_open()));
    menu->addAction(on_open);

    statusBar();

    mpv = mpv_create();
    if (!mpv)
        throw "can't create mpv instance";

    // Create a video child window. Force Qt to create a native window, and
    // pass the window ID to the mpv wid option. This doesn't work on OSX,
    // because Cocoa doesn't support this form of embedding.
    mpv_container = new QWidget(this);
    setCentralWidget(mpv_container);
    mpv_container->setAttribute(Qt::WA_NativeWindow);
    // If you have a HWND, use: int64_t wid = (intptr_t)hwnd;
    int64_t wid = mpv_container->winId();
    mpv_set_option(mpv, "wid", MPV_FORMAT_INT64, &wid);

    // Enable default bindings, because we're lazy. Normally, a player using
    // mpv as backend would implement its own key bindings.
    mpv_set_option_string(mpv, "input-default-bindings", "yes");

    // Let us receive property change events with MPV_EVENT_PROPERTY_CHANGE if
    // this property changes.
    mpv_observe_property(mpv, 0, "time-pos", MPV_FORMAT_DOUBLE);

    // From this point on, the wakeup function will be called. The callback
    // can come from any thread, so we use the Qt QEvent mechanism to relay
    // the wakeup in a thread-safe way.
    mpv_set_wakeup_callback(mpv, wakeup, this);

    if (mpv_initialize(mpv) < 0)
        throw "mpv failed to initialize";
}
Esempio n. 6
0
KNMusicBackendMpvThread::KNMusicBackendMpvThread(QObject *parent) :
    KNMusicStandardBackendThread(parent),
    m_volumeCurve(QEasingCurve(QEasingCurve::OutQuad)),
    m_filePath(QString()),
    m_totalDuration(-1),
    m_duration(-1),
    m_startPosition(-1),
    m_endPosition(-1),
    m_mpvHandle(nullptr),
    m_state(MusicUtil::Stopped),
    m_volumeSize(100)
{
    //Initial the locale settings.
    setlocale(LC_NUMERIC, "C");
    //Create the mpv handle.
    m_mpvHandle=mpv_create();
    //Check out the mpv handle.
    if(!m_mpvHandle)
    {
        //Cannot create an instance for mpv.
        return;
    }
    //Set mpv options.
    // No mouse handling.
    mpv_set_option_string(m_mpvHandle, "input-cursor", "no");
    // No cursor-autohide.
    mpv_set_option_string(m_mpvHandle, "cursor-autohide", "no");
    mpv_set_option_string(m_mpvHandle, "no-video", NULL);

    // get updates when these properties change
    mpv_observe_property(m_mpvHandle, 0, "time-pos", MPV_FORMAT_DOUBLE);

    // setup callback event handling
    mpv_set_wakeup_callback(m_mpvHandle,
                            KNMusicBackendMpvThread::instanceWakeUp,
                            this);
    //Initialize the mpv handler.
    mpv_initialize(m_mpvHandle);
}
Esempio n. 7
0
static void setup_gtk_stuff(mpv_gtk_helper_context *helper)
{
    // Out of severe lazyness, you don't free ctx. This is left as exercise
    // to the reader.
    struct plugin_context *ctx = calloc(1, sizeof(*ctx));
    ctx->helper = helper;

    // Make mpv notify us if there are new events.
    mpv_set_wakeup_callback(ctx->helper->mpv, wakeup_mpv, ctx);

    mpv_observe_property(ctx->helper->mpv, 0, "percent-pos", MPV_FORMAT_INT64);

    GtkWidget *window;

    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    g_signal_connect (window, "delete-event",
                      G_CALLBACK (delete_event), ctx);
    gtk_container_set_border_width (GTK_CONTAINER (window), 10);
    ctx->pbar = gtk_progress_bar_new ();
    gtk_container_add (GTK_CONTAINER (window), ctx->pbar);
    gtk_widget_show (ctx->pbar);
    gtk_widget_show (window);
}
bool PlayerComponent::componentInitialize()
{
  m_mpv = mpv::qt::Handle::FromRawHandle(mpv_create());
  if (!m_mpv)
    throw FatalException(tr("Failed to load mpv."));

  mpv_request_log_messages(m_mpv, "terminal-default");
  mpv_set_option_string(m_mpv, "msg-level", "all=v");

  // No mouse events
  mpv_set_option_string(m_mpv, "input-cursor", "no");
  mpv_set_option_string(m_mpv, "cursor-autohide", "no");

  mpv_set_option_string(m_mpv, "config", "yes");
  mpv_set_option_string(m_mpv, "config-dir", Paths::dataDir().toUtf8().data());

  // We don't need this, so avoid initializing fontconfig.
  mpv_set_option_string(m_mpv, "use-text-osd", "no");

  // This forces the player not to rebase playback time to 0 with mkv. We
  // require this, because mkv transcoding lets files start at times other
  // than 0, and web-client expects that we return these times unchanged.
  mpv::qt::set_option_variant(m_mpv, "demuxer-mkv-probe-start-time", false);

  // Always use the system mixer.
  mpv_set_option_string(m_mpv, "softvol", "no");

  // Just discard audio output if no audio device could be opened. This gives
  // us better flexibility how to react to such errors (instead of just
  // aborting playback immediately).
  mpv_set_option_string(m_mpv, "audio-fallback-to-null", "yes");

  // Do not let the decoder downmix (better customization for us).
  mpv::qt::set_option_variant(m_mpv, "ad-lavc-downmix", false);

  // Make it load the hwdec interop, so hwdec can be enabled at runtime.
  mpv::qt::set_option_variant(m_mpv, "hwdec-preload", "auto");

  // User-visible application name used by some audio APIs (at least PulseAudio).
  mpv_set_option_string(m_mpv, "audio-client-name", QCoreApplication::applicationName().toUtf8().data());
  // User-visible stream title used by some audio APIs (at least PulseAudio and wasapi).
  mpv_set_option_string(m_mpv, "title", QCoreApplication::applicationName().toUtf8().data());

  // Apply some low-memory settings on RPI, which is relatively memory-constrained.
#ifdef TARGET_RPI
  // The backbuffer makes seeking back faster (without having to do a HTTP-level seek)
  mpv::qt::set_option_variant(m_mpv, "cache-backbuffer", 10 * 1024); // KB
  // The demuxer queue is used for the readahead, and also for dealing with badly
  // interlaved audio/video. Setting it too low increases sensitivity to network
  // issues, and could cause playback failure with "bad" files.
  mpv::qt::set_option_variant(m_mpv, "demuxer-max-bytes", 50 * 1024 * 1024); // bytes
#endif

  mpv_observe_property(m_mpv, 0, "pause", MPV_FORMAT_FLAG);
  mpv_observe_property(m_mpv, 0, "cache-buffering-state", MPV_FORMAT_INT64);
  mpv_observe_property(m_mpv, 0, "playback-time", MPV_FORMAT_DOUBLE);
  mpv_observe_property(m_mpv, 0, "vo-configured", MPV_FORMAT_FLAG);
  mpv_observe_property(m_mpv, 0, "duration", MPV_FORMAT_DOUBLE);
  mpv_observe_property(m_mpv, 0, "audio-device-list", MPV_FORMAT_NODE);

  connect(this, &PlayerComponent::onMpvEvents, this, &PlayerComponent::handleMpvEvents, Qt::QueuedConnection);

  mpv_set_wakeup_callback(m_mpv, wakeup_cb, this);

  if (mpv_initialize(m_mpv) < 0)
    throw FatalException(tr("Failed to initialize mpv."));

  // Setup a hook with the ID 1, which is run during the file is loaded.
  // Used to delay playback start for display framerate switching.
  // (See handler in handleMpvEvent() for details.)
  mpv::qt::command_variant(m_mpv, QStringList() << "hook-add" << "on_load" << "1" << "0");

  updateAudioDeviceList();
  setAudioConfiguration();
  updateSubtitleSettings();
  updateVideoSettings();

  connect(SettingsComponent::Get().getSection(SETTINGS_SECTION_VIDEO), &SettingsSection::valuesUpdated,
          this, &PlayerComponent::updateVideoSettings);

  connect(SettingsComponent::Get().getSection(SETTINGS_SECTION_SUBTITLES), &SettingsSection::valuesUpdated,
          this, &PlayerComponent::updateSubtitleSettings);

  connect(SettingsComponent::Get().getSection(SETTINGS_SECTION_AUDIO), &SettingsSection::valuesUpdated,
          this, &PlayerComponent::setAudioConfiguration);

  return true;
}
Esempio n. 9
0
void gmpv_mpv_obj_initialize(GmpvMpvObj *mpv)
{
	GSettings *main_settings = g_settings_new(CONFIG_ROOT);
	gchar *config_dir = get_config_dir_path();
	gchar *mpvopt = NULL;
	gchar *current_vo = NULL;
	gchar *mpv_version = NULL;

	const struct
	{
		const gchar *name;
		const gchar *value;
	}
	options[] = {	{"osd-level", "1"},
			{"softvol", "yes"},
			{"force-window", "yes"},
			{"input-default-bindings", "yes"},
			{"audio-client-name", ICON_NAME},
			{"title", "${media-title}"},
			{"autofit-larger", "75%"},
			{"window-scale", "1"},
			{"pause", "no"},
			{"ytdl", "yes"},
			{"osd-bar", "no"},
			{"input-cursor", "no"},
			{"cursor-autohide", "no"},
			{"softvol-max", "100"},
			{"config", "yes"},
			{"screenshot-template", "gnome-mpv-shot%n"},
			{"config-dir", config_dir},
			{NULL, NULL} };

	g_assert(mpv->mpv_ctx);

	for(gint i = 0; options[i].name; i++)
	{
		g_debug(	"Applying default option --%s=%s",
				options[i].name,
				options[i].value );

		mpv_set_option_string(	mpv->mpv_ctx,
					options[i].name,
					options[i].value );
	}

	if(g_settings_get_boolean(main_settings, "mpv-config-enable"))
	{
		gchar *mpv_conf
			= g_settings_get_string
				(main_settings, "mpv-config-file");

		g_info("Loading config file: %s", mpv_conf);
		mpv_load_config_file(mpv->mpv_ctx, mpv_conf);

		g_free(mpv_conf);
	}

	if(g_settings_get_boolean(main_settings, "mpv-input-config-enable"))
	{
		gchar *input_conf
			= g_settings_get_string
				(main_settings, "mpv-input-config-file");

		g_info("Loading input config file: %s", input_conf);
		load_input_conf(mpv, input_conf);

		g_free(input_conf);
	}
	else
	{
		load_input_conf(mpv, NULL);
	}

	mpvopt = g_settings_get_string(main_settings, "mpv-options");

	g_debug("Applying extra mpv options: %s", mpvopt);

	/* Apply extra options */
	if(mpv_obj_apply_args(mpv->mpv_ctx, mpvopt) < 0)
	{
		const gchar *msg
			= _("Failed to apply one or more MPV options.");

		g_signal_emit_by_name(mpv, "mpv-error", msg);
	}

	if(mpv->force_opengl)
	{
		g_info("Forcing --vo=opengl-cb");
		mpv_set_option_string(mpv->mpv_ctx, "vo", "opengl-cb");

	}
	else
	{
		g_debug(	"Attaching mpv window to wid %#x",
				(guint)mpv->wid );

		mpv_set_option(mpv->mpv_ctx, "wid", MPV_FORMAT_INT64, &mpv->wid);
	}

	mpv_observe_property(mpv->mpv_ctx, 0, "aid", MPV_FORMAT_INT64);
	mpv_observe_property(mpv->mpv_ctx, 0, "chapters", MPV_FORMAT_INT64);
	mpv_observe_property(mpv->mpv_ctx, 0, "core-idle", MPV_FORMAT_FLAG);
	mpv_observe_property(mpv->mpv_ctx, 0, "fullscreen", MPV_FORMAT_FLAG);
	mpv_observe_property(mpv->mpv_ctx, 0, "pause", MPV_FORMAT_FLAG);
	mpv_observe_property(mpv->mpv_ctx, 0, "length", MPV_FORMAT_DOUBLE);
	mpv_observe_property(mpv->mpv_ctx, 0, "media-title", MPV_FORMAT_STRING);
	mpv_observe_property(mpv->mpv_ctx, 0, "playlist-pos", MPV_FORMAT_INT64);
	mpv_observe_property(mpv->mpv_ctx, 0, "track-list", MPV_FORMAT_NODE);
	mpv_observe_property(mpv->mpv_ctx, 0, "volume", MPV_FORMAT_DOUBLE);
	mpv_set_wakeup_callback(mpv->mpv_ctx, wakeup_callback, mpv);
	mpv_check_error(mpv_initialize(mpv->mpv_ctx));


	mpv_version = gmpv_mpv_obj_get_property_string(mpv, "mpv-version");
	current_vo = gmpv_mpv_obj_get_property_string(mpv, "current-vo");

	g_info("Using %s", mpv_version);

	if(current_vo && !GDK_IS_X11_DISPLAY(gdk_display_get_default()))
	{
		g_info(	"The chosen vo is %s but the display is not X11; "
			"forcing --vo=opengl-cb and resetting",
			current_vo );

		mpv->force_opengl = TRUE;
		mpv->state.paused = FALSE;

		gmpv_mpv_obj_reset(mpv);
	}
	else
	{
		GSettings *win_settings;
		gdouble volume;

		win_settings = g_settings_new(CONFIG_WIN_STATE);
		volume = g_settings_get_double(win_settings, "volume")*100;

		g_debug("Setting volume to %f", volume);
		mpv_set_property(	mpv->mpv_ctx,
					"volume",
					MPV_FORMAT_DOUBLE,
					&volume );

		/* The vo should be opengl-cb if current_vo is NULL*/
		if(!current_vo)
		{
			mpv->opengl_ctx =	mpv_get_sub_api
						(	mpv->mpv_ctx,
							MPV_SUB_API_OPENGL_CB );
		}

		gmpv_mpv_opt_handle_msg_level(mpv);
		gmpv_mpv_opt_handle_fs(mpv);
		gmpv_mpv_opt_handle_geometry(mpv);

		mpv->force_opengl = FALSE;
		mpv->state.ready = TRUE;
		g_signal_emit_by_name(mpv, "mpv-init");

		g_clear_object(&win_settings);
	}

	g_clear_object(&main_settings);
	g_free(config_dir);
	g_free(mpvopt);
	mpv_free(current_vo);
	mpv_free(mpv_version);
}
Esempio n. 10
0
void MpvAudioOutput::observe_property(const std::string &name, mpv_format format) {
    auto r = mpv_observe_property(handle_, 0, name.c_str(), format);
    if (r < 0)
        qDebug() << "Failed mpv_observe_property " << name.c_str() << ": " << mpv_error_string(r);
}