Example #1
0
static void
mpegts_base_program_remove_stream (MpegTSBase * base,
    MpegTSBaseProgram * program, guint16 pid)
{
  MpegTSBaseClass *klass;
  MpegTSBaseStream *stream = program->streams[pid];

  GST_DEBUG ("pid:0x%04x", pid);

  if (G_UNLIKELY (stream == NULL)) {
    /* Can happen if the PCR PID is the same as a audio/video PID */
    GST_DEBUG ("Stream already removed");
    return;
  }

  klass = GST_MPEGTS_BASE_GET_CLASS (base);

  /* If subclass needs it, inform it of the stream we are about to remove */
  if (klass->stream_removed)
    klass->stream_removed (base, stream);

  program->stream_list = g_list_remove_all (program->stream_list, stream);
  g_free (stream);
  program->streams[pid] = NULL;
}
Example #2
0
/**
 * The function will deallocate all Image structures which are referenced only
 * from pile (ie having ref == 1 ) in pile and remove them from list.
 *
 * In case some Image structure is referenced not only from pile, function will
 * terminate prematurely and return error. Invocation can be repeated when all
 * references to the structure are removed.
 *
 * \return OK on success
 */
RCode pile_destroy() {
	GList*	iterator = NULL;

	if ( NULL == pile_list_head ) {
		// no need to destroy empty pile
		return OK;
	}

	iterator = g_list_first(pile_list_head);
	while ( NULL !=  iterator  ) {
		TRACE_MESSAGE(PILE, TL_DEBUG, "Deallocating %s", ((Image*)iterator->data)->name);
		if ( FAIL == image_unref((Image*)iterator->data) ) {
			ERROR_NOTE("Unable to deallocate image structure");

			// attempt to leave image list in consistent state after failing to
			// free Image structure. Remove all elements of list which do not
			// point to Image structure anymore (ie previously freed)
			pile_list_head = g_list_remove_all(pile_list_head, NULL);
			return FAIL;
		}

		iterator->data = NULL;
		iterator = g_list_next(iterator);
	}

	TRACE_MESSAGE(PILE, TL_DEBUG, "Freeing image pile list");
	g_list_free(pile_list_head);

	// This needs to be here since freed list elements are returned to glib
	// allocator but remain valid! So it will look as if we have one more
	// element in list.
	pile_list_head = NULL;
	return OK;
}
Example #3
0
static DBusHandlerResult
mce_signal_filter (DBusConnection *connection, DBusMessage *msg, void *user_data)
{
    (void) connection;
    (void) user_data;

    if (dbus_message_is_signal(msg, MCE_SIGNAL_IF, MCE_LED_PATTERN_DEACTIVATED_SIG)) {
        DBusError error;
        dbus_error_init(&error);

        gchar *pattern = NULL;

        if (!dbus_message_get_args(msg, &error, DBUS_TYPE_STRING, &pattern, DBUS_TYPE_INVALID)) {
            N_WARNING ("%s >> failed to read MCE signal arguments, cause: %s", __FUNCTION__, error.message);
            dbus_error_free(&error);
        } else {
            GList *event;
            N_DEBUG ("%s >> mce finished playing %s", __FUNCTION__, pattern);
            for (event = active_events; event != NULL; event = g_list_next(event)) {
                MceData *data = (MceData *) event->data;
                if (g_strcmp0(pattern, data->pattern) == 0) {
                    n_sink_interface_complete(data->iface, data->request);
                    N_DEBUG ("%s >> led pattern %s complete", __FUNCTION__, data->pattern);
                    active_events = g_list_remove_all(active_events, data);
                    break;
                }
            }
        }
    }

    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
Example #4
0
int mwConference_destroy(struct mwConference *conf,
			 guint32 reason, const char *text) {

  struct mwServiceConference *srvc;
  struct mwOpaque info = { 0, 0 };
  int ret = 0;

  g_return_val_if_fail(conf != NULL, -1);

  srvc = conf->service;
  g_return_val_if_fail(srvc != NULL, -1);

  /* remove conference from the service */
  srvc->confs = g_list_remove_all(srvc->confs, conf);

  /* close the channel if applicable */
  if(conf->channel) {
    if(text && *text) {
      info.len = strlen(text);
      info.data = (guchar *) text;
    }

    ret = mwChannel_destroy(conf->channel, reason, &info);
  }
  
  /* free the conference */
  conf_free(conf);

  return ret;
}
Example #5
0
/**
 * rstto_file_dispose:
 * @object:
 *
 */
static void
rstto_file_dispose (GObject *object)
{
    RsttoFile *r_file = RSTTO_FILE (object);
    gint i = 0;

    if (r_file->priv)
    {
        if (r_file->priv->file)
        {
            g_object_unref (r_file->priv->file);
            r_file->priv->file = NULL;
        }
        if (r_file->priv->display_name)
        {
            g_free (r_file->priv->display_name);
            r_file->priv->display_name = NULL;
        }
        if (r_file->priv->content_type)
        {
            g_free (r_file->priv->content_type);
            r_file->priv->content_type = NULL;
        }
        if (r_file->priv->path)
        {
            g_free (r_file->priv->path);
            r_file->priv->path = NULL;
        }
        if (r_file->priv->thumbnail_path)
        {
            g_free (r_file->priv->thumbnail_path);
            r_file->priv->thumbnail_path = NULL;
        }
        if (r_file->priv->uri)
        {
            g_free (r_file->priv->uri);
            r_file->priv->uri = NULL;
        }
        if (r_file->priv->collate_key)
        {
            g_free (r_file->priv->collate_key);
            r_file->priv->collate_key = NULL;
        }

        for (i = 0; i < THUMBNAIL_SIZE_COUNT; ++i)
        {
            if (r_file->priv->thumbnails[i])
            {
                g_object_unref (r_file->priv->thumbnails[i]);
                r_file->priv->thumbnails[i] = NULL;
            }
        }

        g_free (r_file->priv);
        r_file->priv = NULL;

        open_files = g_list_remove_all (open_files, r_file);
    }
}
Example #6
0
void destroy_execp(void *obj)
{
	Execp *execp = (Execp *)obj;
	if (execp->frontend) {
		// This is a frontend element
		execp->backend->instances = g_list_remove_all(execp->backend->instances, execp);
		free_and_null(execp->frontend);
		remove_area(&execp->area);
		free_area(&execp->area);
		free_and_null(execp);
	} else {
		// This is a backend element
		stop_timeout(execp->backend->timer);
		execp->backend->timer = NULL;

		if (execp->backend->icon) {
			imlib_context_set_image(execp->backend->icon);
			imlib_free_image();
			execp->backend->icon = NULL;
		}
		free_and_null(execp->backend->buf_output);
		free_and_null(execp->backend->text);
		free_and_null(execp->backend->icon_path);
		if (execp->backend->child) {
			kill(-execp->backend->child, SIGHUP);
			execp->backend->child = 0;
		}
		if (execp->backend->child_pipe >= 0) {
			close(execp->backend->child_pipe);
			execp->backend->child_pipe = -1;
		}
		if (execp->backend->cmd_pids) {
			g_tree_destroy(execp->backend->cmd_pids);
			execp->backend->cmd_pids = NULL;
		}

		execp->backend->bg = NULL;
		pango_font_description_free(execp->backend->font_desc);
		execp->backend->font_desc = NULL;
		free_and_null(execp->backend->command);
		free_and_null(execp->backend->tooltip);
		free_and_null(execp->backend->lclick_command);
		free_and_null(execp->backend->mclick_command);
		free_and_null(execp->backend->rclick_command);
		free_and_null(execp->backend->dwheel_command);
		free_and_null(execp->backend->uwheel_command);

		if (execp->backend->instances) {
			fprintf(stderr, "Error: Attempt to destroy backend while there are still frontend instances!\n");
			exit(-1);
		}
		free(execp->backend);
		free(execp);
	}
}
Example #7
0
static void
_remove_participant (gpointer user_data,
                 GObject *where_the_object_was)
{
  FsRtpConference *self = FS_RTP_CONFERENCE (user_data);

  GST_OBJECT_LOCK (self);
  self->priv->participants =
    g_list_remove_all (self->priv->participants, where_the_object_was);
  GST_OBJECT_UNLOCK (self);
}
static void
_remove_stream (gpointer user_data,
                GObject *where_the_object_was)
{
  FsMsnSession *self = FS_MSN_SESSION (user_data);

  FS_MSN_SESSION_LOCK (self);
  self->priv->streams =
    g_list_remove_all (self->priv->streams, where_the_object_was);
  FS_MSN_SESSION_UNLOCK (self);
}
Example #9
0
static void
_remove_session (gpointer user_data,
                 GObject *where_the_object_was)
{
  FsRtpConference *self = FS_RTP_CONFERENCE (user_data);

  GST_OBJECT_LOCK (self);
  self->priv->sessions =
    g_list_remove_all (self->priv->sessions, where_the_object_was);
  self->priv->sessions_cookie++;
  GST_OBJECT_UNLOCK (self);
}
Example #10
0
File: UgUtils.c Project: Endz0/uget
GList*	ug_uri_list_remove_scheme (GList* list, const gchar* scheme)
{
	GList*	link;
	gchar*	text;

	for (link = list;  link;  link = link->next) {
		text = g_uri_parse_scheme (link->data);
		if (text && strcmp (text, scheme) == 0) {
			g_free (link->data);
			link->data = NULL;
		}
		g_free (text);
	}
	return g_list_remove_all (list, NULL);
}
Example #11
0
static void
mce_sink_stop (NSinkInterface *iface, NRequest *request)
{
    (void) iface;

    MceData *data = (MceData*) n_request_get_data (request, MCE_KEY);
    g_assert (data != NULL);

    if (data->pattern) {
        toggle_pattern (data->pattern, FALSE);
        g_free (data->pattern);
        data->pattern = NULL;
    }

    active_events = g_list_remove_all(active_events, data);
    g_slice_free (MceData, data);
}
Example #12
0
/*! \brief Remove a weak reference watcher from a weak ref list.
 * \par Function Description
 * Removes a weak reference callback from the weak reference list \a
 * weak_refs, returning the new head of \a weak_refs.
 *
 * \param [in,out] weak_refs    List of registered weak references.
 * \param [in] notify_func      Notify function to search for.
 * \param [in] user_data        User data to search for.
 *
 * \return new head of \a weak_refs list.
 */
GList *
s_weakref_remove (GList *weak_refs, void (*notify_func)(void *, void *),
                  void *user_data)
{
  GList *iter;
  struct WeakRef *entry;
  for (iter = weak_refs; iter != NULL; iter = g_list_next (iter)) {
    entry = iter->data;
    if ((entry != NULL) &&
        (entry->notify_func == notify_func) &&
        (entry->user_data == user_data)) {
      g_free (entry);
      iter->data = NULL;
    }
  }
  return g_list_remove_all (weak_refs, NULL);
}
Example #13
0
/**
 * as_node_remove_attribute: (skip)
 * @node: a #AsNode
 * @key: the attribute key
 *
 * Removes a node attribute, e.g. "type"
 *
 * Since: 0.2.0
 **/
void
as_node_remove_attribute (AsNode *node, const gchar *key)
{
	AsNodeAttr *attr;
	AsNodeData *data;

	g_return_if_fail (node != NULL);
	g_return_if_fail (key != NULL);

	if (node->data == NULL)
		return;
	data = (AsNodeData *) node->data;
	attr = as_node_attr_find (data, key);
	if (attr == NULL)
		return;
	data->attrs = g_list_remove_all (data->attrs, attr);
	as_node_attr_free (attr);
}
Example #14
0
static void place_free(struct mwPlace *place) {
  struct mwServicePlace *srvc;

  if(! place) return;
  
  srvc = place->service;
  g_return_if_fail(srvc != NULL);

  srvc->places = g_list_remove_all(srvc->places, place);

  mw_datum_clear(&place->client_data);

  g_hash_table_destroy(place->members);

  g_free(place->name);
  g_free(place->title);
  g_free(place);
}
Example #15
0
void
gkd_gpg_agent_accept (void)
{
	Client *client;
	struct sockaddr_un addr;
	socklen_t addrlen;
	GError *error = NULL;
	GList *l;
	int new_fd;

	g_return_if_fail (socket_fd != -1);

	/* Cleanup any completed dispatch threads */
	for (l = socket_clients; l; l = g_list_next (l)) {
		client = l->data;
		if (g_atomic_int_get (&client->sock) == -1) {
			g_thread_join (client->thread);
			g_slice_free (Client, client);
			l->data = NULL;
		}
	}
	socket_clients = g_list_remove_all (socket_clients, NULL);

	addrlen = sizeof (addr);
	new_fd = accept (socket_fd, (struct sockaddr*) &addr, &addrlen);
	if (new_fd < 0) {
		g_warning ("cannot accept GPG agent connection: %s", strerror (errno));
		return;
	}

	client = g_slice_new0 (Client);
	client->sock = new_fd;

	/* And create a new thread/process */
	client->thread = g_thread_create (run_client_thread, &client->sock, TRUE, &error);
	if (!client->thread) {
		g_warning ("couldn't create thread GPG agent connection: %s",
		           error && error->message ? error->message : "");
		g_slice_free (Client, client);
		return;
	}

	socket_clients = g_list_append (socket_clients, client);
}
Example #16
0
static void insert_requested_icon(TwitterConvIcon * conv_icon)
{
    GList          *mark_list = NULL;

    if (!conv_icon)
        return;

    mark_list = conv_icon->request_list;

    purple_debug_info(PLUGIN_ID, "about to insert icon for pending requests\n");

    if (mark_list) {
        g_list_foreach(mark_list, (GFunc) insert_icon_at_mark, conv_icon);
        mark_list = g_list_remove_all(mark_list, NULL);
        g_list_free(mark_list);
        conv_icon->request_list = NULL;
    }

}
Example #17
0
/** clean and free a conference structure */
static void conf_free(struct mwConference *conf) {
  struct mwServiceConference *srvc;

  /* this shouldn't ever happen, but just to be sure */
  g_return_if_fail(conf != NULL);
  
  srvc = conf->service;

  if(conf->members)
    g_hash_table_destroy(conf->members);

  srvc->confs = g_list_remove_all(srvc->confs, conf);

  mw_datum_clear(&conf->client_data);
  
  g_free(conf->name);
  g_free(conf->title);
  g_free(conf);
}
Example #18
0
static void add_fill_favory_language(GtkSourceLanguage* lang) {
	GList* list;
	const gchar* name = lang ? gtk_source_language_get_name(lang) : 0;
	if( !name )
		return;

	list = g_list_remove_all(g_self->favory_language_list, name);
	g_self->favory_language_list = g_list_prepend(list, (gchar*)name);

	for(;;) {
		list = g_list_nth(g_self->favory_language_list, 16);
		if( !list )
			break;
		g_self->favory_language_list = g_list_delete_link(g_self->favory_language_list, list);
	}

	g_self->last_favory_lang = lang;

	fill_favory_language_menu();
}
Example #19
0
static void
gst_live_adder_release_pad (GstElement * element, GstPad * pad)
{
    GstLiveAdder *adder;
    GstLiveAdderPadPrivate *padprivate;

    adder = GST_LIVE_ADDER (element);

    GST_DEBUG_OBJECT (adder, "release pad %s:%s", GST_DEBUG_PAD_NAME (pad));

    GST_OBJECT_LOCK (element);
    padprivate = gst_pad_get_element_private (pad);
    gst_pad_set_element_private (pad, NULL);
    adder->sinkpads = g_list_remove_all (adder->sinkpads, pad);
    GST_OBJECT_UNLOCK (element);

    g_free (padprivate);

    gst_element_remove_pad (element, pad);
}
void janus_streaming_destroy_session(janus_plugin_session *handle, int *error) {
	if(stopping || !initialized) {
		*error = -1;
		return;
	}	
	janus_streaming_session *session = (janus_streaming_session *)handle->plugin_handle; 
	if(!session) {
		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
		*error = -2;
		return;
	}
	JANUS_LOG(LOG_VERB, "Removing streaming session...\n");
	if(session->mountpoint) {
		session->mountpoint->listeners = g_list_remove_all(session->mountpoint->listeners, session);
	}
	janus_mutex_lock(&sessions_mutex);
	g_hash_table_remove(sessions, handle);
	janus_mutex_unlock(&sessions_mutex);
	/* Cleaning up and removing the session is done in a lazy way */
	session->destroy = TRUE;
	return;
}
Example #21
0
/**
 * Removes a subscription which was being monitored.
 *
 * @param sub a #GamSubscription to remove
 * @returns TRUE if removing the subscription succeeded, FALSE otherwise
 */
gboolean
gam_kqueue_remove_subscription (GamSubscription *sub)
{
  GHashTable *hash;
  SubMonitor *smon;

  hash = gam_subscription_is_dir(sub) ? dir_hash : file_hash;
  smon = g_hash_table_lookup(hash, gam_subscription_get_path(sub));

  if (! smon)
    return FALSE;

  smon->subs = g_list_remove_all(smon->subs, sub);
  if (! smon->subs)
    {
      g_hash_table_remove(hash, MONITOR(smon)->pathname);
      gam_kqueue_sub_monitor_free(smon);
    }

  gam_subscription_cancel(sub);

  return TRUE;
}
Example #22
0
void note_delete(ConboyNote *note)
{
	AppData *app_data = app_data_get();

	/* Delete file */
	if (!conboy_storage_note_delete(CONBOY_STORAGE(app_data->storage), note)) {
		g_printerr("ERROR: The note with the guid %s could not be deleted \n", note->guid);
	}

	/* Remove from list store */
	conboy_note_store_remove(CONBOY_NOTE_STORE(app_data->note_store), note);

	/* If it was the current note, that has been deleted, change current note */
	if (app_data->current_element && note == app_data->current_element->data) {

		g_printerr("INFO: Current active note has been deleted. Changing history\n");

		if (app_data->current_element->prev) {
			app_data->current_element = app_data->current_element->prev;
		} else if (app_data->current_element->next) {
			app_data->current_element = app_data->current_element->next;
		} else {
			/* It was the last note. Empty history. */
			app_data->current_element = NULL;
			app_data->note_history = NULL;
		}
	}

	/* Remove note from history */
	if (app_data->note_history != NULL) {
		app_data->note_history = g_list_remove_all(app_data->note_history, note);
	}

	/* Destroy note object */
	g_object_unref(note);
	note = NULL;
}
Example #23
0
static void
mpegts_parse_pad_removed (GstElement * element, GstPad * pad)
{
  MpegTSParsePad *tspad;
  MpegTSBase *base = (MpegTSBase *) element;
  MpegTSParse2 *parse = GST_MPEGTS_PARSE (element);

  if (gst_pad_get_direction (pad) == GST_PAD_SINK)
    return;

  tspad = (MpegTSParsePad *) gst_pad_get_element_private (pad);
  if (tspad) {
    mpegts_parse_destroy_tspad (parse, tspad);

    parse->srcpads = g_list_remove_all (parse->srcpads, pad);
  }
  if (parse->srcpads == NULL) {
    base->push_data = FALSE;
    base->push_section = FALSE;
  }

  if (GST_ELEMENT_CLASS (parent_class)->pad_removed)
    GST_ELEMENT_CLASS (parent_class)->pad_removed (element, pad);
}
Example #24
0
/* manual word completion - called when TAB is pressed */
char *word_complete(WINDOW_REC *window, const char *line, int *pos, int erase, int backward)
{
	static int startpos = 0, wordlen = 0;
        int old_startpos, old_wordlen;

	GString *result;
	const char *cmdchars;
	char *word, *wordstart, *linestart, *ret, *data;
	int continue_complete, want_space, expand_escapes;

	g_return_val_if_fail(line != NULL, NULL);
	g_return_val_if_fail(pos != NULL, NULL);

	continue_complete = complist != NULL && *pos == last_line_pos &&
		g_strcmp0(line, last_line) == 0;

	if (erase && !continue_complete)
		return NULL;

	old_startpos = startpos;
	old_wordlen = wordlen;

	if (!erase && continue_complete) {
		word = NULL;
                linestart = NULL;
	} else {
		char* old_wordstart;

		/* get the word we want to complete */
		word = get_word_at(line, *pos, &wordstart);
		old_wordstart = wordstart;

		startpos = (int) (wordstart-line);
		wordlen = strlen(word);

		/* remove trailing spaces from linestart */
		while (wordstart > line && isseparator_space(wordstart[-1]))
			wordstart--;

		/* unless everything was spaces */
		if (old_wordstart > line && wordstart == line)
			wordstart = old_wordstart - 1;

		linestart = g_strndup(line, (int) (wordstart-line));

		/* completions usually add space after the word, that makes
		   things a bit harder. When continuing a completion
		   "/msg nick1 "<tab> we have to cycle to nick2, etc.
		   BUT if we start completion with "/msg "<tab>, we don't
		   want to complete the /msg word, but instead complete empty
		   word with /msg being in linestart. */
		if (!erase && *pos > 0 && isseparator_space(line[*pos-1]) &&
		    (*linestart == '\0' || !isseparator_space(wordstart[-1]))) {
			char *old;

			old = linestart;
			/* we want to move word into linestart */
			if (*linestart == '\0') {
				linestart = g_strdup(word);
			} else {
				GString *str = g_string_new(linestart);
				if (old_wordstart[-1] != str->str[str->len - 1]) {
					/* do not accidentally duplicate the word separator */
					g_string_append_c(str, old_wordstart[-1]);
				}
				g_string_append(str, word);
				linestart = g_string_free(str, FALSE);
			}
			g_free(old);

			g_free(word);
			word = g_strdup("");

			startpos = *linestart == '\0' ? 0 :
				strlen(linestart)+1;
			wordlen = 0;
		}

	}

	if (erase) {
		signal_emit("complete erase", 3, window, word, linestart);

                /* jump to next completion */
                startpos = old_startpos;
		wordlen = old_wordlen;
	}

	if (continue_complete) {
		/* complete from old list */
		if (backward)
			complist = complist->prev != NULL ? complist->prev :
				g_list_last(complist);
		else
			complist = complist->next != NULL ? complist->next :
				g_list_first(complist);
		want_space = last_want_space;
	} else {
		int keep_word = settings_get_bool("completion_keep_word");
		/* get new completion list */
		free_completions();

		want_space = TRUE;
		signal_emit("complete word", 5, &complist, window, word, linestart, &want_space);
		last_want_space = want_space;

		if (complist != NULL) {
			/* Remove all nulls (from the signal) before doing further processing */
			complist = g_list_remove_all(g_list_first(complist), NULL);

			if (keep_word) {
				complist = g_list_append(complist, g_strdup(word));
			}

			if (backward) {
				complist = g_list_last(complist);
				if (keep_word) {
					complist = complist->prev;
				}
			}
		}
	}

	g_free(linestart);
	g_free(word);

	if (complist == NULL)
		return NULL;

        /* get the cmd char */
	cmdchars = settings_get_str("cmdchars");

	/* get the expand_escapes setting */
	expand_escapes = settings_get_bool("expand_escapes");

	/* escape if the word doesn't begin with '/' and expand_escapes are turned on */
	data = strchr(cmdchars, *line) == NULL && expand_escapes ?
		escape_string_backslashes(complist->data) : g_strdup(complist->data);

	/* word completed */
	*pos = startpos + strlen(data);

	/* replace the word in line - we need to return
	   a full new line */
	result = g_string_new(line);
	g_string_erase(result, startpos, wordlen);
	g_string_insert(result, startpos, data);

	if (want_space) {
		if (!isseparator(result->str[*pos]))
			g_string_insert_c(result, *pos, ' ');
		(*pos)++;
	}

	wordlen = strlen(data);
	last_line_pos = *pos;
	g_free_not_null(last_line);
	last_line = g_strdup(result->str);

	ret = result->str;
	g_string_free(result, FALSE);

	/* free the data */
	g_free(data);

	return ret;
}
/* Thread to handle incoming messages */
static void *janus_streaming_handler(void *data) {
	JANUS_LOG(LOG_VERB, "Joining thread\n");
	janus_streaming_message *msg = NULL;
	int error_code = 0;
	char *error_cause = calloc(1024, sizeof(char));
	if(error_cause == NULL) {
		JANUS_LOG(LOG_FATAL, "Memory error!\n");
		return NULL;
	}
	while(initialized && !stopping) {
		if(!messages || (msg = g_queue_pop_head(messages)) == NULL) {
			usleep(50000);
			continue;
		}
		janus_streaming_session *session = (janus_streaming_session *)msg->handle->plugin_handle;
		if(!session) {
			JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
			janus_streaming_message_free(msg);
			continue;
		}
		if(session->destroy) {
			janus_streaming_message_free(msg);
			continue;
		}
		/* Handle request */
		error_code = 0;
		JANUS_LOG(LOG_VERB, "Handling message: %s\n", msg->message);
		if(msg->message == NULL) {
			JANUS_LOG(LOG_ERR, "No message??\n");
			error_code = JANUS_STREAMING_ERROR_NO_MESSAGE;
			sprintf(error_cause, "%s", "No message??");
			goto error;
		}
		json_error_t error;
		json_t *root = json_loads(msg->message, 0, &error);
		if(!root) {
			JANUS_LOG(LOG_ERR, "JSON error: on line %d: %s\n", error.line, error.text);
			error_code = JANUS_STREAMING_ERROR_INVALID_JSON;
			sprintf(error_cause, "JSON error: on line %d: %s", error.line, error.text);
			goto error;
		}
		if(!json_is_object(root)) {
			JANUS_LOG(LOG_ERR, "JSON error: not an object\n");
			error_code = JANUS_STREAMING_ERROR_INVALID_JSON;
			sprintf(error_cause, "JSON error: not an object");
			goto error;
		}
		json_t *request = json_object_get(root, "request");
		if(!request) {
			JANUS_LOG(LOG_ERR, "Missing element (request)\n");
			error_code = JANUS_STREAMING_ERROR_MISSING_ELEMENT;
			sprintf(error_cause, "Missing element (request)");
			goto error;
		}
		if(!json_is_string(request)) {
			JANUS_LOG(LOG_ERR, "Invalid element (request should be a string)\n");
			error_code = JANUS_STREAMING_ERROR_INVALID_ELEMENT;
			sprintf(error_cause, "Invalid element (request should be a string)");
			goto error;
		}
		const char *request_text = json_string_value(request);
		json_t *result = NULL;
		char *sdp_type = NULL, *sdp = NULL;
		if(!strcasecmp(request_text, "list")) {
			result = json_object();
			json_t *list = json_array();
			JANUS_LOG(LOG_VERB, "Request for the list of mountpoints\n");
			/* Return a list of all available mountpoints */
			GList *mountpoints_list = g_hash_table_get_values(mountpoints);
			GList *m = mountpoints_list;
			while(m) {
				janus_streaming_mountpoint *mp = (janus_streaming_mountpoint *)m->data;
				json_t *ml = json_object();
				json_object_set_new(ml, "id", json_integer(mp->id));
				json_object_set_new(ml, "description", json_string(mp->description));
				json_object_set_new(ml, "type", json_string(mp->streaming_type == janus_streaming_type_live ? "live" : "on demand"));
				json_array_append_new(list, ml);
				m = m->next;
			}
			json_object_set_new(result, "list", list);
			g_list_free(mountpoints_list);
		} else if(!strcasecmp(request_text, "watch")) {
			json_t *id = json_object_get(root, "id");
			if(id && !json_is_integer(id)) {
				JANUS_LOG(LOG_ERR, "Invalid element (id should be an integer)\n");
				error_code = JANUS_STREAMING_ERROR_INVALID_ELEMENT;
				sprintf(error_cause, "Invalid element (id should be an integer)");
				goto error;
			}
			gint64 id_value = json_integer_value(id);
			janus_streaming_mountpoint *mp = g_hash_table_lookup(mountpoints, GINT_TO_POINTER(id_value));
			if(mp == NULL) {
				JANUS_LOG(LOG_VERB, "No such mountpoint/stream %"SCNu64"\n", id_value);
				error_code = JANUS_STREAMING_ERROR_NO_SUCH_MOUNTPOINT;
				sprintf(error_cause, "No such mountpoint/stream %"SCNu64"", id_value);
				goto error;
			}
			JANUS_LOG(LOG_VERB, "Request to watch mountpoint/stream %"SCNu64"\n", id_value);
			session->stopping = FALSE;
			session->mountpoint = mp;
			if(mp->streaming_type == janus_streaming_type_on_demand) {
				g_thread_new(session->mountpoint->name, &janus_streaming_ondemand_thread, session);
			}
			/* TODO Check if user is already watching a stream, if the video is active, etc. */
			mp->listeners = g_list_append(mp->listeners, session);
			sdp_type = "offer";	/* We're always going to do the offer ourselves, never answer */
			char sdptemp[1024];
			memset(sdptemp, 0, 1024);
			gchar buffer[100];
			memset(buffer, 0, 100);
			gint64 sessid = janus_get_monotonic_time();
			gint64 version = sessid;	/* FIXME This needs to be increased when it changes, so time should be ok */
			g_sprintf(buffer,
				"v=0\r\no=%s %"SCNu64" %"SCNu64" IN IP4 127.0.0.1\r\n",
					"-", sessid, version);
			g_strlcat(sdptemp, buffer, 1024);
			g_strlcat(sdptemp, "s=Streaming Test\r\nt=0 0\r\n", 1024);
			if(mp->codecs.audio_pt >= 0) {
				/* Add audio line */
				g_sprintf(buffer,
					"m=audio 1 RTP/SAVPF %d\r\n"
					"c=IN IP4 1.1.1.1\r\n",
					mp->codecs.audio_pt);
				g_strlcat(sdptemp, buffer, 1024);
				if(mp->codecs.audio_rtpmap) {
					g_sprintf(buffer,
						"a=rtpmap:%d %s\r\n",
						mp->codecs.audio_pt, mp->codecs.audio_rtpmap);
					g_strlcat(sdptemp, buffer, 1024);
				}
				g_strlcat(sdptemp, "a=sendonly\r\n", 1024);
			}
			if(mp->codecs.video_pt >= 0) {
				/* Add video line */
				g_sprintf(buffer,
					"m=video 1 RTP/SAVPF %d\r\n"
					"c=IN IP4 1.1.1.1\r\n",
					mp->codecs.video_pt);
				g_strlcat(sdptemp, buffer, 1024);
				if(mp->codecs.video_rtpmap) {
					g_sprintf(buffer,
						"a=rtpmap:%d %s\r\n",
						mp->codecs.video_pt, mp->codecs.video_rtpmap);
					g_strlcat(sdptemp, buffer, 1024);
				}
				g_strlcat(sdptemp, "a=sendonly\r\n", 1024);
			}
			sdp = g_strdup(sdptemp);
			JANUS_LOG(LOG_VERB, "Going to offer this SDP:\n%s\n", sdp);
			result = json_object();
			json_object_set_new(result, "status", json_string("preparing"));
		} else if(!strcasecmp(request_text, "start")) {
			JANUS_LOG(LOG_VERB, "Starting the streaming\n");
			result = json_object();
			/* We wait for the setup_media event to start: on the other hand, it may have already arrived */
			json_object_set_new(result, "status", json_string(session->started ? "started" : "starting"));
		} else if(!strcasecmp(request_text, "pause")) {
			JANUS_LOG(LOG_VERB, "Pausing the streaming\n");
			session->started = FALSE;
			result = json_object();
			json_object_set_new(result, "status", json_string("pausing"));
		} else if(!strcasecmp(request_text, "stop")) {
			JANUS_LOG(LOG_VERB, "Stopping the streaming\n");
			session->stopping = TRUE;
			session->started = FALSE;
			result = json_object();
			json_object_set_new(result, "status", json_string("stopping"));
			if(session->mountpoint) {
				JANUS_LOG(LOG_VERB, "  -- Removing the session from the mountpoint listeners\n");
				if(g_list_find(session->mountpoint->listeners, session) != NULL) {
					JANUS_LOG(LOG_VERB, "  -- -- Found!\n");
				}
				session->mountpoint->listeners = g_list_remove_all(session->mountpoint->listeners, session);
			}
			session->mountpoint = NULL;
		} else {
			JANUS_LOG(LOG_VERB, "Unknown request '%s'\n", request_text);
			error_code = JANUS_STREAMING_ERROR_INVALID_REQUEST;
			sprintf(error_cause, "Unknown request '%s'", request_text);
			goto error;
		}
		
		/* Any SDP to handle? */
		if(msg->sdp) {
			JANUS_LOG(LOG_VERB, "This is involving a negotiation (%s) as well (but we really don't care):\n%s\n", msg->sdp_type, msg->sdp);
		}

		json_decref(root);
		/* Prepare JSON event */
		json_t *event = json_object();
		json_object_set_new(event, "streaming", json_string("event"));
		if(result != NULL)
			json_object_set(event, "result", result);
		char *event_text = json_dumps(event, JSON_INDENT(3));
		json_decref(event);
		if(result != NULL)
			json_decref(result);
		JANUS_LOG(LOG_VERB, "Pushing event: %s\n", event_text);
		int ret = gateway->push_event(msg->handle, &janus_streaming_plugin, msg->transaction, event_text, sdp_type, sdp);
		JANUS_LOG(LOG_VERB, "  >> %d (%s)\n", ret, janus_get_api_error(ret));
		g_free(event_text);
		if(sdp)
			g_free(sdp);
		janus_streaming_message_free(msg);
		continue;
		
error:
		{
			if(root != NULL)
				json_decref(root);
			/* Prepare JSON error event */
			json_t *event = json_object();
			json_object_set_new(event, "streaming", json_string("event"));
			json_object_set_new(event, "error_code", json_integer(error_code));
			json_object_set_new(event, "error", json_string(error_cause));
			char *event_text = json_dumps(event, JSON_INDENT(3));
			json_decref(event);
			JANUS_LOG(LOG_VERB, "Pushing event: %s\n", event_text);
			int ret = gateway->push_event(msg->handle, &janus_streaming_plugin, msg->transaction, event_text, NULL, NULL);
			JANUS_LOG(LOG_VERB, "  >> %d (%s)\n", ret, janus_get_api_error(ret));
			g_free(event_text);
			janus_streaming_message_free(msg);
		}
	}
	g_free(error_cause);
	JANUS_LOG(LOG_VERB, "Leaving thread\n");
	return NULL;
}
Example #26
0
int main (int   argc,char *argv[])
{
	
	GList *list1 = NULL,*list2 = NULL,*l,*l1,*list3 = NULL;
	int i;
	int *value;
	const char mem_allocator[]  = "mem_allocator";
	GAllocator *allocator;
	
	int num1[] = 
	{
		1,2,3
	};
	
	int num2[] = 
	{
		4,5,6
	};
	
	#ifdef SYMBIAN
	
	g_log_set_handler (NULL,  G_LOG_FLAG_FATAL| G_LOG_FLAG_RECURSION | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING | G_LOG_LEVEL_MESSAGE | G_LOG_LEVEL_INFO | G_LOG_LEVEL_DEBUG, &mrtLogHandler, NULL);
	#endif /*SYMBIAN*/
	
	allocator = g_allocator_new(mem_allocator,500);

	for(i=0;i<3;i++)
		list1 = g_list_append (list1, &num1[i]);
		
	for(i=0;i<3;i++)
		list2 = g_list_append (list2, &num2[i]);
	
	
	list1 = g_list_concat(list1,list2);
	
	for(i=0;i<6;i++)
	{
		l = g_list_nth(list1,i);
		g_assert(*(gint *)(l->data) == i+1);
	}
	
	list2 = g_list_copy(list1);
	
	for(i=0;i<3;i++)
	{
		l = g_list_nth(list2,i);
		g_assert(*(gint *)(l->data) == i+1);
	}
	
	l = g_list_first(list2);
	g_assert(*(gint *)(l->data) == 1);
	
	value = (int *)g_list_nth_data(list1,1);
	
	g_assert(*value == 2);
	
	l = g_list_nth(list1,3);
	
	l1 = g_list_nth_prev(l,2);

	for(i=0;i<5;i++)
	{
		l = g_list_nth(l1,i);
		g_assert(*(gint *)(l->data) == i+2);
	}
	
	g_list_push_allocator(allocator);
	
	list3 = g_list_append(list3,&num1[2]);
	
	g_assert(*(gint *)(list3->data) == 3);
	
	g_list_pop_allocator();
	
	list3 = g_list_append(list3,&num1[0]);
	
	g_assert(*(gint *)(list3->next->data) == 1);
	
	list1 = g_list_append(list1,&num1[0]);
	
	i = g_list_length(list1);
	
	list1 = g_list_remove_all(list1,&num1[0]);
	
	i = g_list_length(list1);
	
	g_assert(g_list_length(list1) == 5); // should be this value as we will remove 2 1's from the list
	
	for(i==0;i<g_list_length(list1);i++)
	{
		l = g_list_nth(list1,i);
		g_assert(*(gint *)(l->data) != 1);
	}
	
	g_allocator_free(allocator);
	
	#ifdef SYMBIAN
  	testResultXml("list_test");
  	#endif /* EMULATOR */
	
	return 0;
}
Example #27
0
/*! \brief Update a component.
 *
 * \par Function Description
 * Updates \a o_current to the latest version of the symbol available
 * in the symbol library, while preserving any attributes set in the
 * current schematic. On success, returns the new OBJECT which
 * replaces \a o_current on the page; \a o_current is deleted. On
 * failure, returns NULL, and \a o_current is left unchanged.
 *
 * \param [in]     w_current The GSCHEM_TOPLEVEL object.
 * \param [in,out] o_current The OBJECT to be updated.
 *
 * \return the new OBJECT that replaces \a o_current.
 */
OBJECT *
o_update_component (GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
{
  TOPLEVEL *toplevel = w_current->toplevel;
  OBJECT *o_new;
  PAGE *page;
  GList *new_attribs;
  GList *old_attribs;
  GList *iter;
  const CLibSymbol *clib;

  g_return_val_if_fail (o_current != NULL, NULL);
  g_return_val_if_fail (o_current->type == OBJ_COMPLEX, NULL);
  g_return_val_if_fail (o_current->complex_basename != NULL, NULL);

  page = o_get_page (toplevel, o_current);

  /* This should be replaced with API to invalidate only the specific
   * symbol name we want to update */
  s_clib_flush_symbol_cache ();
  clib = s_clib_get_symbol_by_name (o_current->complex_basename);

  if (clib == NULL) {
    s_log_message (_("Could not find symbol [%s] in library. Update failed.\n"),
                   o_current->complex_basename);
    return NULL;
  }

  /* Unselect the old object. */
  o_selection_remove (toplevel, page->selection_list, o_current);

  /* Create new object and set embedded */
  o_new = o_complex_new (toplevel, OBJ_COMPLEX, DEFAULT_COLOR,
                         o_current->complex->x,
                         o_current->complex->y,
                         o_current->complex->angle,
                         o_current->complex->mirror,
                         clib, o_current->complex_basename,
                         1);
  if (o_complex_is_embedded (o_current)) {
    o_embed (toplevel, o_new);
  }

  new_attribs = o_complex_promote_attribs (toplevel, o_new);

  /* Cull any attributes from new COMPLEX that are already attached to
   * old COMPLEX. Note that the new_attribs list is kept consistent by
   * setting GList data pointers to NULL if their OBJECTs are
   * culled. At the end, the new_attribs list is updated by removing
   * all list items with NULL data. This is slightly magic, but
   * works. */
  for (iter = new_attribs; iter != NULL; iter = g_list_next (iter)) {
    OBJECT *attr_new = iter->data;
    gchar *name;
    gchar *value;

    g_assert (attr_new->type == OBJ_TEXT);

    o_attrib_get_name_value (attr_new, &name, NULL);

    value = o_attrib_search_attached_attribs_by_name (o_current, name, 0);
    if (value != NULL) {
      o_attrib_remove (toplevel, &o_new->attribs, attr_new);
      s_delete_object (toplevel, attr_new);
      iter->data = NULL;
    }

    g_free (name);
    g_free (value);
  }
  new_attribs = g_list_remove_all (new_attribs, NULL);

  /* Detach attributes from old OBJECT and attach to new OBJECT */
  old_attribs = g_list_copy (o_current->attribs);
  o_attrib_detach_all (toplevel, o_current);
  o_attrib_attach_list (toplevel, old_attribs, o_new, 1);
  g_list_free (old_attribs);

  /* Add new attributes to page */
  s_page_append_list (toplevel, page, new_attribs);

  /* Update pinnumbers for current slot */
  s_slot_update_object (toplevel, o_new);

  /* Replace old OBJECT with new OBJECT */
  s_page_replace (toplevel, page, o_current, o_new);
  s_delete_object (toplevel, o_current);

  /* Select new OBJECT */
  o_selection_add (toplevel, page->selection_list, o_new);

  /* mark the page as modified */
  toplevel->page_current->CHANGED = 1;
  o_undo_savestate (w_current, UNDO_ALL);

  return o_new;
}
Example #28
0
void
TimeManager::RemoveTimeout (guint timeout_id)
{
	runtime_get_windowing_system ()->RemoveTimeout (timeout_id);
	registered_timeouts = g_list_remove_all (registered_timeouts, GUINT_TO_POINTER (timeout_id));
}
Example #29
0
static void
update_device_list (BluetoothApplet *applet,
					gpointer user_data)
{
	GtkUIManager *uimanager;
	GList *actions, *devices, *l;
	gboolean has_devices = FALSE;

	uimanager = GTK_UI_MANAGER (gtk_builder_get_object (xml, "bluetooth-applet-ui-manager"));

	devices = bluetooth_applet_get_devices (applet);

	if (devices == NULL) {
		/* No devices? Remove everything */
		actions = gtk_action_group_list_actions (devices_action_group);
		g_list_foreach (actions, (GFunc) remove_action_item, uimanager);
		g_list_free (actions);
		goto done;
	}

	/* Get a list of actions, and we'll remove the ones with a
	 * device in the list. We remove the submenu items first */
	actions = gtk_action_group_list_actions (devices_action_group);
	for (l = actions; l != NULL; l = l->next) {
		if (bluetooth_verify_address (gtk_action_get_name (l->data)) == FALSE)
			l->data = NULL;
	}
	actions = g_list_remove_all (actions, NULL);

	for (l = devices; l != NULL; l = g_list_next (l)) {
		BluetoothSimpleDevice *device = l->data;
		GtkAction *action, *status, *oper;
		char *name;

		if (device_has_submenu (device) == FALSE) {
			g_boxed_free (BLUETOOTH_TYPE_SIMPLE_DEVICE, device);
			continue;
		}

		has_devices = TRUE;

		action = gtk_action_group_get_action (devices_action_group, device->bdaddr);
		oper = NULL;
		status = NULL;
		if (action) {
			char *action_name;

			actions = g_list_remove (actions, action);

			action_name = g_strdup_printf ("%s-status", device->bdaddr);
			status = gtk_action_group_get_action (devices_action_group, action_name);
			g_free (action_name);

			action_name = g_strdup_printf ("%s-action", device->bdaddr);
			oper = gtk_action_group_get_action (devices_action_group, action_name);
			g_free (action_name);
		}

		name = escape_label_for_action (device->alias);

		if (action == NULL) {
			guint menu_merge_id;
			char *action_path;

			/* The menu item with descendants */
			action = gtk_action_new (device->bdaddr, name, NULL, NULL);

			gtk_action_group_add_action (devices_action_group, action);
			g_object_unref (action);
			menu_merge_id = gtk_ui_manager_new_merge_id (uimanager);
			gtk_ui_manager_add_ui (uimanager, menu_merge_id,
					       "/bluetooth-applet-popup/devices-placeholder", device->bdaddr, device->bdaddr,
					       GTK_UI_MANAGER_MENU, FALSE);
			g_object_set_data_full (G_OBJECT (action),
						"merge-id", GUINT_TO_POINTER (menu_merge_id), NULL);

			/* The status menu item */
			status = add_menu_item (device->bdaddr,
						"status",
						device->connected ? _("Connected") : _("Disconnected"),
						uimanager,
						menu_merge_id,
						NULL);
			gtk_action_set_sensitive (status, FALSE);

			if (device->can_connect) {
				action_path = g_strdup_printf ("/bluetooth-applet-popup/devices-placeholder/%s/%s-status",
							       device->bdaddr, device->bdaddr);
				action_set_bold (uimanager, status, action_path);
				g_free (action_path);
			} else {
				gtk_action_set_visible (status, FALSE);
			}

			/* The connect button */
			oper = add_menu_item (device->bdaddr,
					      "action",
					      device->connected ? _("Disconnect") : _("Connect"),
					      uimanager,
					      menu_merge_id,
					      G_CALLBACK (on_connect_activate));
			if (!device->can_connect)
				gtk_action_set_visible (oper, FALSE);

			add_separator_item (device->bdaddr, "connect-sep", uimanager, menu_merge_id);

			/* The Send to... button */
			if (device->capabilities & BLUETOOTH_CAPABILITIES_OBEX_PUSH) {
				add_menu_item (device->bdaddr,
					       "sendto",
					       _("Send files..."),
					       uimanager,
					       menu_merge_id,
					       G_CALLBACK (sendto_callback));
				g_object_set_data_full (G_OBJECT (action),
							"alias", g_strdup (device->alias), g_free);
			}
			if (device->capabilities & BLUETOOTH_CAPABILITIES_OBEX_FILE_TRANSFER) {
				add_menu_item (device->bdaddr,
					       "browse",
					       _("Browse files..."),
					       uimanager,
					       menu_merge_id,
					       G_CALLBACK (browse_callback));
			}

			add_separator_item (device->bdaddr, "files-sep", uimanager, menu_merge_id);

			if (device->type == BLUETOOTH_TYPE_KEYBOARD && program_available (GNOMECC)) {
				add_menu_item (device->bdaddr,
					       "keyboard",
					       _("Keyboard Settings"),
					       uimanager,
					       menu_merge_id,
					       G_CALLBACK (keyboard_callback));
			}
			if (device->type == BLUETOOTH_TYPE_MOUSE && program_available (GNOMECC)) {
				add_menu_item (device->bdaddr,
					       "mouse",
					       _("Mouse and Touchpad Settings"),
					       uimanager,
					       menu_merge_id,
					       G_CALLBACK (mouse_callback));
			}
			if ((device->type == BLUETOOTH_TYPE_HEADSET ||
			     device->type == BLUETOOTH_TYPE_HEADPHONES ||
			     device->type == BLUETOOTH_TYPE_OTHER_AUDIO) && program_available (GNOMECC)) {
				add_menu_item (device->bdaddr,
					       "sound",
					       _("Sound Settings"),
					       uimanager,
					       menu_merge_id,
					       G_CALLBACK (sound_callback));
			}
		} else {
			gtk_action_set_label (action, name);

			if (device->can_connect) {
				gtk_action_set_visible (status, TRUE);
				gtk_action_set_visible (oper, TRUE);
				set_device_status_label (device->bdaddr, device->connected ? CONNECTED : DISCONNECTED);
				gtk_action_set_label (oper, device->connected ? _("Disconnect") : _("Connect"));
			} else {
				gtk_action_set_visible (status, FALSE);
				gtk_action_set_visible (oper, FALSE);
			}
		}
		g_free (name);

		if (oper != NULL) {
			g_object_set_data_full (G_OBJECT (oper),
						"connected", GINT_TO_POINTER (device->connected ? CONNECTED : DISCONNECTED), NULL);
			g_object_set_data_full (G_OBJECT (oper),
						"device-path", g_strdup (device->device_path), g_free);
		}

		/* And now for the trick of the day */
		if (device->connected != FALSE) {
			char *path;

			path = g_strdup_printf ("/bluetooth-applet-popup/devices-placeholder/%s", device->bdaddr);
			action_set_bold (uimanager, action, path);
			g_free (path);
		}

		g_boxed_free (BLUETOOTH_TYPE_SIMPLE_DEVICE, device);
	}

	/* Remove the left-over devices */
	g_list_foreach (actions, (GFunc) remove_action_item, uimanager);
	g_list_free (actions);

	/* Cleanup */
	g_list_free (devices);
done:
	gtk_ui_manager_ensure_update (uimanager);

	gtk_action_set_visible (GTK_ACTION (gtk_builder_get_object (xml, "devices-label")),
				has_devices);
}
Example #30
0
static void
update_device_list (GtkTreeIter *parent)
{
	GtkUIManager *uimanager;
	GtkTreeIter iter;
	gboolean cont;
	guint num_devices;
	GList *actions, *l;

	num_devices = 0;

	uimanager = GTK_UI_MANAGER (gtk_builder_get_object (xml, "bluetooth-applet-ui-manager"));

	if (parent == NULL) {
		/* No default adapter? Remove everything */
		actions = gtk_action_group_list_actions (devices_action_group);
		g_list_foreach (actions, (GFunc) remove_action_item, uimanager);
		g_list_free (actions);
		goto done;
	}

	/* Get a list of actions, and we'll remove the ones with a
	 * device in the list. We remove the submenu items first */
	actions = gtk_action_group_list_actions (devices_action_group);
	for (l = actions; l != NULL; l = l->next) {
		if (bluetooth_verify_address (gtk_action_get_name (l->data)) == FALSE)
			l->data = NULL;
	}
	actions = g_list_remove_all (actions, NULL);

	cont = gtk_tree_model_iter_children (devices_model, &iter, parent);
	while (cont) {
		GHashTable *services;
		DBusGProxy *proxy;
		char *alias, *address, **uuids, *name;
		gboolean is_connected;
		BluetoothType type;
		GtkAction *action, *status, *oper;

		gtk_tree_model_get (devices_model, &iter,
				    BLUETOOTH_COLUMN_PROXY, &proxy,
				    BLUETOOTH_COLUMN_ADDRESS, &address,
				    BLUETOOTH_COLUMN_SERVICES, &services,
				    BLUETOOTH_COLUMN_ALIAS, &alias,
				    BLUETOOTH_COLUMN_UUIDS, &uuids,
				    BLUETOOTH_COLUMN_TYPE, &type,
				    -1);

		if (device_has_submenu ((const char **) uuids, services, type) == FALSE ||
		    address == NULL || proxy == NULL || alias == NULL) {
			if (proxy != NULL)
				g_object_unref (proxy);

			if (services != NULL)
				g_hash_table_unref (services);
			g_strfreev (uuids);
			g_free (alias);
			g_free (address);
			cont = gtk_tree_model_iter_next (devices_model, &iter);
			continue;
		}

		action = gtk_action_group_get_action (devices_action_group, address);
		oper = NULL;
		status = NULL;
		if (action) {
			char *action_name;

			actions = g_list_remove (actions, action);

			action_name = g_strdup_printf ("%s-status", address);
			status = gtk_action_group_get_action (devices_action_group, action_name);
			g_free (action_name);

			action_name = g_strdup_printf ("%s-action", address);
			oper = gtk_action_group_get_action (devices_action_group, action_name);
			g_free (action_name);
		}

		/* If one service is connected, then we're connected */
		is_connected = FALSE;
		if (services != NULL) {
			GList *list, *l;

			list = g_hash_table_get_values (services);
			for (l = list; l != NULL; l = l->next) {
				BluetoothStatus val = GPOINTER_TO_INT (l->data);
				if (val == BLUETOOTH_STATUS_CONNECTED ||
				    val == BLUETOOTH_STATUS_PLAYING) {
					is_connected = TRUE;
					break;
				}
			}
			g_list_free (list);
		}

		name = escape_label_for_action (alias);

		if (action == NULL) {
			guint menu_merge_id;
			char *action_path;

			/* The menu item with descendants */
			action = gtk_action_new (address, name, NULL, NULL);

			gtk_action_group_add_action (devices_action_group, action);
			g_object_unref (action);
			menu_merge_id = gtk_ui_manager_new_merge_id (uimanager);
			gtk_ui_manager_add_ui (uimanager, menu_merge_id,
					       "/bluetooth-applet-popup/devices-placeholder", address, address,
					       GTK_UI_MANAGER_MENU, FALSE);
			g_object_set_data_full (G_OBJECT (action),
						"merge-id", GUINT_TO_POINTER (menu_merge_id), NULL);

			/* The status menu item */
			status = add_menu_item (address,
						"status",
						is_connected ? _("Connected") : _("Disconnected"),
						uimanager,
						menu_merge_id,
						NULL);
			gtk_action_set_sensitive (status, FALSE);

			if (services != NULL) {
				action_path = g_strdup_printf ("/bluetooth-applet-popup/devices-placeholder/%s/%s-status",
							       address, address);
				action_set_bold (uimanager, status, action_path);
				g_free (action_path);
			} else {
				gtk_action_set_visible (status, FALSE);
			}

			/* The connect button */
			oper = add_menu_item (address,
					      "action",
					      is_connected ? _("Disconnect") : _("Connect"),
					      uimanager,
					      menu_merge_id,
					      G_CALLBACK (on_connect_activate));
			if (services == NULL)
				gtk_action_set_visible (oper, FALSE);

			add_separator_item (address, "connect-sep", uimanager, menu_merge_id);

			/* The Send to... button */
			if (device_has_uuid ((const char **) uuids, "OBEXObjectPush") != FALSE) {
				add_menu_item (address,
					       "sendto",
					       _("Send files..."),
					       uimanager,
					       menu_merge_id,
					       G_CALLBACK (sendto_callback));
				g_object_set_data_full (G_OBJECT (action),
							"alias", g_strdup (alias), g_free);
			}
			if (device_has_uuid ((const char **) uuids, "OBEXFileTransfer") != FALSE) {
				add_menu_item (address,
					       "browse",
					       _("Browse files..."),
					       uimanager,
					       menu_merge_id,
					       G_CALLBACK (browse_callback));
			}

			add_separator_item (address, "files-sep", uimanager, menu_merge_id);

			if (type == BLUETOOTH_TYPE_KEYBOARD && program_available (KEYBOARD_PREFS)) {
				add_menu_item (address,
					       "keyboard",
					       _("Open Keyboard Preferences..."),
					       uimanager,
					       menu_merge_id,
					       G_CALLBACK (keyboard_callback));
			}
			if (type == BLUETOOTH_TYPE_MOUSE && program_available (MOUSE_PREFS)) {
				add_menu_item (address,
					       "mouse",
					       _("Open Mouse Preferences..."),
					       uimanager,
					       menu_merge_id,
					       G_CALLBACK (mouse_callback));
			}
			if ((type == BLUETOOTH_TYPE_HEADSET ||
			     type == BLUETOOTH_TYPE_HEADPHONES ||
			     type == BLUETOOTH_TYPE_OTHER_AUDIO) && program_available (SOUND_PREFS)) {
				add_menu_item (address,
					       "sound",
					       _("Open Sound Preferences..."),
					       uimanager,
					       menu_merge_id,
					       G_CALLBACK (sound_callback));
			}
		} else {
			gtk_action_set_label (action, name);

			gtk_action_set_visible (status, services != NULL);
			gtk_action_set_visible (oper, services != NULL);
			if (services != NULL) {
				set_device_status_label (address, is_connected ? CONNECTED : DISCONNECTED);
				gtk_action_set_label (oper, is_connected ? _("Disconnect") : _("Connect"));
			}
		}
		g_free (name);

		if (oper != NULL) {
			g_object_set_data_full (G_OBJECT (oper),
						"connected", GINT_TO_POINTER (is_connected ? CONNECTED : DISCONNECTED), NULL);
			g_object_set_data_full (G_OBJECT (oper),
						"device-path", g_strdup (dbus_g_proxy_get_path (proxy)), g_free);
		}

		/* And now for the trick of the day */
		if (is_connected != FALSE) {
			char *path;

			path = g_strdup_printf ("/bluetooth-applet-popup/devices-placeholder/%s", address);
			action_set_bold (uimanager, action, path);
			g_free (path);
		}

		num_devices++;

		if (proxy != NULL)
			g_object_unref (proxy);

		if (services != NULL)
			g_hash_table_unref (services);
		g_strfreev (uuids);
		g_free (alias);
		g_free (address);
		cont = gtk_tree_model_iter_next (devices_model, &iter);
	}

	/* Remove the left-over devices */
	g_list_foreach (actions, (GFunc) remove_action_item, uimanager);
	g_list_free (actions);

done:
	gtk_ui_manager_ensure_update (uimanager);

	gtk_action_set_visible (GTK_ACTION (gtk_builder_get_object (xml, "devices-label")),
				num_devices > 0);
}