renatofilho@487
|
1 |
#ifdef HAVE_CONFIG_H
|
renatofilho@487
|
2 |
#include "config.h"
|
renatofilho@487
|
3 |
#endif
|
renatofilho@487
|
4 |
|
renatofilho@487
|
5 |
#include <sys/types.h>
|
renatofilho@487
|
6 |
#include <sys/socket.h>
|
morphbr@534
|
7 |
#include <arpa/inet.h>
|
renatofilho@487
|
8 |
#include <netdb.h>
|
renatofilho@487
|
9 |
#include <netinet/in.h>
|
renatofilho@487
|
10 |
#include <unistd.h>
|
renatofilho@487
|
11 |
#include <glib.h>
|
renatofilho@487
|
12 |
#include <glib/gprintf.h>
|
renatofilho@487
|
13 |
#include <string.h>
|
morphbr@534
|
14 |
#include <stdlib.h>
|
renatofilho@520
|
15 |
|
renatofilho@487
|
16 |
#include "gmyth-stream-client.h"
|
renatofilho@487
|
17 |
|
morphbr@534
|
18 |
#define BUFFER_SIZE 1024
|
renatofilho@487
|
19 |
|
renatofilho@487
|
20 |
#define GMYTH_STREAM_CLIENT_GET_PRIVATE(obj) \
|
morphbr@534
|
21 |
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GMYTH_TYPE_STREAM_CLIENT,\
|
morphbr@534
|
22 |
GMythStreamClientPrivate))
|
morphbr@534
|
23 |
|
morphbr@534
|
24 |
|
morphbr@534
|
25 |
typedef struct _sock _socket;
|
morphbr@534
|
26 |
struct _sock
|
morphbr@534
|
27 |
{
|
morphbr@534
|
28 |
gint fd;
|
morphbr@534
|
29 |
struct sockaddr_in addr;
|
morphbr@534
|
30 |
};
|
renatofilho@487
|
31 |
|
renatofilho@487
|
32 |
|
renatofilho@487
|
33 |
typedef struct _GMythStreamClientPrivate GMythStreamClientPrivate;
|
renatofilho@487
|
34 |
struct _GMythStreamClientPrivate
|
renatofilho@487
|
35 |
{
|
morphbr@534
|
36 |
const gchar *host;
|
morphbr@534
|
37 |
_socket* sock;
|
morphbr@534
|
38 |
_socket* sock_stream;
|
morphbr@534
|
39 |
gboolean connected;
|
renatofilho@487
|
40 |
};
|
renatofilho@487
|
41 |
|
renatofilho@487
|
42 |
|
morphbr@534
|
43 |
static void gmyth_stream_client_class_init (GMythStreamClientClass *klass);
|
morphbr@534
|
44 |
static void gmyth_stream_client_init (GMythStreamClient *object);
|
morphbr@534
|
45 |
static void gmyth_stream_client_dispose (GObject *object);
|
morphbr@534
|
46 |
static void gmyth_stream_client_finalize (GObject *object);
|
renatofilho@520
|
47 |
|
renatofilho@487
|
48 |
|
renatofilho@487
|
49 |
G_DEFINE_TYPE(GMythStreamClient, gmyth_stream_client, G_TYPE_OBJECT)
|
renatofilho@487
|
50 |
|
morphbr@534
|
51 |
|
morphbr@534
|
52 |
static _socket*
|
morphbr@534
|
53 |
create_socket (const gchar* hostname, gint port)
|
morphbr@534
|
54 |
{
|
morphbr@534
|
55 |
_socket* sock = (_socket*)g_malloc(sizeof(_socket));
|
morphbr@534
|
56 |
|
morphbr@534
|
57 |
sock->fd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
morphbr@534
|
58 |
if (sock->fd == -1) {
|
morphbr@534
|
59 |
g_debug ("Fail to create sock");
|
morphbr@534
|
60 |
g_free(sock);
|
morphbr@534
|
61 |
return NULL;
|
morphbr@534
|
62 |
}
|
morphbr@534
|
63 |
|
morphbr@534
|
64 |
sock->addr.sin_family = AF_INET;
|
morphbr@534
|
65 |
sock->addr.sin_addr.s_addr = inet_addr(hostname);
|
morphbr@534
|
66 |
sock->addr.sin_port = htons(port);
|
morphbr@534
|
67 |
|
morphbr@534
|
68 |
if (connect (sock->fd, (struct sockaddr *) &(sock->addr), \
|
morphbr@534
|
69 |
sizeof (sock->addr)) == -1) {
|
morphbr@534
|
70 |
g_debug ("Fail to connect with server");
|
morphbr@534
|
71 |
g_free(sock);
|
morphbr@534
|
72 |
return NULL;
|
morphbr@534
|
73 |
}
|
morphbr@534
|
74 |
|
morphbr@534
|
75 |
return sock;
|
morphbr@534
|
76 |
}
|
morphbr@534
|
77 |
|
morphbr@534
|
78 |
static gint
|
morphbr@534
|
79 |
read_message (int socket)
|
morphbr@534
|
80 |
{
|
morphbr@534
|
81 |
gint64 total_read = 0;
|
morphbr@534
|
82 |
gint result = -1;
|
morphbr@534
|
83 |
gchar buffer[BUFFER_SIZE];
|
morphbr@534
|
84 |
gchar** response;
|
morphbr@534
|
85 |
|
morphbr@534
|
86 |
total_read = recv(socket, buffer, BUFFER_SIZE, 0);
|
morphbr@534
|
87 |
|
morphbr@534
|
88 |
if (total_read > 0) {
|
morphbr@534
|
89 |
response = g_strsplit_set(buffer, " +\n", 8);
|
morphbr@534
|
90 |
|
morphbr@534
|
91 |
if ( g_ascii_strcasecmp(response[0], "OK") == 0 ) {
|
morphbr@534
|
92 |
|
morphbr@534
|
93 |
int payload = atoi(response[1]);
|
morphbr@534
|
94 |
|
morphbr@534
|
95 |
if (payload == 0)
|
morphbr@534
|
96 |
result = 0;
|
morphbr@534
|
97 |
|
morphbr@534
|
98 |
else if (payload == 1) {
|
morphbr@534
|
99 |
total_read = recv(socket, buffer, BUFFER_SIZE, 0);
|
morphbr@534
|
100 |
|
morphbr@534
|
101 |
response = g_strsplit_set(buffer, "+\n", 8);
|
morphbr@534
|
102 |
result = atoi(response[1]);
|
morphbr@534
|
103 |
}
|
morphbr@534
|
104 |
|
morphbr@534
|
105 |
}
|
morphbr@534
|
106 |
|
morphbr@534
|
107 |
g_strfreev(response);
|
morphbr@534
|
108 |
}
|
morphbr@534
|
109 |
|
morphbr@534
|
110 |
return result;
|
morphbr@534
|
111 |
}
|
morphbr@534
|
112 |
|
morphbr@534
|
113 |
|
renatofilho@487
|
114 |
static void
|
renatofilho@487
|
115 |
gmyth_stream_client_class_init (GMythStreamClientClass *klass)
|
renatofilho@520
|
116 |
{
|
morphbr@534
|
117 |
GObjectClass *gobject_class;
|
morphbr@534
|
118 |
gobject_class = (GObjectClass *) klass;
|
renatofilho@487
|
119 |
|
morphbr@534
|
120 |
g_type_class_add_private (klass, sizeof (GMythStreamClientPrivate));
|
morphbr@534
|
121 |
gobject_class->dispose = gmyth_stream_client_dispose;
|
morphbr@534
|
122 |
gobject_class->finalize = gmyth_stream_client_finalize;
|
renatofilho@487
|
123 |
}
|
renatofilho@487
|
124 |
|
renatofilho@487
|
125 |
static void
|
renatofilho@487
|
126 |
gmyth_stream_client_init (GMythStreamClient *self)
|
renatofilho@487
|
127 |
{
|
morphbr@534
|
128 |
GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self);
|
morphbr@534
|
129 |
priv->sock = NULL;
|
morphbr@534
|
130 |
priv->sock_stream = NULL;
|
renatofilho@487
|
131 |
}
|
renatofilho@487
|
132 |
|
renatofilho@520
|
133 |
static void
|
renatofilho@487
|
134 |
gmyth_stream_client_dispose (GObject *object)
|
renatofilho@487
|
135 |
{
|
renatofilho@487
|
136 |
gmyth_stream_client_disconnect (GMYTH_STREAM_CLIENT (object));
|
renatofilho@487
|
137 |
}
|
renatofilho@487
|
138 |
|
renatofilho@487
|
139 |
|
renatofilho@520
|
140 |
static void
|
renatofilho@487
|
141 |
gmyth_stream_client_finalize (GObject *object)
|
renatofilho@487
|
142 |
{
|
renatofilho@487
|
143 |
}
|
renatofilho@487
|
144 |
|
renatofilho@520
|
145 |
GMythStreamClient*
|
renatofilho@520
|
146 |
gmyth_stream_client_new ()
|
renatofilho@487
|
147 |
{
|
morphbr@534
|
148 |
return GMYTH_STREAM_CLIENT (g_object_new (GMYTH_TYPE_STREAM_CLIENT, NULL));
|
renatofilho@487
|
149 |
}
|
renatofilho@487
|
150 |
|
renatofilho@487
|
151 |
gboolean
|
renatofilho@487
|
152 |
gmyth_stream_client_connect (GMythStreamClient *self, const gchar *server, guint port)
|
renatofilho@487
|
153 |
{
|
morphbr@534
|
154 |
GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self);
|
morphbr@534
|
155 |
g_return_val_if_fail (priv->connected == FALSE, TRUE);
|
renatofilho@487
|
156 |
|
morphbr@534
|
157 |
priv->host = server;
|
morphbr@534
|
158 |
priv->sock = create_socket (server, port);
|
morphbr@534
|
159 |
if (priv->sock == NULL) return FALSE;
|
renatofilho@487
|
160 |
|
renatofilho@487
|
161 |
priv->connected = TRUE;
|
renatofilho@487
|
162 |
return TRUE;
|
renatofilho@487
|
163 |
}
|
renatofilho@487
|
164 |
|
renatofilho@487
|
165 |
void
|
renatofilho@487
|
166 |
gmyth_stream_client_disconnect (GMythStreamClient *self)
|
renatofilho@487
|
167 |
{
|
renatofilho@487
|
168 |
GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self);
|
renatofilho@520
|
169 |
|
morphbr@534
|
170 |
g_return_if_fail (priv->connected == TRUE);
|
renatofilho@487
|
171 |
|
morphbr@534
|
172 |
close (priv->sock->fd);
|
morphbr@534
|
173 |
//shutdown (priv->sock->fd, SHUT_RDWR);
|
morphbr@569
|
174 |
g_free(priv->sock);
|
morphbr@569
|
175 |
priv->sock = NULL;
|
renatofilho@520
|
176 |
priv->connected = FALSE;
|
renatofilho@487
|
177 |
}
|
renatofilho@487
|
178 |
|
morphbr@534
|
179 |
gint
|
renatofilho@487
|
180 |
gmyth_stream_client_open_stream (GMythStreamClient *self,
|
morphbr@534
|
181 |
const gchar* file_name,
|
morphbr@534
|
182 |
const gchar* mux,
|
morphbr@534
|
183 |
const gchar* vcodec,
|
morphbr@534
|
184 |
guint vbitrate,
|
morphbr@534
|
185 |
gdouble fps,
|
morphbr@534
|
186 |
const gchar* acodec,
|
morphbr@534
|
187 |
guint abitrate,
|
morphbr@534
|
188 |
guint width, guint height,
|
morphbr@534
|
189 |
const gchar* opt)
|
renatofilho@487
|
190 |
{
|
morphbr@534
|
191 |
gchar *cmd;
|
morphbr@534
|
192 |
GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self);
|
renatofilho@520
|
193 |
|
morphbr@534
|
194 |
g_return_val_if_fail (priv->connected == TRUE, FALSE);
|
morphbr@534
|
195 |
g_return_val_if_fail (file_name != NULL, FALSE);
|
renatofilho@487
|
196 |
|
morphbr@534
|
197 |
cmd = g_strdup_printf ("SETUP %s %s %s %d %f %s %d %d %d %s\n",
|
morphbr@534
|
198 |
file_name,
|
morphbr@534
|
199 |
(mux == NULL ? "X" : mux),
|
morphbr@534
|
200 |
(vcodec == NULL ? "X" : vcodec),
|
morphbr@534
|
201 |
vbitrate,
|
morphbr@534
|
202 |
fps,
|
morphbr@534
|
203 |
(acodec == NULL ? "X" : acodec),
|
morphbr@534
|
204 |
abitrate,
|
morphbr@534
|
205 |
width, height,
|
morphbr@534
|
206 |
(opt == NULL ? "X" : opt) );
|
renatofilho@520
|
207 |
|
morphbr@534
|
208 |
if (send (priv->sock->fd, cmd, strlen (cmd), MSG_CONFIRM) == -1) {
|
morphbr@534
|
209 |
g_free (cmd);
|
morphbr@534
|
210 |
return -1;
|
morphbr@534
|
211 |
}
|
morphbr@534
|
212 |
g_free (cmd);
|
renatofilho@487
|
213 |
|
morphbr@534
|
214 |
read_message(priv->sock->fd);
|
renatofilho@520
|
215 |
|
morphbr@534
|
216 |
return 0;
|
renatofilho@520
|
217 |
}
|
renatofilho@520
|
218 |
|
morphbr@534
|
219 |
|
morphbr@534
|
220 |
gint
|
morphbr@534
|
221 |
gmyth_stream_client_play_stream (GMythStreamClient *self)
|
renatofilho@520
|
222 |
{
|
morphbr@534
|
223 |
GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self);
|
renatofilho@520
|
224 |
|
morphbr@534
|
225 |
g_return_val_if_fail (priv->connected == TRUE, FALSE);
|
renatofilho@487
|
226 |
|
morphbr@534
|
227 |
if (send (priv->sock->fd, "PLAY\n", 5, 0) == -1) {
|
morphbr@534
|
228 |
return -1;
|
morphbr@534
|
229 |
}
|
renatofilho@520
|
230 |
|
morphbr@534
|
231 |
gint port = read_message(priv->sock->fd);
|
morphbr@534
|
232 |
priv->sock_stream = create_socket(priv->host, port);
|
renatofilho@520
|
233 |
|
morphbr@534
|
234 |
return priv->sock_stream->fd;
|
renatofilho@520
|
235 |
}
|
renatofilho@487
|
236 |
|
renatofilho@487
|
237 |
void
|
morphbr@534
|
238 |
gmyth_stream_client_close_stream (GMythStreamClient *self)
|
renatofilho@487
|
239 |
{
|
morphbr@534
|
240 |
GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self);
|
morphbr@534
|
241 |
g_return_if_fail (priv->connected == TRUE);
|
renatofilho@520
|
242 |
|
morphbr@534
|
243 |
if (send (priv->sock->fd, "STOP\n", 5, 0) == -1) {
|
morphbr@534
|
244 |
return;
|
morphbr@534
|
245 |
}
|
renatofilho@520
|
246 |
|
morphbr@534
|
247 |
read_message(priv->sock->fd);
|
morphbr@534
|
248 |
|
morphbr@534
|
249 |
close(priv->sock_stream->fd);
|
morphbr@534
|
250 |
g_free(priv->sock_stream);
|
morphbr@534
|
251 |
priv->sock_stream = NULL;
|
renatofilho@487
|
252 |
}
|