Beispiel #1
0
struct mp_resolve_result *mp_resolve_quvi(const char *url, struct MPOpts *opts)
{
    quvi_t q = quvi_new();
    if (quvi_ok(q) == QUVI_FALSE)
        return NULL;

    // Don't try to use quvi on an URL that's not directly supported, since
    // quvi will do a network access anyway in order to check for HTTP
    // redirections etc.
    // The documentation says this will fail on "shortened" URLs.
    if (quvi_supports(q, (char *) url, QUVI_SUPPORTS_MODE_OFFLINE, 
                                       QUVI_SUPPORTS_TYPE_ANY) == QUVI_FALSE) {
        quvi_free(q);
        return NULL;
    }

    mp_msg(MSGT_OPEN, MSGL_INFO, "[quvi] Checking URL...\n");

    // Can use quvi_query_formats() to get a list of formats like this:
    // "fmt05_240p|fmt18_360p|fmt34_360p|fmt35_480p|fmt43_360p|fmt44_480p"
    // (This example is youtube specific.)
    // That call requires an extra net access. quvi_next_media_url() doesn't
    // seem to do anything useful. So we can't really do anything useful
    // except pass through the user's format setting.
    quvi_media_t m = quvi_media_new(q, (char *) url);
    if (quvi_ok(q) == QUVI_FALSE) {
        mp_msg(MSGT_OPEN, MSGL_ERR, "[quvi] %s\n", quvi_errmsg(q));
        quvi_free(q);
        return NULL;
    }
    quvi_media_stream_select(m, opts->quvi_format);
    if (quvi_ok(q) == QUVI_FALSE) {
        mp_msg(MSGT_OPEN, MSGL_ERR, "[quvi] %s\n", quvi_errmsg(q));
        quvi_free(q);
        return NULL;
    }

    struct mp_resolve_result *result =
        talloc_zero(NULL, struct mp_resolve_result);

    char *val;
    
    quvi_media_get(m, QUVI_MEDIA_STREAM_PROPERTY_URL, &val);
    if (quvi_ok(q) == QUVI_TRUE)
        result->url = talloc_strdup(result, val);

    quvi_media_get(m, QUVI_MEDIA_PROPERTY_TITLE, &val);
    if (quvi_ok(q) == QUVI_TRUE)
        result->title = talloc_strdup(result, val);

    quvi_media_free(m);
    quvi_free(q);

    if (!result->url) {
        talloc_free(result);
        result = NULL;
    }

    return result;
}
Beispiel #2
0
/* Choose subtitle language from the available languages. */
gint lutil_choose_subtitle(const quvi_t q, const quvi_subtitle_t qsub,
                           const gchar *lang, const lutil_cb_printerr xperr,
                           quvi_subtitle_lang_t *l,
                           const gboolean fail_if_none)
{
  g_assert(xperr != NULL);
  g_assert(lang != NULL);
  g_assert(qsub != NULL);
  g_assert(q != NULL);

  *l = quvi_subtitle_select(qsub, lang);
  if (quvi_ok(q) == QUVI_FALSE)
    {
      xperr(_("libquvi: while selecting subtitle: %s"), quvi_errmsg(q));
      return (EXIT_FAILURE);
    }
  else
    {
      if (*l == NULL && fail_if_none == TRUE)
        {
          xperr(_("libquvi: failed to find any subtitles"));
          return (EXIT_FAILURE);
        }
      return (EXIT_SUCCESS);
    }
}
Beispiel #3
0
static gint _copy_subtitle(const gchar *mfpath, const gchar *url,
                           lutil_cb_printerr xperr)
{
  quvi_subtitle_lang_t ql;
  quvi_subtitle_t qsub;
  gint r;

  if (opts.core.subtitle_language == NULL)
    return (EXIT_SUCCESS);

  qsub = quvi_subtitle_new(q, url);
  if (quvi_ok(q) == FALSE)
    {
      xperr(_("libquvi: while querying subtitles: %s"), quvi_errmsg(q));
      return (EXIT_FAILURE);
    }

  _dump_languages(qsub);

  r = lutil_choose_subtitle(q, qsub, opts.core.subtitle_language,
                            xperr, &ql, FALSE);
  if (r == EXIT_SUCCESS)
    {
      if (ql != NULL)
        {
          quvi_subtitle_export_t qse;

          qse = quvi_subtitle_export_new(ql, opts.core.subtitle_export_format);
          if (quvi_ok(q) == TRUE)
            r = _write_subtitle(ql, qse, mfpath, xperr);
          else
            xperr(_("libquvi: while exporting subtitle: %s"), quvi_errmsg(q));

          quvi_subtitle_export_free(qse);
        }
      else
        g_print(_("skip <transfer>: subtitle extraction\n"));
    }
  quvi_subtitle_free(qsub);

  return (r);
}
Beispiel #4
0
/* Choose a stream from the available streams. */
gint lutil_choose_stream(const quvi_t q, const quvi_media_t qm,
                         const gchar *stream, const lutil_cb_printerr xperr)
{
  g_assert(stream != NULL);
  g_assert(xperr != NULL);
  g_assert(qm != NULL);
  g_assert(q != NULL);

  quvi_media_stream_select(qm, stream);
  if (quvi_ok(q) == QUVI_FALSE)
    {
      xperr(_("libquvi: while selecting stream: %s"), quvi_errmsg(q));
      return (EXIT_FAILURE);
    }
  return (EXIT_SUCCESS);
}
/* Resolve URL redirections with exception rules. */
gchar *l_exec_util_resolve_redirections(_quvi_t q, const gchar *url)
{
  lua_State *l;
  gchar *r;

  q->status.rc = l_load_util_script(q, script_fname, script_func);

  if (quvi_ok(q) == QUVI_FALSE)
    return (NULL);

  l = q->handle.lua;
  l_setfield_s(l, US_INPUT_URL, url, -1); /* Set as qargs.input_url */

  /*
   * 1=qargs [qargs: set in l_load_util_script]
   * 1=returns a string
   */
  if (lua_pcall(l, 1, 1, 0))
    {
      g_string_assign(q->status.errmsg, lua_tostring(l, -1));

      /* Keep error code if it was set by a callback: quvi.resolve
       * calling the network callback responsible for resolving URL
       * redirections. The error is most likely a network error. */
      if (q->status.rc != QUVI_ERROR_CALLBACK)
        q->status.rc = QUVI_ERROR_SCRIPT;

      return (NULL);
    }

  r = NULL;

  if (lua_isstring(l, -1))
    {
      const gchar *s = lua_tostring(l, -1);
      if (g_strcmp0(s, url) != 0) /* Ignore, unless it is different. */
        r = g_strdup(s);
    }
  else
    luaL_error(l, "%s: did not return a string", script_func);

  lua_pop(l, 1);

  /* quvi.resolve which is called from the script sets q->status.rc . */
  return (r);
}