Merge pull request #1129 from jmarshallnz/remove_smb_auth_details_in_add_source
[vuplus_xbmc] / lib / cmyth / libcmyth / commbreak.c
1 /*
2  *  Copyright (C) 2005-2012, Jon Gettler
3  *  http://www.mvpmc.org/
4  *
5  *  This library is free software; you can redistribute it and/or
6  *  modify it under the terms of the GNU Lesser General Public
7  *  License as published by the Free Software Foundation; either
8  *  version 2.1 of the License, or (at your option) any later version.
9  *
10  *  This library is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  *  Lesser General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Lesser General Public
16  *  License along with this library; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <errno.h>
24 #include <cmyth_local.h>
25
26 static void
27 cmyth_commbreaklist_destroy(cmyth_commbreaklist_t cbl)
28 {
29         int i;
30
31         cmyth_dbg(CMYTH_DBG_DEBUG, "%s\n", __FUNCTION__);
32         if (!cbl) {
33                 return;
34         }
35         for (i = 0; i < cbl->commbreak_count; ++i) {
36                 if (cbl->commbreak_list[i]) {
37                         ref_release(cbl->commbreak_list[i]);
38                 }
39                 cbl->commbreak_list[i] = NULL;
40         }
41         if (cbl->commbreak_list) {
42                 free(cbl->commbreak_list);
43         }
44 }
45
46 cmyth_commbreaklist_t
47 cmyth_commbreaklist_create(void)
48 {
49         cmyth_commbreaklist_t ret;
50
51         cmyth_dbg(CMYTH_DBG_DEBUG, "%s\n", __FUNCTION__);
52         ret = ref_alloc(sizeof(*ret));
53         if (!ret) {
54                 return(NULL);
55         }
56         ref_set_destroy(ret, (ref_destroy_t)cmyth_commbreaklist_destroy);
57
58         ret->commbreak_list = NULL;
59         ret->commbreak_count = 0;
60         return ret;
61 }
62
63 void
64 cmyth_commbreak_destroy(cmyth_commbreak_t b)
65 {
66         cmyth_dbg(CMYTH_DBG_DEBUG, "%s {\n", __FUNCTION__);
67         if (!b) {
68                 cmyth_dbg(CMYTH_DBG_DEBUG, "%s }!a\n", __FUNCTION__);
69                 return;
70         }
71         cmyth_dbg(CMYTH_DBG_DEBUG, "%s }\n", __FUNCTION__);
72 }
73
74 cmyth_commbreak_t
75 cmyth_commbreak_create(void)
76 {
77         cmyth_commbreak_t ret = ref_alloc(sizeof(*ret));
78
79         cmyth_dbg(CMYTH_DBG_DEBUG, "%s {\n", __FUNCTION__);
80         if (!ret) {
81                 cmyth_dbg(CMYTH_DBG_DEBUG, "%s }!\n", __FUNCTION__);
82                 return NULL;
83         }
84         ref_set_destroy(ret, (ref_destroy_t)cmyth_commbreak_destroy);
85
86         ret->start_mark = 0;
87         ret->start_offset = 0;
88         ret->end_mark = 0;
89         ret->end_offset = 0;
90
91         cmyth_dbg(CMYTH_DBG_DEBUG, "%s }\n", __FUNCTION__);
92         return ret;
93 }
94
95 cmyth_commbreaklist_t
96 cmyth_get_commbreaklist(cmyth_conn_t conn, cmyth_proginfo_t prog)
97 {
98         unsigned int len = CMYTH_UTC_LEN + CMYTH_LONGLONG_LEN + 19;
99         int err;
100         int count;
101         char *buf;
102         int r;
103
104         cmyth_commbreaklist_t breaklist = cmyth_commbreaklist_create();
105
106         buf = alloca(len);
107         if (!buf) {
108                 return breaklist;
109         }
110
111         sprintf(buf,"%s %ld %i", "QUERY_COMMBREAK", prog->proginfo_chanId, 
112                 (int)cmyth_timestamp_to_unixtime(prog->proginfo_rec_start_ts));
113         pthread_mutex_lock(&mutex);
114         if ((err = cmyth_send_message(conn, buf)) < 0) {
115                 cmyth_dbg(CMYTH_DBG_ERROR,
116                         "%s: cmyth_send_message() failed (%d)\n",
117                         __FUNCTION__, err);
118                 goto out;
119         }
120
121         count = cmyth_rcv_length(conn);
122         if (count < 0) {
123                 cmyth_dbg(CMYTH_DBG_ERROR,
124                         "%s: cmyth_rcv_length() failed (%d)\n",
125                         __FUNCTION__, count);
126                 goto out;
127         }
128
129         if ((r = cmyth_rcv_commbreaklist(conn, &err, breaklist, count)) < 0) {
130                 cmyth_dbg(CMYTH_DBG_ERROR,
131                         "%s: cmyth_rcv_string() failed (%d)\n",
132                         __FUNCTION__, r);
133                 goto out;
134         }
135
136         out:
137         pthread_mutex_unlock(&mutex);
138         return breaklist;
139 }
140
141 cmyth_commbreaklist_t
142 cmyth_get_cutlist(cmyth_conn_t conn, cmyth_proginfo_t prog)
143 {
144         unsigned int len = CMYTH_UTC_LEN + CMYTH_LONGLONG_LEN + 17;
145         int err;
146         int count;
147         char *buf;
148         int r;
149
150         cmyth_commbreaklist_t breaklist = cmyth_commbreaklist_create();
151
152         buf = alloca(len);
153         if (!buf) {
154                 return breaklist;
155         }
156
157         sprintf(buf,"%s %ld %i", "QUERY_CUTLIST", prog->proginfo_chanId, 
158                 (int)cmyth_timestamp_to_unixtime(prog->proginfo_rec_start_ts));
159
160         if ((err = cmyth_send_message(conn, buf)) < 0) {
161                 cmyth_dbg(CMYTH_DBG_ERROR,
162                         "%s: cmyth_send_message() failed (%d)\n",
163                         __FUNCTION__, err);
164                 goto out;
165         }
166
167         count = cmyth_rcv_length(conn);
168         if (count < 0) {
169                 cmyth_dbg(CMYTH_DBG_ERROR,
170                         "%s: cmyth_rcv_length() failed (%d)\n",
171                         __FUNCTION__, count);
172                 goto out;
173         }
174
175         if ((r = cmyth_rcv_commbreaklist(conn, &err, breaklist, count)) < 0) {
176                 cmyth_dbg(CMYTH_DBG_ERROR,
177                         "%s: cmyth_rcv_string() failed (%d)\n",
178                         __FUNCTION__, r);
179                 goto out;
180         }
181
182         out:
183         pthread_mutex_unlock(&mutex);
184         return breaklist;
185 }
186
187 int cmyth_rcv_commbreaklist(cmyth_conn_t conn, int *err, 
188                         cmyth_commbreaklist_t breaklist, int count)
189 {
190         int consumed;
191         int total = 0;
192         long rows;
193         int64_t mark;
194         long long start = -1;
195         char *failed = NULL;
196         cmyth_commbreak_t commbreak;
197         unsigned short type;
198         unsigned short start_type;
199         int i;
200
201         if (count <= 0) {
202                 *err = EINVAL;
203                 return 0;
204         }
205
206         /*
207          * Get number of rows
208          */
209         consumed = cmyth_rcv_long(conn, err, &rows, count);
210         count -= consumed;
211         total += consumed;
212         if (*err) {
213                 failed = "cmyth_rcv_long";
214                 goto fail;
215         }
216
217         if (rows < 0) {
218                 cmyth_dbg(CMYTH_DBG_DEBUG, "%s: no commercial breaks found.\n",
219                         __FUNCTION__);
220                 return 0;
221         }
222
223         for (i = 0; i < rows; i++) {
224                 consumed = cmyth_rcv_ushort(conn, err, &type, count);
225                 count -= consumed;
226                 total += consumed;
227                 if (*err) {
228                         failed = "cmyth_rcv_ushort";
229                         goto fail;
230                 }
231
232                 consumed = cmyth_rcv_int64(conn, err, &mark, count);
233                 count -= consumed;
234                 total += consumed;
235                 if (*err) {
236                         failed = "cmyth_rcv_long long";
237                         goto fail;
238                 }
239                 if (type == CMYTH_COMMBREAK_START || type == CMYTH_CUTLIST_START) {
240                         start = mark;
241                         start_type = type;
242                 } else if (type == CMYTH_COMMBREAK_END || type == CMYTH_CUTLIST_END) {
243                         if (start >= 0 &&
244                             ((type == CMYTH_COMMBREAK_END && start_type == CMYTH_COMMBREAK_START)
245                              || (type == CMYTH_CUTLIST_END && start_type == CMYTH_CUTLIST_START)))
246                         {
247                                 commbreak = cmyth_commbreak_create();
248                                 commbreak->start_mark = start;
249                                 commbreak->end_mark = mark;
250                                 start = -1;
251                                 breaklist->commbreak_list = realloc(breaklist->commbreak_list,
252                                         (++breaklist->commbreak_count) * sizeof(cmyth_commbreak_t));
253                                 breaklist->commbreak_list[breaklist->commbreak_count - 1] = commbreak;
254                         } else {
255                                 cmyth_dbg(CMYTH_DBG_WARN,
256                                         "%s: ignoring 'end' marker without a 'start' marker at %lld\n",
257                                         __FUNCTION__, type, mark);
258                         }
259                 } else {
260                                 cmyth_dbg(CMYTH_DBG_WARN,
261                                         "%s: type (%d) is not a COMMBREAK or CUTLIST\n",
262                                         __FUNCTION__, type);
263                 }
264         }
265
266         /*
267          * If the last entry is a start marker then it doesn't have an associated end marker. In this
268          * case we choose to simply ignore it. Another option is to put in a really large fake end marker
269          * but that may cause strange seek behaviour in a client application.
270          */
271
272         return total;
273
274         fail:
275         cmyth_dbg(CMYTH_DBG_ERROR, "%s: %s() failed (%d)\n",
276                 __FUNCTION__, failed, *err);
277         return total;
278 }
279
280 cmyth_commbreaklist_t
281 cmyth_mysql_get_commbreaklist(cmyth_database_t db, cmyth_conn_t conn, cmyth_proginfo_t prog)
282 {
283         cmyth_commbreaklist_t breaklist = cmyth_commbreaklist_create();
284         char start_ts_dt[CMYTH_TIMESTAMP_LEN + 1];
285         int r;
286
287         cmyth_timestamp_to_display_string(start_ts_dt, prog->proginfo_rec_start_ts, 0);
288         pthread_mutex_lock(&mutex);
289         if ((r=cmyth_mysql_get_commbreak_list(db, prog->proginfo_chanId, start_ts_dt, breaklist, conn->conn_version)) < 0) {
290                 cmyth_dbg(CMYTH_DBG_ERROR,
291                         "%s: cmyth_mysql_get_commbreak_list() failed (%d)\n",
292                         __FUNCTION__, r);
293                 goto out;
294         }
295
296         fprintf(stderr, "Found %li commercial breaks for current program.\n", breaklist->commbreak_count);
297         if (r != breaklist->commbreak_count) {
298                 fprintf(stderr, "commbreak error.  Setting number of commercial breaks to zero\n");
299                 cmyth_dbg(CMYTH_DBG_ERROR, "%s  - returned rows=%d commbreak_count=%li\n",__FUNCTION__, r,breaklist->commbreak_count);
300                 breaklist->commbreak_count = 0;
301         }
302         out:
303         pthread_mutex_unlock(&mutex);
304         return breaklist;
305 }