2 * Copyright (C) 2004-2010, Eric Lund
3 * http://www.mvpmc.org/
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.
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.
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
21 * proglist.c - functions to manage MythTV timestamps. Primarily,
22 * these allocate timestamps and convert between string
23 * and cmyth_proglist_t and between long long and
30 #include <cmyth_local.h>
33 * cmyth_proglist_destroy(void)
35 * Scope: PRIVATE (static)
39 * Destroy and free a timestamp structure. This should only be called
40 * by ref_release(). All others should use
41 * ref_release() to release references to time stamps.
48 cmyth_proglist_destroy(cmyth_proglist_t pl)
52 cmyth_dbg(CMYTH_DBG_DEBUG, "%s\n", __FUNCTION__);
56 for (i = 0; i < pl->proglist_count; ++i) {
57 if (pl->proglist_list[i]) {
58 ref_release(pl->proglist_list[i]);
60 pl->proglist_list[i] = NULL;
62 if (pl->proglist_list) {
63 free(pl->proglist_list);
68 * cmyth_proglist_create(void)
74 * Create a timestamp structure and return a pointer to the structure.
78 * Success: A non-NULL cmyth_proglist_t (this type is a pointer)
80 * Failure: A NULL cmyth_proglist_t
83 cmyth_proglist_create(void)
87 cmyth_dbg(CMYTH_DBG_DEBUG, "%s\n", __FUNCTION__);
88 ret = ref_alloc(sizeof(*ret));
92 ref_set_destroy(ret, (ref_destroy_t)cmyth_proglist_destroy);
94 ret->proglist_list = NULL;
95 ret->proglist_count = 0;
100 * cmyth_proglist_get_item(cmyth_proglist_t pl, int index)
106 * Retrieve the program information structure found at index 'index'
107 * in the list in 'pl'. Return the program information structure
108 * held. Before forgetting the reference to this program info structure
109 * the caller must call ref_release().
113 * Success: A non-null cmyth_proginfo_t (this is a pointer type)
115 * Failure: A NULL cmyth_proginfo_t
118 cmyth_proglist_get_item(cmyth_proglist_t pl, int index)
121 cmyth_dbg(CMYTH_DBG_ERROR, "%s: NULL program list\n",
125 if (!pl->proglist_list) {
126 cmyth_dbg(CMYTH_DBG_ERROR, "%s: NULL list\n",
130 if ((index < 0) || (index >= pl->proglist_count)) {
131 cmyth_dbg(CMYTH_DBG_ERROR, "%s: index %d out of range\n",
132 __FUNCTION__, index);
135 ref_hold(pl->proglist_list[index]);
136 return pl->proglist_list[index];
140 cmyth_proglist_delete_item(cmyth_proglist_t pl, cmyth_proginfo_t prog)
143 cmyth_proginfo_t old;
147 cmyth_dbg(CMYTH_DBG_ERROR, "%s: NULL program list\n",
152 cmyth_dbg(CMYTH_DBG_ERROR, "%s: NULL program item\n",
157 pthread_mutex_lock(&mutex);
159 for (i=0; i<pl->proglist_count; i++) {
160 if (cmyth_proginfo_compare(prog, pl->proglist_list[i]) == 0) {
161 old = pl->proglist_list[i];
162 memmove(pl->proglist_list+i,
163 pl->proglist_list+i+1,
164 (pl->proglist_count-i-1)*sizeof(cmyth_proginfo_t));
165 pl->proglist_count--;
173 pthread_mutex_unlock(&mutex);
179 * cmyth_proglist_get_count(cmyth_proglist_t pl)
185 * Retrieve the number of elements in the program information
190 * Success: A number >= 0 indicating the number of items in 'pl'
195 cmyth_proglist_get_count(cmyth_proglist_t pl)
198 cmyth_dbg(CMYTH_DBG_ERROR, "%s: NULL program list\n",
202 return pl->proglist_count;
206 * cmyth_proglist_get_list(cmyth_conn_t conn,
207 * cmyth_proglist_t proglist,
208 * char *msg, char *func)
210 * Scope: PRIVATE (static)
214 * Obtain a program list from the query specified in 'msg' from the
215 * function 'func'. Make the query on 'conn' and put the results in
225 cmyth_proglist_get_list(cmyth_conn_t conn,
226 cmyth_proglist_t proglist,
227 char *msg, const char *func)
234 cmyth_dbg(CMYTH_DBG_ERROR, "%s: no connection\n", func);
238 cmyth_dbg(CMYTH_DBG_ERROR, "%s: no program list\n", func);
242 pthread_mutex_lock(&mutex);
244 if ((err = cmyth_send_message(conn, msg)) < 0) {
245 cmyth_dbg(CMYTH_DBG_ERROR,
246 "%s: cmyth_send_message() failed (%d)\n",
251 count = cmyth_rcv_length(conn);
253 cmyth_dbg(CMYTH_DBG_ERROR,
254 "%s: cmyth_rcv_length() failed (%d)\n",
259 if (strcmp(msg, "QUERY_GETALLPENDING") == 0) {
262 if ((r=cmyth_rcv_long(conn, &err, &c, count)) < 0) {
263 cmyth_dbg(CMYTH_DBG_ERROR,
264 "%s: cmyth_rcv_length() failed (%d)\n",
271 if (cmyth_rcv_proglist(conn, &err, proglist, count) != count) {
272 cmyth_dbg(CMYTH_DBG_ERROR,
273 "%s: cmyth_rcv_proglist() < count\n",
277 cmyth_dbg(CMYTH_DBG_ERROR,
278 "%s: cmyth_rcv_proglist() failed (%d)\n",
287 pthread_mutex_unlock(&mutex);
293 * cmyth_proglist_get_all_recorded(cmyth_conn_t control,
294 * cmyth_proglist_t *proglist)
300 * Make a request on the control connection 'control' to obtain a list
301 * of completed or in-progress recordings. Build a list of program
302 * information structures and put a malloc'ed pointer to the list (an
303 * array of pointers) in proglist.
307 * Success: A held, noon-NULL cmyth_proglist_t
312 cmyth_proglist_get_all_recorded(cmyth_conn_t control)
315 cmyth_proglist_t proglist = cmyth_proglist_create();
317 if (proglist == NULL) {
318 cmyth_dbg(CMYTH_DBG_ERROR,
319 "%s: cmyth_proglist_create() failed\n",
324 if (control->conn_version < 65) {
325 strcpy(query, "QUERY_RECORDINGS Play");
328 strcpy(query, "QUERY_RECORDINGS Ascending");
330 if (cmyth_proglist_get_list(control, proglist,
333 cmyth_dbg(CMYTH_DBG_ERROR,
334 "%s: cmyth_proglist_get_list() failed\n",
336 ref_release(proglist);
343 * cmyth_proglist_get_all_pending(cmyth_conn_t control,
344 * cmyth_proglist_t *proglist)
350 * Make a request on the control connection 'control' to obtain a list
351 * of pending recordings. Build a list of program information
352 * structures and put a malloc'ed pointer to the list (an array of
353 * pointers) in proglist.
357 * Success: A held, noon-NULL cmyth_proglist_t
362 cmyth_proglist_get_all_pending(cmyth_conn_t control)
364 cmyth_proglist_t proglist = cmyth_proglist_create();
366 if (proglist == NULL) {
367 cmyth_dbg(CMYTH_DBG_ERROR,
368 "%s: cmyth_proglist_create() failed\n",
373 if (cmyth_proglist_get_list(control, proglist,
374 "QUERY_GETALLPENDING",
376 cmyth_dbg(CMYTH_DBG_ERROR,
377 "%s: cmyth_proglist_get_list() failed\n",
379 ref_release(proglist);
386 * cmyth_proglist_get_all_scheduled(cmyth_conn_t control,
387 * cmyth_proglist_t *proglist)
393 * Make a request on the control connection 'control' to obtain a list
394 * of scheduled recordings. Build a list of program information
395 * structures and put a malloc'ed pointer to the list (an array of
396 * pointers) in proglist.
400 * Success: A held, noon-NULL cmyth_proglist_t
405 cmyth_proglist_get_all_scheduled(cmyth_conn_t control)
407 cmyth_proglist_t proglist = cmyth_proglist_create();
409 if (proglist == NULL) {
410 cmyth_dbg(CMYTH_DBG_ERROR,
411 "%s: cmyth_proglist_create() failed\n",
416 if (cmyth_proglist_get_list(control, proglist,
417 "QUERY_GETALLSCHEDULED",
419 cmyth_dbg(CMYTH_DBG_ERROR,
420 "%s: cmyth_proglist_get_list() failed\n",
422 ref_release(proglist);
429 * cmyth_proglist_get_conflicting(cmyth_conn_t control,
430 * cmyth_proglist_t *proglist)
436 * Make a request on the control connection 'control' to obtain a list
437 * of conflicting recordings. Build a list of program information
438 * structures and put a malloc'ed pointer to the list (an array of
439 * pointers) in proglist.
443 * Success: A held, noon-NULL cmyth_proglist_t
448 cmyth_proglist_get_conflicting(cmyth_conn_t control)
450 cmyth_proglist_t proglist = cmyth_proglist_create();
452 if (proglist == NULL) {
453 cmyth_dbg(CMYTH_DBG_ERROR,
454 "%s: cmyth_proglist_create() failed\n",
459 if (cmyth_proglist_get_list(control, proglist,
460 "QUERY_GETCONFLICTING",
462 cmyth_dbg(CMYTH_DBG_ERROR,
463 "%s: cmyth_proglist_get_list() failed\n",
465 ref_release(proglist);
472 * sort_timestamp(const void *a, const void *b)
478 * Return an integer value to specify the relative position of the timestamp
479 * This is a helper function for the sort function called by qsort. It will
480 * sort any of the timetstamps for the qsort functions
489 static int sort_timestamp(cmyth_timestamp_t X, cmyth_timestamp_t Y)
492 if (X->timestamp_year > Y->timestamp_year)
494 else if (X->timestamp_year < Y->timestamp_year)
496 else /* X->timestamp_year == Y->timestamp_year */
498 if (X->timestamp_month > Y->timestamp_month)
500 else if (X->timestamp_month < Y->timestamp_month)
502 else /* X->timestamp_month == Y->timestamp_month */
504 if (X->timestamp_day > Y->timestamp_day)
506 else if (X->timestamp_day < Y->timestamp_day)
508 else /* X->timestamp_day == Y->timestamp_day */
510 if (X->timestamp_hour > Y->timestamp_hour)
512 else if (X->timestamp_hour < Y->timestamp_hour)
514 else /* X->timestamp_hour == Y->timestamp_hour */
516 if (X->timestamp_minute > Y->timestamp_minute)
518 else if (X->timestamp_minute < Y->timestamp_minute)
520 else /* X->timestamp_minute == Y->timestamp_minute */
522 if (X->timestamp_second > Y->timestamp_second)
524 else if (X->timestamp_second < Y->timestamp_second)
526 else /* X->timestamp_second == Y->timestamp_second */
536 * recorded_compare(const void *a, const void *b)
542 * Return an integer value to a qsort function to specify the relative
543 * position of the recorded date
553 recorded_compare(const void *a, const void *b)
555 const cmyth_proginfo_t x = *(cmyth_proginfo_t *)a;
556 const cmyth_proginfo_t y = *(cmyth_proginfo_t *)b;
557 cmyth_timestamp_t X = x->proginfo_rec_start_ts;
558 cmyth_timestamp_t Y = y->proginfo_rec_start_ts;
560 return sort_timestamp(X, Y);
564 * airdate_compare(const void *a, const void *b)
570 * Return an integer value to a qsort function to specify the relative
571 * position of the original airdate
581 airdate_compare(const void *a, const void *b)
583 const cmyth_proginfo_t x = *(cmyth_proginfo_t *)a;
584 const cmyth_proginfo_t y = *(cmyth_proginfo_t *)b;
585 const cmyth_timestamp_t X = x->proginfo_originalairdate;
586 const cmyth_timestamp_t Y = y->proginfo_originalairdate;
588 return sort_timestamp(X, Y);
592 * cmyth_proglist_sort(cmyth_proglist_t pl, int count, int sort)
598 * Sort the epispde list by mythtv_sort setting. Check to ensure that the
599 * program list is not null and pass the proglist_list to the qsort function
607 cmyth_proglist_sort(cmyth_proglist_t pl, int count, cmyth_proglist_sort_t sort)
610 cmyth_dbg(CMYTH_DBG_ERROR, "%s: NULL program list\n",
614 if (!pl->proglist_list) {
615 cmyth_dbg(CMYTH_DBG_ERROR, "%s: NULL list\n",
620 cmyth_dbg(CMYTH_DBG_ERROR,
621 "cmyth_proglist_sort\n");
624 case MYTHTV_SORT_DATE_RECORDED: /* Default Date Recorded */
625 qsort((cmyth_proginfo_t)pl->proglist_list, count, sizeof(pl->proglist_list) , recorded_compare);
627 case MYTHTV_SORT_ORIGINAL_AIRDATE: /*Default Date Recorded */
628 qsort((cmyth_proginfo_t)pl->proglist_list, count, sizeof(pl->proglist_list) , airdate_compare);
631 printf("Unsupported MythTV sort type\n");
634 cmyth_dbg(CMYTH_DBG_ERROR,
635 "end cmyth_proglist_sort\n");