summaryrefslogtreecommitdiff
path: root/src/util.c
blob: 186251e79ad0222a858e9c4f236939ae8849098b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include "util.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <glib.h>

#include <gst/base/gstbytewriter.h>

gpointer
cmumble_find_by_id(GList *list, gsize member_offset, guint id)
{
	gpointer el = NULL;
	GList *l;

	for (l = list; l; l = l->next) {
		if (G_STRUCT_MEMBER(uint32_t, l->data, member_offset) == id) {
			el = l->data;
			break;
		}
	}

	return el;
}

gchar *
cmumble_get_os_name(void)
{
	FILE *f;
	char *line = NULL;
	char *os = NULL, *value, *end;
	size_t key_len = strlen("PRETTY_NAME=");
	size_t n;

	f = fopen("/etc/os-release", "r");
	if (f == NULL)
		return NULL;

	while (getline(&line, &n, f) != -1) {
		if (strncmp("PRETTY_NAME=", line, key_len) == 0 && (n - key_len) > 1) {
			value = &line[key_len];
			if (strlen(value) == 0)
				continue;

			end = &value[strlen(value) - 1];
			if (*end == '\n')
				*end-- = '\0';

			if (strlen(value) < 2)
				continue;

			if (value[0] == '"')
				value++;

			if (*end == '"')
				*end = '\0';

			os = strdup(value);
			goto out;
		}
	}

out:
	free(line);
	fclose(f);
	return os;
}

/* This code is taken from gst-plugins-bad/ext/opus/gstopusheader.c */
GstBuffer *
_gst_opus_enc_create_id_buffer(gint nchannels, gint n_stereo_streams,
			       gint sample_rate, guint8 channel_mapping_family,
			       const guint8 *channel_mapping)
{
  GstBuffer *buffer;
  GstByteWriter bw;
  gboolean hdl = TRUE;

  g_return_val_if_fail (nchannels > 0 && nchannels < 256, NULL);
  g_return_val_if_fail (n_stereo_streams >= 0, NULL);
  g_return_val_if_fail (n_stereo_streams <= nchannels - n_stereo_streams, NULL);

  gst_byte_writer_init (&bw);

  /* See http://wiki.xiph.org/OggOpus */
  hdl &= gst_byte_writer_put_data (&bw, (const guint8 *) "OpusHead", 8);
  hdl &= gst_byte_writer_put_uint8 (&bw, 0x01); /* version number */
  hdl &= gst_byte_writer_put_uint8 (&bw, nchannels);
  hdl &= gst_byte_writer_put_uint16_le (&bw, 0);        /* pre-skip */
  hdl &= gst_byte_writer_put_uint32_le (&bw, sample_rate);
  hdl &= gst_byte_writer_put_uint16_le (&bw, 0);        /* output gain */
  hdl &= gst_byte_writer_put_uint8 (&bw, channel_mapping_family);
  if (channel_mapping_family > 0) {
    hdl &= gst_byte_writer_put_uint8 (&bw, nchannels - n_stereo_streams);
    hdl &= gst_byte_writer_put_uint8 (&bw, n_stereo_streams);
    hdl &= gst_byte_writer_put_data (&bw, channel_mapping, nchannels);
  }

  if (!hdl)
    GST_WARNING ("Error creating header");

  buffer = gst_byte_writer_reset_and_get_buffer (&bw);

  GST_BUFFER_OFFSET (buffer) = 0;
  GST_BUFFER_OFFSET_END (buffer) = 0;

  return buffer;
}

static int
create_gst_buffer_array (GValue *array, GstBuffer * buf, ...)
{
  va_list va;
  GValue value = { 0 };

  g_value_init (array, GST_TYPE_ARRAY);

  va_start (va, buf);
  /* put buffers in a fixed list */
  while (buf) {
    g_assert (gst_buffer_is_writable (buf));

    /* mark buffer */
    GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);

    g_value_init (&value, GST_TYPE_BUFFER);
    buf = gst_buffer_copy (buf);
    GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
    gst_value_set_buffer (&value, buf);
    gst_buffer_unref (buf);
    gst_value_array_append_value (&array, &value);
    g_value_unset (&value);

    buf = va_arg (va, GstBuffer *);
  }

  return 0;