2 * Copyright (C) 2009,2010,2011 Toni Gundogdu <legatvs@gmail.com>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 * @mainpage libquvi C API
24 * This documentation describes the libquvi C API.
26 * @author Toni Gundogdu
37 #include <stdint.h> /* C99 header */
40 /** @defgroup libquvi_types Types
41 * Describes the constants and the types used with the API.
45 /** @enum QUVIversion Types used with quvi_version() */
48 QUVI_VERSION
= 0x00, /**< Version string only */
49 QUVI_VERSION_LONG
/**< Version string, build date and misc. features */
52 /** @enum QUVIcode Return codes */
56 QUVI_OK
= 0x00, /**< OK */
57 QUVI_MEM
, /**< Memory allocation failed */
58 QUVI_BADHANDLE
, /**< Bad session handle */
59 QUVI_INVARG
, /**< Invalid function argument */
60 QUVI_CURLINIT
, /**< libcurl initialization failed */
61 QUVI_LAST
, /**< Indicates end of list iteration */
62 QUVI_ABORTEDBYCALLBACK
, /**< Aborted by callback function */
63 QUVI_LUAINIT
, /**< Lua initialization failure */
64 QUVI_NOLUAWEBSITE
, /**< Failed to find lua website scripts */
65 QUVI_NOLUAUTIL
, /**< Failed to find lua util scripts */
66 _INTERNAL_QUVI_LAST
, /**< For library internal use only */
67 /* Dynamically generated errors */
68 QUVI_PCRE
= 0x40, /**< libpcre error occurred @deprecated Since 0.2.9 */
69 QUVI_NOSUPPORT
, /**< libquvi does not support the website */
70 QUVI_CURL
, /**< libcurl error occurred */
71 QUVI_ICONV
, /**< libiconv error occurred */
72 QUVI_LUA
/**< lua error occurred */
75 /** @enum QUVIstatus Status codes */
78 QUVISTATUS_FETCH
= 0x00, /**< Status changed to fetch (page, config, etc.) */
79 QUVISTATUS_VERIFY
, /**< Status changed to verify media URL */
80 QUVISTATUS_SHORTENED
/**< Status changed to check for shortened URL */
83 /** @enum QUVIstatusType Status type codes */
86 /* QUVISTATUS_FETCH: */
87 QUVISTATUSTYPE_PAGE
= 0x00, /**< Fetching page */
88 QUVISTATUSTYPE_CONFIG
, /**< Fetching config */
89 QUVISTATUSTYPE_PLAYLIST
, /**< Fetching playlist */
91 QUVISTATUSTYPE_DONE
/**< General purpose "done" status type */
94 /** @enum QUVIoption Option codes to be used with quvi_setopt()
96 * If QUVIOPT_NOSHORTENED is set to >= 1, the library will not "decompress"
97 * the shortened URLs before using them. Unless shortened URLs are
98 * "decompressed", the library will report them as "unsupported".
100 * If QUVIOPT_NOVERIFY is set to >= 1, the library will not verify the
101 * media URL, and query the details (e.g. length in bytes, content type,
102 * file suffix). Unless the download URLs are verified, the library will
103 * report invalid values (0 or empty strings) for these details.
107 QUVIOPT_FORMAT
= 0x00, /**< Requested format */
108 QUVIOPT_NOVERIFY
, /**< Do not verify URL */
109 QUVIOPT_STATUSFUNCTION
, /**< Callback function for status updates */
110 QUVIOPT_WRITEFUNCTION
, /**< Callback function for writing data */
111 QUVIOPT_NOSHORTENED
, /**< Do not "decompress" shortened URLs */
112 QUVIOPT_CATEGORY
/**< Bit pattern of (OR'd) website script categories */
115 #define QUVIINFO_VOID 0x100000 /**< void type */
116 #define QUVIINFO_LONG 0x200000 /**< long type */
117 #define QUVIINFO_STRING 0x300000 /**< string type */
118 #define QUVIINFO_DOUBLE 0x400000 /**< double type */
119 #define QUVIINFO_TYPEMASK 0xf00000 /**< type mask */
121 /** @enum QUVIcategory Website script category
123 * Specify which of the website script categories the application wants
124 * to use. The library defaults to QUVIPROTO_HTTP for historical reasons.
126 * @note Consider setting the appropriate category in your application,
127 * the default behaviour is planned to change to "QUVIPROTO_ALL" in 0.2.20
130 * @sa QUVIOPT_CATEGORY
134 QUVIPROTO_HTTP
= 0x1, /**< Protocol category HTTP */
135 QUVIPROTO_MMS
= 0x2, /**< Protocol category MMS */
136 QUVIPROTO_RTSP
= 0x4, /**< Protocol category RTSP */
137 QUVIPROTO_RTMP
= 0x8, /**< Protocol category RTMP */
139 (QUVIPROTO_HTTP
|QUVIPROTO_MMS
|QUVIPROTO_RTSP
|QUVIPROTO_RTMP
)
140 /**< All protocol categories */
143 /** @enum QUVIinfo Info codes to be used with quvi_getinfo()
145 * The library creates a cURL handle which is used to fetch and
146 * verify parsed details. The cURL handle is initialized
147 * with the following libcurl options:
148 * - CURLOPT_USERAGENT ("Mozilla/5.0")
149 * - CURLOPT_FOLLOWLOCATION (1)
150 * - CURLOPT_NOBODY (0)
152 * You can, of course, override those settings in your program. You
153 * can even use the cURL handle in your program until quvi_close()
154 * is called which will release the handle. See the src/quvi.c for
155 * an example of this. Note that libquvi uses the libcurl easy
156 * interface and not the multi interface.
158 * @warning If you use the libquvi created cURL handle in your program,
159 * leave the releasing of the handle for the library to do.
163 QUVIINFO_NONE
= 0x00, /**< Unused */
164 QUVIINFO_CURL
= QUVIINFO_VOID
+ 1,/**< Session libcurl handle */
165 QUVIINFO_CURLCODE
= QUVIINFO_LONG
+ 2,/**< Last libcurl returned code */
166 QUVIINFO_HTTPCODE
= QUVIINFO_LONG
+ 3,/**< Last libcurl returned HTTP code */
167 /* Add new ones below. */
168 _QUVIINFO_LAST
= 3 /**< Placeholder */
171 #define QUVIPROPERTY_STRING 0x100000 /**< string type */
172 #define QUVIPROPERTY_LONG 0x200000 /**< long type */
173 #define QUVIPROPERTY_DOUBLE 0x300000 /**< double type */
174 #define QUVIPROPERTY_TYPEMASK 0xf00000 /**< type mask */
176 /** @enum QUVIproperty Video property codes to be used with quvi_getprop() */
179 QUVIPROP_NONE
= 0x00, /**< Unused */
180 QUVIPROP_HOSTID
= QUVIPROPERTY_STRING
+ 1, /**< Host ID */
181 QUVIPROP_PAGEURL
= QUVIPROPERTY_STRING
+ 2, /**< Page URL */
182 QUVIPROP_PAGETITLE
= QUVIPROPERTY_STRING
+ 3, /**< Page title */
183 QUVIPROP_MEDIAID
= QUVIPROPERTY_STRING
+ 4, /**< Media ID */
184 QUVIPROP_MEDIAURL
= QUVIPROPERTY_STRING
+ 5, /**< Media URL */
185 QUVIPROP_MEDIACONTENTLENGTH
= QUVIPROPERTY_DOUBLE
+ 6, /**< Media content length in bytes */
186 QUVIPROP_MEDIACONTENTTYPE
= QUVIPROPERTY_STRING
+ 7, /**< Media content-type */
187 QUVIPROP_FILESUFFIX
= QUVIPROPERTY_STRING
+ 8, /**< Parsed file suffix */
188 QUVIPROP_HTTPCODE
= QUVIPROPERTY_LONG
+ 9, /**< Last libcurl returned HTTP code */
189 QUVIPROP_FORMAT
= QUVIPROPERTY_STRING
+ 10, /**< Requested format, set using QUVIOPT_FORMAT */
190 QUVIPROP_STARTTIME
= QUVIPROPERTY_STRING
+ 11, /**< Start time for media */
191 QUVIPROP_MEDIATHUMBNAILURL
= QUVIPROPERTY_STRING
+ 12, /**< Media cover URL, if any */
192 QUVIPROP_MEDIADURATION
= QUVIPROPERTY_DOUBLE
+ 13, /**< Media duration in msecs */
193 /* Add new ones below. Bump _QUVIPROP_LAST accordingly. */
195 /* -- Deprecated as of 0.2.15. Note that these exist only for
196 * backward-compatibility. This may change in the future. New
197 * applications should use the appropriate QUVIPROP_MEDIA* enums
200 QUVIPROP_VIDEOID
= QUVIPROPERTY_STRING
+ 4, /**< Video ID
201 @deprecated Since 0.2.15, use QUVIPROP_MEDIAID instead */
202 QUVIPROP_VIDEOURL
= QUVIPROPERTY_STRING
+ 5, /**< Video URL
203 @deprecated Since 0.2.15, use QUVIPROP_MEDIAURL instead */
204 QUVIPROP_VIDEOFILELENGTH
= QUVIPROPERTY_DOUBLE
+ 6, /**< Video file
205 length @deprecated Since 0.2.15, use QUVIPROP_MEDIACONTENTLENGTH instead */
206 QUVIPROP_VIDEOFILECONTENTTYPE
= QUVIPROPERTY_STRING
+ 7, /**< Video file
207 content-type @deprecated Since 0.2.15, use QUVIPROP_MEDIACONTENTTYPE
209 QUVIPROP_VIDEOFILESUFFIX
= QUVIPROPERTY_STRING
+ 8, /**< Video file
210 suffix @deprecated Since 0.2.15, use QUVIPROP_FILESUFFIX instead */
211 QUVIPROP_VIDEOFORMAT
= QUVIPROPERTY_STRING
+ 10, /**< Requested
212 video format, set using QUVIOPT_FORMAT @deprecated Since 0.2.15, use
213 QUVIPROP_FORMAT instead */
215 _QUVIPROP_LAST
= 13 /**< Placeholder */
218 /** @brief libquvi session handle */
219 typedef void *quvi_t
;
220 /** @brief Media parsing session handle
223 typedef void *quvi_media_t
;
224 /** @brief Video parsing session handle
225 * @deprecated Since 0.2.15, use quvi_media_t instead
227 typedef void *quvi_video_t
;
230 * @brief Status callback function
232 * Callback function for status changes.
234 * @note Returning a non-zero value from the callback function will stop libquvi
238 * static int status_callback (long param, void *data)
240 * quvi_word status, type;
242 * status = quvi_loword(param);
243 * type = quvi_hiword(param);
247 * case QUVISTATUS_SHORTENED:
250 * case QUVISTATUSTYPE_DONE:
254 * printf (":: Check for shortened URL ...");
258 * case QUVISTATUS_FETCH:
261 * case QUVISTATUSTYPE_CONFIG:
262 * printf(":: Fetch config ...");
264 * case QUVISTATUSTYPE_PLAYLIST:
265 * printf(":: Fetch playlist ...");
267 * case QUVISTATUSTYPE_DONE:
271 * printf(":: Fetch %s ...",(char*)data);
275 * case QUVISTATUS_VERIFY:
278 * case QUVISTATUSTYPE_DONE:
282 * printf(":: Verify URL ...");
290 * int main (int argc, char *argv[])
294 * quvi_setopt(quvi, QUVIOPT_STATUSFUNCTION, status_callback);
299 typedef int (*quvi_callback_status
) (long param
, void *data
);
301 #define QUVI_WRITEFUNC_ABORT 0x10000000 /**< Abort writing */
304 * @brief Write callback function
306 * This function gets called by libquvi (or libcurl) as soon as
307 * there is data received that needs to be saved.
309 * @note Returning QUVI_WRITEFUNC_ABORT from the callback function will stop write
311 typedef int (*quvi_callback_write
) (char *buffer
,
316 /** @brief Word type */
317 typedef uint32_t quvi_word
;
318 /** @brief Byte type */
319 typedef uint8_t quvi_byte
;
321 /** @} */ /* End of libquvi_types group. */
324 /** @defgroup libquvi_macros Macros
325 * Describes the available macros.
329 /** @brief Return a low byte from a word type variable */
330 #define quvi_lobyte(w) ((quvi_byte)((uint64_t)(w) & 0xff))
331 /** @brief Return a high byte from a word type variable */
332 #define quvi_hibyte(w) ((quvi_byte)((uint64_t)(w) >> 8))
334 /** @brief Return a low word from a long type variable */
335 #define quvi_loword(l) ((quvi_word)((uint64_t)(l) & 0xffff))
336 /** @brief Return a high word from a long type variable */
337 #define quvi_hiword(l) ((quvi_word)((uint64_t)(l) >> 16))
339 /** @} */ /* End of libquvi_macros group. */
344 #endif /* __cplusplus */
346 /** @defgroup libquvi_api Functions
347 * Describes the available C API functions.
351 /** @defgroup libquvi_init Initializing
356 * @brief Start a new libquvi session
358 * Initializes a new session handle and locates the website scripts
359 * used to parse the page URLs. The library searches the following
360 * paths in the following order:
362 * - $QUVI_BASEDIR defined path (exclusive, overrides default search paths)
363 * - Current working directory (./lua/website/)
365 * - $HOME/.config/quvi/
366 * - $HOME/.local/share/quvi/
367 * - --datadir=DIR (and pkgdatadir) specified with configure (script)
368 * - These directories are typically $prefix/share/ and $prefix/share/quvi/
370 * Note that you can have libquvi dump (to stderr) the scanned directory paths
371 * by setting the QUVI_SHOW_SCANDIR environment variable.
373 * @param quvi Pointer to a new handle
376 * - Close each created handle with quvi_close() when done using it
377 * - libcurl will use the http_proxy environment setting if it is set
378 * - See http://curl.haxx.se/libcurl/c/curl_easy_setopt.html on how to override that
380 * @return Non-zero if an error occurred
386 * #include <quvi/quvi.h>
390 * rc = quvi_init(&quvi);
393 * fprintf(stderr, "error: libquvi: %s\n", quvi_strerror(quvi,rc));
398 QUVIcode
quvi_init(quvi_t
*quvi
);
401 /** @defgroup libquvi_release Releasing
406 * @brief End a libquvi session
408 * @param quvi Handle to a session
420 void quvi_close(quvi_t
*quvi
);
422 /** @} */ /* End of libquvi_release group. */
423 /** @} */ /* End of libquvi_init group. */
426 /** @defgroup libquvi_setup Setting up
431 * @brief Set options for a libquvi session handle
433 * @param quvi Handle to a libquvi session
434 * @param opt Option ID
435 * @param ... Parameter
437 * @return Non-zero if an error occurred
445 * quvi_setopt(quvi, QUVIOPT_FORMAT, "hd");
449 QUVIcode
quvi_setopt(quvi_t quvi
, QUVIoption opt
, ...);
452 * @brief Default write callback.
454 * This is the default write callback function that libquvi
455 * uses to write data received using libcurl.
457 * @return The number of bytes actually taken care of
459 size_t quvi_write_callback_default(void *ptr
, size_t size
, size_t nmemb
, void *stream
);
461 /** @} */ /* End of libquvi_setup group. */
464 /** @defgroup libquvi_getinfo Getting session information
469 * @brief Get information from a libquvi session handle
471 * @param quvi Handle to a libquvi session
472 * @param info Info ID
473 * @param ... Parameter
475 * @return Non-zero if an error occurred
477 * @warning Do not attempt to free the memory returned by this function
484 * long last_httpcode;
486 * quvi_getinfo(quvi, QUVIINFO_CURL, &curl);
487 * quvi_getinfo(quvi, QUVIINFO_HTTPCODE, &last_httpcode);
491 QUVIcode
quvi_getinfo(quvi_t quvi
, QUVIinfo info
, ...);
493 /** @} */ /* End of libquvi_getinfo group. */
495 /** @defgroup libquvi_parse Parsing media URLs
500 * @brief Start a new media parsing session
502 * @param quvi Handle to a session
503 * @param url Null-terminated string to an URL
504 * @param media Pointer to a new media session handle
506 * @note Close each created handle when done and/or before reusing it
508 * @return Non-zero if an error occurred
510 * @sa quvi_parse_close
515 * quvi_media_t media;
517 * quvi_parse(quvi, "http://vimeo.com/1485507", &media);
521 QUVIcode
quvi_parse(quvi_t quvi
, char *url
, quvi_media_t
*media
);
524 /** @defgroup libquvi_getprop Getting parsed media properties
529 * @brief Get media property information from a media session handle
531 * @param media Handle to a media session
532 * @param prop Property ID
533 * @param ... Parameter
535 * @return Non-zero if an error occurred
537 * @warning Do not attempt to free the memory returned by this function
545 * quvi_getprop(media, QUVIPROP_MEDIAURL, &url);
550 QUVIcode
quvi_getprop(quvi_media_t media
, QUVIproperty prop
, ...);
552 /** @} */ /* End of libquvi_getprop group. */
555 /** @defgroup libquvi_parse_util Utility functions
560 * @brief Move to the next media URL (if any)
562 * Used to iterate the parsed media URLs. Typically there is only one,
563 * although some websites have split the media into several segments.
565 * @param media Handle to a media session
567 * @return Non-zero if end of list was reached (QUVI_LAST) or an error occurred
569 * @remark Historically "cctv" website used segments
580 * quvi_getprop(media, QUVIPROP_MEDIAURL, &url);
583 * while (quvi_next_media_url(media) == QUVI_OK);
586 QUVIcode
quvi_next_media_url(quvi_media_t media
);
589 * @brief Move to the next video URL (if any)
591 * Used to iterate the parsed video URLs. Typically there is only one,
592 * although some websites have split the videos into several segments.
594 * @param video Handle to a video session
596 * @return Non-zero if end of list was reached (QUVI_LAST) or an error occurred
598 * @remark Historically "cctv" website used segments
600 * @deprecated Since 0.2.15, use quvi_next_media_url() instead
609 * quvi_getprop(media, QUVIPROP_MEDIAURL, &url);
612 * while (quvi_next_videolink(video) == QUVI_OK);
615 QUVIcode
quvi_next_videolink(quvi_video_t video
);
617 /** @} */ /* End of libquvi_parse_util group. */
620 /** @defgroup libquvi_parse_release Releasing
625 * @brief End a media parsing session
627 * @param media Pointer to a media session
634 * quvi_media_t media;
637 * quvi_parse(quvi, ..., &media);
638 * quvi_parse_close(&media);
642 void quvi_parse_close(quvi_media_t
*media
);
644 /** @} */ /* End of libquvi_parse_release group */
645 /** @} */ /* End of libquvi_parse group */
648 /** @defgroup libquvi_misc Misc. utility functions
653 * @brief Check whether the library could parse the URL
655 * The library checks the URL with each website script to see whether it
656 * could parse the URL.
658 * This function is designed to work without an Internet connection.
659 * This design has a drawback: most shortened URLs (e.g. is.gd, bit.ly,
660 * goo.gl, etc.) will fail with this function (QUVI_NOSUPPORTED).
661 * Such URLs would normally have to be resolved over an Internet
662 * connection. See also the notes.
664 * @param quvi Handle to session
665 * @param url Null-terminated string to an URL
668 * - Fails (QUVI_NOSUPPORT) with most shortened URLs (e.g. is.gd, goo.gl)
669 * - Works with a limited number of URL shorteners (youtu.be, dai.ly)
674 * - 0.2.9 - 0.2.14: Limited to basic domain name comparison
675 * - 0.2.15: Improved heuristics: Additional checks for different URL parts
677 * @return Non-zero if an error occurred
679 QUVIcode
quvi_supported(quvi_t quvi
, char *url
);
682 * @brief Return next supported website
684 * This function can be used to iterate the supported websites.
686 * @param quvi Handle to a session
687 * @param domain Pointer to a null-terminated string (e.g. "youtube.com")
688 * @param formats Pointer to a null-terminated string (e.g. "default|best|hq|hd")
690 * @return QUVI_OK or a non-zero value if an error occurred
691 * - QUVI_LAST indicates end of the list of the websites
692 * - Any other returned non-zero value indicates an actual error and
693 * should be handled accordingly (e.g. relaying the return code to
697 * - Both domain and formats string must be quvi_free()d after use
698 * - Return value QUVI_LAST is a non-zero value and indicates the end iteration
699 * - Consider handling errors
705 * while (quvi_next_supported_website(quvi, &domain, &formats) == QUVI_OK)
707 * printf("%s\t%s\n", domain, formats);
709 * quvi_free(formats);
713 QUVIcode
quvi_next_supported_website(quvi_t quvi
, char **domain
, char **formats
);
716 * @brief Next supported host
718 * Iterate the list of the supported hosts.
720 * @param domain Pointer to a null-terminated string
721 * @param formats Pointer to a null-terminated string
723 * @return QUVI_LAST (always)
725 * @deprecated Since 0.2.0, use quvi_next_supported_website() instead
727 QUVIcode
quvi_next_host(char **domain
, char **formats
);
730 * @brief Return a string describing the error code
732 * @param quvi Handle to a libquvi session
733 * @param code Error code
735 * @return Null-terminated string
737 * @warning Do not attempt to free the memory returned by this function
742 * QUVIcode rc = quvi_init(&quvi);
745 * fprintf(stderr, "error: %s\n", quvi_strerror(quvi,rc));
751 char *quvi_strerror(quvi_t quvi
, QUVIcode code
);
754 * @brief Return libquvi version
756 * @param type Version type
758 * @return Null-terminated string
760 * @warning Do not attempt to free the memory returned by this function
764 * puts( quvi_version(QUVI_VERSION_LONG) );
767 char *quvi_version(QUVIversion type
);
770 * @brief Free allocated memory
772 * @param ptr Pointer to data
774 void quvi_free(void *ptr
);
776 /** @} */ /* End of libquvi_misc group. */
777 /** @} */ /* End of libquvi_api group. */
781 #endif /* __cplusplus */
784 /* vim: set ts=2 sw=2 tw=72 expandtab: */