Example #1
0
static int
no_lib(media_pipe_t *mp, const char *codec)
{
  notify_add(mp->mp_prop_notifications, NOTIFY_WARNING, NULL, 10,
	     _("Unable to accelerate %s, library not loaded."), codec);
  return 1;
}
Example #2
0
static void *
audio_output_thread(void *aux)
{
  audio_mode_t *am;
  int r;
  audio_fifo_t *af = &af0;

  thefifo = af;

  am = audio_mode_current;

  while(audio_run) {
    r = am->am_entry(am, af);
    am = audio_mode_current;

    if(r == -1) {
      /* Device error, sleep to avoid busy looping.
	 Hopefully the error will resolve itself (if another app
	 is blocking output, etc)
      */
      sleep(1);
    } else {
      if(am)
	notify_add(NULL, NOTIFY_INFO, NULL, 5, 
		   _("Switching audio output to %s"), 
		   am->am_title);
    }
  }
  return NULL;
}
Example #3
0
static JSBool 
js_notify(JSContext *cx, JSObject *obj,
		uintN argc, jsval *argv, jsval *rval)
{
  const char *text;
  int delay;
  const char *icon = NULL;

  if(!JS_ConvertArguments(cx, argc, argv, "si/s", &text, &delay, &icon))
    return JS_FALSE;

  notify_add(NULL, NOTIFY_INFO, icon, delay, rstr_alloc("%s"), text);

  return JS_TRUE;
}
Example #4
0
static void
keyring_clear(void *opaque, prop_event_t event, ...)
{
  hts_mutex_lock(&keyring_mutex);
  htsmsg_release(persistent_keyring);
  htsmsg_release(temporary_keyring);

  persistent_keyring = htsmsg_create_map();
  temporary_keyring = htsmsg_create_map();

  htsmsg_store_save(persistent_keyring, "keyring");
  hts_mutex_unlock(&keyring_mutex);

  notify_add(NULL, NOTIFY_WARNING, NULL, 3, _("Rembered passwords erased"));
}
Example #5
0
static void 
dvdprobe(callout_t *co, void *aux)
{
  disc_scanner_t *ds = aux;

  callout_arm(&ds->ds_timer, dvdprobe, ds, 1);

  if(ds->ds_disc_inserted == 0) {

    DI_Mount();

    if(DI_GetStatus() == DVD_NO_DISC)
      return;

    TRACE(TRACE_INFO, "DVD", "DVD inserted");
    ds->ds_disc_inserted = 1;
    ds->ds_disc_ready = 0;

  } else {
    uint32_t s = DI_GetStatus();


    if(s == DVD_UNKNOWN) {
      ds->ds_disc_inserted = 0;
      notify_add(NOTIFY_ERROR, NULL, 5, "Unknown disc inserted, ejecting...");
      DI_Eject();
      return;
    }

    if(!(s & DVD_READY)) {
      TRACE(TRACE_DEBUG, "DVD", "Waiting for disc ready state = %x", s);
      return;
    }

    if(!ds->ds_disc_ready)
      check_disc_type(ds);

    if(DI_GetCoverRegister(&s) || !(s & DVD_COVER_DISC_INSERTED)) {
      ds->ds_disc_inserted = 0;
      TRACE(TRACE_INFO, "DVD", "DVD no longer present");
      
      if(ds->ds_service != NULL) {
	service_destroy(ds->ds_service);
	ds->ds_service = NULL;
      }
    }
  }
}
Example #6
0
static void *
video_player_idle(void *aux)
{
  video_playback_t *vp = aux;
  int run = 1;
  event_t *e = NULL, *next;
  media_pipe_t *mp = vp->vp_mp;
  char errbuf[256];
  prop_t *errprop = prop_ref_inc(prop_create(mp->mp_prop_root, "error"));

  while(run) {

    if(e == NULL)
      e = mp_dequeue_event(mp);
    

    if(event_is_type(e, EVENT_PLAY_URL)) {
      prop_set_void(errprop);
      event_playurl_t *ep = (event_playurl_t *)e;
      int flags = 0;
      if(ep->primary)
	flags |= BACKEND_VIDEO_PRIMARY;
      if(ep->no_audio)
	flags |= BACKEND_VIDEO_NO_AUDIO;

      next = backend_play_video(ep->url, mp, flags, ep->priority,
				errbuf, sizeof(errbuf));

      if(next == NULL) {
	notify_add(NOTIFY_ERROR, NULL, 5, "URL: %s\nError: %s", 
		   ep->url, errbuf);
	prop_set_string(errprop, errbuf);
      }
      event_release(e);
      e = next;
      continue;

    } else if(event_is_type(e, EVENT_EXIT)) {
      event_release(e);
      break;
    }
    event_release(e);
    e = NULL;
  }
  prop_ref_dec(errprop);
  return NULL;
}
Example #7
0
static int ln_add(lua_State *L) {
	struct luanotify *N = luaL_checkudata(L, 1, CQS_NOTIFY);
	const char *name = luaL_checkstring(L, 2);
	int flags = luaL_optinteger(L, 3, NOTIFY_ALL);
	int error;

	if ((error = notify_add(N->notify, name, flags))) {
		lua_pushboolean(L, 0);
		lua_pushinteger(L, error);

		return 2;
	} else {
		lua_pushboolean(L, 1);

		return 1;
	}
} /* ln_add() */
/**
 * e_data_cal_view_notify_objects_added:
 * @query: A query object.
 * @objects: List of objects that have been added.
 *
 * Notifies all query listeners of the addition of a list of objects.
 */
void
e_data_cal_view_notify_objects_added (EDataCalView *view, const GList *objects)
{
	EDataCalViewPrivate *priv;
	const GList *l;

	g_return_if_fail (view && E_IS_DATA_CAL_VIEW (view));
	priv = view->priv;

	if (objects == NULL)
		return;

	g_mutex_lock (priv->pending_mutex);

	for (l = objects; l; l = l->next) {
		notify_add (view, e_util_utf8_make_valid (l->data));
	}

	g_mutex_unlock (priv->pending_mutex);
}
Example #9
0
static void
handle_method_call(GDBusConnection *connection, const gchar *sender,
		   const gchar *object_path, const gchar *interface_name,
		   const gchar *method_name, GVariant *param,
		   GDBusMethodInvocation *inv, gpointer user_data)
{
  TRACE(TRACE_DEBUG, "CONNMAN", "agent method call: %s", method_name);

  if(!strcmp(method_name, "ReportError")) {
    connman_service_t *cs = connman_service_from_params(param);

    const char *msg =
      g_variant_get_string(g_variant_get_child_value(param, 1), NULL);

    notify_add(NULL, NOTIFY_ERROR, NULL, 3,
	       rstr_alloc("%s\n%s"), cs ? cs->cs_name : "Unknown network", msg);
    g_dbus_method_invocation_return_value(inv, NULL);

  } else if(!strcmp(method_name, "RequestInput")) {
    connman_service_t *cs = connman_service_from_params(param);

    if(cs == NULL) {
      g_dbus_method_invocation_return_error_literal(inv,
						    G_DBUS_ERROR,
						    G_DBUS_ERROR_INVALID_ARGS,
						    "Unknown service");
      return;
    }

    agent_request_input(cs, g_variant_get_child_value(param, 1), inv);

  } else {
    g_dbus_method_invocation_return_error(inv,
					  G_DBUS_ERROR,
					  G_DBUS_ERROR_INVALID_ARGS,
					  "Unknown method %s",
					  method_name);
    return;
  }
}
/**
 * e_data_book_view_notify_update:
 * @book_view: an #EDataBookView
 * @contact: an #EContact
 *
 * Notify listeners that @contact has changed. This can
 * trigger an add, change or removal event depending on
 * whether the change causes the contact to start matching,
 * no longer match, or stay matching the query specified
 * by @book_view.
 **/
void
e_data_book_view_notify_update (EDataBookView *book_view,
                                EContact      *contact)
{
    EDataBookViewPrivate *priv = book_view->priv;
    gboolean currently_in_view, want_in_view;
    const gchar *id;
    gchar *vcard;

    if (!priv->running)
        return;

    g_mutex_lock (priv->pending_mutex);

    id = e_contact_get_const (contact, E_CONTACT_UID);

    currently_in_view = id_is_in_view (book_view, id);
    want_in_view =
        e_book_backend_sexp_match_contact (priv->card_sexp, contact);

    if (want_in_view) {
        vcard = e_vcard_to_string (E_VCARD (contact),
                                   EVC_FORMAT_VCARD_30);

        if (currently_in_view)
            notify_change (book_view, vcard);
        else
            notify_add (book_view, id, vcard);

        g_free (vcard);
    } else {
        if (currently_in_view)
            notify_remove (book_view, id);
        /* else nothing; we're removing a card that wasn't there */
    }

    g_mutex_unlock (priv->pending_mutex);
}
/**
 * e_data_book_view_notify_update_vcard:
 * @book_view: an #EDataBookView
 * @vcard: a plain vCard
 *
 * Notify listeners that @vcard has changed. This can
 * trigger an add, change or removal event depending on
 * whether the change causes the contact to start matching,
 * no longer match, or stay matching the query specified
 * by @book_view.  This method should be preferred over
 * #e_data_book_view_notify_update when the native
 * representation of a contact is a vCard.
 **/
void
e_data_book_view_notify_update_vcard (EDataBookView *book_view, gchar *vcard)
{
    EDataBookViewPrivate *priv = book_view->priv;
    gboolean currently_in_view, want_in_view;
    const gchar *id;
    EContact *contact;

    if (!priv->running) {
        g_free (vcard);
        return;
    }

    g_mutex_lock (priv->pending_mutex);

    contact = e_contact_new_from_vcard (vcard);
    id = e_contact_get_const (contact, E_CONTACT_UID);
    currently_in_view = id_is_in_view (book_view, id);
    want_in_view =
        e_book_backend_sexp_match_contact (priv->card_sexp, contact);

    if (want_in_view) {
        if (currently_in_view)
            notify_change (book_view, vcard);
        else
            notify_add (book_view, id, vcard);
    } else {
        if (currently_in_view)
            notify_remove (book_view, id);
    }

    /* Do this last so that id is still valid when notify_ is called */
    g_object_unref (contact);
    g_free (vcard);

    g_mutex_unlock (priv->pending_mutex);
}
Example #12
0
static void
check_disc_type(disc_scanner_t *ds)
{
  char *buf = memalign(32, 2048);
  char title[64];
  int r = DI_ReadDVD(buf, 1, 16);

  if(r) {
    notify_add(NOTIFY_ERROR, NULL, 5, "Unable to read disc, ejecting...");
    DI_Eject();

  } else {
    char *p = &buf[40];
    while(*p > 32 && p != &buf[72])
      p++;
    *p = 0;
    
    snprintf(title, sizeof(title), "DVD: %s", buf + 40);
    ds->ds_service = service_create(title, "dvd:/dev/di",
				    SVC_TYPE_VIDEO, NULL, 0);
    ds->ds_disc_ready = 1;
  }
  free(buf);
}
/**
 * e_data_book_view_notify_update_prefiltered_vcard:
 * @book_view: an #EDataBookView
 * @id: the UID of this contact
 * @vcard: a plain vCard
 *
 * Notify listeners that @vcard has changed. This can
 * trigger an add, change or removal event depending on
 * whether the change causes the contact to start matching,
 * no longer match, or stay matching the query specified
 * by @book_view.  This method should be preferred over
 * #e_data_book_view_notify_update when the native
 * representation of a contact is a vCard.
 *
 * The important difference between this method and
 * #e_data_book_view_notify_update and #e_data_book_view_notify_update_vcard is
 * that it doesn't match the contact against the book view query to see if it
 * should be included, it assumes that this has been done and the contact is
 * known to exist in the view.
 **/
void
e_data_book_view_notify_update_prefiltered_vcard (EDataBookView *book_view, const gchar *id, gchar *vcard)
{
    EDataBookViewPrivate *priv = book_view->priv;
    gboolean currently_in_view;

    if (!priv->running) {
        g_free (vcard);
        return;
    }

    g_mutex_lock (priv->pending_mutex);

    currently_in_view = id_is_in_view (book_view, id);

    if (currently_in_view)
        notify_change (book_view, vcard);
    else
        notify_add (book_view, id, vcard);

    g_free (vcard);

    g_mutex_unlock (priv->pending_mutex);
}
Example #14
0
static int
video_ps3_vdec_codec_create(media_codec_t *mc, const media_codec_params_t *mcp,
			    media_pipe_t *mp)
{
  vdec_decoder_t *vdd;
  struct vdec_type dec_type = {0};
  struct vdec_attr dec_attr = {0};
  int spu_threads;
  int r;


  switch(mc->codec_id) {
  case AV_CODEC_ID_MPEG2VIDEO:
    if(!vdec_mpeg2_loaded)
      return no_lib(mp, "MPEG-2");

    dec_type.codec_type = VDEC_CODEC_TYPE_MPEG2;
    dec_type.profile_level = VDEC_MPEG2_MP_HL;
    spu_threads = 1;
    break;

  case AV_CODEC_ID_H264:
    if(mcp != NULL) {

      if(mcp->profile == FF_PROFILE_H264_CONSTRAINED_BASELINE)
	return 1; // can't play this

      if(mcp->profile >= FF_PROFILE_H264_HIGH_10)
	return 1; // No 10bit support

      if(mcp->extradata != NULL) {
	h264_parser_t hp;

	hexdump("extradata", mcp->extradata, mcp->extradata_size);

	if(h264_parser_init(&hp, mcp->extradata, mcp->extradata_size)) {
	  notify_add(mp->mp_prop_notifications, NOTIFY_WARNING, NULL, 10,
		     _("Cell-h264: Broken headers, Disabling acceleration"));
	  return -1;
	}

	TRACE(TRACE_DEBUG, "VDEC", "Dumping SPS");
	int too_big_refframes = 0;
	for(int i = 0; i < H264_PARSER_NUM_SPS; i++) {
	  const h264_sps_t *s = &hp.sps_array[i];
	  if(!s->present)
	    continue;
	  TRACE(TRACE_DEBUG, "VDEC",
		"SPS[%d]: %d x %d profile:%d level:%d.%d ref-frames:%d",
		i, s->mb_width * 16, s->mb_height * 16,
		s->profile,
		s->level / 10,
		s->level % 10,
		s->num_ref_frames);

	  if(s->mb_height >= 68 && s->num_ref_frames > 4)
	    too_big_refframes = s->num_ref_frames;
	}
	h264_parser_fini(&hp);

	if(too_big_refframes) {
	  notify_add(mp->mp_prop_notifications, NOTIFY_WARNING, NULL, 10,
		     _("Cell-h264: %d Ref-frames for 1080 content is incompatible with PS3 HW decoder. Disabling acceleration"), too_big_refframes);
	  return -1;
	}
      }
    }

    if(!vdec_h264_loaded) 
      return no_lib(mp, "h264");

    dec_type.codec_type = VDEC_CODEC_TYPE_H264;
    if(mcp != NULL && mcp->level > 42) {
      notify_add(mp->mp_prop_notifications, NOTIFY_WARNING, NULL, 10,
		 _("Cell-h264: Forcing level 4.2 for content in level %d.%d. This may break video playback."), mcp->level / 10, mcp->level % 10);
    }
    dec_type.profile_level = 42;
    spu_threads = 4;
    break;

  default:
    return 1;
  }

  r = vdec_query_attr(&dec_type, &dec_attr);
  if(r) {
    notify_add(mp->mp_prop_notifications, NOTIFY_WARNING, NULL, 10,
	       _("Unable to query Cell codec. Error 0x%x"), r);
    return 1;
  }

  vdd = calloc(1, sizeof(vdec_decoder_t));


#define ROUND_UP(p, round) ((p + round - 1) & ~(round - 1))

  size_t allocsize = ROUND_UP(dec_attr.mem_size, 1024*1024);
  u32 taddr;

  if(Lv2Syscall3(348, allocsize, 0x400, (u64)&taddr)) {
    notify_add(mp->mp_prop_notifications, NOTIFY_WARNING, NULL, 10,
	       _("Unable to open Cell codec. Unable to allocate %d bytes of RAM"), dec_attr.mem_size);
    return 1;
  }
  vdd->mem = (void *)(uint64_t)taddr;

  TRACE(TRACE_DEBUG, "VDEC", "Opening codec %s level %d using %d bytes of RAM",
	mc->codec_id == AV_CODEC_ID_H264 ? "h264" : "MPEG2",
	dec_type.profile_level,
	dec_attr.mem_size);

  vdd->config.mem_addr = (intptr_t)vdd->mem;
  vdd->config.mem_size = dec_attr.mem_size;
  vdd->config.num_spus = spu_threads;
  vdd->config.ppu_thread_prio = VDEC_PPU_PRIO;
  vdd->config.spu_thread_prio = VDEC_SPU_PRIO;
  vdd->config.ppu_thread_stack_size = 1 << 14;

  vdec_closure c;
  c.fn = (intptr_t)OPD32(decoder_callback);
  c.arg = (intptr_t)vdd;

  r = vdec_open(&dec_type, &vdd->config, &c, &vdd->handle);
  if(r) {
    notify_add(mp->mp_prop_notifications, NOTIFY_WARNING, NULL, 10,
	       _("Unable to open Cell codec. Error 0x%x"), r);
    Lv2Syscall1(349, (uint64_t)vdd->mem);
    free(vdd);
    return 1;
  }

  if(mcp != NULL) {
    vdd->level_major = mcp->level / 10;
    vdd->level_minor = mcp->level % 10;
  }

  if(mc->codec_id == AV_CODEC_ID_H264 && mcp != NULL && mcp->extradata_size)
    h264_to_annexb_init(&vdd->annexb, mcp->extradata, mcp->extradata_size);

  vdd->max_order = -1;

  hts_mutex_init(&vdd->mtx);
  hts_cond_init(&vdd->audone, &vdd->mtx);
  hts_cond_init(&vdd->seqdone, &vdd->mtx);

  TRACE(TRACE_DEBUG, "VDEC", 
	"Cell accelerated codec created using %d bytes of RAM",
	dec_attr.mem_size);

  mc->opaque = vdd;
  mc->decode = decoder_decode;
  mc->flush  = decoder_flush;
  mc->close  = decoder_close;


  vdec_start_sequence(vdd->handle);

  return 0;
}
Example #15
0
int	cc_notify(buffer_t* out, command_t* cmd, uint8_t argc, char** argv)
{
  unsigned int session_id = 0, i;
  connection_t* c;
  char* endp = NULL;
  uint8_t arg = 1;
  unsigned int on_off = 1, valid;
  enum notify_type type;
  const char* name,* alias_name = NULL;

  if (NULL == argv)
    return EFAULT;
  c = connect_findbybuffer(out);
  if (NULL == c)
    return EDOOFUS;
  if (arg < argc)
  {
    session_id = strtol(argv[arg], &endp, 0);
    if (session_id)
    {
      if (errno || NULL == endp || '\0' != *endp)
	return EUSAGE;
      if (!c->info.has_admin)
	return EACCES;
      c = connect_findbyid(session_id);
      if (NULL == c)
	return ENOSESSION;
      arg++;
    }
  }
  if (!(arg < argc))
  {
    rset_t* rset;
    char* typestr;

    /* display a list of notifications for this client and exit */
    rset = rset_new(NULL, 2, c->notify_count);
    if (NULL == rset || rset->num_fields < 2 ||
	rset->num_records < c->notify_count ||
	NULL == (rset->fields[0] = strdup("type")) ||
	NULL == (rset->fields[1] = strdup("name")))
    {
      rset_free(rset);
      return errno;
    }
    for (i = 0; i < c->notify_count; i++)
    {
      switch (c->notify_list[i].type)
      {
      case NOTIFY_VAR:
	typestr = "env";
	break;
      case NOTIFY_DB:
	typestr = "rset";
	break;
      default:
	typestr = NULL;
	break;
      }
      if (NULL != typestr)
	rset_setval(rset, i, 0, typestr);
      rset_setval(rset, i, 1, c->notify_list[i].name);
    }
    output_rset(out, NULL, NULL, rset);
    rset_free(rset);
    return ENONE;
  }
  if (!strcasecmp(argv[arg], "on"))
    on_off = 1;
  else
  if (!strcasecmp(argv[arg], "off"))
    on_off = 0;
  else
  if (session_id)
    return EUSAGE;
  else
    arg--;
  arg++;
  do
  {
    if (!(arg < argc))
    {
      if (on_off)
	return EUSAGE;
      for (i = c->notify_count; i > 0; i--)
	notify_del(c, c->notify_list[i - 1].type, c->notify_list[i - 1].name);
      return ENONE;
    }
    if (!strcasecmp(argv[arg], "env"))
    {
      arg++;
      type = NOTIFY_VAR;
    } else
    if (!strcasecmp(argv[arg], "rset"))
    {
      arg++;
      type = NOTIFY_DB;
    } else
      type = NOTIFY_VAR;
    if (!(arg < argc))
      return EUSAGE;
    if (NULL == (name = argv[arg++]))
      return EINVAL;
    valid = NOTIFY_DB == type ? rset_validname(name) : var_validname(name);
    if (!valid)
    {
      buf_append(out, "ERR: name cannot contain illegal chars\n");
      return EIGNORE;
    }

    if (on_off)
    {
      if (arg < argc)
      {
	if (arg + 2 != argc || strcasecmp(argv[arg++], "as"))
	  return EUSAGE;
	alias_name = argv[arg];
	valid = NOTIFY_DB == type ?
		rset_validname(name) : var_validname(name);
	if (!valid)
	{
	  buf_append(out, "ERR: alias name cannot contain illegal chars\n");
	  return EIGNORE;
	}
	if (!strcmp(name, alias_name))
	  alias_name = NULL;
      }
      notify_add(c, type, name, alias_name);
      if (NOTIFY_DB == type)
	server_listen4rset(name);
      return ENONE;
    }
    /* loop on "off" names */
    notify_del(c, type, name);
  } while (arg < argc);

  return ENOSYS;
}
Example #16
0
static int
video_ps3_vdec_codec_create(media_codec_t *mc, const media_codec_params_t *mcp,
			    media_pipe_t *mp)
{
  vdec_decoder_t *vdd;
  struct vdec_type dec_type = {0};
  struct vdec_attr dec_attr = {0};
  int spu_threads;
  int r;


  switch(mc->codec_id) {
  case CODEC_ID_MPEG2VIDEO:
    if(!vdec_mpeg2_loaded)
      return no_lib(mp, "MPEG-2");

    dec_type.codec_type = VDEC_CODEC_TYPE_MPEG2;
    dec_type.profile_level = VDEC_MPEG2_MP_HL;
    spu_threads = 1;
    break;

  case CODEC_ID_H264:
    if(mcp != NULL && mcp->profile == FF_PROFILE_H264_CONSTRAINED_BASELINE)
      return 1; // can't play this

    if(!vdec_h264_loaded) 
      return no_lib(mp, "h264");

    dec_type.codec_type = VDEC_CODEC_TYPE_H264;
    if(mcp != NULL && mcp->level > 42) {
      notify_add(mp->mp_prop_notifications, NOTIFY_WARNING, NULL, 10,
		 _("Cell-h264: Forcing level 4.2 for content in level %d.%d. This may break video playback."), mcp->level / 10, mcp->level % 10);
    }
    dec_type.profile_level = 42;
    spu_threads = 4;
    break;

  default:
    return 1;
  }

  r = vdec_query_attr(&dec_type, &dec_attr);
  if(r) {
    notify_add(mp->mp_prop_notifications, NOTIFY_WARNING, NULL, 10,
	       _("Unable to query Cell codec. Error 0x%x"), r);
    return 1;
  }

  vdd = calloc(1, sizeof(vdec_decoder_t));


#define ROUND_UP(p, round) ((p + round - 1) & ~(round - 1))

  size_t allocsize = ROUND_UP(dec_attr.mem_size, 1024*1024);
  u32 taddr;

  if(Lv2Syscall3(348, allocsize, 0x400, (u64)&taddr)) {
    notify_add(mp->mp_prop_notifications, NOTIFY_WARNING, NULL, 10,
	       _("Unable to open Cell codec. Unable to allocate %d bytes of RAM"), dec_attr.mem_size);
    return 1;
  }
  vdd->mem = (void *)(uint64_t)taddr;

  TRACE(TRACE_DEBUG, "VDEC", "Opening codec %s level %d using %d bytes of RAM",
	mc->codec_id == CODEC_ID_H264 ? "h264" : "MPEG2",
	dec_type.profile_level,
	dec_attr.mem_size);

  vdd->config.mem_addr = (intptr_t)vdd->mem;
  vdd->config.mem_size = dec_attr.mem_size;
  vdd->config.num_spus = spu_threads;
  vdd->config.ppu_thread_prio = VDEC_PPU_PRIO;
  vdd->config.spu_thread_prio = VDEC_SPU_PRIO;
  vdd->config.ppu_thread_stack_size = 1 << 14;

  vdec_closure c;
  c.fn = (intptr_t)OPD32(decoder_callback);
  c.arg = (intptr_t)vdd;

  r = vdec_open(&dec_type, &vdd->config, &c, &vdd->handle);
  if(r) {
    notify_add(mp->mp_prop_notifications, NOTIFY_WARNING, NULL, 10,
	       _("Unable to open Cell codec. Error 0x%x"), r);
    Lv2Syscall1(349, (uint64_t)vdd->mem);
    free(vdd);
    return 1;
  }

  if(mcp != NULL) {
    vdd->level_major = mcp->level / 10;
    vdd->level_minor = mcp->level % 10;
  }

  if(mc->codec_id == CODEC_ID_H264 && mcp != NULL && mcp->extradata_size)
    h264_to_annexb_init(&vdd->annexb, mcp->extradata, mcp->extradata_size);

  vdd->max_order = -1;

  hts_mutex_init(&vdd->mtx);
  hts_cond_init(&vdd->audone, &vdd->mtx);
  hts_cond_init(&vdd->seqdone, &vdd->mtx);

  TRACE(TRACE_DEBUG, "VDEC", 
	"Cell accelerated codec created using %d bytes of RAM",
	dec_attr.mem_size);

  mc->opaque = vdd;
  mc->decode = decoder_decode;
  mc->flush  = decoder_flush;
  mc->close  = decoder_close;


  vdec_start_sequence(vdd->handle);

  return 0;
}