# HG changeset patch # User renatofilho # Date 1170355321 0 # Node ID 22a17127789ea88195c42ed85f7d17f87e023de7 # Parent 69382cca242eb0eb08a15222e41df76a35bb5aa4 [svn r322] created branch gmyth-0.1b diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/AUTHORS --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/AUTHORS Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,4 @@ +Alexsandro Jose Virginio dos Santos +Hallyson Luiz de Morais Melo +Leonardo Sobral Cunha +Rosfran Lins Borges diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/COPYING --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/COPYING Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/ChangeLog --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/ChangeLog Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,24 @@ +2006-08-17 Rosfran Borges + * Added the correct gstreamer-base package (GSTBASE) at the configure.ac; + GSTBASE_CFLAGS and GSTBASE_LIBS variables had the same values from + the GST_CFLAGS/GST_LIBS. + +2006-08-16 Rosfran Borges + * Fixed some installation issues, regarding lib-installing to the + correct directory, and copying the header files to the destination + dir (make install). + * Put 'pkg-config' resource to the Maemo Myth library. The name of the + PKG-CONFIG resource is 'maemo-myth', plus the minor and major version. + Actually, the version is '0.1', so the library config file is: + 'maemo-myth-0.1.pc'. You can type: 'pkg-config --cflags --libs + maemo-myth-0.1'. + * Many adjustments in the automake/autoconf configuration files + (configure.ac, Makefile.am) - some autotools misusage fixed. + * Added the MythURI structure, and the URI parsing utility functions + (missing in the GLib). + * Some functions were exported (myth_socket, gmyth_context), that's + why many ther modules need to use them. + * Fixed some library dependencies. + * Prepared to be used inside the GStreamer (linking with the MythTV + plug-in). + diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/INSTALL --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/INSTALL Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,229 @@ +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software +Foundation, Inc. + + This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. (Caching is +disabled by default to prevent problems with accidental use of stale +cache files.) + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You only need +`configure.ac' if you want to change it or regenerate `configure' using +a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not support the `VPATH' +variable, you have to compile the package for one architecture at a +time in the source code directory. After you have installed the +package for one architecture, use `make distclean' before reconfiguring +for another architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the `--target=TYPE' option to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +will cause the specified gcc to be used as the C compiler (unless it is +overridden in the site shell script). + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of the options to `configure', and exit. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/Makefile.am --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/Makefile.am Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,23 @@ +SUBDIRS= src + +### all of the standard pc files we need to generate +pcfiles = gmyth-@GMYTH_MAJORMINOR@.pc + +all-local: $(pcfiles) + +### how to generate pc files +%-@GMYTH_MAJORMINOR@.pc: %.pc + cp $< $@ + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = $(pcfiles) + +include aminclude.am + +EXTRA_DIST = \ + autogen.sh \ + gmyth.pc.in \ + AUTHORS \ + COPYING \ + README + diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/aminclude.am --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/aminclude.am Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,186 @@ +# Copyright (C) 2004 Oren Ben-Kiki +# This file is distributed under the same terms as the Automake macro files. + +# Generate automatic documentation using Doxygen. Goals and variables values +# are controlled by the various DX_COND_??? conditionals set by autoconf. +# +# The provided goals are: +# doxygen-doc: Generate all doxygen documentation. +# doxygen-run: Run doxygen, which will generate some of the documentation +# (HTML, CHM, CHI, MAN, RTF, XML) but will not do the post +# processing required for the rest of it (PS, PDF, and some MAN). +# doxygen-man: Rename some doxygen generated man pages. +# doxygen-ps: Generate doxygen PostScript documentation. +# doxygen-pdf: Generate doxygen PDF documentation. +# +# Note that by default these are not integrated into the automake goals. If +# doxygen is used to generate man pages, you can achieve this integration by +# setting man3_MANS to the list of man pages generated and then adding the +# dependency: +# +# $(man3_MANS): doxygen-doc +# +# This will cause make to run doxygen and generate all the documentation. +# +# The following variable is intended for use in Makefile.am: +# +# DX_CLEANFILES = everything to clean. +# +# This is usually added to MOSTLYCLEANFILES. + +## --------------------------------- ## +## Format-independent Doxygen rules. ## +## --------------------------------- ## + +if DX_COND_doc + +## ------------------------------- ## +## Rules specific for HTML output. ## +## ------------------------------- ## + +if DX_COND_html + +DX_CLEAN_HTML = @DX_DOCDIR@/html + +endif DX_COND_html + +## ------------------------------ ## +## Rules specific for CHM output. ## +## ------------------------------ ## + +if DX_COND_chm + +DX_CLEAN_CHM = @DX_DOCDIR@/chm + +if DX_COND_chi + +DX_CLEAN_CHI = @DX_DOCDIR@/@PACKAGE@.chi + +endif DX_COND_chi + +endif DX_COND_chm + +## ------------------------------ ## +## Rules specific for MAN output. ## +## ------------------------------ ## + +if DX_COND_man + +DX_CLEAN_MAN = @DX_DOCDIR@/man + +endif DX_COND_man + +## ------------------------------ ## +## Rules specific for RTF output. ## +## ------------------------------ ## + +if DX_COND_rtf + +DX_CLEAN_RTF = @DX_DOCDIR@/rtf + +endif DX_COND_rtf + +## ------------------------------ ## +## Rules specific for XML output. ## +## ------------------------------ ## + +if DX_COND_xml + +DX_CLEAN_XML = @DX_DOCDIR@/xml + +endif DX_COND_xml + +## ----------------------------- ## +## Rules specific for PS output. ## +## ----------------------------- ## + +if DX_COND_ps + +DX_CLEAN_PS = @DX_DOCDIR@/@PACKAGE@.ps + +DX_PS_GOAL = doxygen-ps + +doxygen-ps: @DX_DOCDIR@/@PACKAGE@.ps + +@DX_DOCDIR@/@PACKAGE@.ps: @DX_DOCDIR@/@PACKAGE@.tag + cd @DX_DOCDIR@/latex; \ + rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \ + $(DX_LATEX) refman.tex; \ + $(MAKEINDEX_PATH) refman.idx; \ + $(DX_LATEX) refman.tex; \ + countdown=5; \ + while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \ + refman.log > /dev/null 2>&1 \ + && test $$countdown -gt 0; do \ + $(DX_LATEX) refman.tex; \ + countdown=`expr $$countdown - 1`; \ + done; \ + $(DX_DVIPS) -o ../@PACKAGE@.ps refman.dvi + +endif DX_COND_ps + +## ------------------------------ ## +## Rules specific for PDF output. ## +## ------------------------------ ## + +if DX_COND_pdf + +DX_CLEAN_PDF = @DX_DOCDIR@/@PACKAGE@.pdf + +DX_PDF_GOAL = doxygen-pdf + +doxygen-pdf: @DX_DOCDIR@/@PACKAGE@.pdf + +@DX_DOCDIR@/@PACKAGE@.pdf: @DX_DOCDIR@/@PACKAGE@.tag + cd @DX_DOCDIR@/latex; \ + rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \ + $(DX_PDFLATEX) refman.tex; \ + $(DX_MAKEINDEX) refman.idx; \ + $(DX_PDFLATEX) refman.tex; \ + countdown=5; \ + while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \ + refman.log > /dev/null 2>&1 \ + && test $$countdown -gt 0; do \ + $(DX_PDFLATEX) refman.tex; \ + countdown=`expr $$countdown - 1`; \ + done; \ + mv refman.pdf ../@PACKAGE@.pdf + +endif DX_COND_pdf + +## ------------------------------------------------- ## +## Rules specific for LaTeX (shared for PS and PDF). ## +## ------------------------------------------------- ## + +if DX_COND_latex + +DX_CLEAN_LATEX = @DX_DOCDIR@/latex + +endif DX_COND_latex + +.PHONY: doxygen-run doxygen-doc $(DX_PS_GOAL) $(DX_PDF_GOAL) + +.INTERMEDIATE: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL) + +doxygen-run: @DX_DOCDIR@/@PACKAGE@.tag + +doxygen-doc: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL) + +@DX_DOCDIR@/@PACKAGE@.tag: $(DX_CONFIG) $(pkginclude_HEADERS) + rm -rf @DX_DOCDIR@ + $(DX_ENV) $(DX_DOXYGEN) $(srcdir)/$(DX_CONFIG) + +DX_CLEANFILES = \ + @DX_DOCDIR@/@PACKAGE@.tag \ + -r \ + $(DX_CLEAN_HTML) \ + $(DX_CLEAN_CHM) \ + $(DX_CLEAN_CHI) \ + $(DX_CLEAN_MAN) \ + $(DX_CLEAN_RTF) \ + $(DX_CLEAN_XML) \ + $(DX_CLEAN_PS) \ + $(DX_CLEAN_PDF) \ + $(DX_CLEAN_LATEX) + +endif DX_COND_doc diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/autogen.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/autogen.sh Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,102 @@ +#!/bin/sh +# Run this to generate all the initial makefiles, etc. + +DIE=0 +package=gmyth +srcfile=configure.ac + +# a quick cvs co if necessary to alleviate the pain - may remove this +# when developers get a clue ;) +if test ! -d common; +then + echo "+ getting common/ from svn" + svn co common +fi + +# source helper functions +if test ! -f common/autogen-helper.sh; +then + echo There is something wrong with your source tree. + echo You are missing common/autogen-helper.sh + exit 1 +fi +. common/autogen-helper.sh + +CONFIGURE_DEF_OPT='--enable-maintainer-mode' +# uncomment below to disable the UPnP features +CONFIGURE_DEF_OPT="$CONFIGURE_DEF_OPT --disable-upnp" +CONFIGURE_EXT_OPT="$@" + +autogen_options + +echo -n "+ check for build tools" +if test ! -z "$NOCHECK"; then echo " skipped"; else echo; fi +version_check "autoconf" "$AUTOCONF autoconf autoconf-2.54 autoconf-2.53" \ + "ftp://ftp.gnu.org/pub/gnu/autoconf/" 2 53 || DIE=1 +version_check "automake" "$AUTOMAKE automake automake-1.9 automake-1.8 automake-1.7 automake-1.6" \ + "ftp://ftp.gnu.org/pub/gnu/automake/" 1 6 || DIE=1 +version_check "libtoolize" "$LIBTOOLIZE libtoolize" \ + "ftp://ftp.gnu.org/pub/gnu/libtool/" 1 5 0 || DIE=1 +version_check "pkg-config" "" \ + "http://www.freedesktop.org/software/pkgconfig" 0 8 0 || DIE=1 + +die_check $DIE + +aclocal_check || DIE=1 +autoheader_check || DIE=1 + +die_check $DIE + +# if no arguments specified then this will be printed +if test -z "$*"; then + echo "+ checking for autogen.sh options" + echo " This autogen script will automatically run ./configure as:" + echo " ./configure $CONFIGURE_DEF_OPT $CONFIGURE_EXT_OPT" + echo " To pass any additional options, please specify them on the $0" + echo " command line." +fi + +toplevel_check $srcfile + +tool_run "$aclocal" "-I m4 $ACLOCAL_FLAGS" +tool_run "$libtoolize" "--copy --force" +tool_run "$autoheader" + +# touch the stamp-h.in build stamp so we don't re-run autoheader in maintainer mode -- wingo +echo timestamp > stamp-h.in 2> /dev/null + +tool_run "$autoconf" +tool_run "$automake" "-a -c" + +# if enable exists, add an -enable option for each of the lines in that file +if test -f enable; then + for a in `cat enable`; do + CONFIGURE_FILE_OPT="--enable-$a" + done +fi + +# if disable exists, add an -disable option for each of the lines in that file +if test -f disable; then + for a in `cat disable`; do + CONFIGURE_FILE_OPT="$CONFIGURE_FILE_OPT --disable-$a" + done +fi + +test -n "$NOCONFIGURE" && { + echo "+ skipping configure stage for package $package, as requested." + echo "+ autogen.sh done." + exit 0 +} + +echo "+ running configure ... " +test ! -z "$CONFIGURE_DEF_OPT" && echo " ./configure default flags: $CONFIGURE_DEF_OPT" +test ! -z "$CONFIGURE_EXT_OPT" && echo " ./configure external flags: $CONFIGURE_EXT_OPT" +test ! -z "$CONFIGURE_FILE_OPT" && echo " ./configure enable/disable flags: $CONFIGURE_FILE_OPT" +echo + +./configure $CONFIGURE_DEF_OPT $CONFIGURE_EXT_OPT $CONFIGURE_FILE_OPT || { + echo " configure failed" + exit 1 +} + +echo "Now type 'make' to compile $package." diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/common/Makefile.am --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/common/Makefile.am Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,1 @@ +EXTRA_DIST = autogen-helper.sh diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/common/autogen-helper.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/common/autogen-helper.sh Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,302 @@ +# a silly hack that generates autoregen.sh but it's handy +echo "#!/bin/sh" > autoregen.sh +echo "./autogen.sh $@ \$@" >> autoregen.sh +chmod +x autoregen.sh + +# helper functions for autogen.sh + +debug () +# print out a debug message if DEBUG is a defined variable +{ + if test ! -z "$DEBUG" + then + echo "DEBUG: $1" + fi +} + +version_check () +# check the version of a package +# first argument : package name (executable) +# second argument : optional path where to look for it instead +# third argument : source download url +# rest of arguments : major, minor, micro version +# all consecutive ones : suggestions for binaries to use +# (if not specified in second argument) +{ + PACKAGE=$1 + PKG_PATH=$2 + URL=$3 + MAJOR=$4 + MINOR=$5 + MICRO=$6 + + # for backwards compatibility, we let PKG_PATH=PACKAGE when PKG_PATH null + if test -z "$PKG_PATH"; then PKG_PATH=$PACKAGE; fi + debug "major $MAJOR minor $MINOR micro $MICRO" + VERSION=$MAJOR + if test ! -z "$MINOR"; then VERSION=$VERSION.$MINOR; else MINOR=0; fi + if test ! -z "$MICRO"; then VERSION=$VERSION.$MICRO; else MICRO=0; fi + + debug "major $MAJOR minor $MINOR micro $MICRO" + + for SUGGESTION in $PKG_PATH; do + COMMAND="$SUGGESTION" + + # don't check if asked not to + test -z "$NOCHECK" && { + echo -n " checking for $COMMAND >= $VERSION ... " + } || { + # we set a var with the same name as the package, but stripped of + # unwanted chars + VAR=`echo $PACKAGE | sed 's/-//g'` + debug "setting $VAR" + eval $VAR="$COMMAND" + return 0 + } + + debug "checking version with $COMMAND" + ($COMMAND --version) < /dev/null > /dev/null 2>&1 || + { + echo "not found." + continue + } + # strip everything that's not a digit, then use cut to get the first field + pkg_version=`$COMMAND --version|head -n 1|sed 's/^[^0-9]*//'|cut -d' ' -f1` + debug "pkg_version $pkg_version" + # remove any non-digit characters from the version numbers to permit numeric + # comparison + pkg_major=`echo $pkg_version | cut -d. -f1 | sed s/[a-zA-Z\-].*//g` + pkg_minor=`echo $pkg_version | cut -d. -f2 | sed s/[a-zA-Z\-].*//g` + pkg_micro=`echo $pkg_version | cut -d. -f3 | sed s/[a-zA-Z\-].*//g` + test -z "$pkg_major" && pkg_major=0 + test -z "$pkg_minor" && pkg_minor=0 + test -z "$pkg_micro" && pkg_micro=0 + debug "found major $pkg_major minor $pkg_minor micro $pkg_micro" + + #start checking the version + debug "version check" + + # reset check + WRONG= + + if [ ! "$pkg_major" -gt "$MAJOR" ]; then + debug "major: $pkg_major <= $MAJOR" + if [ "$pkg_major" -lt "$MAJOR" ]; then + debug "major: $pkg_major < $MAJOR" + WRONG=1 + elif [ ! "$pkg_minor" -gt "$MINOR" ]; then + debug "minor: $pkg_minor <= $MINOR" + if [ "$pkg_minor" -lt "$MINOR" ]; then + debug "minor: $pkg_minor < $MINOR" + WRONG=1 + elif [ "$pkg_micro" -lt "$MICRO" ]; then + debug "micro: $pkg_micro < $MICRO" + WRONG=1 + fi + fi + fi + + if test ! -z "$WRONG"; then + echo "found $pkg_version, not ok !" + continue + else + echo "found $pkg_version, ok." + # we set a var with the same name as the package, but stripped of + # unwanted chars + VAR=`echo $PACKAGE | sed 's/-//g'` + debug "setting $VAR" + eval $VAR="$COMMAND" + return 0 + fi + done + + echo "not found !" + echo "You must have $PACKAGE installed to compile $package." + echo "Download the appropriate package for your distribution," + echo "or get the source tarball at $URL" + return 1; +} + +aclocal_check () +{ + # normally aclocal is part of automake + # so we expect it to be in the same place as automake + # so if a different automake is supplied, we need to adapt as well + # so how's about replacing automake with aclocal in the set var, + # and saving that in $aclocal ? + # note, this will fail if the actual automake isn't called automake* + # or if part of the path before it contains it + if [ -z "$automake" ]; then + echo "Error: no automake variable set !" + return 1 + else + aclocal=`echo $automake | sed s/automake/aclocal/` + debug "aclocal: $aclocal" + if [ "$aclocal" != "aclocal" ]; + then + CONFIGURE_DEF_OPT="$CONFIGURE_DEF_OPT --with-aclocal=$aclocal" + fi + if [ ! -x `which $aclocal` ]; then + echo "Error: cannot execute $aclocal !" + return 1 + fi + fi +} + +autoheader_check () +{ + # same here - autoheader is part of autoconf + # use the same voodoo + if [ -z "$autoconf" ]; then + echo "Error: no autoconf variable set !" + return 1 + else + autoheader=`echo $autoconf | sed s/autoconf/autoheader/` + debug "autoheader: $autoheader" + if [ "$autoheader" != "autoheader" ]; + then + CONFIGURE_DEF_OPT="$CONFIGURE_DEF_OPT --with-autoheader=$autoheader" + fi + if [ ! -x `which $autoheader` ]; then + echo "Error: cannot execute $autoheader !" + return 1 + fi + fi + +} + +autoconf_2_52d_check () +{ + # autoconf 2.52d has a weird issue involving a yes:no error + # so don't allow it's use + test -z "$NOCHECK" && { + ac_version=`$autoconf --version|head -n 1|sed 's/^[a-zA-Z\.\ ()]*//;s/ .*$//'` + if test "$ac_version" = "2.52d"; then + echo "autoconf 2.52d has an issue with our current build." + echo "We don't know who's to blame however. So until we do, get a" + echo "regular version. RPM's of a working version are on the gstreamer site." + exit 1 + fi + } + return 0 +} + +die_check () +{ + # call with $DIE + # if set to 1, we need to print something helpful then die + DIE=$1 + if test "x$DIE" = "x1"; + then + echo + echo "- Please get the right tools before proceeding." + echo "- Alternatively, if you're sure we're wrong, run with --nocheck." + exit 1 + fi +} + +autogen_options () +{ + if test "x$1" = "x"; then + return 0 + fi + + while test "x$1" != "x" ; do + optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` + case "$1" in + --noconfigure) + NOCONFIGURE=defined + AUTOGEN_EXT_OPT="$AUTOGEN_EXT_OPT --noconfigure" + echo "+ configure run disabled" + shift + ;; + --nocheck) + AUTOGEN_EXT_OPT="$AUTOGEN_EXT_OPT --nocheck" + NOCHECK=defined + echo "+ autotools version check disabled" + shift + ;; + --debug) + DEBUG=defined + AUTOGEN_EXT_OPT="$AUTOGEN_EXT_OPT --debug" + echo "+ debug output enabled" + shift + ;; + --prefix=*) + CONFIGURE_EXT_OPT="$CONFIGURE_EXT_OPT --prefix=$optarg" + echo "+ passing --prefix=$optarg to configure" + shift + ;; + --prefix) + shift + echo "DEBUG: $1" + CONFIGURE_EXT_OPT="$CONFIGURE_EXT_OPT --prefix=$1" + echo "+ passing --prefix=$1 to configure" + shift + ;; + -h|--help) + echo "autogen.sh (autogen options) -- (configure options)" + echo "autogen.sh help options: " + echo " --noconfigure don't run the configure script" + echo " --nocheck don't do version checks" + echo " --debug debug the autogen process" + echo " --prefix will be passed on to configure" + echo + echo " --with-autoconf PATH use autoconf in PATH" + echo " --with-automake PATH use automake in PATH" + echo + echo "to pass options to configure, put them as arguments after -- " + exit 1 + ;; + --with-automake=*) + AUTOMAKE=$optarg + echo "+ using alternate automake in $optarg" + CONFIGURE_DEF_OPT="$CONFIGURE_DEF_OPT --with-automake=$AUTOMAKE" + shift + ;; + --with-autoconf=*) + AUTOCONF=$optarg + echo "+ using alternate autoconf in $optarg" + CONFIGURE_DEF_OPT="$CONFIGURE_DEF_OPT --with-autoconf=$AUTOCONF" + shift + ;; + --disable*|--enable*|--with*) + echo "+ passing option $1 to configure" + CONFIGURE_EXT_OPT="$CONFIGURE_EXT_OPT $1" + shift + ;; + --) shift ; break ;; + *) echo "- ignoring unknown autogen.sh argument $1"; shift ;; + esac + done + + for arg do CONFIGURE_EXT_OPT="$CONFIGURE_EXT_OPT $arg"; done + if test ! -z "$CONFIGURE_EXT_OPT" + then + echo "+ options passed to configure: $CONFIGURE_EXT_OPT" + fi +} + +toplevel_check () +{ + srcfile=$1 + test -f $srcfile || { + echo "You must run this script in the top-level $package directory" + exit 1 + } +} + + +tool_run () +{ + tool=$1 + options=$2 + run_if_fail=$3 + echo "+ running $tool $options..." + $tool $options || { + echo + echo $tool failed + eval $run_if_fail + exit 1 + } +} diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/configure.ac --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/configure.ac Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,182 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ(2.50) + +AC_INIT([gmyth],[0.1]) + +dnl AC_CONFIG_SRCDIR([src/mmyth_main.c]) +AC_CONFIG_HEADER(config.h) + +dnl when going to/from release please set the nano (fourth number) right ! +dnl releases only do Wall, SVN and prerelease does Werror too +AS_VERSION(gmyth, GMYTH, 0, 1, 0, 3, GMYTH_SVN="no", GMYTH_SVN="yes") +GMYTH_MAJORMINOR=$GMYTH_MAJOR_VERSION.$GMYTH_MINOR_VERSION +AC_SUBST(GMYTH_MAJORMINOR) + +dnl AM_MAINTAINER_MODE provides the option to enable maintainer mode +AM_MAINTAINER_MODE +dnl make aclocal work in maintainer mode +AC_SUBST(ACLOCAL_AMFLAGS, "-I m4") + +# Checks for programs. +# check for tools +# Make sure CFLAGS is defined to stop AC_PROC_CC adding -g +CFLAGS="$CFLAGS -Wall" +AC_PROG_CC +AC_PROG_LIBTOOL + +dnl Generate doxygen documentation +DX_HTML_FEATURE(ON) +DX_CHM_FEATURE(OFF) +DX_CHI_FEATURE(OFF) +DX_MAN_FEATURE(OFF) +DX_RTF_FEATURE(OFF) +DX_XML_FEATURE(OFF) +DX_PDF_FEATURE(OFF) +DX_PS_FEATURE(OFF) +DX_INIT_DOXYGEN(gmyth, doxygen.cfg, docs) + +# Checks for libraries. + +# Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS([fcntl.h stdint.h stdlib.h string.h sys/ioctl.h sys/socket.h unistd.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_TYPE_PID_T +AC_STRUCT_TM +AC_HEADER_TIME +AC_HEADER_STDBOOL + +# Checks for library functions. +AC_FUNC_FORK +AC_FUNC_STRFTIME +AC_FUNC_SELECT_ARGTYPES +AC_PROG_GCC_TRADITIONAL +AC_FUNC_MALLOC +AC_FUNC_MKTIME +AC_FUNC_STRFTIME +AC_FUNC_VPRINTF +AC_CHECK_FUNCS([memset socket stime strstr strtoul gethostname inet_ntoa localtime_r select strrchr localtime strptime]) + +############################## +# Checks for Network functions +############################## + +AC_CHECK_FUNCS([socket]) +AC_CHECK_FUNCS([inet_ntoa]) +AC_CHECK_HEADERS([ifaddrs.h]) +AC_CHECK_FUNCS([getifaddrs]) +AC_CHECK_FUNCS([time]) + +AM_INIT_AUTOMAKE($PACKAGE, $VERSION) + +CFLAGS="$CFLAGS -I/usr/include" +LDFLAGS="$LDFLAGS -L/usr/lib" + +# Checks required packages + +dnl Test if --disable-debug given +AC_ARG_ENABLE(debug, + AC_HELP_STRING([--disable-debug], [enable debugging mode])) +if test x"$enable_debug" != xno; then + CFLAGS="$CFLAGS -g -DGMYTH_USE_DEBUG" +else + CFLAGS="$CFLAGS -O2 -DG_DISABLE_CHECKS" +fi + +# Check for pkgconfig +AC_CHECK_PROG(HAVE_PKGCONFIG, pkg-config, yes, no) +# Give error and exit if we don't have pkgconfig +if test "x$HAVE_PKGCONFIG" = "xno"; then + AC_MSG_ERROR(you need to have pkgconfig installed !) +fi + +# Check for Glib2.0 +PKG_CHECK_MODULES(GLIB, glib-2.0, HAVE_GLIB=yes,HAVE_GLIB=no) + +# Give error and exit if we don't have glib +if test "x$HAVE_GLIB" = "xno"; then + AC_MSG_ERROR(you need glib-2.0 installed) +fi + +# make GLIB_CFLAGS and GLIB_LIBS available +AC_SUBST(GLIB_CFLAGS) +AC_SUBST(GLIB_LIBS) + +# Check for GObject2.0 +PKG_CHECK_MODULES(GOBJECT, + gobject-2.0, + HAVE_GOBJECT=yes, HAVE_GOBJECT=no) + +# Give error and exit if we don't have gobject +if test "x$HAVE_GOBJECT" = "xno"; then + AC_MSG_ERROR(you need gobject-2.0 installed) +fi + +# make GOBJECT_CFLAGS and GOBJECT_LIBS available +AC_SUBST(GOBJECT_CFLAGS) +AC_SUBST(GOBJECT_LIBS) + +# Check for libxml-2.0 +PKG_CHECK_MODULES(LIBXML, libxml-2.0, HAVE_LIBXML=yes,HAVE_LIBXML=no) + +# Give error and exit if we don't have libxml +if test "x$HAVE_LIBXML" = "xno"; then + AC_MSG_ERROR(you need libxml-2.0 installed) +fi + +# make LIBXML_CFLAGS and LIBXML_LIBS available +AC_SUBST(LIBXML_CFLAGS) +AC_SUBST(LIBXML_LIBS) + +# Check for libcurl +PKG_CHECK_MODULES(LIBCURL, libcurl, HAVE_LIBCRUL=yes, HAVE_LIBCURL=no) + +# Give error and exit if we don't have libcurl +if test "x$HAVE_LIBCURL" = "xno"; then + AC_MSG_ERROR(you need libcurl installed) +fi + +# make LIBCURL_CFLAGS and LIBCURL_LIBS available +AC_SUBST(LIBCURL_CFLAGS) +AC_SUBST(LIBCURL_LIBS) + + +# +# mysql libraries +# +AC_CHECK_PROG(MYSQL_CFLAGS,mysql_config,`mysql_config --cflags`) +if test -z "$MYSQL_CFLAGS"; then + AC_MSG_ERROR([Could not find mysql_config script. Make sure the mysql client libraries are installed]) +fi +AC_SUBST(MYSQL_CFLAGS) + + +AC_CHECK_PROG(MYSQL_LIBS,mysql_config,`mysql_config --libs`) +if test -z "$MYSQL_LIBS"; then + AC_MSG_ERROR([Could not find mysql_config script. Make sure the mysql client libraries are installed]) +fi +AC_SUBST(MYSQL_LIBS) + +#dnl Enable gtk-doc +#GTK_DOC_CHECK(1.4) + +AC_SUBST(CFLAGS) +AC_SUBST(LDFLAGS) +AC_SUBST(LIBS) + +AC_OUTPUT([ +Makefile +src/Makefile +tests/Makefile +gmyth.pc]) + +if test "x$enable_debug" != "xno"; then + AC_MSG_NOTICE([Debug: Enabled]) +else + AC_MSG_NOTICE([Debug: Disabled]) +fi + diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/data/settings/history.dat --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/data/settings/history.dat Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,3 @@ +# MIPTV history file +# Stores the last network frequency used +602000000 diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/debian/changelog --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/debian/changelog Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,6 @@ +gmyth (0.1-indt1) unstable; urgency=low + + * Initial Maemo Package. + + -- Hallyson Melo Fri, 15 Sep 2006 10:26:16 -0300 + diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/debian/compat --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/debian/compat Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,1 @@ +4 diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/debian/control --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/debian/control Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,19 @@ +Source: gmyth +Priority: optional +Maintainer: Hallyson Melo +Build-Depends: debhelper (>= 4.0.0) +Standards-Version: 3.6.2 +Section: libs + +Package: gmyth +Section: libs +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, libcurl3 +Description: The gmyth library binary files. GMyth is a library intended to access mythtv backend functionalities from a glib/gobject perspective. It includes access to the program guide, recorded programs, scheduling, etc. + +Package: gmyth-dev +Section: libdevel +Architecture: any +Depends: gmyth (= ${Source-Version}), libcurl3, libcurl3-openssl-dev +Description: The gmyth library development files. GMyth is a library intended to access mythtv backend functionalities from a glib/gobject perspective. It includes access to the program guide, recorded programs, scheduling, etc. + diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/debian/gmyth-dev.install --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/debian/gmyth-dev.install Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,6 @@ +debian/tmp/usr/include/* +debian/tmp/usr/lib/lib*.a +debian/tmp/usr/lib/lib*.so +debian/tmp/usr/lib/pkgconfig/* +debian/tmp/usr/lib/*.la +debian/tmp/usr/share/pkgconfig/* diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/debian/gmyth.install --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/debian/gmyth.install Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,1 @@ +debian/tmp/usr/lib/lib*.so.* diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/debian/rules --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/debian/rules Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,20 @@ +#!/usr/bin/make -f + +include /usr/share/cdbs/1/rules/debhelper.mk +include /usr/share/cdbs/1/class/autotools.mk +include /usr/share/cdbs/1/rules/simple-patchsys.mk +include /usr/share/cdbs/1/rules/utils.mk + +# debian package version +version=$(shell dpkg-parsechangelog | grep ^Version: | cut -d ' ' -f 2) + +maint: debian/control + +common_conf_flags = \ + --disable-debug + +# FIXME: should disable docs for arch only builds +DEB_CONFIGURE_EXTRA_FLAGS := $(common_conf_flags) + + +.PHONY: maint diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/doxygen.cfg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/doxygen.cfg Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,212 @@ +# Doxyfile 1.4.2 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = $(PROJECT)-$(VERSION) +PROJECT_NUMBER = +OUTPUT_DIRECTORY = $(DOCDIR) +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +USE_WINDOWS_ENCODING = NO +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = YES +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +STRIP_FROM_INC_PATH = $(SRCDIR)/src/libgmyth +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = $(SRCDIR)/src/libgmyth +SHORT_NAMES = YES +JAVADOC_AUTOBRIEF = YES +MULTILINE_CPP_IS_BRIEF = NO +DETAILS_AT_TOP = YES +INHERIT_DOCS = YES +DISTRIBUTE_GROUP_DOC = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = YES +OPTIMIZE_OUTPUT_JAVA = NO +SUBGROUPING = YES +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = YES +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = YES +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = NO +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +SORT_BRIEF_DOCS = NO +SORT_BY_SCOPE_NAME = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = YES +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = $(SRCDIR)/src/libgmyth +FILE_PATTERNS = *.c *.h +RECURSIVE = YES +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXAMPLE_PATH = $(SRCDIR)/src/gui +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = YES +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +VERBATIM_HEADERS = YES +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = NO +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = $(GENERATE_HTML) +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +GENERATE_HTMLHELP = $(GENERATE_CHM) +CHM_FILE = ../$(PROJECT).chm +HHC_LOCATION = $(HHC_PATH) +GENERATE_CHI = $(GENERATE_CHI) +BINARY_TOC = YES +TOC_EXPAND = YES +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = YES +TREEVIEW_WIDTH = 250 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = $(GENERATE_LATEX) +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = $(PAPER_SIZE) +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = NO +USE_PDFLATEX = NO +LATEX_BATCHMODE = YES +LATEX_HIDE_INDICES = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = $(GENERATE_RTF) +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = $(GENERATE_MAN) +MAN_OUTPUT = man +MAN_EXTENSION = .1 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = $(GENERATE_XML) +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = $(DOCDIR)/$(PROJECT).tag +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = $(PERL_PATH) +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = $(HAVE_DOT) +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +UML_LOOK = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = $(DOT_PATH) +DOTFILE_DIRS = +MAX_DOT_GRAPH_WIDTH = 1024 +MAX_DOT_GRAPH_HEIGHT = 1024 +MAX_DOT_GRAPH_DEPTH = 0 +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/gmyth.pc.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/gmyth.pc.in Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,12 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: gmyth +Description: Myth TV library based upon GLib/GObject paradigm +Version: @VERSION@ +Requires: gobject-2.0 glib-2.0 libcurl + +Libs: @MYSQL_LIBS@ -L${libdir} -lgmyth -lcurl +Cflags: -I${includedir}/gmyth diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/m4/AUTHORS --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/m4/AUTHORS Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,4 @@ +Alexsandro Jose Virginio dos Santos +Hallyson Luiz de Morais Melo +Leonardo Sobral Cunha +Rosfran Lins Borges diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/m4/COPYING --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/m4/COPYING Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/m4/ChangeLog --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/m4/ChangeLog Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,24 @@ +2006-08-17 Rosfran Borges + * Added the correct gstreamer-base package (GSTBASE) at the configure.ac; + GSTBASE_CFLAGS and GSTBASE_LIBS variables had the same values from + the GST_CFLAGS/GST_LIBS. + +2006-08-16 Rosfran Borges + * Fixed some installation issues, regarding lib-installing to the + correct directory, and copying the header files to the destination + dir (make install). + * Put 'pkg-config' resource to the Maemo Myth library. The name of the + PKG-CONFIG resource is 'maemo-myth', plus the minor and major version. + Actually, the version is '0.1', so the library config file is: + 'maemo-myth-0.1.pc'. You can type: 'pkg-config --cflags --libs + maemo-myth-0.1'. + * Many adjustments in the automake/autoconf configuration files + (configure.ac, Makefile.am) - some autotools misusage fixed. + * Added the MythURI structure, and the URI parsing utility functions + (missing in the GLib). + * Some functions were exported (myth_socket, mmyth_context), that's + why many ther modules need to use them. + * Fixed some library dependencies. + * Prepared to be used inside the GStreamer (linking with the MythTV + plug-in). + diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/m4/INSTALL --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/m4/INSTALL Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,236 @@ +Installation Instructions +************************* + +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free +Software Foundation, Inc. + +This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + +Basic Installation +================== + +These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. (Caching is +disabled by default to prevent problems with accidental use of stale +cache files.) + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You only need +`configure.ac' if you want to change it or regenerate `configure' using +a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + +Some systems require unusual options for compilation or linking that the +`configure' script does not know about. Run `./configure --help' for +details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + +You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not support the `VPATH' +variable, you have to compile the package for one architecture at a +time in the source code directory. After you have installed the +package for one architecture, use `make distclean' before reconfiguring +for another architecture. + +Installation Names +================== + +By default, `make install' installs the package's commands under +`/usr/local/bin', include files under `/usr/local/include', etc. You +can specify an installation prefix other than `/usr/local' by giving +`configure' the option `--prefix=PREFIX'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +pass the option `--exec-prefix=PREFIX' to `configure', the package uses +PREFIX as the prefix for installing programs and libraries. +Documentation and other data files still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=DIR' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + +Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + +There may be some features `configure' cannot figure out automatically, +but needs to determine by the type of machine the package will run on. +Usually, assuming the package is built to be run on the _same_ +architectures, `configure' can figure that out, but if it prints a +message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the option `--target=TYPE' to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + +If you want to set default values for `configure' scripts to share, you +can create a site shell script called `config.site' that gives default +values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + +Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +causes the specified `gcc' to be used as the C compiler (unless it is +overridden in the site shell script). Here is a another example: + + /bin/bash ./configure CONFIG_SHELL=/bin/bash + +Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent +configuration-related scripts to be executed by `/bin/bash'. + +`configure' Invocation +====================== + +`configure' recognizes the following options to control how it operates. + +`--help' +`-h' + Print a summary of the options to `configure', and exit. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/m4/Makefile.am --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/m4/Makefile.am Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,10 @@ +SUBDIRS= src pixmaps + +include aminclude.am + +EXTRA_DIST = \ + autogen.sh \ + AUTHORS \ + COPYING \ + README + diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/m4/ac_doxygen.m4 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/m4/ac_doxygen.m4 Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,312 @@ +# This file is part of Autoconf. -*- Autoconf -*- + +# Copyright (C) 2004 Oren Ben-Kiki +# This file is distributed under the same terms as the Autoconf macro files. + +# Generate automatic documentation using Doxygen. Works in concert with the +# aminclude.m4 file and a compatible doxygen configuration file. Defines the +# following public macros: +# +# DX_???_FEATURE(ON|OFF) - control the default setting fo a Doxygen feature. +# Supported features are 'DOXYGEN' itself, 'DOT' for generating graphics, +# 'HTML' for plain HTML, 'CHM' for compressed HTML help (for MS users), 'CHI' +# for generating a seperate .chi file by the .chm file, and 'MAN', 'RTF', +# 'XML', 'PDF' and 'PS' for the appropriate output formats. The environment +# variable DOXYGEN_PAPER_SIZE may be specified to override the default 'a4wide' +# paper size. +# +# By default, HTML, PDF and PS documentation is generated as this seems to be +# the most popular and portable combination. MAN pages created by Doxygen are +# usually problematic, though by picking an appropriate subset and doing some +# massaging they might be better than nothing. CHM and RTF are specific for MS +# (note that you can't generate both HTML and CHM at the same time). The XML is +# rather useless unless you apply specialized post-processing to it. +# +# The macro mainly controls the default state of the feature. The use can +# override the default by specifying --enable or --disable. The macros ensure +# that contradictory flags are not given (e.g., --enable-doxygen-html and +# --enable-doxygen-chm, --enable-doxygen-anything with --disable-doxygen, etc.) +# Finally, each feature will be automatically disabled (with a warning) if the +# required programs are missing. +# +# Once all the feature defaults have been specified, call DX_INIT_DOXYGEN with +# the following parameters: a one-word name for the project for use as a +# filename base etc., an optional configuration file name (the default is +# 'Doxyfile', the same as Doxygen's default), and an optional output directory +# name (the default is 'doxygen-doc'). + +## ----------## +## Defaults. ## +## ----------## + +DX_ENV="" +AC_DEFUN([DX_FEATURE_doc], ON) +AC_DEFUN([DX_FEATURE_dot], ON) +AC_DEFUN([DX_FEATURE_man], OFF) +AC_DEFUN([DX_FEATURE_html], ON) +AC_DEFUN([DX_FEATURE_chm], OFF) +AC_DEFUN([DX_FEATURE_chi], OFF) +AC_DEFUN([DX_FEATURE_rtf], OFF) +AC_DEFUN([DX_FEATURE_xml], OFF) +AC_DEFUN([DX_FEATURE_pdf], ON) +AC_DEFUN([DX_FEATURE_ps], ON) + +## --------------- ## +## Private macros. ## +## --------------- ## + +# DX_ENV_APPEND(VARIABLE, VALUE) +# ------------------------------ +# Append VARIABLE="VALUE" to DX_ENV for invoking doxygen. +AC_DEFUN([DX_ENV_APPEND], [AC_SUBST([DX_ENV], ["$DX_ENV $1='$2'"])]) + +# DX_DIRNAME_EXPR +# --------------- +# Expand into a shell expression prints the directory part of a path. +AC_DEFUN([DX_DIRNAME_EXPR], + [[expr ".$1" : '\(\.\)[^/]*$' \| "x$1" : 'x\(.*\)/[^/]*$']]) + +# DX_IF_FEATURE(FEATURE, IF-ON, IF-OFF) +# ------------------------------------- +# Expands according to the M4 (static) status of the feature. +AC_DEFUN([DX_IF_FEATURE], [ifelse(DX_FEATURE_$1, ON, [$2], [$3])]) + +# DX_REQUIRE_PROG(VARIABLE, PROGRAM) +# ---------------------------------- +# Require the specified program to be found for the DX_CURRENT_FEATURE to work. +AC_DEFUN([DX_REQUIRE_PROG], [ +AC_PATH_TOOL([$1], [$2]) +if test "$DX_FLAG_[]DX_CURRENT_FEATURE$$1" = 1; then + AC_MSG_WARN([$2 not found - will not DX_CURRENT_DESCRIPTION]) + AC_SUBST([DX_FLAG_[]DX_CURRENT_FEATURE], 0) +fi +]) + +# DX_TEST_FEATURE(FEATURE) +# ------------------------ +# Expand to a shell expression testing whether the feature is active. +AC_DEFUN([DX_TEST_FEATURE], [test "$DX_FLAG_$1" = 1]) + +# DX_CHECK_DEPEND(REQUIRED_FEATURE, REQUIRED_STATE) +# ------------------------------------------------- +# Verify that a required features has the right state before trying to turn on +# the DX_CURRENT_FEATURE. +AC_DEFUN([DX_CHECK_DEPEND], [ +test "$DX_FLAG_$1" = "$2" \ +|| AC_MSG_ERROR([doxygen-DX_CURRENT_FEATURE ifelse([$2], 1, + requires, contradicts) doxygen-DX_CURRENT_FEATURE]) +]) + +# DX_CLEAR_DEPEND(FEATURE, REQUIRED_FEATURE, REQUIRED_STATE) +# ---------------------------------------------------------- +# Turn off the DX_CURRENT_FEATURE if the required feature is off. +AC_DEFUN([DX_CLEAR_DEPEND], [ +test "$DX_FLAG_$1" = "$2" || AC_SUBST([DX_FLAG_[]DX_CURRENT_FEATURE], 0) +]) + +# DX_FEATURE_ARG(FEATURE, DESCRIPTION, +# CHECK_DEPEND, CLEAR_DEPEND, +# REQUIRE, DO-IF-ON, DO-IF-OFF) +# -------------------------------------------- +# Parse the command-line option controlling a feature. CHECK_DEPEND is called +# if the user explicitly turns the feature on (and invokes DX_CHECK_DEPEND), +# otherwise CLEAR_DEPEND is called to turn off the default state if a required +# feature is disabled (using DX_CLEAR_DEPEND). REQUIRE performs additional +# requirement tests (DX_REQUIRE_PROG). Finally, an automake flag is set and +# DO-IF-ON or DO-IF-OFF are called according to the final state of the feature. +AC_DEFUN([DX_ARG_ABLE], [ + AC_DEFUN([DX_CURRENT_FEATURE], [$1]) + AC_DEFUN([DX_CURRENT_DESCRIPTION], [$2]) + AC_ARG_ENABLE(doxygen-$1, + [AS_HELP_STRING(DX_IF_FEATURE([$1], [--disable-doxygen-$1], + [--enable-doxygen-$1]), + DX_IF_FEATURE([$1], [don't $2], [$2]))], + [ +case "$enableval" in +#( +y|Y|yes|Yes|YES) + AC_SUBST([DX_FLAG_$1], 1) + $3 +;; #( +n|N|no|No|NO) + AC_SUBST([DX_FLAG_$1], 0) +;; #( +*) + AC_MSG_ERROR([invalid value '$enableval' given to doxygen-$1]) +;; +esac +], [ +AC_SUBST([DX_FLAG_$1], [DX_IF_FEATURE([$1], 1, 0)]) +$4 +]) +if DX_TEST_FEATURE([$1]); then + $5 + : +fi +if DX_TEST_FEATURE([$1]); then + AM_CONDITIONAL(DX_COND_$1, :) + $6 + : +else + AM_CONDITIONAL(DX_COND_$1, false) + $7 + : +fi +]) + +## -------------- ## +## Public macros. ## +## -------------- ## + +# DX_XXX_FEATURE(DEFAULT_STATE) +# ----------------------------- +AC_DEFUN([DX_DOXYGEN_FEATURE], [AC_DEFUN([DX_FEATURE_doc], [$1])]) +AC_DEFUN([DX_MAN_FEATURE], [AC_DEFUN([DX_FEATURE_man], [$1])]) +AC_DEFUN([DX_HTML_FEATURE], [AC_DEFUN([DX_FEATURE_html], [$1])]) +AC_DEFUN([DX_CHM_FEATURE], [AC_DEFUN([DX_FEATURE_chm], [$1])]) +AC_DEFUN([DX_CHI_FEATURE], [AC_DEFUN([DX_FEATURE_chi], [$1])]) +AC_DEFUN([DX_RTF_FEATURE], [AC_DEFUN([DX_FEATURE_rtf], [$1])]) +AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])]) +AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])]) +AC_DEFUN([DX_PDF_FEATURE], [AC_DEFUN([DX_FEATURE_pdf], [$1])]) +AC_DEFUN([DX_PS_FEATURE], [AC_DEFUN([DX_FEATURE_ps], [$1])]) + +# DX_INIT_DOXYGEN(PROJECT, [CONFIG-FILE], [OUTPUT-DOC-DIR]) +# --------------------------------------------------------- +# PROJECT also serves as the base name for the documentation files. +# The default CONFIG-FILE is "Doxyfile" and OUTPUT-DOC-DIR is "doxygen-doc". +AC_DEFUN([DX_INIT_DOXYGEN], [ + +# Files: +AC_SUBST([DX_PROJECT], [$1]) +AC_SUBST([DX_CONFIG], [ifelse([$2], [], Doxyfile, [$2])]) +AC_SUBST([DX_DOCDIR], [ifelse([$3], [], doxygen-doc, [$3])]) + +# Environment variables used inside doxygen.cfg: +DX_ENV_APPEND(SRCDIR, $srcdir) +DX_ENV_APPEND(PROJECT, $DX_PROJECT) +DX_ENV_APPEND(DOCDIR, $DX_DOCDIR) +DX_ENV_APPEND(VERSION, $PACKAGE_VERSION) + +# Doxygen itself: +DX_ARG_ABLE(doc, [generate any doxygen documentation], + [], + [], + [DX_REQUIRE_PROG([DX_DOXYGEN], doxygen) + DX_REQUIRE_PROG([DX_PERL], perl)], + [DX_ENV_APPEND(PERL_PATH, $DX_PERL)]) + +# Dot for graphics: +DX_ARG_ABLE(dot, [generate graphics for doxygen documentation], + [DX_CHECK_DEPEND(doc, 1)], + [DX_CLEAR_DEPEND(doc, 1)], + [DX_REQUIRE_PROG([DX_DOT], dot)], + [DX_ENV_APPEND(HAVE_DOT, YES) + DX_ENV_APPEND(DOT_PATH, [`DX_DIRNAME_EXPR($DX_DOT)`])], + [DX_ENV_APPEND(HAVE_DOT, NO)]) + +# Man pages generation: +DX_ARG_ABLE(man, [generate doxygen manual pages], + [DX_CHECK_DEPEND(doc, 1)], + [DX_CLEAR_DEPEND(doc, 1)], + [], + [DX_ENV_APPEND(GENERATE_MAN, YES)], + [DX_ENV_APPEND(GENERATE_MAN, NO)]) + +# RTF file generation: +DX_ARG_ABLE(rtf, [generate doxygen RTF documentation], + [DX_CHECK_DEPEND(doc, 1)], + [DX_CLEAR_DEPEND(doc, 1)], + [], + [DX_ENV_APPEND(GENERATE_RTF, YES)], + [DX_ENV_APPEND(GENERATE_RTF, NO)]) + +# XML file generation: +DX_ARG_ABLE(xml, [generate doxygen XML documentation], + [DX_CHECK_DEPEND(doc, 1)], + [DX_CLEAR_DEPEND(doc, 1)], + [], + [DX_ENV_APPEND(GENERATE_XML, YES)], + [DX_ENV_APPEND(GENERATE_XML, NO)]) + +# (Compressed) HTML help generation: +DX_ARG_ABLE(chm, [generate doxygen compressed HTML help documentation], + [DX_CHECK_DEPEND(doc, 1)], + [DX_CLEAR_DEPEND(doc, 1)], + [DX_REQUIRE_PROG([DX_HHC], hhc)], + [DX_ENV_APPEND(HHC_PATH, $DX_HHC) + DX_ENV_APPEND(GENERATE_HTML, YES) + DX_ENV_APPEND(GENERATE_HTMLHELP, YES)], + [DX_ENV_APPEND(GENERATE_HTMLHELP, NO)]) + +# Seperate CHI file generation. +DX_ARG_ABLE(chi, [generate doxygen seperate compressed HTML help index file], + [DX_CHECK_DEPEND(chm, 1)], + [DX_CLEAR_DEPEND(chm, 1)], + [], + [DX_ENV_APPEND(GENERATE_CHI, YES)], + [DX_ENV_APPEND(GENERATE_CHI, NO)]) + +# Plain HTML pages generation: +DX_ARG_ABLE(html, [generate doxygen plain HTML documentation], + [DX_CHECK_DEPEND(doc, 1) DX_CHECK_DEPEND(chm, 0)], + [DX_CLEAR_DEPEND(doc, 1) DX_CLEAR_DEPEND(chm, 0)], + [], + [DX_ENV_APPEND(GENERATE_HTML, YES)], + [DX_TEST_FEATURE(chm) || DX_ENV_APPEND(GENERATE_HTML, NO)]) + +# PostScript file generation: +DX_ARG_ABLE(ps, [generate doxygen PostScript documentation], + [DX_CHECK_DEPEND(doc, 1)], + [DX_CLEAR_DEPEND(doc, 1)], + [DX_REQUIRE_PROG([DX_LATEX], latex) + DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex) + DX_REQUIRE_PROG([DX_DVIPS], dvips) + DX_REQUIRE_PROG([DX_EGREP], egrep)]) + +# PDF file generation: +DX_ARG_ABLE(pdf, [generate doxygen PDF documentation], + [DX_CHECK_DEPEND(doc, 1)], + [DX_CLEAR_DEPEND(doc, 1)], + [DX_REQUIRE_PROG([DX_PDFLATEX], pdflatex) + DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex) + DX_REQUIRE_PROG([DX_EGREP], egrep)]) + +# LaTeX generation for PS and/or PDF: +if DX_TEST_FEATURE(ps) || DX_TEST_FEATURE(pdf); then + AM_CONDITIONAL(DX_COND_latex, :) + DX_ENV_APPEND(GENERATE_LATEX, YES) +else + AM_CONDITIONAL(DX_COND_latex, false) + DX_ENV_APPEND(GENERATE_LATEX, NO) +fi + +# Paper size for PS and/or PDF: +AC_ARG_VAR(DOXYGEN_PAPER_SIZE, + [a4wide (default), a4, letter, legal or executive]) +case "$DOXYGEN_PAPER_SIZE" in +#( +"") + AC_SUBST(DOXYGEN_PAPER_SIZE, "") +;; #( +a4wide|a4|letter|legal|executive) + DX_ENV_APPEND(PAPER_SIZE, $DOXYGEN_PAPER_SIZE) +;; #( +*) + AC_MSG_ERROR([unknown DOXYGEN_PAPER_SIZE='$DOXYGEN_PAPER_SIZE']) +;; +esac + +#For debugging: +#echo DX_FLAG_doc=$DX_FLAG_doc +#echo DX_FLAG_dot=$DX_FLAG_dot +#echo DX_FLAG_man=$DX_FLAG_man +#echo DX_FLAG_html=$DX_FLAG_html +#echo DX_FLAG_chm=$DX_FLAG_chm +#echo DX_FLAG_chi=$DX_FLAG_chi +#echo DX_FLAG_rtf=$DX_FLAG_rtf +#echo DX_FLAG_xml=$DX_FLAG_xml +#echo DX_FLAG_pdf=$DX_FLAG_pdf +#echo DX_FLAG_ps=$DX_FLAG_ps +#echo DX_ENV=$DX_ENV +]) diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/m4/as-compiler-flag.m4 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/m4/as-compiler-flag.m4 Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,33 @@ +dnl as-compiler-flag.m4 0.1.0 + +dnl autostars m4 macro for detection of compiler flags + +dnl David Schleef + +dnl $Id: as-compiler-flag.m4,v 1.1.1.1 2005/08/26 00:42:44 andrunko Exp $ + +dnl AS_COMPILER_FLAG(CFLAGS, ACTION-IF-ACCEPTED, [ACTION-IF-NOT-ACCEPTED]) +dnl Tries to compile with the given CFLAGS. +dnl Runs ACTION-IF-ACCEPTED if the compiler can compile with the flags, +dnl and ACTION-IF-NOT-ACCEPTED otherwise. + +AC_DEFUN([AS_COMPILER_FLAG], +[ + AC_MSG_CHECKING([to see if compiler understands $1]) + + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $1" + + AC_TRY_COMPILE([ ], [], [flag_ok=yes], [flag_ok=no]) + CFLAGS="$save_CFLAGS" + + if test "X$flag_ok" = Xyes ; then + $2 + true + else + $3 + true + fi + AC_MSG_RESULT([$flag_ok]) +]) + diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/m4/as-expand.m4 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/m4/as-expand.m4 Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,40 @@ +dnl AS_AC_EXPAND(VAR, CONFIGURE_VAR) +dnl +dnl example +dnl AS_AC_EXPAND(SYSCONFDIR, $sysconfdir) +dnl will set SYSCONFDIR to /usr/local/etc if prefix=/usr/local + +AC_DEFUN([AS_AC_EXPAND], +[ + EXP_VAR=[$1] + FROM_VAR=[$2] + + dnl first expand prefix and exec_prefix if necessary + prefix_save=$prefix + exec_prefix_save=$exec_prefix + + dnl if no prefix given, then use /usr/local, the default prefix + if test "x$prefix" = "xNONE"; then + prefix=$ac_default_prefix + fi + dnl if no exec_prefix given, then use prefix + if test "x$exec_prefix" = "xNONE"; then + exec_prefix=$prefix + fi + + full_var="$FROM_VAR" + dnl loop until it doesn't change anymore + while true; do + new_full_var="`eval echo $full_var`" + if test "x$new_full_var"="x$full_var"; then break; fi + full_var=$new_full_var + done + + dnl clean up + full_var=$new_full_var + AC_SUBST([$1], "$full_var") + + dnl restore prefix and exec_prefix + prefix=$prefix_save + exec_prefix=$exec_prefix_save +]) diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/m4/as-version.m4 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/m4/as-version.m4 Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,59 @@ +dnl version.m4 0.0.5 +dnl autostars m4 macro for versioning +dnl thomas@apestaart.org +dnl +dnl AS_VERSION(PACKAGE, PREFIX, MAJOR, MINOR, MICRO, NANO, ACTION_IF_NO_NANO, ACTION_IF_NANO) +dnl example +dnl AS_VERSION(gstreamer, GST_VERSION, 0, 3, 2,) +dnl for a 0.3.2 release version +dnl +dnl this macro +dnl - defines [$PREFIX]_MAJOR, MINOR and MICRO +dnl - if NANO is empty, then we're in release mode, else in cvs/dev mode +dnl - defines [$PREFIX], VERSION, and [$PREFIX]_RELEASE +dnl - executes the relevant action +dnl - AC_SUBST's PACKAGE, VERSION, [$PREFIX] and [$PREFIX]_RELEASE +dnl as well as the little ones +dnl - doesn't call AM_INIT_AUTOMAKE anymore because it prevents +dnl maintainer mode from running ok +dnl +dnl don't forget to put #undef [$2] and [$2]_RELEASE in acconfig.h + +AC_DEFUN([AS_VERSION], +[ + PACKAGE=[$1] + [$2]_MAJOR_VERSION=[$3] + [$2]_MINOR_VERSION=[$4] + [$2]_MICRO_VERSION=[$5] + NANO=[$6] + [$2]_NANO_VERSION=$NANO + if test "x$NANO" = "x" || test "x$NANO" = "x0"; + then + AC_MSG_NOTICE(configuring [$1] for release) + VERSION=[$3].[$4].[$5] + [$2]_RELEASE=1 + dnl execute action + ifelse([$7], , :, [$7]) + else + AC_MSG_NOTICE(configuring [$1] for development with nano $NANO) + VERSION=[$3].[$4].[$5].$NANO + [$2]_RELEASE=`date +%Y%m%d_%H%M%S` + dnl execute action + ifelse([$8], , :, [$8]) + fi + + [$2]_VERSION=$VERSION + AC_DEFINE_UNQUOTED([$2]_VERSION, "$[$2]_VERSION", [Define the version]) + AC_SUBST([$2]_VERSION) + + AC_SUBST([$2]_RELEASE) + + AC_SUBST([$2]_MAJOR_VERSION) + AC_SUBST([$2]_MINOR_VERSION) + AC_SUBST([$2]_MICRO_VERSION) + AC_SUBST([$2]_NANO_VERSION) + AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Define the package name]) + AC_SUBST(PACKAGE) + AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Define the version]) + AC_SUBST(VERSION) +]) diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/m4/configure.ac --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/m4/configure.ac Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,234 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ(2.50) + +AC_INIT([gmyth],[0.1]) + +dnl AC_CONFIG_SRCDIR([src/mmyth_main.c]) +AC_CONFIG_HEADER(config.h) + +dnl when going to/from release please set the nano (fourth number) right ! +dnl releases only do Wall, SVN and prerelease does Werror too +AS_VERSION(gmyth, GMYTH, 0, 1, 0, 3, GMYTH_SVN="no", GMYTH_SVN="yes") + +GMYTH_MAJORMINOR=$GMYTH_MAJOR_VERSION.$GMYTH_MINOR_VERSION + +AC_SUBST(GMYTH_MAJORMINOR) + +dnl AM_MAINTAINER_MODE provides the option to enable maintainer mode +AM_MAINTAINER_MODE +dnl make aclocal work in maintainer mode +AC_SUBST(ACLOCAL_AMFLAGS, "-I m4") + +# Checks for programs. +# check for tools +# Make sure CFLAGS is defined to stop AC_PROC_CC adding -g +CFLAGS="$CFLAGS -Wall" +AC_PROG_CC +AC_PROG_LIBTOOL + +dnl Generate doxygen documentation +DX_HTML_FEATURE(ON) +DX_CHM_FEATURE(OFF) +DX_CHI_FEATURE(OFF) +DX_MAN_FEATURE(OFF) +DX_RTF_FEATURE(OFF) +DX_XML_FEATURE(OFF) +DX_PDF_FEATURE(OFF) +DX_PS_FEATURE(OFF) +DX_INIT_DOXYGEN(gmyth, doxygen.cfg, docs) + + +# Checks for libraries. + +# Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS([fcntl.h stdint.h stdlib.h string.h sys/ioctl.h sys/socket.h unistd.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_TYPE_PID_T +AC_STRUCT_TM + +# Checks for library functions. +AC_FUNC_FORK +AC_PROG_GCC_TRADITIONAL +AC_FUNC_MALLOC +AC_FUNC_MKTIME +AC_FUNC_VPRINTF +AC_CHECK_FUNCS([memset socket stime strstr strtoul]) + +AM_INIT_AUTOMAKE($PACKAGE, $VERSION) + +# Checks required packages + +dnl Test if --disable-debug given +AC_ARG_ENABLE(debug, + [AC_HELP_STRING([--disable-debug], [disable debugging mode])], + enable_debug="$enableval", + enable_debug=yes) + +if test "x$enable_debug" = "xyes" ; then + CFLAGS="$CFLAGS -g" +else + AC_DEFINE( NDEBUG, 1, [disable debug messages] ) + CFLAGS="$CFLAGS -O2 -DG_DISABLE_CHECKS -DNDEBUG" +fi + +AM_CONDITIONAL( NDEBUG, test "x$enable_debug" = "xyes" ) + +# Check for pkgconfig +AC_CHECK_PROG(HAVE_PKGCONFIG, pkg-config, yes, no) +# Give error and exit if we don't have pkgconfig +if test "x$HAVE_PKGCONFIG" = "xno"; then + AC_MSG_ERROR(you need to have pkgconfig installed !) +fi + +# Check for Glib2.0 +PKG_CHECK_MODULES(GLIB, glib-2.0, HAVE_GLIB=yes,HAVE_GLIB=no) + +# Give error and exit if we don't have glib +if test "x$HAVE_GLIB" = "xno"; then + AC_MSG_ERROR(you need glib-2.0 installed) +fi + +# make GLIB_CFLAGS and GLIB_LIBS available +AC_SUBST(GLIB_CFLAGS) +AC_SUBST(GLIB_LIBS) + +# Check for GObject2.0 +PKG_CHECK_MODULES(GOBJECT, + gobject-2.0, + HAVE_GOBJECT=yes, HAVE_GOBJECT=no) + +# Give error and exit if we don't have gobject +if test "x$HAVE_GOBJECT" = "xno"; then + AC_MSG_ERROR(you need gobject-2.0 installed) +fi + +# make GOBJECT_CFLAGS and GOBJECT_LIBS available +AC_SUBST(GOBJECT_CFLAGS) +AC_SUBST(GOBJECT_LIBS) + +# Check for GTK+-2.0 +PKG_CHECK_MODULES(GTK, gtk+-2.0, HAVE_GTK=yes,HAVE_GTK=no) + +# Give error and exit if we don't have gtk +if test "x$HAVE_GTK" = "xyes"; then + AC_DEFINE(WITH_GTK, 1, [build with GTK+ related stuff]) + dnl AC_MSG_ERROR(you need gtk+-2.0 installed) +else + AC_MSG_RESULT(no) +fi + +AM_CONDITIONAL(WITH_GTK, test "x$HAVE_GTK" = "xyes" ) + +# make GTK_CFLAGS and GTK_LIBS available +AC_SUBST(GTK_CFLAGS) +AC_SUBST(GTK_LIBS) + +dnl ========== Check for Hildon Libraries +PKG_CHECK_MODULES(HILDON, + hildon-lgpl libosso hildon-status-bar-lib libhildonmenu hildon-base-lib hildon-control-panel hildon-libs, + HAVE_HILDON=yes, HAVE_HILDON=no) + +if test "x$HAVE_HILDON" = "xyes"; then + AC_DEFINE(MAEMO_PLATFORM, 1, [build with hildon libs]) + HILDON_CFLAGS="$HILDON_CFLAGS -DMAEMO_PLATFORM=1" +else + AC_MSG_RESULT(no) +fi + +AM_CONDITIONAL(MAEMO_PLATFORM, test "x$HAVE_HILDON" = "xyes") + +dnl make HILDON_CFLAGS and HILDON_LIBS available +AC_SUBST(HILDON_CFLAGS) +AC_SUBST(HILDON_LIBS) + +# Check for libxml-2.0 +PKG_CHECK_MODULES(LIBXML, libxml-2.0, HAVE_LIBXML=yes,HAVE_LIBXML=no) + +# Give error and exit if we don't have libxml +if test "x$HAVE_LIBXML" = "xno"; then + AC_MSG_ERROR(you need libxml-2.0 installed) +fi + +# make LIBXML_CFLAGS and LIBXML_LIBS available +AC_SUBST(LIBXML_CFLAGS) +AC_SUBST(LIBXML_LIBS) + + +# check for gstreamer development files +GST_REQUIRED=0.10 +GST_MAJORMINOR=0.10 +PKG_CHECK_MODULES(GST, \ + gstreamer-$GST_MAJORMINOR >= $GST_REQUIRED, + HAVE_GST=yes, HAVE_GST=no) + +# Give error and exit if we don't have gstreamer +if test "x$HAVE_GST" = "xno"; then + AC_MSG_ERROR(you need gstreamer development packages installed !) +fi + +# make GST_CFLAGS and GST_LIBS available +AC_SUBST(GST_CFLAGS) +AC_SUBST(GST_LIBS) + +# check for gstreamer-base plugins (xoverlay interface) +GSTBASE_REQUIRED=0.10 +GSTBASE_MAJORMINOR=0.10 +PKG_CHECK_MODULES(GSTBASE, \ + gstreamer-base-$GSTBASE_MAJORMINOR >= $GSTBASE_REQUIRED, + HAVE_GSTBASE=yes, HAVE_GSTBASE=no) + +# Give error and exit if we don't have gstreamer base libraries +if test "x$HAVE_GSTBASE" = "xno"; then + AC_MSG_ERROR(you need gstreamer base development packages installed !) +fi + +# make GSTBASE_CFLAGS and GSTBASE_LIBS available +AC_SUBST(GSTBASE_CFLAGS) +AC_SUBST(GSTBASE_LIBS) + + +# make GST_MAJORMINOR available in Makefile.am +AC_SUBST(GST_MAJORMINOR) + +# +# mysql libraries +# +AC_CHECK_PROG(MYSQL_CFLAGS,mysql_config,`mysql_config --cflags`) +if test -z "$MYSQL_CFLAGS"; then + AC_MSG_ERROR([Could not find mysql_config script. Make sure the mysql client libraries are installed]) +fi +AC_SUBST(MYSQL_CFLAGS) + + +AC_CHECK_PROG(MYSQL_LIBS,mysql_config,`mysql_config --libs`) +if test -z "$MYSQL_LIBS"; then + AC_MSG_ERROR([Could not find mysql_config script. Make sure the mysql client libraries are installed]) +fi +AC_SUBST(MYSQL_LIBS) + +## Check for gmyth-0.1 + +PKG_CHECK_MODULES(LIBGMYTH, gmyth-0.1, HAVE_LIBGMYTH=yes,HAVE_LIBGMYTH=no) + +# Give error and exit if we don't have gmyth-0.1 +if test "x$HAVE_LIBGMYTH" = "xno"; then + AC_MSG_ERROR(you need gmyth-0.1 installed) +fi + +# make LIBXML_CFLAGS and LIBXML_LIBS available +AC_SUBST(LIBGMYTH_CFLAGS) +AC_SUBST(LIBGMYTH_LIBS) + +#dnl Enable gtk-doc +#GTK_DOC_CHECK(1.4) + + +AC_CONFIG_FILES([Makefile + src/Makefile + pixmaps/Makefile]) +AC_OUTPUT diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/Makefile.am --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/Makefile.am Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,85 @@ +SUBDIRS = . + +lib_LTLIBRARIES = libgmyth.la + +BUILT_SOURCES = \ + gmyth_marshal.c \ + gmyth_marshal.h + +libgmyth_la_SOURCES = \ + gmyth_common.c \ + gmyth_debug.c \ + gmyth_epg.c \ + gmyth_recorder.c \ + gmyth_remote_util.c \ + gmyth_tvchain.c \ + gmyth_scheduler.c \ + gmyth_util.c \ + gmyth_query.c \ + gmyth_socket.c \ + gmyth_stringlist.c \ + gmyth_monitor_handler.c \ + gmyth_file_transfer.c \ + gmyth_livetv.c \ + gmyth_backendinfo.c \ + gmyth_programinfo.c \ + gmyth_uri.c \ + gmyth_http.c \ + $(BUILT_SOURCES) + + +EXTRA_libgmyth_la_SOURCES = gmyth_marshal.list + +gmyth_marshal.h: gmyth_marshal.list + glib-genmarshal --header --prefix=gmyth_marshal gmyth_marshal.list > gmyth_marshal.h.tmp + mv gmyth_marshal.h.tmp gmyth_marshal.h + +gmyth_marshal.c: gmyth_marshal.list gmyth_marshal.h + echo "#include \"glib-object.h\"" > gmyth_marshal.c.tmp + echo "#include \"gmyth_marshal.h\"" >> gmyth_marshal.c.tmp + glib-genmarshal --body --prefix=gmyth_marshal $(srcdir)/gmyth_marshal.list >> gmyth_marshal.c.tmp + mv gmyth_marshal.c.tmp gmyth_marshal.c + +libgmyth_la_CFLAGS = \ + -DDATADIR=\"$(pkgdatadir)\" \ + $(GLIB_CFLAGS) \ + $(GOBJECT_CFLAGS) \ + $(GST_CFLAGS) \ + $(GSTBASE_CFLAGS) \ + $(GSTPLUGINSBASE_CFLAGS) \ + $(MYSQL_CFLAGS) \ + $(LIBXML_CFLAGS) + +libgmyth_la_LDFLAGS = \ + -export-dynamic \ + $(MYSQL_LIBS) \ + $(GST_LIBS) \ + $(GSTBASE_LIBS) \ + $(GSTPLUGINS_LIBS) \ + $(LIBXML_LIBS) + +libgmyth_includedir = \ + $(pkgincludedir) + +libgmyth_include_HEADERS = \ + gmyth.h \ + gmyth_common.h \ + gmyth_debug.h \ + gmyth_epg.h \ + gmyth_recorder.h \ + gmyth_scheduler.h \ + gmyth_tvchain.h \ + gmyth_util.h \ + gmyth_query.h \ + gmyth_socket.h \ + gmyth_remote_util.h \ + gmyth_stringlist.h \ + gmyth_monitor_handler.h \ + gmyth_file_transfer.h \ + gmyth_livetv.h \ + gmyth_backendinfo.h \ + gmyth_programinfo.h \ + gmyth_uri.h \ + gmyth_http.h + +CLEANFILES = $(BUILT_SOURCES) diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth.h Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,51 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth.h + * + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Renato Filho + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + + +#ifndef _GMYTH_H_ +#define _GMYTH_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif /* _GMYTH_H_ */ diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_backendinfo.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_backendinfo.c Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,258 @@ + +/** + * GMyth Library + * + * @file gmyth/gmyth_backend_info.c + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Hallyson Melo + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gmyth_backendinfo.h" +#include "gmyth_uri.h" +#include "gmyth_debug.h" + +static void gmyth_backend_info_class_init (GMythBackendInfoClass *klass); +static void gmyth_backend_info_init (GMythBackendInfo *object); + +static void gmyth_backend_info_dispose (GObject *object); +static void gmyth_backend_info_finalize (GObject *object); + +G_DEFINE_TYPE(GMythBackendInfo, gmyth_backend_info, G_TYPE_OBJECT) + +static void +gmyth_backend_info_class_init (GMythBackendInfoClass *klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + + gobject_class->dispose = gmyth_backend_info_dispose; + gobject_class->finalize = gmyth_backend_info_finalize; +} + +static void +gmyth_backend_info_init (GMythBackendInfo *backend_info) +{ + backend_info->hostname = NULL; + backend_info->username = NULL; + backend_info->password = NULL; + backend_info->db_name = NULL; + backend_info->port = -1; + backend_info->uri = NULL; +} + +static void +gmyth_backend_info_dispose (GObject *object) +{ + GMythBackendInfo *backend_info = GMYTH_BACKEND_INFO (object); + + g_free (backend_info->hostname); + g_free (backend_info->username); + g_free (backend_info->password); + g_free (backend_info->db_name); + + backend_info->hostname = NULL; + backend_info->username = NULL; + backend_info->password = NULL; + backend_info->db_name = NULL; + backend_info->port = -1; + + if ( backend_info->uri != NULL ) + { + g_object_unref(backend_info->uri); + backend_info->uri = NULL; + } + + G_OBJECT_CLASS (gmyth_backend_info_parent_class)->dispose (object); +} + +static void +gmyth_backend_info_finalize (GObject *object) +{ + g_signal_handlers_destroy (object); + + G_OBJECT_CLASS (gmyth_backend_info_parent_class)->finalize (object); +} + +/** Creates a new instance of GMythBackendInfo. + * + * @return a new instance of GMythBackendInfo. + */ +GMythBackendInfo* +gmyth_backend_info_new () +{ + GMythBackendInfo *backend_info = + GMYTH_BACKEND_INFO (g_object_new(GMYTH_BACKEND_INFO_TYPE, NULL)); + + return backend_info; +} + +GMythBackendInfo* +gmyth_backend_info_new_full (const gchar *hostname, const gchar *username, + const gchar *password, const gchar *db_name, gint port) +{ + GMythBackendInfo *backend_info = + GMYTH_BACKEND_INFO (g_object_new(GMYTH_BACKEND_INFO_TYPE, NULL)); + + backend_info->uri = gmyth_uri_new_with_value( + g_strdup_printf( "myth://%s:%s@%s:%d/?%s", username, password, hostname, port, db_name ) ); + + gmyth_backend_info_set_hostname (backend_info, hostname); + gmyth_backend_info_set_username (backend_info, username); + gmyth_backend_info_set_password (backend_info, password); + gmyth_backend_info_set_db_name (backend_info, db_name); + gmyth_backend_info_set_port (backend_info, port); + + return backend_info; +} + +GMythBackendInfo* +gmyth_backend_info_new_with_uri ( const gchar *uri_str ) +{ + GMythBackendInfo *backend_info = + GMYTH_BACKEND_INFO (g_object_new(GMYTH_BACKEND_INFO_TYPE, NULL)); + + backend_info->uri = gmyth_uri_new_with_value( uri_str ); + + gchar** path_parts = g_strsplit( gmyth_uri_get_path( backend_info->uri ), "&", -1 ); + + gmyth_backend_info_set_hostname (backend_info, gmyth_uri_get_host ( backend_info->uri ) ); + gmyth_backend_info_set_username (backend_info, gmyth_uri_get_user( backend_info->uri ) ); + gmyth_backend_info_set_password (backend_info, gmyth_uri_get_password( backend_info->uri ) ); + /* gets the path info to database name, from the URI, and removes the trash chars */ + gmyth_backend_info_set_db_name (backend_info, path_parts != NULL && path_parts[0] != NULL + && strlen( path_parts[0] ) > 0 ? g_strstrip( g_strdup( g_strdelimit( path_parts[0], "/?", ' ' ) ) ) + : gmyth_uri_get_path( backend_info->uri ) ); + gmyth_backend_info_set_port (backend_info, gmyth_uri_get_port( backend_info->uri ) ); + + g_strfreev( path_parts ); + + return backend_info; +} + +void +gmyth_backend_info_set_hostname (GMythBackendInfo *backend_info, const gchar *hostname) +{ + g_return_if_fail (backend_info != NULL); + + if ( NULL == hostname || strlen(hostname) <= 0 ) + { + gmyth_debug ( "Error trying to set a hostname equals to NULL." ); + } else { + backend_info->hostname = g_strdup (hostname); + } +} + +void +gmyth_backend_info_set_username (GMythBackendInfo *backend_info, const gchar *username) +{ + g_return_if_fail (backend_info != NULL); + + backend_info->username = g_strdup (username); +} + +void +gmyth_backend_info_set_password (GMythBackendInfo *backend_info, const gchar *password) +{ + g_return_if_fail (backend_info != NULL); + + backend_info->password = g_strdup (password); +} + +void +gmyth_backend_info_set_db_name (GMythBackendInfo *backend_info, const gchar *db_name) +{ + g_return_if_fail (backend_info != NULL); + + backend_info->db_name = g_strdup (db_name); +} + +void +gmyth_backend_info_set_port (GMythBackendInfo *backend_info, const gint port ) +{ + g_return_if_fail (backend_info != NULL); + + if ( port <= 0 ) + { + gmyth_debug ( "Error trying to set a hostname equals to NULL (it doesn't using UPnP)." ); + } else { + backend_info->port = port; + } +} + +const gchar* +gmyth_backend_info_get_hostname (GMythBackendInfo *backend_info) +{ + g_return_val_if_fail (backend_info != NULL, NULL); + + return backend_info->hostname; +} + +const gchar* +gmyth_backend_info_get_username (GMythBackendInfo *backend_info) +{ + g_return_val_if_fail (backend_info != NULL, NULL); + + return backend_info->username; +} + +const gchar* +gmyth_backend_info_get_password (GMythBackendInfo *backend_info) +{ + g_return_val_if_fail (backend_info != NULL, NULL); + + return backend_info->password; +} + +const gchar* +gmyth_backend_info_get_db_name (GMythBackendInfo *backend_info) +{ + g_return_val_if_fail (backend_info != NULL, NULL); + + return backend_info->db_name; +} + +gint +gmyth_backend_info_get_port (GMythBackendInfo *backend_info) +{ + g_return_val_if_fail (backend_info != NULL, -1); + + return backend_info->port; +} + +const GMythURI* +gmyth_backend_info_get_uri (GMythBackendInfo *backend_info) +{ + + if ( NULL == backend_info->uri ) + { + backend_info->uri = gmyth_uri_new_with_value( + g_strdup_printf( "myth://%s:%s@%s:%d/?%s", backend_info->username, backend_info->password, + backend_info->hostname, backend_info->port, backend_info->db_name ) ); + } + + return backend_info->uri; +} + + diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_backendinfo.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_backendinfo.h Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,101 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_backend_info.h + * + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Hallyson Melo + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GMYTH_BACKEND_INFO_H__ +#define __GMYTH_BACKEND_INFO_H__ + +#include + +#include "gmyth_uri.h" + +G_BEGIN_DECLS + +#define GMYTH_BACKEND_INFO_TYPE (gmyth_backend_info_get_type ()) +#define GMYTH_BACKEND_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_BACKEND_INFO_TYPE, GMythBackendInfo)) +#define GMYTH_BACKEND_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_BACKEND_INFO_TYPE, GMythBackendInfoClass)) +#define IS_GMYTH_BACKEND_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_BACKEND_INFO_TYPE)) +#define IS_GMYTH_BACKEND_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_BACKEND_INFO_TYPE)) +#define GMYTH_BACKEND_INFO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_BACKEND_INFO_TYPE, GMythBackendInfoClass)) + + +typedef struct _GMythBackendInfo GMythBackendInfo; +typedef struct _GMythBackendInfoClass GMythBackendInfoClass; + +struct _GMythBackendInfoClass +{ + GObjectClass parent_class; + + /* callbacks */ + /* no one for now */ +}; + +struct _GMythBackendInfo +{ + GObject parent; + + gchar *hostname; + gchar *username; + gchar *password; + gchar *db_name; + gint port; + gchar *path; + + GMythURI* uri; +}; + + +GType gmyth_backend_info_get_type (void); +GMythBackendInfo* gmyth_backend_info_new (void); +GMythBackendInfo* gmyth_backend_info_new_full (const gchar *hostname, + const gchar *username, + const gchar *password, + const gchar *db_name, + gint port); +GMythBackendInfo* gmyth_backend_info_new_with_uri (const gchar *uri_str); +void gmyth_backend_info_set_hostname (GMythBackendInfo *backend_info, + const gchar *hostname); +void gmyth_backend_info_set_username (GMythBackendInfo *backend_info, + const gchar *username); +void gmyth_backend_info_set_password (GMythBackendInfo *backend_info, + const gchar *password); +void gmyth_backend_info_set_db_name (GMythBackendInfo *backend_info, + const gchar *db_name); +void gmyth_backend_info_set_port (GMythBackendInfo *backend_info, + gint port); +const gchar* gmyth_backend_info_get_hostname (GMythBackendInfo *backend_info); +const gchar* gmyth_backend_info_get_username (GMythBackendInfo *backend_info); +const gchar* gmyth_backend_info_get_password (GMythBackendInfo *backend_info); +const gchar* gmyth_backend_info_get_db_name (GMythBackendInfo *backend_info); +gint gmyth_backend_info_get_port (GMythBackendInfo *backend_info); + +const GMythURI* gmyth_backend_info_get_uri (GMythBackendInfo *backend_info); + +/*const gchar* gmyth_backend_info_get_full_uri (GMythBackendInfo *backend_info);*/ + +G_END_DECLS + +#endif /* __GMYTH_BACKEND_INFO_H__ */ + diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_common.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_common.c Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,124 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_common.c + * + * @brief

This file contains basic common functions for the gmyth library. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Leonardo Sobral Cunha + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gmyth_common.h" +#include "gmyth_debug.h" +#include "gmyth_util.h" + +static void free_channel_data(gpointer data, gpointer user_data); +static void free_program_data(gpointer data, gpointer user_data); + +/** Frees the memory allocated to the GMythChannelInfo objects inside list. + * The list memory is also released by g_list_free(). If LIST is NULL it + * simply returns. + * + * @param list the GList containing a list of GMythChannelInfo to free. + */ +void +gmyth_free_channel_list(GList *list) +{ + if (list == NULL) { + g_warning ("%s received null GList as parameter", __FUNCTION__); + return; + } + + g_list_foreach (list, free_channel_data, NULL); + + g_list_free (list); +} + +/** Frees the memory allocated to the GMythProgramInfo objects inside list. + * The list memory is also released by g_list_free(). If list is NULL it + * simply returns. + * + * @param list the GList containing a list of GMythProgramInfo to free. + */ +void +gmyth_free_program_list(GList *list) +{ + if (list == NULL) { + g_warning ("%s received null GList as parameter", __FUNCTION__); + return; + } + + g_list_foreach (list, free_program_data, NULL); + + g_list_free (list); +} + +void +gmyth_channel_info_print(GMythChannelInfo *channel_info) +{ + if ( channel_info != NULL ) + { + gmyth_debug("ChannelInfo (Name, Num, ID) = (%s, %s, %d)\n", + channel_info->channel_name->str, channel_info->channel_num->str, + channel_info->channel_ID); + } +} + +void +gmyth_program_info_print(GMythProgramInfo *program_info) +{ + + if ( program_info != NULL ) { + + gmyth_debug( "ProgramInfo\n\tTitle = %s\n\t" + "Description = %s\n\t" + "Start time= %s\t" + "End time = %s\n" + "Path name = %s\n" + "File size = %lld\n" + , program_info->title->str, + program_info->description->str, + gmyth_util_time_to_string_from_time_val(program_info->startts), + gmyth_util_time_to_string_from_time_val(program_info->endts), + program_info->pathname->str, + program_info->filesize ); + + } + +} + +static void +free_channel_data(gpointer data, gpointer user_data) +{ + if(data) + g_free((GMythChannelInfo*) data); +} + +static void +free_program_data(gpointer data, gpointer user_data) +{ + if(data) + g_object_unref((GMythProgramInfo*) data); +} + diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_common.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_common.h Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,61 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_common.h + * + * @brief

This file contains basic common functions for the gmyth library. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Leonardo Sobral Cunha + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef GMYTH_COMMON_H_ +#define GMYTH_COMMON_H_ + +#include +#include + +#include "gmyth_programinfo.h" + +G_BEGIN_DECLS + +/** + * The GMythChannelInfo structure represents the channel information + * stored in the backend database. + */ +typedef struct { + /** The channel ID in backend database */ + gint channel_ID; + + GString* channel_num; + + /** The channel name in backend database */ + GString *channel_name; + +} GMythChannelInfo; + +void gmyth_free_channel_list(GList *list); +void gmyth_free_program_list(GList *list); + +void gmyth_channel_info_print(GMythChannelInfo *channel_info); +void gmyth_program_info_print(GMythProgramInfo *program_info); + +G_END_DECLS + +#endif /* GMYTH_COMMON_H_ */ diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_debug.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_debug.c Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,56 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_debug.c + * + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Renato Filho + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gmyth_debug.h" + +void +gmyth_debug_real (const char *func, + const char *file, + const int line, + gboolean newline, + const char *format, ...) +{ + va_list args; + char buffer[1025]; + char str_time[255]; + time_t the_time; + + va_start (args, format); + + g_vsnprintf (buffer, 1024, format, args); + + va_end (args); + + time (&the_time); + strftime (str_time, 254, "%H:%M:%S", localtime (&the_time)); + + g_printerr (newline ? "(%s) [%p] [%s] %s:%d: %s\n" : "(%s) [%p] [%s] %s:%d: %s", + str_time, g_thread_self (), func, file, line, buffer); +} diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_debug.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_debug.h Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,49 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_debug.h + * + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Renato Filho + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GMYTH_DEBUG_H__ +#define __GMYTH_DEBUG_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +#ifdef GMYTH_USE_DEBUG +#define gmyth_debug(...) gmyth_debug_real (__FUNCTION__, __FILE__, __LINE__, TRUE, __VA_ARGS__) +#else +#define gmyth_debug(...) +#endif + +void gmyth_debug_real (const char *func, + const char *file, + int line, + gboolean newline, + const char *format, ...) G_GNUC_PRINTF (5, 6); + +G_END_DECLS +#endif diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_epg.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_epg.c Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,299 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_epg.c + * + * @brief

GMythEPG class provides access to the program and channel data + * from the Electronic Program Guide (EPG) of the Mythtv backend. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Leonardo Sobral Cunha + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#include "gmyth_epg.h" +#include "gmyth_programinfo.h" +#include "gmyth_util.h" +#include "gmyth_debug.h" + +static void gmyth_epg_class_init (GMythEPGClass *klass); +static void gmyth_epg_init (GMythEPG *object); + +static void gmyth_epg_dispose (GObject *object); +static void gmyth_epg_finalize (GObject *object); + +G_DEFINE_TYPE(GMythEPG, gmyth_epg, G_TYPE_OBJECT) + +static void +gmyth_epg_class_init (GMythEPGClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->dispose = gmyth_epg_dispose; + gobject_class->finalize = gmyth_epg_finalize; +} + +static void +gmyth_epg_init (GMythEPG *gmyth_epg) +{ + +} + +static void +gmyth_epg_dispose (GObject *object) +{ + //GMythEPG *gmyth_epg = GMYTH_EPG(object); + + G_OBJECT_CLASS (gmyth_epg_parent_class)->dispose (object); +} + +static void +gmyth_epg_finalize (GObject *object) +{ + g_signal_handlers_destroy (object); + + G_OBJECT_CLASS (gmyth_epg_parent_class)->finalize (object); +} + +/** + * Creates a new instance of GMythEPG. + * + * @return a new instance of GMythEPG. + */ +GMythEPG* +gmyth_epg_new (void) +{ + GMythEPG *epg = GMYTH_EPG (g_object_new(GMYTH_EPG_TYPE, NULL)); + + return epg; +} + +/** Connects to the Mysql database in the backend. The backend address + * is loaded from the GMythSettings instance. + * + * @param gmyth_epg the GMythEPG instance to be connected. + * @return true if connection was success, false if failed. + */ +gboolean +gmyth_epg_connect (GMythEPG *gmyth_epg, GMythBackendInfo *backend_info) +{ + assert(gmyth_epg); + + if (gmyth_epg->sqlquery == NULL) { + gmyth_debug ("[%s] Creating gmyth_query", __FUNCTION__); + gmyth_epg->sqlquery = gmyth_query_new ( ); + } + + if (!gmyth_query_connect(gmyth_epg->sqlquery, backend_info)) { + g_warning ("[%s] Error while connecting to db", __FUNCTION__); + return FALSE; + } + + return TRUE; +} + +/** Disconnects from the Mysql database in the backend. + * + * @param gmyth_epg the GMythEPG instance to be disconnected + * @return true if disconnection was success, false if failed. + */ +gboolean +gmyth_epg_disconnect (GMythEPG *gmyth_epg) +{ + assert(gmyth_epg); + + if (gmyth_epg->sqlquery != NULL) { + g_object_unref (gmyth_epg->sqlquery); + gmyth_epg->sqlquery = NULL; + } + + return TRUE; +} + +/** Retrieves the available list of channels from the backend Mysql database. + * + * @param gmyth_epg the GMythEPG instance. + * @param glist_ptr the GList pointer to be filled with the loaded list address. + * @return The amount of channels retrieved from database, or -1 if error. + */ +gint +gmyth_epg_get_channel_list (GMythEPG *gmyth_epg, GList **glist_ptr) +{ + MYSQL_RES *msql_res; + + assert(gmyth_epg); + + msql_res = gmyth_query_process_statement (gmyth_epg->sqlquery, + "SELECT chanid, channum, name FROM channel;"); + + (*glist_ptr) = NULL; + + if (msql_res == NULL) { + g_warning ("[%s] msql query returned NULL MYSQL_RES", __FUNCTION__); + return -1; + } else { + MYSQL_ROW row; + GMythChannelInfo *channel_info; + + while ((row = mysql_fetch_row (msql_res)) != NULL){ + + channel_info = g_new0(GMythChannelInfo, 1); + channel_info->channel_ID = g_ascii_strtoull (row[0], NULL, 10); + channel_info->channel_num = g_string_new (row[1]); + channel_info->channel_name = g_string_new (row[2]); + + gmyth_channel_info_print(channel_info); + + (*glist_ptr) = g_list_append ((*glist_ptr), channel_info); + } + } + mysql_free_result (msql_res); + return (!(*glist_ptr)) ? 0 : g_list_length (*glist_ptr); +} + +/** + * Retrieves the available list of channels from the backend Mysql database. + * + * @param gmyth_epg the GMythEPG instance. + * @param proglist the GList pointer to be filled with the loaded list. + * @param chan_num the channel num on which to search for program. + * @param starttime the start time to search for programs. + * @param endtime the end time to search for programs. + * @return The amount of channels retrieved from database, or -1 if error. + */ +gint +gmyth_epg_get_program_list (GMythEPG *gmyth_epg, GList **proglist, + const gint chan_num, GTimeVal *starttime, GTimeVal *endtime) +{ + + gchar *startts = gmyth_util_time_to_string_from_time_val(starttime); + gchar *endts = gmyth_util_time_to_string_from_time_val(endtime); + MYSQL_ROW row; + GString *querystr; + + assert(gmyth_epg); + + querystr = g_string_new( + "SELECT DISTINCT program.chanid, program.starttime, program.endtime, " + " program.title, program.subtitle, program.description, " + " program.category, channel.channum, channel.callsign, " + " channel.name, program.previouslyshown, channel.commfree, " + " channel.outputfilters, program.seriesid, program.programid, " + " program.airdate, program.stars, program.originalairdate, " + " program.category_type, oldrecstatus.recordid, " + " oldrecstatus.rectype, oldrecstatus.recstatus, " + " oldrecstatus.findid " + "FROM program " + "LEFT JOIN channel ON program.chanid = channel.chanid " + "LEFT JOIN oldrecorded AS oldrecstatus ON " + " program.title = oldrecstatus.title AND " + " channel.callsign = oldrecstatus.station AND " + " program.starttime = oldrecstatus.starttime " + ); + + g_string_append_printf (querystr, + "WHERE program.chanid = %d " + " AND program.endtime >= '%s' " + " AND program.starttime <= '%s' " + " AND program.manualid = 0 ", + chan_num, startts, endts); + + if (!g_strrstr(querystr->str, " GROUP BY ")) + querystr = g_string_append(querystr, + " GROUP BY program.starttime, channel.channum, " + " channel.callsign, program.title "); + + if (!g_strrstr(querystr->str, " LIMIT ")) + querystr = g_string_append(querystr, " LIMIT 1000 "); + + MYSQL_RES *res_set = + gmyth_query_process_statement(gmyth_epg->sqlquery, querystr->str); + + if (res_set == NULL) { + g_warning ("[%s] msql query returned NULL MYSQL_RES", __FUNCTION__); + return -1; + } + + (*proglist) = NULL; + while ((row = mysql_fetch_row (res_set)) != NULL) { + + GMythProgramInfo *p = gmyth_program_info_new (); + p->chanid = g_string_new (row[0]); + + p->startts = gmyth_util_string_to_time_val (row[1]); + p->endts = gmyth_util_string_to_time_val (row[2]); + + p->recstartts = g_new0 (GTimeVal, 1); + p->recstartts->tv_sec = p->startts->tv_sec; + p->recstartts->tv_usec = p->startts->tv_usec; + + p->recendts = g_new0 (GTimeVal, 1); + p->recendts->tv_sec = p->endts->tv_sec; + p->recendts->tv_usec = p->endts->tv_usec; + + p->lastmodified = g_new0 (GTimeVal, 1); + p->lastmodified->tv_sec = p->startts->tv_sec; + p->lastmodified->tv_usec = p->startts->tv_usec; + + p->title = g_string_new (row[3]); + p->subtitle = g_string_new (row[4]); + p->description = g_string_new (row[5]); + p->category = g_string_new (row[6]); + p->chanstr = g_string_new (row[7]); + p->chansign = g_string_new (row[8]); + p->channame = g_string_new (row[9]); + p->repeat = g_ascii_strtoull(row[10], NULL, 10); + p->chancommfree = g_ascii_strtoull(row[11], NULL, 10); + p->chanOutputFilters = g_string_new (row[12]); + p->seriesid = g_string_new (row[13]); + p->programid = g_string_new (row[14]); + p->year = g_string_new (row[15]); + p->stars = g_ascii_strtod(row[16], NULL); + + if (!row[17] || !strcmp(row[17], "")) { + p->originalAirDate = 0; + p->hasAirDate = FALSE; + } else { + p->originalAirDate = gmyth_util_string_to_time_val (row[17]); + p->hasAirDate = TRUE; + } + + p->catType = g_string_new (row[18]); + + *proglist = g_list_append((*proglist), p); + +#if 0 + gmyth_program_info_print(p); +#endif + } + + /* deallocate */ + mysql_free_result (res_set); + g_string_free(querystr, TRUE); + + return TRUE; +} diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_epg.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_epg.h Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,75 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_epg.h + * + * @brief

GMythEPG class provides access to the program and channel data + * from the Electronic Program Guide (EPG) of the Mythtv backend. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Leonardo Sobral Cunha + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef GMYTH_EPG_H_ +#define GMYTH_EPG_H_ + +#include + +#include "gmyth_query.h" +#include "gmyth_common.h" + +G_BEGIN_DECLS + +#define GMYTH_EPG_TYPE (gmyth_epg_get_type ()) +#define GMYTH_EPG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_EPG_TYPE, GMythEPG)) +#define GMYTH_EPG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_EPG_TYPE, GMythEPGClass)) +#define IS_GMYTH_EPG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_EPG_TYPE)) +#define IS_GMYTH_EPG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_EPG_TYPE)) +#define GMYTH_EPG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_EPG_TYPE, GMythEPGClass)) + +typedef struct _GMythEPG GMythEPG; +typedef struct _GMythEPGClass GMythEPGClass; + +struct _GMythEPGClass +{ + GObjectClass parent_class; + + /* callbacks */ + /* no one for now */ +}; + +struct _GMythEPG +{ + GObject parent; + + GMythQuery *sqlquery; +}; + +GType gmyth_epg_get_type (void); + +GMythEPG* gmyth_epg_new (void); + +gboolean gmyth_epg_connect (GMythEPG *gmyth_epg, GMythBackendInfo *backend_info); +gboolean gmyth_epg_disconnect (GMythEPG *gmyth_epg); + +gint gmyth_epg_get_channel_list (GMythEPG *gmyth_epg, GList **glist_ptr); +gint gmyth_epg_get_program_list (GMythEPG *gmyth_epg, GList **proglist, + const gint chanNum, GTimeVal *starttime, GTimeVal *endtime); + +#endif /*GMYTH_EPG_H_*/ diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_file_transfer.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_file_transfer.c Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,705 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_file_transfer.c + * + * @brief

GMythFileTransfer deals with the file streaming media remote/local + * transfering to the MythTV frontend. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Rosfran Lins Borges + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * GStreamer MythTV plug-in properties: + * - location (backend server hostname/URL) [ex.: myth://192.168.1.73:28722/1000_1092091.nuv] + * - path (qurl - remote file to be opened) + * - port number * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gmyth_file_transfer.h" +#include "gmyth_livetv.h" +#include "gmyth_util.h" +#include "gmyth_socket.h" +#include "gmyth_stringlist.h" +#include "gmyth_debug.h" +#include "gmyth_uri.h" +#include "gmyth_marshal.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define GMYTHTV_QUERY_HEADER "QUERY_FILETRANSFER " + +/* default values to the file transfer parameters */ +#define GMYTHTV_USER_READ_AHEAD TRUE +#define GMYTHTV_RETRIES -1 +#define GMYTHTV_FILE_SIZE 0 + +#define GMYTHTV_BUFFER_SIZE 64*1024 + +#define GMYTHTV_VERSION 30 + +#define GMYTHTV_TRANSFER_MAX_WAITS 700 + +#ifdef GMYTHTV_ENABLE_DEBUG +#define GMYTHTV_ENABLE_DEBUG 1 +#else +#undef GMYTHTV_ENABLE_DEBUG +#endif + +/* this NDEBUG is to maintain compatibility with GMyth library */ +#ifndef NDEBUG +#define GMYTHTV_ENABLE_DEBUG 1 +#endif + +enum myth_sock_types { + GMYTH_PLAYBACK_TYPE = 0, + GMYTH_MONITOR_TYPE, + GMYTH_FILETRANSFER_TYPE, + GMYTH_RINGBUFFER_TYPE +}; + +#define GMYTH_FILE_TRANSFER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GMYTH_FILE_TRANSFER_TYPE, GMythFileTransferPrivate)) + +struct _GMythFileTransferPrivate { + + GMythLiveTV *livetv; + + gboolean do_next_program_chain; + +}; + +static void gmyth_file_transfer_class_init (GMythFileTransferClass *klass); +static void gmyth_file_transfer_init (GMythFileTransfer *object); + +static void gmyth_file_transfer_dispose (GObject *object); +static void gmyth_file_transfer_finalize (GObject *object); + +static void gmyth_file_transfer_program_info_changed( GMythFileTransfer *transfer, + gint msg_code, gpointer livetv_transfer ); + +static gboolean gmyth_connect_to_backend (GMythFileTransfer *transfer); + +void gmyth_file_transfer_close( GMythFileTransfer *transfer ); + +static gboolean myth_control_acquire_context( gboolean do_wait ); + +static gboolean myth_control_release_context( ); + +G_DEFINE_TYPE(GMythFileTransfer, gmyth_file_transfer, G_TYPE_OBJECT) + +static void +gmyth_file_transfer_class_init (GMythFileTransferClass *klass) +{ + GObjectClass *gobject_class; + GMythFileTransferClass *gtransfer_class; + + gobject_class = (GObjectClass *) klass; + gtransfer_class = (GMythFileTransferClass *) gobject_class; + + gobject_class->dispose = gmyth_file_transfer_dispose; + gobject_class->finalize = gmyth_file_transfer_finalize; + + g_type_class_add_private (gobject_class, sizeof (GMythFileTransferPrivate)); + + gtransfer_class->program_info_changed_handler = gmyth_file_transfer_program_info_changed; + + gtransfer_class->program_info_changed_handler_signal_id = + g_signal_new ( "program-info-changed", + G_TYPE_FROM_CLASS (gtransfer_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, + 0, + NULL, + NULL, + gmyth_marshal_VOID__INT_POINTER, + G_TYPE_NONE, + 2, + G_TYPE_INT, + G_TYPE_POINTER ); + +} + +static void +gmyth_file_transfer_init (GMythFileTransfer *transfer) +{ + g_return_if_fail( transfer != NULL ); + + transfer->readposition = 0; + transfer->filesize = GMYTHTV_FILE_SIZE; + + transfer->priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); + + transfer->priv->do_next_program_chain = FALSE; + transfer->priv->livetv = NULL; + + transfer->control_sock = NULL; + transfer->sock = NULL; + + transfer->mutex = g_mutex_new(); + + g_signal_connect ( G_OBJECT (transfer), "program-info-changed", + (GCallback)(GMYTH_FILE_TRANSFER_GET_CLASS(transfer)->program_info_changed_handler), + NULL ); + +} + +static void +gmyth_file_transfer_dispose (GObject *object) +{ + GMythFileTransfer *transfer = GMYTH_FILE_TRANSFER (object); + + if ( transfer->mutex != NULL ) + { + g_mutex_free( transfer->mutex ); + transfer->mutex = NULL; + } + + if ( transfer->control_sock != NULL ) + { + g_object_unref( transfer->control_sock ); + transfer->control_sock = NULL; + } + + if ( transfer->sock != NULL ) + { + g_object_unref( transfer->sock ); + transfer->sock = NULL; + } + + if ( transfer->filename != NULL ) + { + g_free( transfer->filename ); + transfer->filename = NULL; + } + + G_OBJECT_CLASS (gmyth_file_transfer_parent_class)->dispose (object); +} + +static void +gmyth_file_transfer_finalize (GObject *object) +{ + g_signal_handlers_destroy (object); + + G_OBJECT_CLASS (gmyth_file_transfer_parent_class)->finalize (object); +} + +// fixme: do we need the card_id???? +GMythFileTransfer* +gmyth_file_transfer_new ( const GMythBackendInfo *backend_info) +{ + GMythFileTransfer *transfer = GMYTH_FILE_TRANSFER (g_object_new (GMYTH_FILE_TRANSFER_TYPE, NULL)); + + transfer->backend_info = (GMythBackendInfo *)backend_info; + g_object_ref (transfer->backend_info); + + return transfer; +} + +GMythFileTransfer* +gmyth_file_transfer_new_with_uri (const gchar* uri_str) +{ + GMythFileTransfer *transfer = GMYTH_FILE_TRANSFER (g_object_new (GMYTH_FILE_TRANSFER_TYPE, NULL)); + + transfer->backend_info = gmyth_backend_info_new_with_uri (uri_str); + + return transfer; +} + +gboolean +gmyth_file_transfer_open (GMythFileTransfer *transfer, const gchar* filename) +{ + gboolean ret = TRUE; + + g_return_val_if_fail (transfer != NULL, FALSE); + g_return_val_if_fail (filename != NULL, FALSE); + + if (transfer->filename != NULL) + { + g_free (transfer->filename); + transfer->filename = NULL; + } + + transfer->filename = g_strdup (filename); + + /* configure the control socket */ + if (transfer->control_sock == NULL) { + if (!gmyth_connect_to_backend (transfer)) { + gmyth_debug ("Connection to backend failed (Control Socket).\n"); + ret = FALSE; + } + } else { + g_warning("Remote transfer control socket already created.\n"); + } + + gmyth_debug ("Got file with size = %lld.\n", transfer->filesize); + + return ret; + +} + +static gboolean +gmyth_connect_to_backend (GMythFileTransfer *transfer) +{ + GString *base_str = NULL; + GString *hostname = NULL; + GMythStringList *strlist = NULL; + gboolean ret = TRUE; + + g_return_val_if_fail (transfer != NULL, FALSE ); + + base_str = g_string_new (""); + + /* Creates the control socket */ + if (transfer->control_sock != NULL) { + g_object_unref (transfer->control_sock); + transfer->control_sock = NULL; + } + + transfer->control_sock = gmyth_socket_new(); + + // Connects the socket, send Mythtv ANN command and verify Mythtv protocol version + if (!gmyth_socket_connect_to_backend (transfer->control_sock, + transfer->backend_info->hostname, transfer->backend_info->port, TRUE)) { + + g_object_unref (transfer->control_sock); + transfer->control_sock = NULL; + return FALSE; + } + + /* Creates the data socket */ + if (transfer->sock != NULL) { + g_object_unref (transfer->sock); + transfer->sock = NULL; + } + + transfer->sock = gmyth_socket_new (); + gmyth_socket_connect (transfer->sock, transfer->backend_info->hostname, transfer->backend_info->port); + + strlist = gmyth_string_list_new(); + hostname = gmyth_socket_get_local_hostname(); + gmyth_debug( "[%s] MythTV version (from backend) = %d.\n", __FUNCTION__, transfer->control_sock->mythtv_version ); + if ( transfer->control_sock->mythtv_version > 26 ) + g_string_printf( base_str, "ANN FileTransfer %s 1 -1", hostname->str); + else + g_string_printf( base_str, "ANN FileTransfer %s", hostname->str); + + gmyth_string_list_append_string (strlist, base_str ); + gmyth_string_list_append_char_array (strlist, transfer->filename); + + gmyth_socket_write_stringlist (transfer->sock, strlist ); + gmyth_socket_read_stringlist (transfer->sock, strlist ); + + /* file identification used in future file transfer requests to backend */ + transfer->file_id = gmyth_string_list_get_int( strlist, 1 ); + + /* Myth URI stream file size - decoded using two 8-bytes sequences (64 bits/long long types) */ + transfer->filesize = gmyth_util_decode_long_long( strlist, 2 ); + + gmyth_debug ( "[%s] ***** Received: recordernum = %d, filesize = %" G_GUINT64_FORMAT "\n", __FUNCTION__, + transfer->file_id, transfer->filesize ); + + if (transfer->filesize < 0 ) { + gmyth_debug ( "[%s] Got filesize equals to %llu is lesser than 0 [invalid stream file]\n", __FUNCTION__, transfer->filesize ); + g_object_unref (transfer->sock); + transfer->sock = NULL; + ret = FALSE; + goto cleanup; + } + +cleanup: + + if ( strlist != NULL ) + g_object_unref( strlist ); + + g_string_free (base_str, TRUE); + g_string_free (hostname, TRUE); + + return ret; +} + +void +gmyth_file_transfer_emit_program_info_changed_signal ( GMythFileTransfer *transfer, gint msg_code, + gpointer live_tv ) +{ + /* + g_signal_emit_by_name ( G_OBJECT(transfer), + "program-info-changed", + msg_code, live_tv ); + */ + + gmyth_debug( "Calling signal handler... [FILE_TRANSFER]" ); + + g_signal_emit ( transfer, + GMYTH_FILE_TRANSFER_GET_CLASS (transfer)->program_info_changed_handler_signal_id, + 0, /* details */ + msg_code, live_tv ); + +} + +gboolean +gmyth_file_transfer_is_open (GMythFileTransfer *transfer) +{ + GMythStringList *strlist; + GString *query; + + g_return_val_if_fail (transfer->control_sock != NULL, FALSE); + g_return_val_if_fail (transfer->sock != NULL, FALSE); + + strlist = gmyth_string_list_new(); + query = g_string_new (GMYTHTV_QUERY_HEADER); + g_string_append_printf (query, "%d", transfer->file_id ); + + gmyth_string_list_append_string (strlist, query ); + gmyth_string_list_append_char_array( strlist, "IS_OPEN" ); + + gmyth_socket_write_stringlist( transfer->control_sock, strlist ); + gmyth_socket_read_stringlist( transfer->control_sock, strlist ); + + g_string_free (query, TRUE); + g_object_unref (strlist); + + return ( strlist != NULL && gmyth_string_list_get_int( strlist, 0 ) == 1 ); +} + +void +gmyth_file_transfer_close( GMythFileTransfer *transfer ) +{ + GMythStringList *strlist; + GString *query; + + g_return_if_fail (transfer->control_sock != NULL); + + strlist = gmyth_string_list_new( ); + query = g_string_new (GMYTHTV_QUERY_HEADER); + g_string_append_printf( query, "%d", transfer->file_id); + + gmyth_string_list_append_string( strlist, query ); + gmyth_string_list_append_char_array( strlist, "DONE" ); + + if ( gmyth_socket_sendreceive_stringlist(transfer->control_sock, strlist) <= 0 ) { + // fixme: time out??? + g_printerr( "Remote file timeout.\n" ); + } + + g_string_free (query, TRUE); + g_object_unref (strlist); + + if (transfer->sock) { + g_object_unref( transfer->sock ); + transfer->sock = NULL; + } + + if (transfer->control_sock) { + g_object_unref( transfer->control_sock ); + transfer->control_sock = NULL; + } + +} + +gint64 +gmyth_file_transfer_seek(GMythFileTransfer *transfer, guint64 pos, gint whence) +{ + GMythStringList *strlist = gmyth_string_list_new(); + GString *query; + + g_return_val_if_fail (transfer->sock != NULL, -1); + g_return_val_if_fail (transfer->control_sock != NULL, -1); + + strlist = gmyth_string_list_new(); + query = g_string_new (GMYTHTV_QUERY_HEADER); + g_string_append_printf (query, "%d", transfer->file_id); + + myth_control_acquire_context( TRUE ); + + gmyth_string_list_append_string( strlist, query ); + gmyth_string_list_append_char_array( strlist, "SEEK" ); + gmyth_string_list_append_uint64( strlist, pos ); + + gmyth_string_list_append_int( strlist, whence ); + + if (pos > 0 ) + gmyth_string_list_append_uint64( strlist, pos ); + else + gmyth_string_list_append_uint64( strlist, transfer->readposition ); + + gmyth_socket_sendreceive_stringlist( transfer->control_sock, strlist ); + + gint64 retval = gmyth_string_list_get_int64(strlist, 0); + transfer->readposition = retval; + gmyth_debug ( "[%s] got reading position pointer from the streaming = %lld\n", + __FUNCTION__, retval ); + + myth_control_release_context( ); + + return retval; +} + +static gboolean +myth_control_acquire_context( gboolean do_wait ) +{ + gboolean ret = TRUE; + //guint max_iter = 50; + + //g_mutex_lock( mutex ); + + //while ( !has_io_access ) + // g_cond_wait( io_watcher_cond, mutex ); + + //has_io_access = FALSE; + + //myth_control_acquire_context (FALSE); + + /* + if ( do_wait ) { + while ( --max_iter > 0 && !g_main_context_wait( io_watcher_context, io_watcher_cond, mutex ) ) + ret = FALSE; + } else if ( !g_main_context_acquire( io_watcher_context ) ) + ret = FALSE; + */ + + //g_static_mutex_lock( &st_mutex ); + + return ret; +} + +static gboolean +myth_control_release_context( ) +{ + gboolean ret = TRUE; + + //g_static_mutex_unlock( &st_mutex ); + + //g_main_context_release( io_watcher_context ); + + //g_main_context_wakeup( io_watcher_context ); + + //has_io_access = TRUE; + + //g_cond_broadcast( io_watcher_cond ); + + //g_mutex_unlock( mutex ); + + return ret; +} + +gint +gmyth_file_transfer_read(GMythFileTransfer *transfer, GByteArray *data, gint size, gboolean read_unlimited) +{ + gint bytes_sent = 0; + gsize bytes_read = 0; + gsize total_read = 0; + + GError *error = NULL; + + GIOChannel *io_channel; + GIOChannel *io_channel_control; + + GIOCondition io_cond; + GIOCondition io_cond_control; + GIOStatus io_status = G_IO_STATUS_NORMAL, io_status_control = G_IO_STATUS_NORMAL; + + gboolean ret = TRUE; + + GString *query; + + g_return_val_if_fail ( data != NULL, -2 ); + + io_channel = transfer->sock->sd_io_ch; + io_channel_control = transfer->control_sock->sd_io_ch; + + io_status = g_io_channel_set_encoding( io_channel, NULL, &error ); + if ( io_status == G_IO_STATUS_NORMAL ) + gmyth_debug ( "[%s] Setting encoding to binary data socket).\n", __FUNCTION__ ); + + io_cond = g_io_channel_get_buffer_condition( io_channel ); + + io_cond_control = g_io_channel_get_buffer_condition( io_channel ); + if ( transfer->sock == NULL || ( io_status == G_IO_STATUS_ERROR ) ) { + g_printerr( "gmyth_file_transfer_read(): Called with no raw socket.\n" ); + //exit(0); // fixme remove this + return -1; + } + + if ( transfer->control_sock == NULL || ( io_status_control == G_IO_STATUS_ERROR ) ) { + g_printerr( "gmyth_file_transfer_read(): Called with no control socket.\n" ); + //exit(0); // fixme remove this + return -1; + } + + query = g_string_new (GMYTHTV_QUERY_HEADER); + g_string_append_printf ( query, "%d", transfer->file_id ); + gmyth_debug ("[%s] Transfer_query = %s\n", __FUNCTION__, query->str ); + + /* send requests to the maximum number of REQUEST_BLOCK messages */ + guint max_tries = 5; + + myth_control_acquire_context( TRUE ); + + while (total_read == 0 && --max_tries > 0) { + GMythStringList *strlist = gmyth_string_list_new(); + + gmyth_string_list_append_char_array( strlist, query->str ); + gmyth_string_list_append_char_array( strlist, "REQUEST_BLOCK" ); + gmyth_string_list_append_int( strlist, size ); + + // Request the block to the backend + gmyth_socket_write_stringlist( transfer->control_sock, strlist ); + + // Receives the backand answer + gmyth_socket_read_stringlist( transfer->control_sock, strlist ); + + if ( strlist != NULL && gmyth_string_list_length( strlist ) > 0 ) + { + bytes_sent = gmyth_string_list_get_int( strlist, 0 ); // -1 on backend error + gmyth_debug ( "[%s] got SENT buffer message = %d\n", __FUNCTION__, bytes_sent ); + + if ( bytes_sent >= 0 ) + { + gchar *data_buffer = g_new0 ( gchar, bytes_sent ); + while ( 0 != bytes_sent ) + { + io_status = g_io_channel_read_chars( io_channel, data_buffer + total_read, + (gsize) bytes_sent, &bytes_read, &error ); + + total_read += bytes_read; + bytes_sent -= bytes_read; + + /* append new data to the increasing byte array */ + data = g_byte_array_append (data, (const guint8*)data_buffer, bytes_read); + gmyth_debug ("Total transfer data read: %d\n", total_read); + } + g_free (data_buffer); + } /* if */ + } else if ( !(transfer->priv != NULL && transfer->priv->livetv != NULL && + transfer->priv->do_next_program_chain) ) { + total_read = GMYTHTV_FILE_TRANSFER_READ_ERROR; + g_object_unref (strlist); + strlist = NULL; + break; + } + g_object_unref (strlist); + strlist = NULL; + } + + if ( bytes_sent == 0 && max_tries == 0 ) + { + gmyth_debug( "Trying to move to the next program chain..." ); + transfer->priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); + + if ( transfer->priv != NULL && transfer->priv->livetv != NULL && + transfer->priv->do_next_program_chain ) + { + + total_read = GMYTHTV_FILE_TRANSFER_NEXT_PROG_CHAIN; + + g_mutex_lock( transfer->mutex ); + + ret = gmyth_livetv_next_program_chain( transfer->priv->livetv ); + + g_mutex_unlock( transfer->mutex ); + + if ( !ret ) + gmyth_debug( "Cannot change to the next program chain!" ); + else + gmyth_debug( "OK!!! MOVED to the next program chain [%s]!", + (gmyth_tvchain_get_id( transfer->priv->livetv->tvchain ))->str ); + } + + } /* if */ + + myth_control_release_context( ); + g_string_free (query, TRUE); + + if ( error != NULL ) { + gmyth_debug ("Cleaning-up ERROR: %s [msg = %s, code = %d]\n", __FUNCTION__, error->message, + error->code); + g_error_free (error); + } + + if ( total_read > 0 ) + transfer->readposition += total_read; + + return total_read; +} + +static void +gmyth_file_transfer_program_info_changed( GMythFileTransfer *transfer, + gint msg_code, gpointer livetv_transfer ) +{ + GMythLiveTV *livetv = GMYTH_LIVETV( livetv_transfer ); + + gmyth_debug( "Program info changed! ( file transfer orig. = %p, ptr. = [%s], user data = [%s] )", transfer, + livetv_transfer != NULL ? "[NOT NULL]" : "[NULL]", livetv != NULL ? "[NOT NULL]" : "[NULL]" ); + + if ( livetv != NULL && transfer == livetv->file_transfer ) + { + gmyth_debug( "YES, the requested program info movement on the LiveTV transfer is authentical!" ); + } + + transfer->priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); + + transfer->priv->livetv = livetv; + transfer->priv->do_next_program_chain = TRUE; + + //g_object_unref( transfer ); +} + +gboolean +gmyth_file_transfer_settimeout( GMythFileTransfer *transfer, gboolean fast ) +{ + + GMythStringList *strlist = NULL; + + g_return_val_if_fail (transfer->sock != NULL, FALSE); + g_return_val_if_fail (transfer->control_sock != NULL, FALSE); + +// if ( transfer->timeoutisfast == fast ) +// return; + + strlist = gmyth_string_list_new(); + gmyth_string_list_append_char_array( strlist, GMYTHTV_QUERY_HEADER ); + gmyth_string_list_append_char_array( strlist, "SET_TIMEOUT" ); + gmyth_string_list_append_int( strlist, fast ); + + gmyth_socket_write_stringlist( transfer->control_sock, strlist ); + gmyth_socket_read_stringlist( transfer->control_sock, strlist ); + +// transfer->timeoutisfast = fast; + + return TRUE; +} + + +guint64 +gmyth_file_transfer_get_filesize (GMythFileTransfer *transfer) +{ + g_return_val_if_fail (transfer != NULL, 0); + return transfer->filesize; +} diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_file_transfer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_file_transfer.h Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,122 @@ +/* vim: set sw=2: -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2; c-indent-level: 2-*- */ +/** + * GMyth Library + * + * @file gmyth/gmyth_file_transfer.h + * + * @brief

GMythFileTransfer deals with the file streaming media remote/local + * transfering to the MythTV frontend. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Rosfran Lins Borges + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GMYTH_FILE_TRANSFER_H__ +#define __GMYTH_FILE_TRANSFER_H__ + +#include +#include + +#include "gmyth_socket.h" +#include "gmyth_uri.h" +#include "gmyth_backendinfo.h" + +#include +#include +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define GMYTH_FILE_TRANSFER_TYPE (gmyth_file_transfer_get_type ()) +#define GMYTH_FILE_TRANSFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_FILE_TRANSFER_TYPE, GMythFileTransfer)) +#define GMYTH_FILE_TRANSFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_FILE_TRANSFER_TYPE, GMythFileTransferClass)) +#define IS_GMYTH_FILE_TRANSFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_FILE_TRANSFER_TYPE)) +#define IS_GMYTH_FILE_TRANSFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_FILE_TRANSFER_TYPE)) +#define GMYTH_FILE_TRANSFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_FILE_TRANSFER_TYPE, GMythFileTransferClass)) + +#define GMYTHTV_FILE_TRANSFER_READ_ERROR -314 +#define GMYTHTV_FILE_TRANSFER_NEXT_PROG_CHAIN -315 + +typedef struct _GMythFileTransfer GMythFileTransfer; +typedef struct _GMythFileTransferClass GMythFileTransferClass; +typedef struct _GMythFileTransferPrivate GMythFileTransferPrivate; + +struct _GMythFileTransferClass +{ + GObjectClass parent_class; + + /* callbacks */ + guint program_info_changed_handler_signal_id; + + /* signal default handlers */ + void (*program_info_changed_handler) ( GMythFileTransfer *transfer, + gint msg_code, gpointer livetv_transfer ); +}; + +struct _GMythFileTransfer +{ + GObject parent; + + /* Myth URI structure */ + gchar *filename; + GMythBackendInfo *backend_info; + + /* MythTV version number */ + gint mythtv_version; + + /* socket descriptors */ + GMythSocket *control_sock; + GMythSocket *sock; + + GMutex *mutex; + + gint64 readposition; + guint64 filesize; + gint file_id; + + GMythFileTransferPrivate *priv; + +}; + +GType gmyth_file_transfer_get_type (void); +GMythFileTransfer *gmyth_file_transfer_new (const GMythBackendInfo *backend_info); +gboolean gmyth_file_transfer_open (GMythFileTransfer *transfer, + const gchar* filename); +void gmyth_file_transfer_close (GMythFileTransfer *transfer); +gboolean gmyth_file_transfer_is_open (GMythFileTransfer *transfer); +gint gmyth_file_transfer_read (GMythFileTransfer *transfer, + GByteArray *data, + gint size, + gboolean read_unlimited); +gint64 gmyth_file_transfer_seek (GMythFileTransfer *transfer, + guint64 pos, + gint whence); +gboolean gmyth_file_transfer_settimeout (GMythFileTransfer *transfer, gboolean fast); +guint64 gmyth_file_transfer_get_filesize (GMythFileTransfer *transfer); + +void gmyth_file_transfer_emit_program_info_changed_signal ( GMythFileTransfer *transfer, + gint msg_code, + gpointer live_tv ); + +G_END_DECLS + +#endif /* __GMYTH_FILE_TRANSFER_H__ */ diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_http.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_http.c Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,343 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_http.c + * + * @brief

GMythHttp class provides a wrapper to access + * data from the database using http+xml + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Artur Duque de Souza <@indt.org.br> + * + */ +/* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#include "gmyth_http.h" +#include "gmyth_debug.h" +#include "gmyth_socket.h" + + +xmlXPathObjectPtr +getnodeset(xmlDocPtr doc, xmlChar *xpath) +{ + + xmlXPathContextPtr context; + xmlXPathObjectPtr result; + + context = xmlXPathNewContext(doc); + result = xmlXPathEvalExpression(xpath, context); + + if(xmlXPathNodeSetIsEmpty(result->nodesetval)) + { + g_fprintf(stderr, "Error: No result at XPath\n"); + return NULL; + } + + xmlXPathFreeContext(context); + return result; +} + + +xmlDocPtr XMLParse (const char *content, int length) +{ + xmlDocPtr doc; /* the resulting document tree */ + + doc = xmlReadMemory(content, length, NULL, NULL, 0); + if (doc == NULL) + { + g_fprintf(stderr, "Error: Failed to parse XML document\n"); + return NULL; + } + + return doc; +} + +xmlXPathObjectPtr getXPath (xmlChar *xpath, xmlDocPtr doc) +{ + xmlXPathObjectPtr result; + result = getnodeset(doc, xpath); + return result; +} + +/** Retrieves the Progam List from the Channel + * + * @param nodeTab A pointer to a node inside the XML + * @return A GSList containing a list of all the programs + */ +GSList* get_Program_List(xmlNodePtr node) +{ + GSList* program_list = NULL; + + while (node != NULL) + { + if (g_ascii_strcasecmp((char *)node->name, "text") != 0) + { + GMythProgram* program = (GMythProgram*)g_malloc(sizeof(struct _GMythProgram)); + + program->title = g_string_new((char *)xmlGetProp(node, (xmlChar *)"title")); + program->subtitle = g_string_new((char *)xmlGetProp(node, (xmlChar *)"subtitle")); + program->catType = g_string_new((char *)xmlGetProp(node, (xmlChar *)"catType")); + program->category = g_string_new((char *)xmlGetProp(node, (xmlChar *)"category")); + + sscanf ((char *)xmlGetProp(node, (xmlChar *)"repeat"), "%d", &(program->repeat)); + + program->startTime = gmyth_util_string_to_time_val ((char *)xmlGetProp(node, \ + (xmlChar *)"startTime")); + program->endTime = gmyth_util_string_to_time_val ((char *)xmlGetProp(node, \ + (xmlChar *)"endTime")); + + program_list = g_slist_append(program_list, program); + } + + node = node->next; + } + + return program_list; +} + +/** Retrieves the Channel List from the ProgramGuide + * + * @param node A pointer to a node inside the XML + * @param epg The struct where is the current epg + * @return The epg from "param" updated + */ +void get_Channel_List (xmlNodePtr node, GMythEpg* epg) +{ + int i; + epg->channelList = NULL; + + for (i=1; i <= epg->numOfChannels; i++) + { + GMythChannel* channel = (GMythChannel*)g_malloc(sizeof(struct _GMythChannel)); + + channel->channelName = g_string_new((char *)xmlGetProp(node, (xmlChar *)"channelName")); + channel->chanNum = g_string_new((char *)xmlGetProp(node, (xmlChar *)"chanNum")); + + sscanf ((char *)xmlGetProp(node, (xmlChar *)"chanId"), "%d", &(channel->chanId)); + sscanf ((char *)xmlGetProp(node, (xmlChar *)"callSign"), "%d", &(channel->callSign)); + + channel->programList = get_Program_List(node->children); + + epg->channelList = g_slist_append(epg->channelList, channel); + } +} + +/** Retrieves the properties from the ProgramGuide + * + * @param nodeTab A pointer to a node inside the XML + * @param epg The struct where is the current epg + * @return The epg from "param" updated + */ +void get_ProgramGuide_Properties (xmlNodePtr nodeTab, GMythEpg* epg) +{ + sscanf ((char *)xmlGetProp(nodeTab, (xmlChar *)"startChanId"), "%d", &(epg->startChanId)); + sscanf ((char *)xmlGetProp(nodeTab, (xmlChar *)"endChanId"), "%d", &(epg->endChanId)); + + epg->version = g_string_new((char *)xmlGetProp(nodeTab, (xmlChar *)"version")); + + sscanf ((char *)xmlGetProp(nodeTab, (xmlChar *)"protoVer"), "%d", &(epg->protoVer)); + sscanf ((char *)xmlGetProp(nodeTab, (xmlChar *)"totalCount"), "%d", &(epg->totalCount)); + sscanf ((char *)xmlGetProp(nodeTab, (xmlChar *)"numOfChannels"), "%d", &(epg->numOfChannels)); + + epg->asOf = gmyth_util_string_to_time_val ((char *)xmlGetProp(nodeTab, (xmlChar *)"asOf")); + epg->startTime = gmyth_util_string_to_time_val ((char *)xmlGetProp(nodeTab, (xmlChar *)"startTime")); + epg->endTime = gmyth_util_string_to_time_val ((char *)xmlGetProp(nodeTab, (xmlChar *)"endTime")); + + sscanf ((char *)xmlGetProp(nodeTab, (xmlChar *)"details"), "%d", &(epg->details)); + + // go to Channel section and retrieve Channels and Programs + get_Channel_List(nodeTab->children->next->children->next, epg); +} + +/** Aux function to retrieve the Eletronic Program Guide + * + * @param doc An XML document (xmlDocPtr) + * @return The epg + */ +void getEpg (xmlDocPtr doc, GMythEpg* epg) +{ + xmlXPathObjectPtr result; + xmlNodeSetPtr nodeset; + xmlChar *keyword; + + int i; + result = getXPath((xmlChar *)"/*", doc); + + if (result) + { + nodeset = result->nodesetval; + for (i=0; i < nodeset->nodeNr; i++) + { + keyword = (xmlChar*)nodeset->nodeTab[i]->name; + if (g_ascii_strcasecmp((char *)keyword, "ProgramGuide") == 0) + get_ProgramGuide_Properties(nodeset->nodeTab[i], epg); + } + xmlXPathFreeObject (result); + } + +} + +/** Retrieves the Eletronic Program Guide from the backend + * + * @param doc An XML document (xmlDocPtr) + * @return The epg + */ +GMythEpg retrieve_epg (GMythBackendInfo *backend_info, int port, \ + GTimeVal* StartTime, GTimeVal* EndTime, \ + gint StartChanId, gint NumOfChannels, \ + gchar* Details) +{ + GMythEpg epg; + MemoryStruct chunk; + + chunk.memory=NULL; /* we expect realloc(NULL, size) to work */ + chunk.size = 0; /* no data at this point */ + + gchar* starttime = (gchar*)g_malloc(sizeof(gchar)*20); + starttime = gmyth_util_time_to_mythformat_from_time_val(StartTime); + + gchar* endtime = (gchar*)g_malloc(sizeof(gchar)*20); + endtime = gmyth_util_time_to_mythformat_from_time_val(EndTime); + + GString* command = g_string_new(""); + g_string_printf(command, "getProgramGuide?StartTime=%s&EndTime=%s&StartChanId=%d" + "&NumOfChannels=%d&Details=%s", starttime, endtime, \ + StartChanId, NumOfChannels, Details); + + chunk = gmyth_http_request(backend_info, command); + xmlDocPtr doc = XMLParse(chunk.memory, strlen(chunk.memory)); + getEpg(doc, &epg); + free(chunk.memory); + + return epg; +} + +/* Aux functions got from libcurl */ +void *myrealloc (void *ptr, size_t size) +{ + /* There might be a realloc() out there that doesn't like reallocing + NULL pointers, so we take care of it here */ + if(ptr) + return realloc(ptr, size); + else + return malloc(size); +} + +size_t +WriteMemoryCallback (void *ptr, size_t size, size_t nmemb, void *data) +{ + size_t realsize = size * nmemb; + MemoryStruct *mem = (struct _MemoryStruct *)data; + + mem->memory = (char *)myrealloc(mem->memory, mem->size + realsize + 1); + if (mem->memory) + { + memcpy(&(mem->memory[mem->size]), ptr, realsize); + mem->size += realsize; + mem->memory[mem->size] = 0; + } + + return realsize; +} + +/** Create a String containing the URL with the command + * + * @param command A string with the command + * @param variables Vars to use with their values \ + * MUST FINISH WITH NULL!!! + * @return The response + */ +GString* gmyth_http_create_command (GString *command, ...) +{ + va_list args; + va_start(args, command); + gchar* s = NULL; + + g_string_append(command, "?"); + + /* Sintax: var, value */ + while ( (s = va_arg(args, gchar *)) != NULL ) + { + g_string_append(command, s); + g_string_append(command, "="); + s = va_arg(args, gchar *); + g_string_append(command, s); + g_string_append(command, "&"); + } + + free(s); + va_end(args); + + return command; +} + +/** Send HTTP Command and receives the result of it + * + * @return A string with the response from the server + * NULL if there is no response. + */ +MemoryStruct gmyth_http_request (GMythBackendInfo *backend_info, GString *command) +{ + LIBXML_TEST_VERSION + + size_t size = strlen(backend_info->hostname) + strlen(command->str) + 13; + gchar *URL = (gchar *)g_malloc(sizeof(gchar)*size); + g_snprintf(URL, size+1, "http://%s:6544/%s", backend_info->hostname, command->str); + + CURL *curl_handle; + + MemoryStruct chunk; + + chunk.memory=NULL; /* we expect realloc(NULL, size) to work */ + chunk.size = 0; /* no data at this point */ + + curl_global_init(CURL_GLOBAL_ALL); + + /* init the curl session */ + curl_handle = curl_easy_init(); + + /* specify URL to get */ + curl_easy_setopt(curl_handle, CURLOPT_URL, URL); + + /* send all data to this function */ + curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); + + /* we pass our 'chunk' struct to the callback function */ + curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk); + + /* some servers don't like requests that are made without a user-agent + field, so we provide one */ + curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0"); + + /* get it! */ + curl_easy_perform(curl_handle); + + /* cleanup curl stuff */ + curl_easy_cleanup(curl_handle); + + return chunk; +} diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_http.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_http.h Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,110 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_http.c + * + * @brief

GMythHttp class provides a wrapper to access + * data from the database using http+xml + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Artur Duque de Souza <@indt.org.br> + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GMYTH_HTTP_H__ +#define __GMYTH_HTTP_H__ + +#include + +#include +#include +#include +#include +#include +#include + +#include "gmyth_backendinfo.h" +#include "gmyth_util.h" + +#include +#include +#include + +G_BEGIN_DECLS + +#define MYTH_PORT_STATUS 6544 + +typedef struct _GMythPacket GMythPacket; +typedef struct _GMythProgram GMythProgram; +typedef struct _GMythChannel GMythChannel; +typedef struct _GMythEpg GMythEpg; +typedef struct _MemoryStruct MemoryStruct; + +struct _MemoryStruct +{ + char *memory; + size_t size; +}; + +struct _GMythPacket +{ + GString *response; + int type; +}; + +struct _GMythProgram +{ + GString* title; + GString* subtitle; + GString* catType; + GString* category; + gint repeat; + GTimeVal* startTime; + GTimeVal* endTime; +}; + +struct _GMythChannel +{ + GString* channelName; + GString* chanNum; + gint chanId; + gint callSign; + GSList* programList; +}; + +struct _GMythEpg +{ + gint startChanId; + gint endChanId; + GString* version; + gint protoVer; + gint totalCount; + gint numOfChannels; + GTimeVal* asOf; + GTimeVal* startTime; + GTimeVal* endTime; + gint details; + GSList* channelList; +}; + +GMythEpg retrieve_epg(GMythBackendInfo *backend_info, int port, GTimeVal* StartTime, GTimeVal* EndTime, gint StartChanId, gint NumOfChannels, gchar* Details); +MemoryStruct gmyth_http_request (GMythBackendInfo *backend_info, GString *command); + +G_END_DECLS + +#endif /* __GMYTH_HTTP_H__ */ diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_livetv.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_livetv.c Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,668 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_livetv.c + * + * @brief

GMythLiveTV starts a remote TV session with the MythTV backend. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Rosfran Lins Borges + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gmyth_livetv.h" +#include "gmyth_remote_util.h" +#include "gmyth_tvchain.h" +#include "gmyth_socket.h" +#include "gmyth_backendinfo.h" +#include "gmyth_debug.h" + +#include "gmyth_file_transfer.h" +#include "gmyth_monitor_handler.h" + +static void gmyth_livetv_class_init (GMythLiveTVClass *klass); +static void gmyth_livetv_init (GMythLiveTV *object); + +static void gmyth_livetv_dispose (GObject *object); +static void gmyth_livetv_finalize (GObject *object); + +static gint tvchain_curr_index = -1; + +static GStaticMutex lock = G_STATIC_MUTEX_INIT; + +#define GMYTHTV_TRANSFER_MAX_WAITS 100 + +G_DEFINE_TYPE(GMythLiveTV, gmyth_livetv, G_TYPE_OBJECT) + +static void +gmyth_livetv_class_init (GMythLiveTVClass *klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + + gobject_class->dispose = gmyth_livetv_dispose; + gobject_class->finalize = gmyth_livetv_finalize; +} + +static void +gmyth_livetv_init (GMythLiveTV *livetv) +{ + livetv->backend_info = NULL; + livetv->local_hostname = NULL; + livetv->file_transfer = NULL; + livetv->setup_done = FALSE; + + livetv->recorder = NULL; + livetv->tvchain = NULL; + livetv->proginfo = NULL; + livetv->uri = NULL; + +} + +static void +gmyth_livetv_dispose (GObject *object) +{ + G_OBJECT_CLASS (gmyth_livetv_parent_class)->dispose (object); +} + +static void +gmyth_livetv_finalize (GObject *object) +{ + g_signal_handlers_destroy (object); + + GMythLiveTV *livetv = GMYTH_LIVETV (object); + + gmyth_debug ("Finalizing livetv"); + + if ( livetv->monitor != NULL ) { + g_object_unref (livetv->monitor); + livetv->monitor = NULL; + } + + if ( livetv->recorder != NULL ) { + g_object_unref (livetv->recorder); + livetv->recorder = NULL; + } + + if ( livetv->tvchain != NULL ) { + g_object_unref (livetv->tvchain); + livetv->tvchain = NULL; + } + + if ( livetv->proginfo != NULL ) { + g_object_unref (livetv->proginfo); + livetv->proginfo = NULL; + } + + if ( livetv->file_transfer != NULL ) { + g_object_unref (livetv->file_transfer); + livetv->file_transfer = NULL; + } + + if ( livetv->backend_info != NULL ) { + g_object_unref (livetv->backend_info); + livetv->backend_info = NULL; + } + + if ( livetv->uri != NULL ) + { + g_object_unref (livetv->uri); + livetv->uri = NULL; + } + + G_OBJECT_CLASS ( gmyth_livetv_parent_class )->finalize ( object ); +} + +GMythLiveTV* +gmyth_livetv_new () +{ + GMythLiveTV *livetv = GMYTH_LIVETV ( g_object_new( GMYTH_LIVETV_TYPE, NULL ) ); + + return livetv; +} + +static void +gmyth_livetv_monitor_signal_handler( GMythMonitorHandler *monitor, gint msg_code, + gchar* message, gpointer user_data ) +{ + GMythLiveTV *live_tv = GMYTH_LIVETV ( user_data ); + //g_object_ref( live_tv ); + + gmyth_debug( "LIVETV Signal handler ( msg = %s, code = %d, live_tv param = %s, user_data = %s )\n", message, msg_code, live_tv != NULL ? "" : + "NULL", user_data != NULL ? "" : "NULL" ); + + if ( NULL == live_tv ) + { + gmyth_debug( "LiveTV_obj is equals to NULL!!!" ); + return; + } + + switch ( msg_code ) + { + + case GMYTH_BACKEND_PROGRAM_INFO_CHANGED: + { + gmyth_debug( "LIVETV Program Changed request received [ msg = %s ]. Watching if the new "\ + "TV Chain ID is the same as the old one...\n", message ); + if ( g_ascii_strcasecmp ( message, (gmyth_tvchain_get_id( live_tv->tvchain ))->str ) != 0 ) { + gmyth_debug( "OK!!! MOVED to the next program chain [actual == %s]!", + (gmyth_tvchain_get_id( live_tv->tvchain ))->str ); + /* advertises the FileTransfer about the program info changed */ + if ( live_tv->file_transfer != NULL ) + { + gmyth_debug( "Emitting signal to the FileTransfer... [ \"program-info-changed \" ]" ); + + gmyth_file_transfer_emit_program_info_changed_signal( live_tv->file_transfer, + msg_code, (gpointer)live_tv ); + + //gmyth_livetv_monitor_handler_stop( live_tv ); + } else + gmyth_debug( "LIVETV file_transfer is NULL!!! Cannot move to the next program chain event received.\n"); + } + } + case GMYTH_BACKEND_DONE_RECORDING: + { + gmyth_debug( "LIVETV Program Changed request received [ msg = %s ]. Watching if the new "\ + "TV Chain ID is the same as the old one...\n", message ); + if ( g_ascii_strcasecmp ( message, (gmyth_tvchain_get_id( live_tv->tvchain ))->str ) != 0 ) { + gmyth_debug( "OK!!! MOVED to the next program chain [actual == %s]!", + (gmyth_tvchain_get_id( live_tv->tvchain ))->str ); + /* advertises the FileTransfer about the program info changed */ + if ( live_tv->file_transfer != NULL ) + { + gmyth_debug( "Emitting signal to the FileTransfer... [ \"program-info-changed \" ]" ); + + gmyth_file_transfer_emit_program_info_changed_signal( live_tv->file_transfer, + msg_code, (gpointer)live_tv ); + + //gmyth_livetv_monitor_handler_stop( live_tv ); + } else + gmyth_debug( "LIVETV file_transfer is NULL!!! Cannot move to the next program chain event received.\n"); + } + + break; + } + default: + break; + } /* switch (Monitor Handler messages) */ + +} + +gboolean +gmyth_livetv_monitor_handler_start( GMythLiveTV *livetv ) +{ + gboolean res = TRUE; + + if ( livetv->monitor != NULL ) + { + g_object_unref( livetv->monitor ); + livetv->monitor = NULL; + } + + livetv->monitor = gmyth_monitor_handler_new ( ); + + res = gmyth_monitor_handler_open (livetv->monitor, livetv->backend_info->hostname, + livetv->backend_info->port ); + + if ( res == TRUE ) + { + gmyth_debug("Connect MythTV Monitor event socket! Trying to start the message handler..."); + + res = gmyth_monitor_handler_start ( livetv->monitor ); + + if (res) + { + gmyth_debug("MythTV Monitor event socket connected and listening!"); + g_signal_connect ( G_OBJECT (livetv->monitor), "backend-events-handler", + (GCallback)gmyth_livetv_monitor_signal_handler, + livetv ); + } + else + { + gmyth_debug("Problems when trying to start MythTV Monitor event socket!"); + goto error; + } + } + +error: + return res; + +} + +void +gmyth_livetv_monitor_handler_stop( GMythLiveTV *livetv ) +{ + + if ( livetv->monitor != NULL ) + { + g_object_unref( livetv->monitor ); + livetv->monitor = NULL; + } + +} + + +/* +static gchar* +gmyth_livetv_create_remote_url( GMythLiveTV *livetv ) +{ + gchar *uri = g_strdup(""); + gmyth_backend_info_get_remote_h + + //gmyth_backend(livetv->backend_info) + + return uri; +} +*/ + +static gboolean +gmyth_livetv_setup_recorder_channel_name ( GMythLiveTV *livetv, gchar* channel, GMythBackendInfo *backend_info ) +{ + gboolean res = TRUE; + + GMythSocket *socket = gmyth_socket_new (); + + livetv->backend_info = backend_info; + + g_static_mutex_lock( &lock ); + + // FIME: Implement this at gmyth_socket + res = gmyth_socket_connect_to_backend (socket, livetv->backend_info->hostname, + livetv->backend_info->port, TRUE); + if (!res) { + g_warning ("[%s] LiveTV can not connect to backend", __FUNCTION__); + res = FALSE; + goto error; + } + + livetv->is_livetv = TRUE; + + livetv->local_hostname = gmyth_socket_get_local_hostname (); + + if ( livetv->local_hostname == NULL ) { + res = FALSE; + goto error; + } + + // Gets the recorder num + livetv->recorder = remote_request_next_free_recorder (socket, -1); + gmyth_socket_close_connection (socket); + + if ( livetv->recorder == NULL ) { + g_warning ("[%s] None remote encoder available", __FUNCTION__); + res = FALSE; + goto error; + } + + // Init remote encoder. Opens its control socket. + res = gmyth_recorder_setup(livetv->recorder); + if ( !res ) { + g_warning ("[%s] Fail while setting remote encoder\n", __FUNCTION__); + res = FALSE; + goto error; + } + + // Creates livetv chain handler + livetv->tvchain = GMYTH_TVCHAIN ( g_object_new(GMYTH_TVCHAIN_TYPE, NULL) ); + gmyth_tvchain_initialize ( livetv->tvchain, livetv->backend_info ); + + if ( livetv->tvchain == NULL || livetv->tvchain->tvchain_id == NULL ) { + res = FALSE; + goto error; + } + + // Spawn live tv. Uses the socket to send mythprotocol data to start livetv in the backend (remotelly) + res = gmyth_recorder_spawntv ( livetv->recorder, + gmyth_tvchain_get_id(livetv->tvchain) ); + if (!res) { + g_warning ("[%s] Fail while spawn tv\n", __FUNCTION__); + res = FALSE; + goto error; + } + + if ( res == TRUE ) { + /* loop finished, set the max tries variable to zero again... */ + gint wait_to_transfer = 0; + + while (wait_to_transfer++ < GMYTHTV_TRANSFER_MAX_WAITS && + (gmyth_recorder_is_recording (livetv->recorder) == FALSE)) + g_usleep (500); + + /* IS_RECORDING again, just like the MythTV backend does... */ + gmyth_recorder_is_recording (livetv->recorder); + + if ( channel != NULL ) + { + /* Pauses remote encoder. */ + res = gmyth_recorder_pause_recording(livetv->recorder); + if ( !res ) { + g_warning ("[%s] Fail while pausing remote encoder\n", __FUNCTION__); + res = FALSE; + goto error; + } + + if ( gmyth_recorder_check_channel_name( livetv->recorder, channel ) ) + { + if ( gmyth_recorder_set_channel_name( livetv->recorder, channel ) ) + { + g_print( "[%s] Channel changed!!! [%s].\n", __FUNCTION__, channel ); + } + } + + } + + sleep (9); /* FIXME: this is evil (tpm) */ + } + + /* DEBUG message */ + GMythProgramInfo* prog_info = gmyth_recorder_get_current_program_info( livetv->recorder ); + + if ( NULL == prog_info ) + { + gmyth_debug( "ProgramInfo is equals to NULL!!!" ); + + return FALSE; + } + /* prints program info data text */ + gmyth_debug( "New ProgramInfo...\n" ); + gmyth_program_info_print( prog_info ); + /* DEBUG message */ + gmyth_debug( "Old ProgramInfo...\n" ); + gmyth_program_info_print( livetv->proginfo ); + + /* check if the program chain could be obtained from the MythTV protocol message */ + if ( prog_info != NULL ) + { + livetv->proginfo = prog_info; + /* testing change channel */ + //gmyth_recorder_spawntv_no_tvchain( livetv->recorder ); + } else { + + /* check for the program info in the TV program chain could be obtained + from the MythTV MySQL database */ + + /* Reload all TV chain from Mysql database. */ + gmyth_tvchain_reload_all (livetv->tvchain); + + if ( livetv->tvchain == NULL ) { + res = FALSE; + goto error; + } + + /* Get program info from database using chanid and starttime */ + livetv->proginfo = gmyth_tvchain_get_program_at (livetv->tvchain, tvchain_curr_index++ ); + if ( livetv->proginfo == NULL ) { + g_warning ("[%s] LiveTV not successfully started.\n", __FUNCTION__ ); + res = FALSE; + goto error; + } else { + res = TRUE; + gmyth_debug ("GMythLiveTV: All requests to backend to start TV were OK. [%s]\n", livetv->proginfo->pathname->str ); + } + + } + + livetv->uri = (GMythURI*)gmyth_backend_info_get_uri( backend_info ); + + g_static_mutex_unlock( &lock ); + + if ( !gmyth_livetv_monitor_handler_start( livetv ) ) + { + res = FALSE; + gmyth_debug( "LiveTV MONITOR handler error on setup!" ); + goto error; + } + + livetv->setup_done = TRUE; + + return res; + +error: + g_print( "[%s] ERROR running LiveTV setup.\n", __FUNCTION__ ); + + if ( livetv->local_hostname != NULL ) { + g_string_free( livetv->local_hostname, FALSE ); + res = FALSE; + } + + if ( livetv->recorder != NULL ) { + g_object_unref (livetv->recorder); + livetv->recorder = NULL; + } + + if ( livetv->tvchain != NULL ) { + g_object_unref (livetv->tvchain); + livetv->tvchain = NULL; + } + + if ( livetv->proginfo != NULL ) { + g_object_unref (livetv->proginfo); + livetv->proginfo = NULL; + } + + if ( livetv->monitor != NULL ) { + g_object_unref (livetv->monitor); + livetv->monitor = NULL; + } + + return res; + +} + +static gboolean +gmyth_livetv_setup_recorder ( GMythLiveTV *livetv, gint channel, GMythBackendInfo *backend_info ) +{ + return gmyth_livetv_setup_recorder_channel_name ( livetv, ( channel != -1 ) ? + g_strdup_printf( "%d", channel ) : NULL, backend_info ); +} + +gboolean +gmyth_livetv_channel_setup ( GMythLiveTV *livetv, gint channel, GMythBackendInfo *backend_info ) +{ + return gmyth_livetv_setup_recorder ( livetv, channel, backend_info ); +} + +gboolean +gmyth_livetv_channel_name_setup ( GMythLiveTV *livetv, gchar* channel, GMythBackendInfo *backend_info ) +{ + return gmyth_livetv_setup_recorder_channel_name ( livetv, channel, backend_info ); +} + +gboolean +gmyth_livetv_setup ( GMythLiveTV *livetv, GMythBackendInfo *backend_info ) +{ + return gmyth_livetv_setup_recorder ( livetv, -1, backend_info ); +} + +gboolean +gmyth_livetv_next_program_chain ( GMythLiveTV *livetv ) +{ + gboolean res = TRUE; + GMythProgramInfo *prog_info = NULL; + + if ( !livetv->setup_done ) + { + gmyth_debug ( "Call the setup function first!" ); + res= FALSE; + goto error; + } + + //if ( !gmyth_livetv_monitor_handler_start( livetv ) ) + // goto error; + prog_info = gmyth_recorder_get_current_program_info( livetv->recorder ); + + if ( NULL == prog_info ) + { + gmyth_debug( "ProgramInfo is equals to NULL!!!" ); + + return FALSE; + } + /* prints program info data text */ + gmyth_program_info_print( prog_info ); + + if ( prog_info != NULL ) { + res = TRUE; + livetv->proginfo = prog_info; + gmyth_debug ("GMythLiveTV: All requests to backend to start TV were OK, program info changed."); + } else { + g_warning ("[%s] LiveTV not successfully started on the next program chain.\n", __FUNCTION__ ); + res = FALSE; + goto error; + } + + livetv->setup_done = TRUE; + + return res; + +error: + g_print( "[%s] ERROR running LiveTV setup.\n", __FUNCTION__ ); + + if ( livetv->local_hostname != NULL ) { + g_string_free( livetv->local_hostname, FALSE ); + res = FALSE; + } + + if ( livetv->recorder != NULL ) { + g_object_unref (livetv->recorder); + livetv->recorder = NULL; + } + + if ( livetv->tvchain != NULL ) { + g_object_unref (livetv->tvchain); + livetv->tvchain = NULL; + } + + if ( livetv->proginfo != NULL ) { + g_object_unref (livetv->proginfo); + livetv->proginfo = NULL; + } + + return res; + +} + +GMythFileTransfer * +gmyth_livetv_create_file_transfer( GMythLiveTV *livetv ) +{ + //GMythURI* uri = NULL; + + if ( NULL == livetv ) + goto done; + + if ( !livetv->setup_done ) + { + gmyth_debug( "Error: You must do the LiveTV setup, just before generating the FileTransfer from LiveTV source!" ); + goto done; + } + + if ( livetv->proginfo != NULL ) + gmyth_debug( "URI path = %s.\n", livetv->proginfo->pathname->str ); + else + gmyth_debug( "URI path = %s.\n", livetv->uri->uri->str ); + + g_static_mutex_lock( &lock ); + + if ( livetv->file_transfer != NULL ) + { + /*gmyth_file_transfer_close( livetv->file_transfer );*/ + g_object_unref( livetv->file_transfer ); + livetv->file_transfer = NULL; + } + + livetv->file_transfer = gmyth_file_transfer_new( livetv->backend_info ); + + if ( NULL == livetv->file_transfer ) + { + gmyth_debug( "Error: couldn't create the FileTransfer from LiveTV source!" ); + goto done; + } + + if ( livetv->uri != NULL ) + { + if ( livetv->uri->path != NULL ) + { + g_string_free( livetv->uri->path, FALSE ); + livetv->uri->path = NULL; + } + livetv->uri->path = g_string_new( g_strrstr( livetv->proginfo->pathname->str, "/" ) ); + } else { + livetv->uri = gmyth_uri_new_with_value( livetv->proginfo->pathname->str ); + } + + if ( NULL == livetv->uri ) + { + gmyth_debug( "Couldn't parse the URI to start LiveTV! [ uri = %s ]", livetv->proginfo->pathname->str ); + goto done; + } + + if ( !gmyth_file_transfer_open( livetv->file_transfer, livetv->uri != NULL ? gmyth_uri_get_path(livetv->uri) : + livetv->proginfo->pathname->str ) ) + { + gmyth_debug( "Error: couldn't open the FileTransfer from LiveTV source!" ); + g_object_unref( livetv->file_transfer ); + livetv->file_transfer = NULL; + goto done; + } + + g_static_mutex_unlock( &lock ); + +done: + /* + if ( uri != NULL ) + { + g_object_unref( uri ); + uri = NULL; + } + */ + + return livetv->file_transfer; + +} + +/* FIXME: How to proceed differently between livetv and recorded content */ +void +gmyth_livetv_stop_playing (GMythLiveTV *livetv) +{ + gmyth_debug ("Stopping the LiveTV...\n"); + + if (livetv->is_livetv) { + if ( !gmyth_recorder_stop_livetv (livetv->recorder) ) { + g_warning ("[%s] Error while stoping remote encoder", __FUNCTION__); + } + } +} + +gboolean +gmyth_livetv_is_playing (GMythLiveTV *livetv) +{ + return TRUE; +} + +void +gmyth_livetv_start_playing (GMythLiveTV *livetv) +{ + + // TODO + +} + diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_livetv.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_livetv.h Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,101 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_livetv.h + * + * @brief

GMythLiveTV starts a remote TV session with the MythTV backend. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Rosfran Lins Borges + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef GMYTH_LIVETV_H_ +#define GMYTH_LIVETV_H_ + +#include +#include + +#include "gmyth_recorder.h" +#include "gmyth_tvchain.h" +#include "gmyth_monitor_handler.h" +#include "gmyth_file_transfer.h" +#include "gmyth_programinfo.h" +#include "gmyth_backendinfo.h" + +G_BEGIN_DECLS + +#define GMYTH_LIVETV_TYPE (gmyth_livetv_get_type ()) +#define GMYTH_LIVETV(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_LIVETV_TYPE, GMythLiveTV)) +#define GMYTH_LIVETV_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_LIVETV_TYPE, GMythLiveTVClass)) +#define IS_GMYTH_LIVETV(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_LIVETV_TYPE)) +#define IS_GMYTH_LIVETV_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_LIVETV_TYPE)) +#define GMYTH_LIVETV_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_LIVETV_TYPE, GMythLiveTVClass)) + +typedef struct _GMythLiveTV GMythLiveTV; +typedef struct _GMythLiveTVClass GMythLiveTVClass; + +struct _GMythLiveTVClass +{ + GObjectClass parent_class; + + /* callbacks */ +}; + +struct _GMythLiveTV +{ + GObject parent; + + GString *local_hostname; + + GMythBackendInfo *backend_info; + + GMythRecorder *recorder; + GMythTVChain *tvchain; + GMythProgramInfo *proginfo; + + GMythFileTransfer *file_transfer; + + GMythMonitorHandler *monitor; + GMythURI *uri; + + gboolean is_livetv; + gboolean setup_done; + +}; + +GType gmyth_livetv_get_type (void); + +GMythLiveTV* gmyth_livetv_new (); + +void gmyth_livetv_start_playing (GMythLiveTV *livetv); +void gmyth_livetv_stop_playing (GMythLiveTV *livetv); + +gboolean gmyth_livetv_setup (GMythLiveTV *livetv, GMythBackendInfo *backend_info); +gboolean gmyth_livetv_channel_setup ( GMythLiveTV *livetv, gint channel, GMythBackendInfo *backend_info ); +gboolean gmyth_livetv_channel_name_setup ( GMythLiveTV *livetv, gchar* channel, GMythBackendInfo *backend_info ); +gboolean gmyth_livetv_next_program_chain ( GMythLiveTV *livetv ); + +GMythFileTransfer *gmyth_livetv_create_file_transfer( GMythLiveTV *livetv ); + +gboolean gmyth_livetv_monitor_handler_start( GMythLiveTV *livetv ); +void gmyth_livetv_monitor_handler_stop( GMythLiveTV *livetv ); + +G_END_DECLS + +#endif /*GMYTH_LIVETV_H_*/ diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_marshal.list --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_marshal.list Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,2 @@ +VOID:INT,STRING +VOID:INT,POINTER diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_monitor_handler.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_monitor_handler.c Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,595 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_monitor_handler.c + * + * @brief

GMythMonitorHandler deals with the streaming media events remote/local + * that are sent to the MythTV frontend. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Rosfran Lins Borges + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * GStreamer MythTV plug-in properties: + * - location (backend server hostname/URL) [ex.: myth://192.168.1.73:28722/1000_1092091.nuv] + * - path (qurl - remote file to be opened) + * - port number * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gmyth_marshal.h" + +#include "gmyth_monitor_handler.h" + +#include "gmyth.h" + +#define GMYTHTV_QUERY_HEADER "QUERY_FILETRANSFER " + +#define GMYTHTV_VERSION 30 + +#define GMYTHTV_TRANSFER_MAX_WAITS 700 + +#define GMYTHTV_BUFFER_SIZE 8*1024 + +#ifdef GMYTHTV_ENABLE_DEBUG +#define GMYTHTV_ENABLE_DEBUG 1 +#else +#undef GMYTHTV_ENABLE_DEBUG +#endif + +/* this NDEBUG is to maintain compatibility with GMyth library */ +#ifndef NDEBUG +#define GMYTHTV_ENABLE_DEBUG 1 +#endif + +//GMainContext *io_watcher_context = NULL; + +//GThread *monitor_th = NULL; + +//static gboolean* myth_control_sock_listener( GIOChannel *io_channel ); +//static gboolean gmyth_monitor_handler_listener( GIOChannel *io_channel, +// GIOCondition condition, gpointer data ); + +//gboolean* gmyth_monitor_handler_listener( GMythMonitorHandler *monitor ); + +void gmyth_monitor_handler_listener( GMythMonitorHandler *monitor, gpointer user_data ); + +static void gmyth_monitor_handler_default_listener( GMythMonitorHandler *monitor, gint msg_code, gchar* message ); + +static GMutex* mutex = NULL; + +//static GCond* io_watcher_cond = NULL; + +static void gmyth_monitor_handler_class_init (GMythMonitorHandlerClass *klass); +static void gmyth_monitor_handler_init (GMythMonitorHandler *object); + +static void gmyth_monitor_handler_dispose (GObject *object); +static void gmyth_monitor_handler_finalize (GObject *object); + +static gboolean gmyth_connect_to_backend_monitor (GMythMonitorHandler *monitor); + +void gmyth_monitor_handler_close( GMythMonitorHandler *monitor ); + +G_DEFINE_TYPE(GMythMonitorHandler, gmyth_monitor_handler, G_TYPE_OBJECT) + +static void +gmyth_monitor_handler_class_init (GMythMonitorHandlerClass *klass) +{ + GObjectClass *gobject_class; + GMythMonitorHandlerClass *gmonitor_class; + + gobject_class = (GObjectClass *) klass; + gmonitor_class = (GMythMonitorHandlerClass *) gobject_class; + + gobject_class->dispose = gmyth_monitor_handler_dispose; + gobject_class->finalize = gmyth_monitor_handler_finalize; + + gmonitor_class->backend_events_handler_signal_id = + g_signal_new ("backend-events-handler", + G_TYPE_FROM_CLASS (gmonitor_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, + 0, + NULL, + NULL, + gmyth_marshal_VOID__INT_STRING, + G_TYPE_NONE, + 2, + G_TYPE_INT, + G_TYPE_STRING); + + gmonitor_class->backend_events_handler = gmyth_monitor_handler_default_listener; + +} + +static void +gmyth_monitor_handler_init (GMythMonitorHandler *monitor) +{ + g_return_if_fail( monitor != NULL ); + + monitor->event_sock = NULL; + monitor->hostname = NULL; + monitor->port = 0; + monitor->actual_index = 0; + + monitor->allow_msgs_listener = TRUE; + + //monitor->backend_msgs = g_hash_table_new( g_int_hash, g_int_equal ); + + /* it is used for signalizing the event socket consumer thread */ + //io_watcher_cond = g_cond_new(); + + /* mutex to control access to the event socket consumer thread */ + //mutex = g_mutex_new(); + + monitor->monitor_th = NULL; + + monitor->gmyth_monitor_handler_listener = gmyth_monitor_handler_listener; +} + +static void +gmyth_monitor_handler_dispose (GObject *object) +{ + + GMythMonitorHandler *monitor = GMYTH_MONITOR_HANDLER (object); + + monitor->allow_msgs_listener = FALSE; + + if ( monitor->monitor_th != NULL ) + { + g_thread_pool_free( monitor->monitor_th, TRUE, FALSE ); + //g_thread_exit( monitor->monitor_th ); + if ( monitor->monitor_th != NULL ) + g_object_unref( monitor->monitor_th ); + monitor->monitor_th = NULL; + } + + if ( monitor->event_sock != NULL ) + { + g_object_unref( monitor->event_sock ); + monitor->event_sock = NULL; + } + + if ( monitor->hostname != NULL ) + { + g_free( monitor->hostname ); + monitor->hostname = NULL; + } + + if ( monitor->backend_msgs != NULL ) + { + g_hash_table_destroy ( monitor->backend_msgs ); + monitor->backend_msgs = NULL; + } + + if ( mutex != NULL ) + { + g_mutex_free( mutex ); + mutex = NULL; + } + + /* + if ( io_watcher_cond != NULL ) + { + g_cond_free( io_watcher_cond ); + io_watcher_cond = NULL; + } + */ + + G_OBJECT_CLASS (gmyth_monitor_handler_parent_class)->dispose (object); +} + +static void +gmyth_monitor_handler_finalize (GObject *object) +{ + g_signal_handlers_destroy (object); + + G_OBJECT_CLASS (gmyth_monitor_handler_parent_class)->finalize (object); +} + +// fixme: do we need the card_id???? +GMythMonitorHandler* +gmyth_monitor_handler_new ( void ) +{ + GMythMonitorHandler *monitor = GMYTH_MONITOR_HANDLER ( g_object_new ( GMYTH_MONITOR_HANDLER_TYPE, + FALSE ) ); + + return monitor; +} + +static gboolean +myth_control_acquire_context( gboolean do_wait ) +{ + + gboolean ret = TRUE; + //guint max_iter = 50; + + //g_mutex_lock( mutex ); + + //while ( !has_io_access ) + // g_cond_wait( io_watcher_cond, mutex ); + + //has_io_access = FALSE; + /* + if ( do_wait ) { + while ( --max_iter > 0 && !g_main_context_wait( io_watcher_context, io_watcher_cond, mutex ) ) + ret = FALSE; + } else if ( !g_main_context_acquire( io_watcher_context ) ) + ret = FALSE; + */ + + //g_static_mutex_lock( &st_mutex ); + + return ret; + +} + +static gboolean +myth_control_release_context( ) +{ + + gboolean ret = TRUE; + + //g_static_mutex_unlock( &st_mutex ); + + //g_main_context_release( io_watcher_context ); + + //g_main_context_wakeup( io_watcher_context ); + + //has_io_access = TRUE; + + //g_cond_broadcast( io_watcher_cond ); + + //g_mutex_unlock( mutex ); + + return ret; + +} + +gboolean +gmyth_monitor_handler_open (GMythMonitorHandler *monitor, const gchar *hostname, gint port) +{ + gboolean ret = TRUE; + + g_return_val_if_fail( hostname != NULL, FALSE ); + + if (monitor->hostname != NULL) { + g_free (monitor->hostname); + monitor->hostname = NULL; + } + + monitor->hostname = g_strdup( hostname ); + monitor->port = port; + + gmyth_debug ("Monitor event socket --- hostname: %s, port %d\n", monitor->hostname, monitor->port); + + /* configure the event socket */ + if ( NULL == monitor->event_sock ) { + if (!gmyth_connect_to_backend_monitor (monitor)) { + g_printerr( "Connection to backend failed (Event Socket).\n" ); + ret = FALSE; + } + } else { + g_warning("Remote monitor event socket already created.\n"); + } + + return ret; + +} + +static gint +gmyth_monitor_handler_is_backend_message( GMythMonitorHandler *monitor, + GMythStringList* strlist, gchar **back_msg_action ) +{ + gint msg_type = GMYTH_BACKEND_NO_MESSAGE; + GString *back_msg = NULL; + + back_msg = gmyth_string_list_get_string( strlist, 0 ); + if ( back_msg != NULL && back_msg->str != NULL && + strstr( back_msg->str, "BACKEND" ) != NULL ) + { + gmyth_debug( "MONITOR HANDLER - Received backend message = %s", back_msg->str ); + *back_msg_action = gmyth_string_list_get_char_array( strlist, 1 ); + + if ( back_msg_action != NULL ) + { + + if ( g_strstr_len( *back_msg_action, strlen( *back_msg_action ), "LIVETV_CHAIN" ) || + g_strstr_len( *back_msg_action, strlen( *back_msg_action ), "RECORDING_LIST_CHANGE" ) || + g_strstr_len( *back_msg_action, strlen( *back_msg_action ), "SCHEDULE_CHANGE" ) || + g_strstr_len( *back_msg_action, strlen( *back_msg_action ), "LIVETV_WATCH" ) ) + { + gmyth_debug( "MONITOR: message type == GMYTH_BACKEND_PROGRAM_INFO_CHANGED, msg = %s", *back_msg_action ); + msg_type = GMYTH_BACKEND_PROGRAM_INFO_CHANGED; + } else if ( g_strstr_len( *back_msg_action, strlen( *back_msg_action ), "DONE_RECORDING" ) ) { + gmyth_debug( "MONITOR: message type == GMYTH_BACKEND_DONE_RECORDING, msg = %s", *back_msg_action ); + msg_type = GMYTH_BACKEND_DONE_RECORDING; + } + + //g_hash_table_insert ( monitor->backend_msgs, + // &(monitor->actual_index), *back_msg_action ); + + } // if + } + + if ( back_msg != NULL ) + { + g_string_free( back_msg, TRUE ); + back_msg = NULL; + } + + return msg_type; + +} + +static void +gmyth_monitor_handler_default_listener( GMythMonitorHandler *monitor, gint msg_code, gchar* message ) +{ + //assert( message!= NULL ); + gmyth_debug( "DEFAULT Signal handler ( msg = %s, code = %d )\n", + message, msg_code ); +} + +static void +gmyth_monitor_handler_print( GString *str, gpointer ptr ) +{ + gmyth_debug( "Backend message event: %s --- ", str->str ); +} + +//static void +//gmyth_monitor_handler_listener (GMythMonitorHandler *monitor, gpointer user_data) +//static gboolean +//gmyth_monitor_handler_listener( GIOChannel *io_channel, GIOCondition condition, gpointer data ) +//gboolean* gmyth_monitor_handler_listener( GMythMonitorHandler *monitor ) +void +gmyth_monitor_handler_listener (GMythMonitorHandler *monitor, gpointer user_data) +{ + //GMythMonitorHandler *monitor = (GMythMonitorHandler*)data; + GIOStatus io_status; + GIOCondition io_cond; + guint recv = 0; + gboolean *ret = g_new0( gboolean, 1 ); + *ret = TRUE; + //gboolean ret = TRUE; + gsize len = 0; + + static guint count = 0; + + GIOChannel *io_channel = monitor->event_sock->sd_io_ch; + //GIOCondition condition = g_io_channel_get_buffer_condition( io_channel ); + + GMythStringList *strlist = NULL; + + //GMythMonitorHandler *monitor = (GMythMonitorHandler*)data; + + myth_control_acquire_context (TRUE); + + if ( io_channel == NULL ) { + g_debug ("Monitor socket is NULL!\n"); + *ret = FALSE; + goto clean_up; + } + + while (monitor->allow_msgs_listener) { + ++count; + + gmyth_debug ("%d - Listening on Monitor socket...!\n", count); + + do + { + + gint bytes_sent = 0; + + strlist = gmyth_string_list_new(); + + if ( monitor->event_sock != NULL ) + { + + len = gmyth_socket_read_stringlist( monitor->event_sock, strlist ); + + if ( strlist != NULL && gmyth_string_list_length( strlist ) > 0 ) + { + bytes_sent = gmyth_string_list_get_int( strlist, 0 ); // -1 on backend error + + gmyth_debug ( "[%s] MONITOR: received data buffer from IO event channel... %d strings gone!\n", + __FUNCTION__, len ); + + recv += len; + + /* debug purpose: prints out all the string list elements */ + g_list_foreach( strlist->glist, (GFunc)gmyth_monitor_handler_print, NULL ); + + gchar *back_msg_action = g_new0( gchar, 1 ); + gint msg_type = gmyth_monitor_handler_is_backend_message( monitor, strlist, + &back_msg_action ); + + g_signal_emit ( monitor, + GMYTH_MONITOR_HANDLER_GET_CLASS (monitor)->backend_events_handler_signal_id, + 0, /* details */ + msg_type, back_msg_action ); + + if (back_msg_action!= NULL) + g_free( back_msg_action ); + + } + + } + + if (strlist!=NULL) + g_object_unref( strlist ); + + io_cond = g_io_channel_get_buffer_condition( io_channel ); + + } while ( recv <= 0 && ( io_cond & G_IO_IN ) != 0 ); + + gmyth_debug ("[%s]\tMONITOR EVENT: Read %d bytes\n", __FUNCTION__, recv ); + + g_usleep( 300 ); + + } /* main GThread while */ + + myth_control_release_context (); + + if ( io_status == G_IO_STATUS_ERROR ) { + //gmyth_debug ("[%s] Error reading: %s\n", __FUNCTION__, error != NULL ? error->message : "" ); + gmyth_debug ("Error reading MONITOR event socket.\n"); + *ret = FALSE; + goto clean_up; + } + +clean_up: + + if (strlist!=NULL) + g_object_unref( strlist ); + + return; + +} + +static gboolean +gmyth_connect_to_backend_monitor (GMythMonitorHandler *monitor) +{ + gboolean ret = TRUE; + + monitor->event_sock = gmyth_socket_new(); + + /* Connects the socket, send Mythtv ANN Monitor and verify Mythtv protocol version */ + if (!gmyth_socket_connect_to_backend_events ( monitor->event_sock, + monitor->hostname, monitor->port, FALSE ) ) + { + g_object_unref (monitor->event_sock); + monitor->event_sock = NULL; + ret = FALSE; + } + + return ret; +} + +static gboolean* +gmyth_monitor_handler_setup( GMythMonitorHandler *monitor, GIOChannel *channel ) +{ + gboolean *ret = g_new0( gboolean, 1 ); + guint src_id = 0; + + *ret = TRUE; + + //io_watcher_context = g_main_context_default(); + //GMainLoop *loop = g_main_loop_new( io_watcher_context, TRUE ); + + //GSource *source; + + if ( channel != NULL ) { + //source = g_io_create_watch( channel, G_IO_IN | G_IO_HUP ); + src_id = g_io_add_watch( channel, G_IO_IN, + (GIOFunc)gmyth_monitor_handler_listener, monitor ); + } else { + *ret = FALSE; + goto cleanup; + } + + //g_source_set_callback ( source, (GSourceFunc)gmyth_monitor_handler_listener, NULL, NULL ); + + //g_source_attach( source, io_watcher_context ); + + //if (NULL == source){ + if (src_id < 0){ + gmyth_debug( "[%s] Error adding watch listener function to the IO control channel!\n", __FUNCTION__ ); + *ret = FALSE; + goto cleanup; + } + + //g_main_loop_run( loop ); + +cleanup: + //if ( source != NULL ) + // g_source_unref( source ); + + //if ( io_watcher_context != NULL ) + // g_main_context_unref( io_watcher_context ); + + //if ( loop != NULL ) + // g_main_loop_unref( loop ); + + return ret; + +} + +gboolean +gmyth_monitor_handler_start (GMythMonitorHandler *monitor) +{ + gboolean *ret = g_new0( gboolean, 1 ); + *ret = TRUE; + + /*if (!g_thread_supported () ) g_thread_init (NULL);*/ + /* + monitor->monitor_th = g_thread_pool_new( (GThreadFunc)gmyth_monitor_handler_listener, + monitor, TRUE, NULL ); + */ + monitor->monitor_th = g_thread_pool_new( (GFunc)gmyth_monitor_handler_listener, + monitor, 3, TRUE, NULL ); + g_thread_pool_push( monitor->monitor_th, monitor, NULL ); + + //if ( ( ret = g_thread_join( monitor_th ) ) == FALSE ) + if ( monitor->monitor_th != NULL ) + //if ( gmyth_monitor_handler_setup( monitor, monitor->event_sock->sd_io_ch ) ) + { + gmyth_debug ( "\n[%s]\tOK! Starting listener on the MONITOR event socket...[thread location = %p]\n", + __FUNCTION__, g_thread_self( ) ); + *ret = TRUE; + } else { + gmyth_debug ( "\n[%s]\tERROR! Coudn't start listener on the MONITOR event socket...[thread location = %p]\n", + __FUNCTION__, g_thread_self( ) ); + *ret = FALSE; + } + +//cleanup: + + gmyth_debug( "[%s] Watch listener function over the IO control channel? %s!!!\n", + __FUNCTION__, ( *ret == TRUE ? "YES" : "NO" ) ); + + return *ret; +} + +void +gmyth_monitor_handler_close( GMythMonitorHandler *monitor ) +{ + + if (monitor->event_sock) { + g_object_unref( monitor->event_sock ); + monitor->event_sock = NULL; + } + + if (monitor->hostname) { + g_free( monitor->hostname ); + monitor->hostname = NULL; + } + +} + diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_monitor_handler.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_monitor_handler.h Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,117 @@ +/* vim: set sw=2: -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2; c-indent-level: 2-*- */ +/** + * GMyth Library + * + * @file gmyth/gmyth_monitor_handler.h + * + * @brief

GMythMonitorHandler deals with the streaming media events remote/local + * that are sent to the MythTV frontend. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Rosfran Lins Borges + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GMYTH_MONITOR_HANDLER_H__ +#define __GMYTH_MONITOR_HANDLER_H__ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "gmyth_socket.h" +#include "gmyth_uri.h" + +G_BEGIN_DECLS + +#define GMYTH_MONITOR_HANDLER_TYPE (gmyth_monitor_handler_get_type ()) +#define GMYTH_MONITOR_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_MONITOR_HANDLER_TYPE, GMythMonitorHandler)) +#define GMYTH_MONITOR_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_MONITOR_HANDLER_TYPE, GMythMonitorHandlerClass)) +#define IS_GMYTH_MONITOR_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_MONITOR_HANDLER_TYPE)) +#define IS_GMYTH_MONITOR_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_MONITOR_HANDLER_TYPE)) +#define GMYTH_MONITOR_HANDLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_MONITOR_HANDLER_TYPE, GMythMonitorHandlerClass)) + +#define GMYTHTV_MONITOR_HANDLER_READ_ERROR -314 + +enum { + GMYTH_BACKEND_NO_MESSAGE = 0, + GMYTH_BACKEND_PROGRAM_INFO_CHANGED, + GMYTH_BACKEND_DONE_RECORDING, + GMYTH_BACKEND_STOP_LIVETV +}; + +typedef struct _GMythMonitorHandler GMythMonitorHandler; +typedef struct _GMythMonitorHandlerClass GMythMonitorHandlerClass; + +struct _GMythMonitorHandlerClass +{ + GObjectClass parent_class; + + /* callbacks */ + guint backend_events_handler_signal_id; + + /* signal default handlers */ + void (*backend_events_handler) (GMythMonitorHandler *monitor, gint msg_code, gchar* message ); +}; + +struct _GMythMonitorHandler +{ + GObject parent; + + /* MythTV version number */ + gint mythtv_version; + + /* socket descriptors */ + GMythSocket *event_sock; + + GThreadPool *monitor_th; + + // gboolean* (*gmyth_monitor_handler_listener)( GMythMonitorHandler *monitor ); + void (*gmyth_monitor_handler_listener)( GMythMonitorHandler *monitor, gpointer user_data ); + + gchar *hostname; + gint port; + + gint64 actual_index; + + gboolean allow_msgs_listener; + + /* stores the messages coming from the backend */ + GHashTable *backend_msgs; + +}; + +GType gmyth_monitor_handler_get_type (void); + +GMythMonitorHandler* gmyth_monitor_handler_new ( void ); + +gboolean gmyth_monitor_handler_open (GMythMonitorHandler *monitor, const gchar *hostname, gint port); + +gboolean gmyth_monitor_handler_start (GMythMonitorHandler *monitor); + +void gmyth_monitor_handler_close (GMythMonitorHandler *monitor); + +G_END_DECLS + +#endif /* __GMYTH_MONITOR_HANDLER_H__ */ diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_programinfo.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_programinfo.c Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,460 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_programinfo.c + * + * @brief

GMythFileTransfer deals with the file streaming media remote/local + * transfering to the MythTV frontend. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Leonardo Sobral Cunha + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "gmyth_programinfo.h" +#include "gmyth_util.h" +#include "gmyth_debug.h" + +static void gmyth_program_info_class_init (GMythProgramInfoClass *klass); +static void gmyth_program_info_init (GMythProgramInfo *object); + +static void gmyth_program_info_dispose (GObject *object); +static void gmyth_program_info_finalize (GObject *object); + +G_DEFINE_TYPE(GMythProgramInfo, gmyth_program_info, G_TYPE_OBJECT) + +static void +gmyth_program_info_class_init (GMythProgramInfoClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->dispose = gmyth_program_info_dispose; + gobject_class->finalize = gmyth_program_info_finalize; +} + +static void +gmyth_program_info_init (GMythProgramInfo *gmyth_program_info) +{ + gmyth_program_info->chancommfree = 0; + + /** A flag informing if the program has video or not. */ + gmyth_program_info->isVideo = FALSE; + gmyth_program_info->lenMins = 0; + + gmyth_program_info->stars = 0.0f; + gmyth_program_info->repeat = 0; + + gmyth_program_info->hasAirDate = FALSE; + + gmyth_program_info->spread = 0; + gmyth_program_info->startCol = 0; + + gmyth_program_info->recpriority2 = 0; + gmyth_program_info->reactivate = 0; + + gmyth_program_info->recordid = 0; + gmyth_program_info->parentid = 0; + + /** The backend video source id associated to this program.*/ + gmyth_program_info->sourceid = 0; + /** the backend input id associated to this program.*/ + gmyth_program_info->inputid = 0; + /** The backend card id associated to this program.*/ + gmyth_program_info->cardid = 0; + gmyth_program_info->shareable = FALSE; + gmyth_program_info->duplicate = FALSE; + + gmyth_program_info->findid = 0; + + gmyth_program_info->programflags = 0; + gmyth_program_info->transcoder = 0; + + gmyth_program_info->recpriority = 0; + + /** The file size of the recorded program.*/ + gmyth_program_info->filesize = -1; + + +} + +static void +gmyth_program_info_dispose (GObject *object) +{ + GMythProgramInfo *gmyth_program_info = GMYTH_PROGRAM_INFO(object); + + if ( gmyth_program_info->chanid != NULL ) + { + g_string_free( gmyth_program_info->chanid, TRUE ); + gmyth_program_info->chanid = NULL; + } + + /** The program start time. */ + if ( gmyth_program_info->startts != NULL ) + { + g_free( gmyth_program_info->startts); + gmyth_program_info->startts = NULL; + } + + /** The program end time. */ + if ( gmyth_program_info->endts != NULL ) + { + g_free( gmyth_program_info->endts ); + gmyth_program_info->endts = NULL; + } + + /** The recording schedule start time. */ + if ( gmyth_program_info->recstartts != NULL ) + { + g_free( gmyth_program_info->recstartts ); + gmyth_program_info->recstartts = NULL; + } + + /** The recording schedule end time */ + if ( gmyth_program_info->recendts != NULL ) + { + g_free(gmyth_program_info->recendts); + gmyth_program_info->recendts = NULL; + } + + /** The program title. */ + if (gmyth_program_info->title != NULL ) + { + g_string_free(gmyth_program_info->title, TRUE); + gmyth_program_info->title = NULL; + } + + /** The program subtitle. */ + if (gmyth_program_info->subtitle != NULL ) + { + g_string_free(gmyth_program_info->subtitle, TRUE ); + gmyth_program_info->subtitle = NULL; + } + /** The program description. */ + if ( gmyth_program_info->description != NULL ) + { + g_string_free( gmyth_program_info->description, TRUE ); + gmyth_program_info->description = NULL; + } + + /** The program category. */ + if ( gmyth_program_info->category != NULL ) + { + g_string_free( gmyth_program_info->category, TRUE ); + gmyth_program_info->category = NULL; + } + + if ( gmyth_program_info->chanstr != NULL ) + { + g_string_free( gmyth_program_info->chanstr, TRUE ); + gmyth_program_info->chanstr = NULL; + } + if ( gmyth_program_info->chansign != NULL ) + { + g_string_free( gmyth_program_info->chansign, TRUE ); + gmyth_program_info->chansign = NULL; + } + /** The associated channel name. */ + if ( gmyth_program_info->channame != NULL ) + { + g_string_free( gmyth_program_info->channame, TRUE ); + gmyth_program_info->channame = NULL; + } + if ( gmyth_program_info->chanOutputFilters != NULL ) + { + g_string_free( gmyth_program_info->chanOutputFilters, TRUE ); + gmyth_program_info->chanOutputFilters = NULL; + } + + if ( gmyth_program_info->seriesid != NULL ) + { + g_string_free( gmyth_program_info->seriesid, TRUE ); + gmyth_program_info->chanOutputFilters = NULL; + + } + /** The program unique id. */ + if ( gmyth_program_info->programid != NULL ) + { + g_string_free( gmyth_program_info->programid, TRUE ); + gmyth_program_info->programid = NULL; + + } + if ( gmyth_program_info->catType != NULL ) + { + g_string_free( gmyth_program_info->catType, TRUE ); + gmyth_program_info->catType = NULL; + + } + + if ( gmyth_program_info->sortTitle != NULL ) + { + g_string_free( gmyth_program_info->sortTitle, TRUE ); + gmyth_program_info->sortTitle = NULL; + + } + + if ( gmyth_program_info->year != NULL ) + { + g_string_free( gmyth_program_info->year, TRUE ); + gmyth_program_info->year = NULL; + + } + + if ( gmyth_program_info->originalAirDate != NULL ) + { + g_free( gmyth_program_info->originalAirDate); + gmyth_program_info->originalAirDate = NULL; + } + if ( gmyth_program_info->lastmodified != NULL ) + { + g_free( gmyth_program_info->lastmodified ); + gmyth_program_info->lastmodified = NULL; + + } + if (gmyth_program_info->lastInUseTime != NULL) + { + g_free( gmyth_program_info->lastInUseTime ); + gmyth_program_info->lastInUseTime = NULL; + } + + if ( gmyth_program_info->schedulerid != NULL ) + { + g_string_free( gmyth_program_info->schedulerid, TRUE ); + gmyth_program_info->schedulerid = NULL; + } + + if ( gmyth_program_info->recgroup != NULL ) + { + g_string_free( gmyth_program_info->recgroup, TRUE ); + gmyth_program_info->recgroup = NULL; + } + if ( gmyth_program_info->playgroup != NULL ) + { + g_string_free( gmyth_program_info->playgroup, TRUE ); + gmyth_program_info->playgroup = NULL; + } + + /** The file name of the recorded program.*/ + if ( gmyth_program_info->pathname != NULL) + { + g_string_free( gmyth_program_info->pathname, TRUE ); + gmyth_program_info->pathname = NULL; + } + + if ( gmyth_program_info->hostname != NULL ) + { + g_string_free( gmyth_program_info->hostname, TRUE ); + gmyth_program_info->hostname = NULL; + } + + G_OBJECT_CLASS (gmyth_program_info_parent_class)->dispose (object); +} + +static void +gmyth_program_info_finalize (GObject *object) +{ + g_signal_handlers_destroy (object); + + G_OBJECT_CLASS (gmyth_program_info_parent_class)->finalize (object); +} + +/** + * Creates a new instance of GMythProgramInfo. + * + * @return a new instance of GMythProgramInfo. + */ +GMythProgramInfo* +gmyth_program_info_new (void) +{ + GMythProgramInfo *program_info = GMYTH_PROGRAM_INFO (g_object_new(GMYTH_PROGRAM_INFO_TYPE, NULL)); + + return program_info; +} + +GMythStringList* +gmyth_program_info_to_string_list (GMythProgramInfo *prog, GMythStringList *slist) +{ + g_return_val_if_fail (prog != NULL, NULL); + g_return_val_if_fail (slist != NULL, NULL); + + gmyth_string_list_append_string (slist, prog->title); /* 0 */ + gmyth_string_list_append_string (slist, prog->subtitle); /* 1 */ + gmyth_string_list_append_string (slist, prog->description); /* 2 */ + gmyth_string_list_append_string (slist, prog->category); /* 3 */ + gmyth_string_list_append_string (slist, prog->chanid); /* 4 */ + gmyth_string_list_append_string (slist, prog->chanstr); /* 5 */ + gmyth_string_list_append_string (slist, prog->chansign); /* 6 */ + gmyth_string_list_append_string (slist, prog->channame); /* 7 */ + gmyth_string_list_append_string (slist, prog->pathname); /* 8 */ + + // fixme + gmyth_string_list_append_int64 (slist, 100/*prog->filesize*/); /* 9 */ + gmyth_string_list_append_int64 (slist, 10); /* 11 */ + + if (prog->startts) + gmyth_string_list_append_int (slist, prog->startts->tv_sec); /* 11 */ //DATETIME_TO_LIST(startts) + else + gmyth_string_list_append_int (slist, 0); + + if (prog->endts) + gmyth_string_list_append_int (slist, prog->endts->tv_sec); /* 12 */ //DATETIME_TO_LIST(endts) + else + gmyth_string_list_append_int (slist, 0); + + gmyth_string_list_append_int (slist, prog->duplicate); /* 13 */ + gmyth_string_list_append_int (slist, prog->shareable); /* 14 */ + gmyth_string_list_append_int (slist, prog->findid); /* 15 */ + gmyth_string_list_append_string (slist, prog->hostname); /* 16 */ + gmyth_string_list_append_int (slist, prog->sourceid); /* 17 */ + gmyth_string_list_append_int (slist, prog->cardid); /* 18 */ + gmyth_string_list_append_int (slist, prog->inputid); /* 19 */ + gmyth_string_list_append_int (slist, prog->recpriority); /* 20 */ + gmyth_string_list_append_int (slist, 0 /*prog->recstatus*/); /* 21 */ + gmyth_string_list_append_int (slist, prog->recordid); /* 22 */ + gmyth_string_list_append_int (slist, 0 /*prog->rectype*/); /* 23 */ + gmyth_string_list_append_int (slist, 0 /*prog->dupin*/); /* 24 */ + gmyth_string_list_append_int (slist, 0 /*prog->dupmethod*/); /* 25 */ + gmyth_string_list_append_int (slist, prog->recstartts != NULL ? prog->recstartts->tv_sec : 0); /* 26 */ //DATETIME_TO_LIST(recstartts) + gmyth_string_list_append_int (slist, prog->recendts != NULL ? prog->recendts->tv_sec : 0); /* 27 */ //DATETIME_TO_LIST(recendts) + gmyth_string_list_append_int (slist, prog->repeat); /* 28 */ + gmyth_string_list_append_int (slist, prog->programflags); /* 29 */ + gmyth_string_list_append_char_array (slist, "Default"); /* 30 */ //prog->(recgroup != "") ? recgroup : "Default") + gmyth_string_list_append_int (slist, prog->chancommfree); /* 31 */ + gmyth_string_list_append_string (slist, prog->chanOutputFilters); /* 32 */ + gmyth_string_list_append_string (slist, prog->seriesid); /* 33 */ + gmyth_string_list_append_string (slist, prog->programid); /* 34 */ + gmyth_string_list_append_string (slist, ""); /* 35 */ + gmyth_string_list_append_int (slist, prog->lastmodified != NULL ? prog->lastmodified->tv_sec : 0); /* 36 */ //DATETIME_TO_LIST(lastmodified) + gmyth_string_list_append_int (slist, 0); /* 37 */ //FLOAT_TO_LIST(stars) + gmyth_string_list_append_int (slist, prog->originalAirDate != NULL ? prog->originalAirDate->tv_sec : 0); /* 38 */ //DATETIME_TO_LIST(QDateTime(originalAirDate)) + gmyth_string_list_append_int (slist, prog->hasAirDate); /* 39 */ + gmyth_string_list_append_char_array (slist, "Default"); /* 40 */ //prog->(playgroup != "") ? playgroup : "Default") + gmyth_string_list_append_int (slist, prog->recpriority2); /* 41 */ + + return slist; +} + +GMythProgramInfo* +gmyth_program_info_from_string_list ( GMythStringList *slist ) +{ + GMythProgramInfo *prog = gmyth_program_info_new(); + + g_return_val_if_fail (slist != NULL, NULL); + /* + Unknown + + + + 1000 + 9 + 1000 + Band + /mnt/store//1000_20070125110059.nuv + 0 + 0 + 1169733659 + 1169735400 + 0 + 0 + 0 + hmelo-desktop + 0 + 1 + 0 + 0 + -2 + 0 + 0 + 15 + 6 + 1169733659 + 1169735400 + 0 + 0 + LiveTV + 0 + + + + 1169733659 + 0.000000 + -1 + 0 + Default + 0 + */ + prog->title = gmyth_string_list_get_string (slist, 0); + prog->subtitle = gmyth_string_list_get_string (slist, 1); + prog->description = gmyth_string_list_get_string (slist, 2); + prog->category = gmyth_string_list_get_string (slist, 3); + prog->chanid = gmyth_string_list_get_string (slist, 4); + prog->chanstr = gmyth_string_list_get_string (slist, 5); + prog->chansign = gmyth_string_list_get_string (slist, 6); + prog->channame = gmyth_string_list_get_string (slist, 7); + prog->pathname = gmyth_string_list_get_string (slist, 8); + prog->filesize = gmyth_string_list_get_int64 (slist, 9); + gmyth_string_list_get_int64 (slist, 10); + + prog->startts = gmyth_util_string_to_time_val( (gmyth_util_time_to_isoformat( + (time_t)gmyth_string_list_get_int (slist, 11) ))->str ); //DATETIME_TO_LIST(startts) + prog->endts = gmyth_util_string_to_time_val( (gmyth_util_time_to_isoformat( + (time_t)gmyth_string_list_get_int (slist, 12) ))->str ); //DATETIME_TO_LIST(endts) + prog->duplicate = gmyth_string_list_get_int (slist, 13); + prog->shareable = gmyth_string_list_get_int (slist, 14); + prog->findid = gmyth_string_list_get_int (slist, 15); + prog->hostname = gmyth_string_list_get_string (slist, 16); + prog->sourceid = gmyth_string_list_get_int (slist, 17); + prog->cardid = gmyth_string_list_get_int (slist, 18); + prog->inputid = gmyth_string_list_get_int (slist, 19); + prog->recpriority = gmyth_string_list_get_int (slist, 20); + prog->reactivate = gmyth_string_list_get_int (slist, 21); + prog->recordid = gmyth_string_list_get_int (slist, 22); + gmyth_string_list_get_int (slist, 23); + gmyth_string_list_get_int (slist, 24); + gmyth_string_list_get_int (slist, 25); + prog->recstartts = gmyth_util_string_to_time_val( (gmyth_util_time_to_isoformat( + (time_t)gmyth_string_list_get_int (slist, 26) ))->str ); //DATETIME_TO_LIST(recstartts) + prog->recendts = gmyth_util_string_to_time_val( (gmyth_util_time_to_isoformat( + (time_t)gmyth_string_list_get_int (slist, 27) ))->str ); //DATETIME_TO_LIST(recendts) + prog->repeat = gmyth_string_list_get_int (slist, 28); + prog->programflags = gmyth_string_list_get_int (slist, 29); + prog->recgroup = gmyth_string_list_get_string (slist, 30); //prog->(recgroup != "") ? recgroup : "Default") + prog->chancommfree = gmyth_string_list_get_int (slist, 31); + prog->chanOutputFilters = gmyth_string_list_get_string (slist, 32); + prog->seriesid = gmyth_string_list_get_string (slist, 33); + prog->programid = gmyth_string_list_get_string (slist, 34); + gmyth_string_list_get_string (slist, 35); + prog->lastmodified = gmyth_util_string_to_time_val( (gmyth_util_time_to_isoformat( + (time_t)gmyth_string_list_get_int (slist, 36) ))->str ); //DATETIME_TO_LIST(lastmodified) + gmyth_string_list_get_int (slist, 37); //FLOAT_TO_LIST(stars) + prog->originalAirDate = gmyth_util_string_to_time_val( (gmyth_util_time_to_isoformat( + (time_t)gmyth_string_list_get_int (slist, 38) ))->str ); //DATETIME_TO_LIST(QDateTime(originalAirDate)) + prog->hasAirDate = gmyth_string_list_get_int (slist, 39); + prog->playgroup = gmyth_string_list_get_string (slist, 40); //prog->(playgroup != "") ? playgroup : "Default") + prog->recpriority2 = gmyth_string_list_get_int (slist, 41); + + return prog; +} diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_programinfo.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_programinfo.h Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,161 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_common.h + * + * @brief

This file contains basic common functions for the gmyth library. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Leonardo Sobral Cunha + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _GMYTH_PROGRAMINFO_H +#define _GMYTH_PROGRAMINFO_H + +#include +#include + +#include "gmyth_stringlist.h" + +G_BEGIN_DECLS + +#define GMYTH_PROGRAM_INFO_TYPE (gmyth_program_info_get_type ()) +#define GMYTH_PROGRAM_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_PROGRAM_INFO_TYPE, GMythProgramInfo)) +#define GMYTH_PROGRAM_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_PROGRAM_INFO_TYPE, GMythProgramInfoClass)) +#define IS_GMYTH_PROGRAM_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_PROGRAM_INFO_TYPE)) +#define IS_GMYTH_PROGRAM_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_PROGRAM_INFO_TYPE)) +#define GMYTH_PROGRAM_INFO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_PROGRAM_INFO_TYPE, GMythProgramInfoClass)) + +typedef struct _GMythProgramInfo GMythProgramInfo; +typedef struct _GMythProgramInfoClass GMythProgramInfoClass; + +struct _GMythProgramInfoClass +{ + GObjectClass parent_class; + + /* callbacks */ +}; + +/** + * The GMythProgramInfo structure represents a program information + * stored in the database. It could be a program from the EPG data, + * a program scheduled to be recorded, or a program already recorded. + */ +struct _GMythProgramInfo +{ + GObject parent; + + /** The channel unique ID. */ + GString *chanid; + + /** The program start time. */ + GTimeVal* startts; + /** The program end time. */ + GTimeVal* endts; + /** The recording schedule start time. */ + GTimeVal* recstartts; + /** The recording schedule end time */ + GTimeVal* recendts; + + /** The program title. */ + GString *title; + /** The program subtitle. */ + GString *subtitle; + /** The program description. */ + GString *description; + /** The program category. */ + GString *category; + + GString *chanstr; + GString *chansign; + /** The associated channel name. */ + GString *channame; + gint chancommfree; + GString *chanOutputFilters; + + GString *seriesid; + /** The program unique id. */ + GString *programid; + GString *catType; + + GString *sortTitle; + + /** A flag informing if the program has video or not. */ + gboolean isVideo; + gint lenMins; + + GString *year; + gdouble stars; + gint repeat; + + GTimeVal* originalAirDate; + GTimeVal* lastmodified; + GTimeVal* lastInUseTime; + + gboolean hasAirDate; + + gint spread; + gint startCol; + + gint recpriority2; + gint reactivate; + + gint recordid; + gint parentid; + + /** The backend video source id associated to this program.*/ + gint sourceid; + /** the backend input id associated to this program.*/ + gint inputid; + /** The backend card id associated to this program.*/ + gint cardid; + gboolean shareable; + gboolean duplicate; + + GString * schedulerid; + gint findid; + + gint programflags; + gint transcoder; + + GString *recgroup; + GString *playgroup; + gint recpriority; + + /** The file size of the recorded program.*/ + gint64 filesize; + + /** The file name of the recorded program.*/ + GString *pathname; + GString *hostname; + + /* AvailableStatusType availableStatus;*/ + +}; + +GType gmyth_program_info_type (void); + +GMythProgramInfo* gmyth_program_info_new (void); + +GMythStringList* gmyth_program_info_to_string_list (GMythProgramInfo *prog, GMythStringList *slist); +GMythProgramInfo* gmyth_program_info_from_string_list (GMythStringList *slist); + +G_END_DECLS + +#endif /*_GMYTH_PROGRAMINFO_H*/ diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_query.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_query.c Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,239 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_query.c + * + * @brief

GMythQuery class provides a wrapper for accessing + * the libmysqlclient funtions. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Leonardo Sobral Cunha + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "gmyth_query.h" +#include "gmyth_debug.h" + +static void gmyth_query_class_init (GMythQueryClass *klass); +static void gmyth_query_init (GMythQuery *object); + +static void gmyth_query_dispose (GObject *object); +static void gmyth_query_finalize (GObject *object); + +static void gmyth_query_print_error (MYSQL *conn, char *message); + +G_DEFINE_TYPE(GMythQuery, gmyth_query, G_TYPE_OBJECT) + +static void +gmyth_query_class_init (GMythQueryClass *klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + + gobject_class->dispose = gmyth_query_dispose; + gobject_class->finalize = gmyth_query_finalize; +} + +static void +gmyth_query_init (GMythQuery *gmyth_query) +{ + gmyth_query->backend_info = NULL; + + /* initialize connection handler */ + gmyth_query->conn = mysql_init (NULL); + + + if (!(gmyth_query->conn)) + g_warning ("[%s] MSQL structure not initialized", __FUNCTION__); + +} + +static void +gmyth_query_dispose (GObject *object) +{ + GMythQuery *gmyth_query = GMYTH_QUERY (object); + + if (gmyth_query->backend_info) { + g_object_unref (gmyth_query->backend_info); + //gmyth_query->backend_info = NULL; + } + + G_OBJECT_CLASS (gmyth_query_parent_class)->dispose (object); +} + +static void +gmyth_query_finalize (GObject *object) +{ + g_signal_handlers_destroy (object); + + G_OBJECT_CLASS (gmyth_query_parent_class)->finalize (object); +} + +/** Creates a new instance of GMythQuery. + * + * @return a new instance of GMythQuery. + */ +GMythQuery* +gmyth_query_new () +{ + GMythQuery *sql_query = GMYTH_QUERY (g_object_new(GMYTH_QUERY_TYPE, NULL)); + + return sql_query; +} + +gboolean +gmyth_query_connect_with_timeout (GMythQuery *gmyth_query, + GMythBackendInfo *backend_info, guint timeout) +{ + assert(gmyth_query); + g_return_val_if_fail (gmyth_query->conn != NULL, FALSE); + if (timeout != 0) { + /* sets connection timeout */ + mysql_options (gmyth_query->conn, MYSQL_OPT_CONNECT_TIMEOUT, (gchar*) &timeout); + } + + return gmyth_query_connect (gmyth_query, backend_info); +} + +/** Connects to the Mysql database in the backend. The backend address + * is loaded from the GMythBackendInfo instance. + * + * @param gmyth_query the GMythEPG instance to be connected. + * @return true if connection was success, false if failed. + */ +gboolean +gmyth_query_connect (GMythQuery *gmyth_query, GMythBackendInfo *backend_info) +{ + assert(gmyth_query); + g_return_val_if_fail (backend_info != NULL, FALSE); + g_return_val_if_fail (backend_info->hostname != NULL, FALSE); + g_return_val_if_fail (backend_info->username != NULL, FALSE); + g_return_val_if_fail (backend_info->password != NULL, FALSE); + g_return_val_if_fail (backend_info->db_name != NULL, FALSE); + + g_object_ref (backend_info); + gmyth_query->backend_info = backend_info; + + if (gmyth_query->conn == NULL) { + gmyth_query_print_error (NULL, "mysql_init() failed (probably out of memory)"); + return FALSE; + } + + /* connect to server */ + if (mysql_real_connect (gmyth_query->conn, + gmyth_query->backend_info->hostname, + gmyth_query->backend_info->username, + gmyth_query->backend_info->password, + gmyth_query->backend_info->db_name, + 0, NULL, 0) == NULL) { + + gmyth_query_print_error (gmyth_query->conn, "mysql_real_connect() failed"); + return FALSE; + } + + g_debug ("[%s] Connection to Mysql server succeeded! (host = %s, user = %s, "\ + "password = %s, db name = %s)", __FUNCTION__, + gmyth_query->backend_info->hostname, gmyth_query->backend_info->username, + gmyth_query->backend_info->password, gmyth_query->backend_info->db_name ); + + return TRUE; +} + +/** Disconnects from the Mysql database in the backend. + * + * @param gmyth_query the GMythQuery instance to be disconnected + * @return true if disconnection was success, false if failed. + */ +gboolean +gmyth_query_disconnect (GMythQuery *gmyth_query) +{ + assert(gmyth_query); + + /* TODO: Check how to return error */ + g_debug ("[%s] Closing gmyth_query->conn", __FUNCTION__); + mysql_close (gmyth_query->conn); + + return TRUE; +} + +static void +gmyth_query_print_error (MYSQL *conn, char *message) +{ + g_debug ("%s", message); + + if (conn != NULL) { +#if MYSQL_VERSION_ID >= 40101 + g_debug ("Error %u (%s): %s\n", + mysql_errno (conn), mysql_sqlstate(conn), mysql_error (conn)); +#else + g_debug ("Error %u: %s\n", + mysql_errno (conn), mysql_error (conn)); +#endif + } +} + +/** Sends the given query to the backend returning the query result as + * MYSQL_RES pointer. + * + * FIXME: this function is returning NULL whether any error happens + * or no rows are returned (e.g. UPDATE or REPLACE). + * + * @param gmyth_query the GMythQuery instance. + * @param stmt_str the query text. + * @return the MYSQL_RES result pointer or NULL if any error happens. + */ +MYSQL_RES* +gmyth_query_process_statement (GMythQuery *gmyth_query, char *stmt_str) +{ + MYSQL_RES *res_set; + + assert(gmyth_query); + + g_debug ("[%s] Running mysql query %s", __FUNCTION__, stmt_str); + + if (gmyth_query == NULL) + return NULL; + + /* the statement failed */ + if (mysql_query (gmyth_query->conn, stmt_str) != 0) { + gmyth_query_print_error (gmyth_query->conn, "Could not execute statement"); + return NULL; + } + + /* the statement succeeded; determine whether it returned data */ + res_set = mysql_store_result (gmyth_query->conn); + if (res_set) { + return res_set; + } else if (mysql_field_count (gmyth_query->conn) == 0) { + g_debug ("%lu rows affected\n", + (unsigned long) mysql_affected_rows (gmyth_query->conn)); + } else { + gmyth_query_print_error (gmyth_query->conn, "Could not retrieve result set"); + } + + return NULL; +} diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_query.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_query.h Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,86 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_query.h + * + * @brief

GMythQuery class provides a wrapper for accessing + * the libmysqlclient funtions. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Leonardo Sobral Cunha + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GMYTH_QUERY_H__ +#define __GMYTH_QUERY_H__ + +#include + +/* MYSQL includes */ +#include + +#include "gmyth_backendinfo.h" + +G_BEGIN_DECLS + +#define GMYTH_QUERY_TYPE (gmyth_query_get_type ()) +#define GMYTH_QUERY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_QUERY_TYPE, GMythQuery)) +#define GMYTH_QUERY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_QUERY_TYPE, GMythQueryClass)) +#define IS_GMYTH_QUERY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_QUERY_TYPE)) +#define IS_GMYTH_QUERY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_QUERY_TYPE)) +#define GMYTH_QUERY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_QUERY_TYPE, GMythQueryClass)) + + +typedef struct _GMythQuery GMythQuery; +typedef struct _GMythQueryClass GMythQueryClass; + +struct _GMythQueryClass +{ + GObjectClass parent_class; + + /* callbacks */ + /* no one for now */ +}; + +struct _GMythQuery +{ + GObject parent; + + GMythBackendInfo *backend_info; + + GString *opt_socket_name; /* socket name (use built-in value) */ + unsigned int opt_flags; /* connection flags (none) */ + + MYSQL *conn; /* pointer to connection handler */ +}; + + +GType gmyth_query_get_type (void); + +GMythQuery* gmyth_query_new ( ); +MYSQL_RES * gmyth_query_process_statement + (GMythQuery *gmyth_query, gchar *stmt_str); + +gboolean gmyth_query_connect (GMythQuery *gmyth_query, GMythBackendInfo *backend_info); +gboolean gmyth_query_connect_with_timeout (GMythQuery *gmyth_query, + GMythBackendInfo *backend_info, guint timeout); +gboolean gmyth_query_disconnect (GMythQuery *gmyth_query); + +G_END_DECLS + +#endif /* __GMYTH_QUERY_H__ */ diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_recorder.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_recorder.c Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,654 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_remote_encoder.c + * + * @brief

GMythRecorder class defines functions for playing live tv. + * + * The remote encoder is used by gmyth_tvplayer to setup livetv. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Hallyson Luiz de Morais Melo + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gmyth_recorder.h" + +#include + +#include "gmyth_stringlist.h" +#include "gmyth_util.h" +#include "gmyth_debug.h" + +#define GMYTHTV_RECORDER_HEADER "QUERY_RECORDER" + +static void gmyth_recorder_class_init (GMythRecorderClass *klass); +static void gmyth_recorder_init (GMythRecorder *object); + +static void gmyth_recorder_dispose (GObject *object); +static void gmyth_recorder_finalize (GObject *object); + +G_DEFINE_TYPE(GMythRecorder, gmyth_recorder, G_TYPE_OBJECT) + +static void +gmyth_recorder_class_init (GMythRecorderClass *klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + + gobject_class->dispose = gmyth_recorder_dispose; + gobject_class->finalize = gmyth_recorder_finalize; +} + +static void +gmyth_recorder_init (GMythRecorder *gmyth_remote_encoder) +{ +} + +static void +gmyth_recorder_dispose (GObject *object) +{ + // GMythRecorder *gmyth_remote_encoder = GMYTH_RECORDER(object); + + G_OBJECT_CLASS (gmyth_recorder_parent_class)->dispose (object); +} + + +static void +gmyth_recorder_finalize (GObject *object) +{ + g_signal_handlers_destroy (object); + + GMythRecorder *recorder = GMYTH_RECORDER(object); + + gmyth_debug ("[%s] Closing control socket", __FUNCTION__); + gmyth_socket_close_connection(recorder->myth_socket); + g_object_unref (recorder->myth_socket); + + G_OBJECT_CLASS (gmyth_recorder_parent_class)->finalize (object); +} + +/** Creates a new instance of GMythRecorder. + * + * @return a new instance of GMythRecorder. + */ +GMythRecorder* +gmyth_recorder_new (int num, GString *hostname, gshort port) +{ + GMythRecorder *encoder = GMYTH_RECORDER ( g_object_new ( + GMYTH_RECORDER_TYPE, FALSE )); + + encoder->recorder_num = num; + encoder->hostname = g_string_new (hostname->str); + encoder->port = port; + + return encoder; +} + +/** Configures the remote encoder instance connecting it to Mythtv backend. + * + * @param recorder the GMythRecorder instance. + * @return TRUE if successfull, FALSE if any error happens. + */ +gboolean +gmyth_recorder_setup (GMythRecorder *recorder) +{ + assert (recorder); + gmyth_debug ("[%s] Creating socket and connecting to backend", __FUNCTION__); + + if (recorder->myth_socket == NULL) { + + recorder->myth_socket = gmyth_socket_new (); + + if (!gmyth_socket_connect_to_backend ( recorder->myth_socket, recorder->hostname->str, + recorder->port, TRUE ) ) { + g_warning ("GMythRemoteEncoder: Connection to backend failed"); + return FALSE; + } + + } else { + g_warning("Remote encoder socket already created\n"); + } + + return TRUE; +} + +/** Sends the SPAWN_LIVETV command through Mythtv protocol. This command + * requests the backend to start capturing TV content. + * + * @param recorder The GMythRecorder instance. + * @param tvchain_id The tvchain unique id. + * @return true if success, false if any error happens. + */ +gboolean +gmyth_recorder_spawntv (GMythRecorder *recorder, GString *tvchain_id) +{ + GMythStringList *str_list; + GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER ); + + gmyth_debug ("[%s] Spawntv with tvchain_id = %s", __FUNCTION__, tvchain_id->str); + + str_list = gmyth_string_list_new (); + + g_string_append_printf ( tmp_str, " %d", recorder->recorder_num ); + + gmyth_string_list_append_string (str_list, tmp_str); + gmyth_string_list_append_string (str_list, g_string_new ("SPAWN_LIVETV")); + gmyth_string_list_append_string (str_list, tvchain_id); + gmyth_string_list_append_int (str_list, 0); // PIP = FALSE (0) + + gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list); + + g_string_free (tmp_str, TRUE); + + tmp_str = gmyth_string_list_get_string (str_list, 0); + if (tmp_str == NULL) { + g_warning ("[%s] Spawntv request returned %s", __FUNCTION__, tmp_str->str); + return FALSE; + } + + if (g_ascii_strncasecmp (tmp_str->str, "ok", 2)) { + g_warning ("[%s] Spawntv request returned %s", __FUNCTION__, tmp_str->str); + g_object_unref (str_list); + return FALSE; + } + + g_object_unref (str_list); + return TRUE; + +} + +/** + * Sends the SPAWN_LIVETV command through Mythtv protocol. This command + * requests the backend to start capturing TV content, but it doesn't need + * the TV chain ID. + * + * @param recorder The GMythRecorder instance. + * @return true if success, false if any error happens. + */ +gboolean +gmyth_recorder_spawntv_no_tvchain (GMythRecorder *recorder) +{ + GMythStringList *str_list; + GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER ); + + gmyth_debug ("[%s] Spawntv, no TV chain!", __FUNCTION__); + + str_list = gmyth_string_list_new (); + + g_string_append_printf ( tmp_str, " %d", recorder->recorder_num ); + + gmyth_string_list_append_string (str_list, tmp_str); + gmyth_string_list_append_string (str_list, g_string_new ("SPAWN_LIVETV")); + + gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list); + + g_string_free (tmp_str, TRUE); + + tmp_str = gmyth_string_list_get_string (str_list, 0); + if (tmp_str == NULL) { + g_warning ("[%s] Spawntv request returned %s", __FUNCTION__, tmp_str->str); + return FALSE; + } + + if (g_ascii_strncasecmp (tmp_str->str, "ok", 2)) { + g_warning ("[%s] Spawntv request returned %s", __FUNCTION__, tmp_str->str); + g_object_unref (str_list); + return FALSE; + } + + g_object_unref (str_list); + return TRUE; + +} + +/** Sends the command STOP_LIVETV to Mythtv backend. + * + * @param recorder the GMythRecorder instance. + * @return true if success, false if any error happens. + */ +gboolean +gmyth_recorder_stop_livetv (GMythRecorder *recorder) +{ + GMythStringList *str_list; + GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER ); + + gmyth_debug ("[%s]", __FUNCTION__); + + str_list = gmyth_string_list_new (); + + g_string_append_printf ( tmp_str, " %d", recorder->recorder_num ); + gmyth_string_list_append_char_array( str_list, "STOP_LIVETV" ); + + gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list); + + g_string_free (tmp_str, TRUE); + + tmp_str = gmyth_string_list_get_string (str_list, 0); + if (g_ascii_strncasecmp (tmp_str->str, "ok", 2)) { + g_warning ("[%s] Stop livetv request returned %s", __FUNCTION__, tmp_str->str); + g_object_unref (str_list); + return FALSE; + } + + g_object_unref (str_list); + return TRUE; + +} + +/** Sends the FRONTEND_READY command through Mythtv protocol. This command + * advertises the backend to start capturing TV content. + * + * @param recorder The GMythRecorder instance. + * @return TRUE if success, FALSE if any error happens. + */ +gboolean +gmyth_recorder_send_frontend_ready_command (GMythRecorder *recorder) +{ + GMythStringList *str_list; + GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER ); + + gmyth_debug ( "[%s] FRONTEND_READY with recorder id = %d", __FUNCTION__, recorder->recorder_num ); + + str_list = gmyth_string_list_new (); + + g_string_append_printf ( tmp_str, " %d", recorder->recorder_num ); + + gmyth_string_list_append_string (str_list, tmp_str); + gmyth_string_list_append_string (str_list, g_string_new ("FRONTEND_READY")); + + gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list); + + g_string_free (tmp_str, TRUE); + + tmp_str = gmyth_string_list_get_string (str_list, 0); + if (tmp_str == NULL) { + g_warning ("[%s] FRONTEND_READY command request couldn't returns, reason: %s", __FUNCTION__, tmp_str->str); + return FALSE; + } + + if (g_ascii_strncasecmp (tmp_str->str, "ok", 2)) { + g_warning ("[%s] FRONTEND_READY request returned %s", __FUNCTION__, tmp_str->str); + g_object_unref (str_list); + return FALSE; + } + + g_object_unref (str_list); + return TRUE; + +} + +/** Send a CHECK_CHANNEL command request to the backend, in order to find if a + * certain channel actually exists. + * + * @param recorder The GMythRecorder instance. + * @param channel The new channel to be checked (string format). + * @return true if success, false if any error happens. + */ +gboolean +gmyth_recorder_check_channel_name (GMythRecorder *recorder, gchar* channel) +{ + GMythStringList *str_list; + GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER ); + + gmyth_debug ("[%s] CHECK_CHANNEL with channel = %s", __FUNCTION__, channel); + + str_list = gmyth_string_list_new (); + + g_string_append_printf ( tmp_str, " %d", recorder->recorder_num ); + + gmyth_string_list_append_string (str_list, tmp_str); + gmyth_string_list_append_string (str_list, g_string_new ("CHECK_CHANNEL")); + gmyth_string_list_append_char_array (str_list, channel); + + gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list); + + g_string_free (tmp_str, TRUE); + + tmp_str = gmyth_string_list_get_string (str_list, 0); + if (tmp_str == NULL) { + g_warning ("[%s] CHECK_CHANNEL request returned %s", __FUNCTION__, tmp_str->str); + return FALSE; + } + + if (g_ascii_strncasecmp (tmp_str->str, "ok", 2) == 0 || g_ascii_strncasecmp (tmp_str->str, "0", 1) == 0 ) { + g_warning ("[%s] CHECK_CHANNEL request returned %s", __FUNCTION__, tmp_str->str); + g_object_unref (str_list); + return FALSE; + } + + g_object_unref (str_list); + return TRUE; + +} + +/** Send a CHECK_CHANNEL command request to the backend, in order to find if a + * certain channel actually exists. + * + * @param recorder The GMythRecorder instance. + * @param channel The new channel to be checked (decimal integer value). + * @return true if success, false if any error happens. + */ +gboolean +gmyth_recorder_check_channel (GMythRecorder *recorder, gint channel) +{ + return gmyth_recorder_check_channel_name( recorder, g_strdup_printf( "%d", channel ) ); +} + +/** Send a SET_CHANNEL command request to the backend, to start streaming on another + * TV content channel. + * + * @param recorder The GMythRecorder instance. + * @param channel The new channel to be loaded. + * @return true if success, false if any error happens. + */ +gboolean +gmyth_recorder_set_channel (GMythRecorder *recorder, gint channel) +{ + GMythStringList *str_list; + GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER ); + + gmyth_debug ("[%s] SET_CHANNEL with channel = %d", __FUNCTION__, channel); + + str_list = gmyth_string_list_new (); + + g_string_append_printf ( tmp_str, " %d", recorder->recorder_num ); + + gmyth_string_list_append_string (str_list, tmp_str); + gmyth_string_list_append_string (str_list, g_string_new ("SET_CHANNEL")); + gmyth_string_list_append_int (str_list, channel); + + gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list); + + g_string_free (tmp_str, TRUE); + + tmp_str = gmyth_string_list_get_string (str_list, 0); + if (tmp_str == NULL) { + g_warning ("[%s] SET_CHANNEL request returned %s", __FUNCTION__, tmp_str->str); + return FALSE; + } + + if (g_ascii_strncasecmp (tmp_str->str, "ok", 2)) { + g_warning ("[%s] SET_CHANNEL request returned %s", __FUNCTION__, tmp_str->str); + g_object_unref (str_list); + return FALSE; + } + + g_object_unref (str_list); + return TRUE; + +} + +/** Send a SET_CHANNEL command request to the backend, to start streaming on another + * TV content channel. + * + * @param recorder The GMythRecorder instance. + * @param channel The new channel to be loaded. + * @return true if success, false if any error happens. + */ +gboolean +gmyth_recorder_set_channel_name (GMythRecorder *recorder, const gchar* channel) +{ + GMythStringList *str_list; + GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER ); + + gmyth_debug ("[%s] SET_CHANNEL with channel name = %s", __FUNCTION__, channel); + + str_list = gmyth_string_list_new (); + + g_string_append_printf ( tmp_str, " %d", recorder->recorder_num ); + + gmyth_string_list_append_string (str_list, tmp_str); + gmyth_string_list_append_string (str_list, g_string_new ("SET_CHANNEL")); + gmyth_string_list_append_char_array (str_list, channel); + + gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list); + + g_string_free (tmp_str, TRUE); + + tmp_str = gmyth_string_list_get_string (str_list, 0); + if (tmp_str == NULL) { + g_warning ("[%s] SET_CHANNEL name request returned %s", __FUNCTION__, tmp_str->str ); + return FALSE; + } + + if (g_ascii_strncasecmp (tmp_str->str, "ok", 2) || g_ascii_strtoull( tmp_str->str, NULL, 10 ) == 0 ) { + g_warning ("[%s] SET_CHANNEL name request returned %s", __FUNCTION__, tmp_str->str); + g_object_unref (str_list); + return FALSE; + } + + g_object_unref (str_list); + return TRUE; + +} + +/** + * Changes the channel of the actual Recorder. + * + * CHANNEL_DIRECTION_UP - Go up one channel in the listing + * + * CHANNEL_DIRECTION_DOWN - Go down one channel in the listing + * + * CHANNEL_DIRECTION_FAVORITE - Go to the next favorite channel + * + * CHANNEL_DIRECTION_SAME - Stay + * + * @param recorder The GMythRecorder instance. + * @param direction The new channel direction where to move to. + * @return true if success, false if any error happens. + */ +gboolean +gmyth_recorder_change_channel (GMythRecorder *recorder, const GMythRecorderChannelChangeDirection direction) +{ + GMythStringList *str_list; + GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER ); + + gmyth_debug ("[%s] CHANGE_CHANNEL to the channel direction = %u", __FUNCTION__, direction); + + str_list = gmyth_string_list_new (); + + g_string_append_printf ( tmp_str, " %d", recorder->recorder_num ); + + gmyth_string_list_append_string (str_list, tmp_str); + gmyth_string_list_append_string (str_list, g_string_new ("CHANGE_CHANNEL")); + gmyth_string_list_append_int (str_list, direction); + + gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list); + + g_string_free (tmp_str, TRUE); + + tmp_str = gmyth_string_list_get_string (str_list, 0); + if (tmp_str == NULL) { + g_warning ("[%s] CHANGE_CHANNEL name request returned %s", __FUNCTION__, tmp_str->str ); + return FALSE; + } + + if (g_ascii_strncasecmp (tmp_str->str, "ok", 2) || g_ascii_strtoull( tmp_str->str, NULL, 10 ) == 0 ) { + g_warning ("[%s] CHANGE_CHANNEL name request returned %s", __FUNCTION__, tmp_str->str); + g_object_unref (str_list); + return FALSE; + } + + g_object_unref (str_list); + return TRUE; + +} + +/** Send a PAUSE command request to the backend, to pause streaming on another + * TV content channel. + * + * @param recorder The GMythRecorder instance. + * @return true if success, false if any error happens. + */ +gboolean +gmyth_recorder_pause_recording ( GMythRecorder *recorder ) +{ + GMythStringList *str_list; + GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER ); + + gmyth_debug ("[%s] PAUSE", __FUNCTION__); + + str_list = gmyth_string_list_new (); + + g_string_append_printf ( tmp_str, " %d", recorder->recorder_num ); + + gmyth_string_list_append_string (str_list, tmp_str); + gmyth_string_list_append_string (str_list, g_string_new ("PAUSE")); + + gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list); + + g_string_free (tmp_str, TRUE); + + tmp_str = gmyth_string_list_get_string (str_list, 0); + if (tmp_str == NULL) { + g_warning ("[%s] PAUSE name request returned %s", __FUNCTION__, tmp_str->str); + return FALSE; + } + + if (g_ascii_strncasecmp (tmp_str->str, "ok", 2)) { + g_warning ("[%s] PAUSE name request returned %s", __FUNCTION__, tmp_str->str); + g_object_unref (str_list); + return FALSE; + } + + g_object_unref (str_list); + return TRUE; + +} + +/** + * Requests the actual program info from the MythTV backend server. + * + * @param recorder The GMythRecorder instance. + * @return The actual program info. + */ +GMythProgramInfo * +gmyth_recorder_get_current_program_info ( GMythRecorder *recorder ) +{ + GMythStringList *str_list; + GMythProgramInfo *program_info = gmyth_program_info_new(); + GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER ); + + str_list = gmyth_string_list_new (); + + g_string_append_printf ( tmp_str, " %d", recorder->recorder_num ); + + gmyth_string_list_append_string (str_list, tmp_str); + + if ( recorder->myth_socket->mythtv_version >= 26 ) + gmyth_string_list_append_string (str_list, g_string_new ("GET_CURRENT_RECORDING")); + else + gmyth_string_list_append_string (str_list, g_string_new ("GET_PROGRAM_INFO")); + + gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list); + + g_string_free (tmp_str, TRUE); + + if (str_list == NULL) { + g_warning ("[%s] GET_PROGRAM_INFO request returned. Error getting program info, string list equals to NULL!", __FUNCTION__); + return FALSE; + } + + program_info = gmyth_program_info_from_string_list( str_list ); + + if ( NULL == program_info ) { + g_warning ("[%s] GET_PROGRAM_INFO request returned. Error getting program info, it is equals to NULL!!!", __FUNCTION__); + g_object_unref (program_info); + return NULL; + } + + g_object_unref (str_list); + return program_info; + +} + +gint64 +gmyth_recorder_get_file_position ( GMythRecorder *recorder ) +{ + gint64 pos = 0; + GString *query = g_string_new( GMYTHTV_RECORDER_HEADER ); + + GMythStringList *str_list = gmyth_string_list_new (); + + g_string_append_printf( query, " %d", recorder->recorder_num ); + + gmyth_string_list_append_string (str_list, query); + gmyth_string_list_append_char_array( str_list, "GET_FILE_POSITION" ); + + gmyth_socket_sendreceive_stringlist ( recorder->myth_socket, str_list ); + + if ( str_list != NULL && gmyth_string_list_length(str_list) > 0 ) + { + GString *str = NULL; + if ( ( str = gmyth_string_list_get_string( str_list, 0 ) ) != NULL && strstr ( str->str, "bad" ) == NULL ) + pos = gmyth_util_decode_long_long( str_list, 0 ); + } + +#ifndef GMYTHTV_ENABLE_DEBUG + g_print( "[%s] Got file position = %lld\n", __FUNCTION__, pos ); +#endif + if (str_list!=NULL) + g_object_unref (str_list); + + return pos; + +} + +gboolean +gmyth_recorder_is_recording ( GMythRecorder *recorder ) +{ + gboolean ret = TRUE; + + g_return_val_if_fail( recorder != NULL, FALSE ); + + GMythStringList *str_list = gmyth_string_list_new (); + GString *message = g_string_new (""); + + g_string_printf( message, "%s %d", GMYTHTV_RECORDER_HEADER, recorder->recorder_num); + gmyth_string_list_append_string (str_list, message); + gmyth_string_list_append_string (str_list, g_string_new ("IS_RECORDING")); + + gmyth_socket_sendreceive_stringlist ( recorder->myth_socket, str_list ); + + if ( str_list != NULL && gmyth_string_list_length(str_list) > 0 ) + { + GString *str = NULL; + if ( ( str = gmyth_string_list_get_string( str_list, 0 ) ) != NULL && strcmp( str->str, "bad" )!= 0 ) + { + gint is_rec = gmyth_string_list_get_int( str_list, 0 ); + if ( is_rec != 0 ) + ret = TRUE; + else + ret = FALSE; + } + } + gmyth_debug( "%s, stream is %s being recorded!\n", ret ? "YES" : "NO", ret ? "" : "NOT" ); + //g_static_mutex_unlock (&mutex); + + if ( str_list != NULL ) + g_object_unref (str_list); + + return ret; + +} diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_recorder.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_recorder.h Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,122 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_recorder.h + * + * @brief

GMythRecorder class defines functions for playing live tv. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Hallyson Luiz de Morais Melo + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GMYTH_RECORDER_H__ +#define __GMYTH_RECORDER_H__ + +#include + +#include "gmyth_socket.h" +#include "gmyth_programinfo.h" + +#include +#include +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define GMYTH_RECORDER_TYPE (gmyth_recorder_get_type ()) +#define GMYTH_RECORDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_RECORDER_TYPE, GMythRecorder)) +#define GMYTH_RECORDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_RECORDER_TYPE, GMythRecorderClass)) +#define IS_GMYTH_RECORDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_RECORDER_TYPE)) +#define IS_GMYTH_RECORDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_RECORDER_TYPE)) +#define GMYTH_RECORDER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_RECORDER_TYPE, GMythRecorderClass)) + + +typedef struct _GMythRecorder GMythRecorder; +typedef struct _GMythRecorderClass GMythRecorderClass; + +struct _GMythRecorderClass +{ + GObjectClass parent_class; + + /* callbacks */ + /* no one for now */ +}; + +struct _GMythRecorder +{ + GObject parent; + + /* socket descriptor */ + GMythSocket *myth_socket; + + gint recorder_num; + GString *hostname; + gint port; +}; + +typedef enum _GMythRecorderChannelChangeDirection { + CHANNEL_DIRECTION_UP = 0, + CHANNEL_DIRECTION_DOWN, + CHANNEL_DIRECTION_FAVORITE, + CHANNEL_DIRECTION_SAME +} GMythRecorderChannelChangeDirection; + +GType gmyth_recorder_get_type (void); + +GMythRecorder* gmyth_recorder_new (int num, + GString *hostname, + gshort port); + +gboolean gmyth_recorder_setup (GMythRecorder *recorder); +gboolean gmyth_recorder_spawntv (GMythRecorder *recorder, + GString *tvchain_id); + +gboolean gmyth_recorder_spawntv_no_tvchain (GMythRecorder *recorder); + +gboolean gmyth_recorder_stop_livetv (GMythRecorder *recorder); + +gboolean gmyth_recorder_send_frontend_ready_command (GMythRecorder *recorder); + +gboolean gmyth_recorder_check_channel (GMythRecorder *recorder, gint channel); + +gboolean gmyth_recorder_check_channel_name (GMythRecorder *recorder, gchar* channel); + +gboolean gmyth_recorder_set_channel (GMythRecorder *recorder, + gint channel); + +gboolean gmyth_recorder_set_channel_name (GMythRecorder *recorder, + const gchar* channel); + +gboolean gmyth_recorder_change_channel (GMythRecorder *recorder, + const GMythRecorderChannelChangeDirection direction); + +gboolean gmyth_recorder_pause_recording ( GMythRecorder *recorder ); + +GMythProgramInfo *gmyth_recorder_get_current_program_info ( GMythRecorder *recorder ); + +gint64 gmyth_recorder_get_file_position ( GMythRecorder *recorder ); + +gboolean gmyth_recorder_is_recording ( GMythRecorder *recorder ); + +G_END_DECLS + +#endif /* __GMYTH_REMOTE_ENCODER_H__ */ diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_remote_util.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_remote_util.c Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,79 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_remote_util.c + * + * @brief

This component provides utility functions for accessing remote data. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Hallyson Luiz de Morais Melo + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gmyth_remote_util.h" + +#include "gmyth_recorder.h" +#include "gmyth_stringlist.h" +#include "gmyth_debug.h" + +/** Requests the Mythtv backend for a free remote recorder. + * + * @param curr The recorder index, or -1 to consider the first one. + * @return the remote encoder instance available, or NULL if any error happens. + */ +GMythRecorder* +remote_request_next_free_recorder (GMythSocket *socket, int curr) +{ + GMythRecorder *recorder = NULL; + GString *hostname; + int num, port; + + GMythStringList *strlist = gmyth_string_list_new(); + + gmyth_debug ("[%s] Request next free recorder in the backend", __FUNCTION__); + + gmyth_string_list_append_char_array (strlist, "GET_NEXT_FREE_RECORDER"); + gmyth_string_list_append_int (strlist, curr); + + if (!gmyth_socket_sendreceive_stringlist(socket, strlist)) { + g_warning ("GET_NEXT_FREE_RECORDER request error!\n"); + return NULL; + } + + num = gmyth_string_list_get_int (strlist, 0); + hostname = gmyth_string_list_get_string (strlist, 1); + port = gmyth_string_list_get_int (strlist, 2); + + if ( num < 0 || port < 0 ) + goto clean_up; + + gmyth_debug ("[%s] Free recorder info received: num: %d, hostname: %s, port: %d", + __FUNCTION__, num, hostname->str, port); + + recorder = gmyth_recorder_new (num, hostname, port); + +clean_up: + + g_object_unref (strlist); + + return recorder; +} diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_remote_util.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_remote_util.h Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,41 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_remote_util.h + * + * @brief

This component provides utility functions for accessing remote data. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Hallyson Luiz de Morais Melo + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __REMOTE_UTIL_H__ +#define __REMOTE_UTIL_H__ + +#include +#include "gmyth_recorder.h" +#include "gmyth_socket.h" + +G_BEGIN_DECLS + +GMythRecorder* remote_request_next_free_recorder (GMythSocket *socket, int curr); + +G_END_DECLS + +#endif diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_scheduler.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_scheduler.c Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,667 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_scheduler.c + * + * @brief

The scheduler encapsulates all functions for browsing, scheduling + * and modifying the recorded content. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Alexsandro Jose Virginio dos Santos + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + +#include "gmyth_scheduler.h" +#include "gmyth_util.h" +#include "gmyth_query.h" +#include "gmyth_socket.h" +#include "gmyth_debug.h" + +static void gmyth_scheduler_class_init (GMythSchedulerClass *klass); +static void gmyth_scheduler_init (GMythScheduler *object); + +static void gmyth_scheduler_dispose (GObject *object); +static void gmyth_scheduler_finalize (GObject *object); + +static gint get_record_id_from_database (GMythScheduler *scheduler); +static void update_backend (GMythScheduler *scheduler, gint record_id); + +G_DEFINE_TYPE(GMythScheduler, gmyth_scheduler, G_TYPE_OBJECT) + +static void +gmyth_scheduler_class_init (GMythSchedulerClass *klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + + gobject_class->dispose = gmyth_scheduler_dispose; + gobject_class->finalize = gmyth_scheduler_finalize; +} + +static void +gmyth_scheduler_init (GMythScheduler *sched) +{ + sched->recordid =0; + sched->type = 0; + sched->search = 0; + sched->profile = g_string_new(""); + + sched->dupin = 0; + sched->dupmethod = 0; + sched->autoexpire = 0; + sched->autotranscode = 0; + sched->transcoder = 0; + + sched->autocommflag = 0; + sched->autouserjob1 = 0; + sched->autouserjob2 = 0; + sched->autouserjob3 = 0; + sched->autouserjob4 = 0; + + sched->startoffset = 0; + sched->endoffset = 0; + sched->maxepisodes = 0; + sched->maxnewest = 0; + + sched->recpriority = 0; + sched->recgroup = 0; + sched->playgroup = 0; + + sched->prefinput = 0; + sched->inactive = 0; + + sched->searchType = g_string_new(""); + sched->searchForWhat = g_string_new(""); + + sched->msqlquery = gmyth_query_new (); +} + +static void +gmyth_scheduler_dispose (GObject *object) +{ + GMythScheduler *scheduler = GMYTH_SCHEDULER (object); + + if (scheduler->backend_info) { + g_object_unref (scheduler->backend_info); + scheduler->backend_info = NULL; + } + + G_OBJECT_CLASS (gmyth_scheduler_parent_class)->dispose (object); +} + +static void +gmyth_scheduler_finalize (GObject *object) +{ + g_signal_handlers_destroy (object); + + G_OBJECT_CLASS (gmyth_scheduler_parent_class)->finalize (object); +} + +/** Creates a new instance of GMythScheduler. + * + * @return a new instance of GMythScheduler. + */ +GMythScheduler* +gmyth_scheduler_new () +{ + GMythScheduler *scheduler = + GMYTH_SCHEDULER (g_object_new(GMYTH_SCHEDULER_TYPE, NULL)); + + return scheduler; +} + +gboolean +gmyth_scheduler_connect (GMythScheduler *scheduler, GMythBackendInfo *backend_info) +{ + return gmyth_scheduler_connect_with_timeout (scheduler, backend_info, 0); +} + +/** Connects to the Mysql database in the backend. The backend address + * is loaded from the GMythSettings instance. + * + * @param scheduler the GMythScheduler instance to be connected. + * @return true if connection was success, false if failed. + */ +gboolean +gmyth_scheduler_connect_with_timeout (GMythScheduler *scheduler, + GMythBackendInfo *backend_info, guint timeout) +{ + assert(scheduler); + g_return_val_if_fail (backend_info != NULL, FALSE); + + g_object_ref (backend_info); + scheduler->backend_info = backend_info; + + if (scheduler->msqlquery == NULL) { + g_warning ("[%s] GMythScheduler db initializing", __FUNCTION__); + scheduler->msqlquery = gmyth_query_new (); + } + + if (!gmyth_query_connect_with_timeout (scheduler->msqlquery, + scheduler->backend_info, timeout)) { + g_warning ("[%s] Error while connecting to db", __FUNCTION__); + return FALSE; + } + + return TRUE; +} + +/** Disconnects from the Mysql database in the backend. + * + * @param scheduler the GMythScheduler instance to be disconnected + * @return true if disconnection was success, false if failed. + */ +gboolean +gmyth_scheduler_disconnect (GMythScheduler *scheduler) +{ + assert(scheduler); + + if (scheduler->msqlquery != NULL) { + gmyth_query_disconnect (scheduler->msqlquery); + g_object_unref (scheduler->msqlquery); + } + + return TRUE; +} + +/** Retrieves from the backend Mysql database the list of recording schedules. + * + * @param scheduler The GMythScheduler instance. + * @param schedule_list the GList pointer to be filled with the loaded list of ScheduleInfo items. + * @return The amount of schedules retrieved from database, or -1 if error. + */ +gint +gmyth_scheduler_get_schedule_list ( GMythScheduler *scheduler, GList **schedule_list) +{ + ScheduleInfo *schedule; + MYSQL_RES *msql_res; + GString *query_str = g_string_new (""); + gchar *date_time = NULL; + + assert(scheduler); + + g_string_printf (query_str, + "SELECT recordid,programid,chanid,starttime,startdate," + "endtime,enddate,title,subtitle,description,category FROM record;"); + + if (scheduler->msqlquery == NULL) { + g_warning ("[%s] Scheduler db connection not initialized", __FUNCTION__); + return -1; + } + msql_res = gmyth_query_process_statement (scheduler->msqlquery, query_str->str); + + if (msql_res == NULL) { + g_warning ("DB retrieval of schedule list failed"); + return -1; + } else { + MYSQL_ROW row; + *schedule_list = NULL; + + while((row = mysql_fetch_row (msql_res)) != NULL) { + schedule = g_new0(ScheduleInfo, 1); + + schedule->record_id = g_ascii_strtoull (row[0], NULL, 10); + schedule->program_id = g_ascii_strtoull (row[1], NULL, 10); + schedule->channel_id = g_ascii_strtoull (row[2], NULL, 10); + + /* generate a time_t from a time and a date db field */ + g_sprintf (date_time, "%sT%s", row[4], row[3]); + + schedule->start_time = gmyth_util_string_to_time_val (date_time); + + /* generate a time_t from a time and a date db field */ + g_sprintf (date_time, "%sT%s", row[6], row[5]); + + schedule->end_time = gmyth_util_string_to_time_val (date_time); + + schedule->title = g_string_new (row[7]); + schedule->subtitle = g_string_new (row[8]); + schedule->description = g_string_new (row[9]); + schedule->category = g_string_new (row[10]); + + (*schedule_list) = g_list_append (*(schedule_list), schedule); + } + } + + mysql_free_result (msql_res); + g_string_free(query_str, TRUE); + g_free(date_time); + + return (*schedule_list == NULL) ? 0 : g_list_length (*schedule_list); +} + +/** Retrieves from the backend Mysql database the list of recorded programs. + * + * @param scheduler The GMythScheduler instance. + * @param recorded_list the GList pointer to be filled with the loaded RecordInfo items. + * @return The amount of recorded retrieved from database, or -1 if error. + */ +gint +gmyth_scheduler_get_recorded_list (GMythScheduler *scheduler, GList **recorded_list) +{ + RecordedInfo *record; + MYSQL_RES *msql_res; + GString *query_str = g_string_new (""); + + assert(scheduler); + + g_string_printf (query_str, + "SELECT recordid,programid,chanid,starttime,progstart," + "endtime,progend,title,subtitle,description,category,filesize,basename FROM recorded WHERE recgroup != 'LiveTV'"); + + if (scheduler->msqlquery == NULL) { + g_warning ("[%s] Scheduler db connection not initialized", __FUNCTION__); + return -1; + } + + msql_res = gmyth_query_process_statement (scheduler->msqlquery, query_str->str); + + if (msql_res == NULL) { + g_warning ("DB retrieval of recording list failed"); + return -1; + } else { + MYSQL_ROW row; + *recorded_list = NULL; + + while((row = mysql_fetch_row (msql_res))!=NULL){ + record = g_new0(RecordedInfo, 1); + + record->record_id = (guint) g_ascii_strtoull (row[0], NULL, 10); + record->program_id = (guint) g_ascii_strtoull (row[1], NULL, 10); + record->channel_id = (guint) g_ascii_strtoull (row[2], NULL, 10); + + record->start_time = gmyth_util_string_to_time_val (row[3]); + record->end_time = gmyth_util_string_to_time_val (row[5]); + + record->title = g_string_new (row[7]); + record->subtitle = g_string_new (row[8]); + record->description = g_string_new (row[9]); + record->category = g_string_new (row[10]); + record->filesize = g_ascii_strtoull (row[11], NULL, 10); + record->basename = g_string_new (row[12]); + + *recorded_list = g_list_append (*recorded_list, record); + } + } + + mysql_free_result (msql_res); + g_string_free(query_str, TRUE); + + return (*recorded_list == NULL) ? 0 : g_list_length (*recorded_list); +} + +/** Requests the Mysql database in the backend to add a new schedule. + * + * @param scheduler the GMythScheduler instance. + * @param schedule_info the ScheduleInfo with recording schedule information + * to be added. record_id = -1 to add a new schedule, otherwise this + * function will update the schedule in the db + * @return gboolean returns FALSE if some error occurs, TRUE otherwise + */ +gboolean +gmyth_scheduler_add_schedule (GMythScheduler *scheduler, + ScheduleInfo *schedule_info) +{ + //GTimeVal *start_tm; + //GTimeVal *end_tm; + + MYSQL_RES *msql_res; + GString *query_str = g_string_new (""); + + gchar *date_time = NULL; + + assert(scheduler); + + if (scheduler->msqlquery == NULL) { + g_warning ("[%s] Scheduler db connection not initialized", __FUNCTION__); + return FALSE; + } + + //TODO: verify if this funtion realy does what it should do! + g_string_printf (query_str, "REPLACE INTO record " + "(recordid, type, chanid, starttime, " + "startdate, endtime, enddate, title," + "profile, recpriority, maxnewest, inactive, " + "maxepisodes, autoexpire, startoffset, endoffset, " + "recgroup, dupmethod, dupin, station, " + "autocommflag, findday, findtime, findid, " + "search, autotranscode, transcoder, tsdefault, " + "autouserjob1, autouserjob2, autouserjob3, autouserjob4) " + " values ( %d, 1, %d, \"%s\"," //recordid, type, chanid, starttime + " \"%s\", \"%s\", \"%s\", \"%s\"," + //startdate, endtime, enddate, title + "DEFAULT, 0, 0, 0, " //profile, recpriority, maxnewest, inactive + "0, 1, 0, 0, " //maxepisodes, autoexpire, startoffset, endoffset + "DEFAULT, 6, 15, %d, " //recgroup, dupmethod, dupin, station + "1, %d, \"%s\", %d, " //autocommflag, findday, findtime, findid + "5, 0, 29, 1, " //search, autotranscode, transcoder, tsdefault + "0, 0, 0, 0 );", //autouserjob1, autouserjob2, autouserjob3, autouserjob4 + schedule_info->record_id, schedule_info->channel_id, + gmyth_util_time_to_string_only_time( schedule_info->start_time ), + gmyth_util_time_to_string_only_date( schedule_info->start_time ), + gmyth_util_time_to_string_only_time( schedule_info->end_time ), + gmyth_util_time_to_string_only_date( schedule_info->end_time ), + schedule_info->title->str, //title + schedule_info->channel_id,//station + (gmyth_util_time_val_to_date( schedule_info->start_time ))->tm_wday, //findday + gmyth_util_time_to_string_only_time( schedule_info->start_time ), //findtime + (gint)(schedule_info->start_time->tv_sec/60/60/24 + 719528)//findid + ); + + gmyth_debug ( "Sending query to MySQL = %s.", query_str->str ); + + msql_res = gmyth_query_process_statement (scheduler->msqlquery, query_str->str); + + /* FIXME: currently no way to detect db error in UPDATE, REPLACES! + if (msql_res == NULL) { + g_warning ("DB retrieval of recording list failed"); + return -1; + }*/ + + /* TODO: verify record_id = -1 semantics */ + if (schedule_info->record_id <= 0) + schedule_info->record_id = get_record_id_from_database(scheduler); + + /* Notify the backend of changes */ + update_backend(scheduler, schedule_info->record_id); + + /* free allocated memory */ + mysql_free_result (msql_res); + g_string_free(query_str, TRUE); + + return 1; +} + +/** Requests the Mysql database in the backend to remove an existing schedule. + * + * @param scheduler the GMythScheduler instance. + * @param record_id The schedule's record id to be removed + * @return gboolean TRUE if success, FALSE if error + */ +gboolean +gmyth_scheduler_delete_schedule (GMythScheduler *scheduler, gint record_id) +{ + + MYSQL_RES *msql_res; + GString *query_str = g_string_new (""); + + assert(scheduler); + + if (scheduler->msqlquery == NULL) { + g_warning ("[%s] Scheduler db connection not initialized", __FUNCTION__); + return FALSE; + } + + //======================================== + g_string_printf (query_str, + "DELETE FROM record WHERE recordid=%d", record_id); + + msql_res = gmyth_query_process_statement (scheduler->msqlquery, query_str->str); + + if (msql_res == NULL) { + g_warning ("[%s] Error while trying to delete a schedule in the database", __FUNCTION__); + return FALSE; + } + + update_backend(scheduler, record_id);// Notify the backend of the changes + + mysql_free_result (msql_res); + g_string_free(query_str, TRUE); + + return TRUE; +} + +/** Requests the Mysql database in the backend to remove an existing recorded item. + * + * @param scheduler the GMythScheduler instance. + * @param record_id The recorded item id to be removed + * @return gboolean TRUE if success, FALSE if error + */ +gboolean +gmyth_scheduler_delete_recorded (GMythScheduler *scheduler, gint record_id) +{ + + MYSQL_RES *msql_res; + + GString *query_str = g_string_new (""); + + assert(scheduler); + + if (scheduler->msqlquery == NULL) { + g_warning ("[%s] Scheduler db connection not initialized", __FUNCTION__); + return FALSE; + } + + //======================================== + g_string_printf (query_str, + "DELETE FROM recorded WHERE recordid=%d", record_id); + + msql_res = gmyth_query_process_statement (scheduler->msqlquery, query_str->str); + + update_backend(scheduler, record_id);// Notify the backend of the changes + + mysql_free_result (msql_res); + g_string_free(query_str, TRUE); + + return TRUE; +} + +/** Retrieves an existing recorded item information from database. The information + * is used to fill the returned GMythProgramInfo. + * + * @param scheduler The GMythScheduler instance. + * @param channel The channel associated to the record + * @param starttime The record start time + * @return A GMythProgramInfo struct with the requested record item + * information, or NULL if error. + */ +GMythProgramInfo* +gmyth_scheduler_get_recorded (GMythScheduler *scheduler, + GString *channel, GTimeVal* starttime) +{ + MYSQL_RES *msql_res; + GMythProgramInfo *proginfo = NULL; + GString *query_str = g_string_new(""); + gchar *time_str = gmyth_util_time_to_string_from_time_val (starttime); + + assert(scheduler); + + if (scheduler->msqlquery == NULL) { + g_warning ("[%s] Scheduler db connection not initialized", __FUNCTION__); + return NULL; + } + + g_string_printf (query_str, "SELECT recorded.chanid,starttime,endtime,title, " + "subtitle,description,channel.channum, " + "channel.callsign,channel.name,channel.commfree, " + "channel.outputfilters,seriesid,programid,filesize, " + "lastmodified,stars,previouslyshown,originalairdate, " + "hostname,recordid,transcoder,playgroup, " + "recorded.recpriority,progstart,progend,basename,recgroup " + "FROM recorded " + "LEFT JOIN channel " + "ON recorded.chanid = channel.chanid " + "WHERE recorded.chanid = \"%s\" " + "AND starttime = \"%s\" ;", + channel->str, time_str); + + msql_res = gmyth_query_process_statement (scheduler->msqlquery, query_str->str); + + if (msql_res /*&& query.size() > 0*/) { + + MYSQL_ROW msql_row = mysql_fetch_row (msql_res); + if (msql_row) { + + proginfo = gmyth_program_info_new(); + + proginfo->chanid = g_string_new (msql_row[0]); + proginfo->startts = gmyth_util_string_to_time_val (msql_row[23]); + proginfo->endts = gmyth_util_string_to_time_val (msql_row[24]); + proginfo->recstartts = gmyth_util_string_to_time_val (msql_row[1]); + proginfo->recendts = gmyth_util_string_to_time_val (msql_row[2]); + proginfo->title = g_string_new (msql_row[3]); + proginfo->subtitle = g_string_new (msql_row[4]); + proginfo->description = g_string_new (msql_row[5]); + + proginfo->chanstr = g_string_new (msql_row[6]); + proginfo->chansign = g_string_new (msql_row[7]); + proginfo->channame = g_string_new (msql_row[0]); + proginfo->chancommfree = g_ascii_strtoull (msql_row[9], NULL, 10); + proginfo->chanOutputFilters = g_string_new (msql_row[10]); + proginfo->seriesid = g_string_new (msql_row[11]); + proginfo->programid = g_string_new (msql_row[12]); + proginfo->filesize = g_ascii_strtoull (msql_row[13], NULL, 10); + + proginfo->lastmodified = gmyth_util_string_to_time_val (msql_row[14]); + + proginfo->stars = g_ascii_strtod (msql_row[15], NULL); + proginfo->repeat = g_ascii_strtoull (msql_row[16], NULL, 10); + + if (msql_row[17] == NULL) { + proginfo->originalAirDate = 0; + proginfo->hasAirDate = FALSE; + } else { + proginfo->originalAirDate = gmyth_util_string_to_time_val (msql_row[17]); + proginfo->hasAirDate = TRUE; + } + + proginfo->hostname = g_string_new (msql_row[18]); + proginfo->recordid = g_ascii_strtoull (msql_row[19], NULL, 10); + proginfo->transcoder = g_ascii_strtoull (msql_row[20], NULL, 10); + + //proginfo->spread = -1; + //proginfo->programflags = proginfo->getProgramFlags(); + + proginfo->recgroup = g_string_new (msql_row[26]); + proginfo->playgroup = g_string_new (msql_row[21]); + proginfo->recpriority = g_ascii_strtoull (msql_row[22], NULL, 10); + + proginfo->pathname = g_string_new (msql_row[25]); + + gmyth_debug ("One program info loaded from mysql database\n"); + } + } + + mysql_free_result (msql_res); + g_string_free(query_str, TRUE); + g_free(time_str); + + return proginfo; +} + +/** Retrieves the next record id. + * + * @param scheduler The GMythScheduler instance. + * @return gint record_id if success, -1 otherwise + */ +static gint +get_record_id_from_database (GMythScheduler *scheduler) +{ + gint record_id; + + assert(scheduler); + + if (scheduler->msqlquery == NULL) { + g_warning ("[%s] Scheduler db connection not initialized", __FUNCTION__); + return 0; + } + + record_id = mysql_insert_id (scheduler->msqlquery->conn); + + return record_id; +} + +/** Notifies the backend of an update in the db. + * + * @param record_id the id of the modified recording. + */ +static void +update_backend(GMythScheduler *scheduler, gint record_id)//fixme: put void and discovery record_id inside +{ + GMythSocket *socket; + GMythStringList *strlist = gmyth_string_list_new (); + GString *datastr = g_string_new ("RESCHEDULE_RECORDINGS "); + + g_string_append_printf (datastr, "%d", record_id); + gmyth_string_list_append_string (strlist, datastr); + + socket = gmyth_socket_new (); + if (gmyth_socket_connect (socket, scheduler->backend_info->hostname, + scheduler->backend_info->port)) { + gmyth_socket_sendreceive_stringlist (socket, strlist); + } else { + g_warning ("[%s] Connection to backend failed!", __FUNCTION__); + } + + g_string_free(datastr, TRUE); + g_object_unref(strlist); +} + +void +gmyth_scheduler_recorded_info_get_preview (RecordedInfo *info, GByteArray* data) +{ +} + +void +gmyth_scheduler_recorded_info_free (RecordedInfo *info) +{ + if (info->title != NULL) + g_string_free (info->title, TRUE); + + if (info->subtitle != NULL) + g_string_free (info->subtitle, TRUE); + + if (info->description != NULL) + g_string_free (info->description, TRUE); + + if (info->category != NULL) + g_string_free (info->category, TRUE); + + if (info->basename != NULL) + g_string_free (info->basename, TRUE); + + g_free (info); +} + +void +gmyth_scheduler_schedule_info_free (ScheduleInfo *info) +{ + if (info->title != NULL) + g_string_free (info->title, TRUE); + + if (info->subtitle != NULL) + g_string_free (info->subtitle, TRUE); + + if (info->description != NULL) + g_string_free (info->description, TRUE); + + if (info->category != NULL) + g_string_free (info->category, TRUE); + + g_free (info); +} + diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_scheduler.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_scheduler.h Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,169 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_scheduler.h + * + * @brief

The scheduler encapsulates all functions for browsing, scheduling + * and modifying the recorded content. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Alexsandro Jose Virginio dos Santos + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GMYTH_SCHEDULER_H__ +#define __GMYTH_SCHEDULER_H__ + +#include +#include + +#include "gmyth_common.h" +#include "gmyth_query.h" +#include "gmyth_backendinfo.h" + +G_BEGIN_DECLS + +#define GMYTH_SCHEDULER_TYPE (gmyth_scheduler_get_type ()) +#define GMYTH_SCHEDULER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_SCHEDULER_TYPE, GMythScheduler)) +#define GMYTH_SCHEDULER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_SCHEDULER_TYPE, GMythSchedulerClass)) +#define IS_GMYTH_SCHEDULER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_SCHEDULER_TYPE)) +#define IS_GMYTH_SCHEDULER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_SCHEDULER_TYPE)) +#define GMYTH_SCHEDULER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_SCHEDULER_TYPE, GMythSchedulerClass)) + + +typedef struct _GMythScheduler GMythScheduler; +typedef struct _GMythSchedulerClass GMythSchedulerClass; + +struct _GMythSchedulerClass +{ + GObjectClass parent_class; + + /* callbacks */ + /* no one for now */ +}; + +struct _GMythScheduler +{ + GObject parent; + + unsigned long recordid; + unsigned long type; + unsigned long search; + GString *profile; + + long dupin; + long dupmethod; + long autoexpire; + short int autotranscode; + long transcoder; + + short int autocommflag; + short int autouserjob1; + short int autouserjob2; + short int autouserjob3; + short int autouserjob4; + + long startoffset; + long endoffset; + long maxepisodes; + long maxnewest; + + long recpriority; + GString *recgroup; + GString *playgroup; + + long prefinput; + short int inactive; + + GString *searchType; + GString *searchForWhat; + + GMythQuery *msqlquery; + GMythBackendInfo *backend_info; +}; + +typedef struct { + gint record_id; + gint program_id; + gint channel_id; + + GTimeVal* start_time; + GTimeVal* end_time; + + GString *title; + GString *subtitle; + GString *description; + GString *category; + +} ScheduleInfo; + +typedef struct { + guint record_id; + guint program_id; + guint channel_id; + + GTimeVal* start_time; + GTimeVal* end_time; + + GString *title; + GString *subtitle; + GString *description; + GString *category; + + GString *basename; + + guint64 filesize; + +} RecordedInfo; + + +GType gmyth_scheduler_get_type (void); + +GMythScheduler* gmyth_scheduler_new (); +gboolean gmyth_scheduler_connect (GMythScheduler *scheduler, + GMythBackendInfo *backend_info); +gboolean gmyth_scheduler_connect_with_timeout (GMythScheduler *scheduler, + GMythBackendInfo *backend_info, guint timeout); +gboolean gmyth_scheduler_disconnect (GMythScheduler *scheduler); + +gint gmyth_scheduler_get_schedule_list (GMythScheduler *scheduler, + GList **sched_list); +gint gmyth_scheduler_get_recorded_list (GMythScheduler *scheduler, + GList **rec_list); + +GMythProgramInfo* gmyth_scheduler_get_recorded (GMythScheduler *scheduler, + GString *channel, GTimeVal* starttime); + +gint gmyth_scheduler_add_schedule(GMythScheduler *scheduler, + ScheduleInfo *schedule_info); + +gint gmyth_scheduler_delete_schedule (GMythScheduler *scheduler, + gint record_id); +gint gmyth_scheduler_delete_recorded (GMythScheduler *scheduler, + gint record_id); + +void gmyth_scheduler_recorded_info_get_preview (RecordedInfo *info, + GByteArray* data); + +void gmyth_scheduler_schedule_info_free (ScheduleInfo *info); +void gmyth_scheduler_recorded_info_free (RecordedInfo *info); + +G_END_DECLS + +#endif /* __GMYTH_SCHEDULER_H__ */ + diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_socket.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_socket.c Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,1082 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_socket.c + * + * @brief

MythTV socket implementation, according to the MythTV Project + * (www.mythtv.org). + * + * This component provides basic socket functionalities to interact with + * the Mythtv backend. + *

+ * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Rosfran Lins Borges + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gmyth_socket.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "gmyth_stringlist.h" +#include "gmyth_uri.h" +#include "gmyth_debug.h" + +#define BUFLEN 512 +#define MYTH_SEPARATOR "[]:[]" +#define MYTH_PROTOCOL_FIELD_SIZE 8 + +/* max number of iterations */ +#define MYTHTV_MAX_VERSION_CHECKS 40 + +// FIXME: put this in the right place +#define MYTHTV_VERSION_DEFAULT 30 + +static GStaticMutex mutex = G_STATIC_MUTEX_INIT; + +static gchar* local_hostname = NULL; + +static void gmyth_socket_class_init (GMythSocketClass *klass); +static void gmyth_socket_init (GMythSocket *object); + +static void gmyth_socket_dispose (GObject *object); +static void gmyth_socket_finalize (GObject *object); + +G_DEFINE_TYPE(GMythSocket, gmyth_socket, G_TYPE_OBJECT) + +static void +gmyth_socket_class_init (GMythSocketClass *klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + + gobject_class->dispose = gmyth_socket_dispose; + gobject_class->finalize = gmyth_socket_finalize; +} + +static void +gmyth_socket_init (GMythSocket *gmyth_socket) +{ + + /* gmyth_socket->local_hostname = NULL; */ + +} + +/** Gets the some important address translation info, from the client socket + * that will open a connection. + * + * @return gint that represents the error number from getaddrinfo(). + */ +static gint +gmyth_socket_toaddrinfo (const gchar *addr, gint port, struct addrinfo **addrInfo ) +{ + struct addrinfo hints; + gchar *portStr = NULL; + gint errorn = EADDRNOTAVAIL; + + g_return_val_if_fail ( addr != NULL, -1 ); + g_debug ("Calling %s\n", __FUNCTION__); + + /* hints = g_malloc0 ( sizeof(struct addrinfo) ); */ + memset ( &hints, 0, sizeof(struct addrinfo) ); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + /* hints.ai_flags = AI_NUMERICHOST; */ + + if ( port != -1 ) + portStr = g_strdup_printf ( "%d", port ); + else + portStr = NULL; + + gmyth_debug ("Getting name resolution for: %s, %d\n", addr, port); + + if ( ( errorn = getaddrinfo(addr, portStr, &hints, addrInfo) ) != 0 ) { + g_printerr( "[%s] Socket ERROR: %s\n", __FUNCTION__, gai_strerror(errorn) ); + } + g_free (portStr); + /* g_free (hints); */ + return errorn; +} + +static gint +gmyth_socket_find_match_address_uri( GMythURI* uri, gchar *address ) { + + if ( g_ascii_strcasecmp( gmyth_uri_get_host( uri ), address ) == 0 ) { + //g_printerr( "Found URI: %s !!!\n", rui_uri_getvalue(uri) ); + return 0; + } else { + return -1; + } + +} + +static const gchar *PATH_PROC_NET_DEV = "/proc/net/dev"; + +/** Gets the list of all local network interfaces (using the /proc/net/dev directory). + * + * @param current_connections A list with all the network interfaces are valid, + * to be applied just like a filter. + * @return List with all the local net interfaces. + */ +static GList * +gmyth_socket_get_local_addrs( GList *current_connections ) +{ + + GList *local_addrs = NULL; + FILE *fd; + gint s; + gchar buffer[256+1]; + gchar ifaddr[20+1]; + gchar *ifname; + gchar *sep; + + s = socket(AF_INET, SOCK_DGRAM, 0); + if (s < 0) + return 0; + fd = fopen(PATH_PROC_NET_DEV, "r"); + fgets(buffer, sizeof(buffer)-1, fd); + fgets(buffer, sizeof(buffer)-1, fd); + while (!feof(fd)) { + ifname = buffer; + sep; + if (fgets(buffer, sizeof(buffer)-1, fd) == NULL) + break; + sep = strrchr(buffer, ':'); + if (sep) + *sep = 0; + while (*ifname == ' ') + ifname++; + struct ifreq req; + strcpy(req.ifr_name, ifname); + if (ioctl(s, SIOCGIFFLAGS, &req) < 0) + continue; + if (!(req.ifr_flags & IFF_UP)) + continue; + if (req.ifr_flags & IFF_LOOPBACK) + continue; + if (ioctl(s, SIOCGIFADDR, &req) < 0) + continue; + g_strlcpy( ifaddr, inet_ntoa(((struct sockaddr_in*)&req.ifr_addr)->sin_addr), sizeof(struct ifaddr)-1 ); + local_addrs = g_list_append( local_addrs, g_strdup( ifaddr ) ); + + gmyth_debug( "( from the /proc/net/dev) Interface name: %s, address: %s\n", + ifname, ifaddr ); + } + fclose(fd); + close(s); + return local_addrs; + +} + + +/** + * Get only the local addresses from the primary interface + */ +static gchar * +gmyth_socket_get_primary_addr() +{ + + gchar *if_eth0 = g_new0( gchar, sizeof(struct ifaddr)-1 ); + GList *if_tmp = NULL; + + GList *interfs = gmyth_socket_get_local_addrs( NULL ); + + if ( interfs != NULL && ( g_list_length( interfs ) > 0 ) ) + { + /* get the first occurrence (primary interface) */ + if_tmp = g_list_first( interfs ); + + if ( if_tmp != NULL ) + g_strlcpy (if_eth0, (gchar *)if_tmp->data, sizeof(struct ifaddr)-1 ); + + } + + if ( interfs != NULL ) + g_list_free( interfs ); + + return if_eth0; +} + +/** This function retrieves the local hostname of the + * client machine. + * + * @return GString* get local hostname. + */ +GString * +gmyth_socket_get_local_hostname () +{ + + char hname[50]; + gint res = gethostname (hname, 50); + + if (res == -1) { + g_debug ("Error while getting hostname"); + return NULL; + } + + return g_string_new (hname); + +#if 0 + GString *str = NULL; + + if ( local_hostname != NULL && strlen(local_hostname) > 0 ) + return g_string_new( local_hostname ); + + gchar *localaddr = NULL; + gboolean found_addr = FALSE; + struct addrinfo* addr_info_data = NULL, *addr_info0 = NULL; + struct sockaddr_in* sa = NULL; + gchar localhostname[MAXHOSTNAMELEN]; + + + if (gethostname (localhostname, MAXHOSTNAMELEN) != 0 ) { + gmyth_debug ( "Error on gethostname" ); + } + localhostname[MAXHOSTNAMELEN-1] = 0; + + gint err = gmyth_socket_toaddrinfo (localhostname, -1, &addr_info_data ); + + if ( err == EADDRNOTAVAIL ) + { + g_warning( "[%s] Address (%s) not available. (reason = %d)\n", __FUNCTION__, localhostname, err ); + return str; + } + + g_static_mutex_lock( &mutex ); + + addr_info0 = addr_info_data; + + while( addr_info0 != NULL && addr_info0->ai_addr != NULL && + ( sa = (struct sockaddr_in*)addr_info0->ai_addr ) != NULL && !found_addr ) { + localaddr = inet_ntoa( sa->sin_addr ); + + if ( localaddr != NULL && ( g_strrstr( localaddr, "127" ) == NULL ) ) { + str = g_string_new (localaddr); + found_addr = TRUE; + g_free (localaddr); + break; + } +/* + if (localaddr != NULL) { + g_free (localaddr); + localaddr = NULL; + } + */ + + addr_info0 = addr_info0->ai_next; + }; + + freeaddrinfo (addr_info_data); + addr_info_data = NULL; + + if ( found_addr == FALSE ) { + gchar *prim_addr = gmyth_socket_get_primary_addr(); + + if ( prim_addr != NULL ) { + g_warning("[%s] Could not determine the local alphanumerical hostname. Setting to %s\n", + __FUNCTION__, prim_addr ); + + str = g_string_new (prim_addr); + g_free (prim_addr); + } else { + str = g_string_new (localhostname); + } + } + + g_static_mutex_unlock (&mutex); + + if ( str != NULL && str->str != NULL ) + local_hostname = g_strdup( str->str ); + + return str; +#endif +} + +static void +gmyth_socket_dispose (GObject *object) +{ + GMythSocket *gmyth_socket = GMYTH_SOCKET(object); + + /* disconnect socket */ + gmyth_socket_close_connection (gmyth_socket); + + g_free (gmyth_socket->hostname); + gmyth_socket->hostname = NULL; + + g_free (local_hostname); + + local_hostname = NULL; + + G_OBJECT_CLASS (gmyth_socket_parent_class)->dispose (object); +} + +static void +gmyth_socket_finalize (GObject *object) +{ + g_signal_handlers_destroy (object); + + G_OBJECT_CLASS (gmyth_socket_parent_class)->finalize (object); +} + +/** Creates a new instance of GMythSocket. + * + * @return a new instance of GMythSocket. + */ +GMythSocket* +gmyth_socket_new () +{ + GMythSocket *gmyth_socket = GMYTH_SOCKET (g_object_new(GMYTH_SOCKET_TYPE, NULL)); + + gmyth_socket->mythtv_version = MYTHTV_VERSION_DEFAULT; + + return gmyth_socket; +} + +/** Try to open an asynchronous connection to the MythTV backend. + * + * @param fd Socket descriptor. + * @param remote Remote address. + * @param len Newly created socket length field. + * @param timeout Timeval argument with the time interval to timeout before closing. + * @param err Error message number. + * @return Any numerical value below 0, if an error had been found. + */ +static gint +gmyth_socket_try_connect ( gint fd, struct sockaddr *remote, gint len, + struct timeval *timeout, gint *err) +{ + /*g_return_val_if_fail( timeout != NULL, 0 );*/ + gint saveflags, ret, back_err; + + fd_set fd_w; + + saveflags = fcntl( fd, F_GETFL, 0 ); + if( saveflags < 0 ) { + g_warning( "[%s] Problems when getting socket flags on fcntl.\n", __FUNCTION__ ); + *err=errno; + return -1; + } + + /* Set non blocking */ + if( fcntl( fd, F_SETFL, saveflags | O_NONBLOCK ) < 0) { + g_warning( "[%s] Problems when setting non-blocking using fcntl.\n", __FUNCTION__ ); + *err=errno; + return -1; + } + + /* This will return immediately */ + *err= connect ( fd, remote, len ); + back_err=errno; + + /* restore flags */ + if( fcntl( fd, F_SETFL, saveflags ) < 0) { + g_warning( "[%s] Problems when trying to restore flags with fcntl.\n", __FUNCTION__ ); + *err=errno; + return -1; + } + + /* return unless the connection was successful or the connect is + still in progress. */ + if( *err < 0 && back_err != EINPROGRESS) { + g_warning( "[%s] Connection unsucessfully (it is not in progress).\n", __FUNCTION__ ); + *err = errno; + return -1; + } + + FD_ZERO( &fd_w ); + FD_SET( fd, &fd_w ); + + *err = select( FD_SETSIZE, NULL, &fd_w, NULL, timeout); + if ( *err < 0 ) { + g_warning( "[%s] Connection unsucessfull (timed out).\n", __FUNCTION__ ); + *err=errno; + return -1; + } + + /* 0 means it timeout out & no fds changed */ + if(*err==0) { + close(fd); + *err=ETIMEDOUT; + return -1; + } + + /* Get the return code from the connect */ + len = sizeof( ret ); + *err=getsockopt( fd, SOL_SOCKET, SO_ERROR, &ret, (socklen_t *) &len); + + if( *err < 0 ) { + g_warning( "[%s] Connection usnsucessfull.\n", __FUNCTION__ ); + *err=errno; + return -1; + } + + /* ret=0 means success, otherwise it contains the errno */ + if (ret) { + *err=ret; + return -1; + } + + *err=0; + return 0; +} + +/** Connects to the backend. + * + * @param gmyth_socket The GMythSocket instance. + * @param hostname The backend hostname or IP address. + * @param port The backend port. + * @return TRUE if success, FALSE if error. + */ + + +gboolean +gmyth_socket_connect (GMythSocket *gmyth_socket, + const gchar *hostname, gint port) +{ + return gmyth_socket_connect_with_timeout (gmyth_socket, + hostname, port, 0); +} + +gboolean +gmyth_socket_connect_with_timeout (GMythSocket *gmyth_socket, + const gchar *hostname, gint port, guint timeout) +{ + struct addrinfo *addr_info_data = NULL, *addr_info0 = NULL; + gint ret_code = -1; + gint errno; + gboolean ret = TRUE; + + gmyth_debug ("CONNECTING %s:%d", hostname, port); + + if ( hostname == NULL ) + gmyth_debug ( "Invalid hostname parameter!\n"); + + /* store hostname and port number */ + if (gmyth_socket->hostname != NULL) { + //g_free (gmyth_socket->hostname); + gmyth_socket->hostname = NULL; + } + + errno = gmyth_socket_toaddrinfo ( hostname, port, &addr_info_data ); + + g_return_val_if_fail( addr_info_data != NULL && hostname != NULL, FALSE ); + + gmyth_socket->hostname = g_strdup( hostname ); + gmyth_socket->port = port; + + for ( addr_info0 = addr_info_data; addr_info0; addr_info0 = addr_info_data->ai_next ) { + /* init socket descriptor */ + gmyth_socket->sd = socket( addr_info0->ai_family, addr_info0->ai_socktype, + addr_info0->ai_protocol ); + + if ( gmyth_socket->sd < 0 ) + continue; + + struct timeval *timeout_val = g_new0 (struct timeval, 1); + if (timeout != 0) { + /*timeout_val = g_new0 (struct timeval, 1);*/ + + timeout_val->tv_sec = timeout; + timeout_val->tv_usec = 0; + } else { + timeout_val->tv_sec = 5; + timeout_val->tv_usec = 100; + } + + if (gmyth_socket_try_connect (gmyth_socket->sd, (struct sockaddr *)addr_info0->ai_addr, + addr_info0->ai_addrlen, timeout_val, &ret_code ) < 0 ) + { + g_printerr( "[%s] Error connecting to backend!\n", __FUNCTION__ ); + if (ret_code == ETIMEDOUT) + g_printerr( "[%s]\tBackend host unreachable!\n", __FUNCTION__ ); + + close (gmyth_socket->sd); + gmyth_socket->sd = -1; + g_printerr ("ERROR: %s\n", gai_strerror(ret_code)); + g_free (timeout_val); + continue; + } + + g_free (timeout_val); + + /* only will be reached if none of the error above occurred */ + break; + } + + freeaddrinfo (addr_info_data); + addr_info_data = NULL; + + if (gmyth_socket->sd_io_ch != NULL) { + g_io_channel_unref (gmyth_socket->sd_io_ch); + gmyth_socket->sd_io_ch = NULL; + } + + gmyth_socket->sd_io_ch = g_io_channel_unix_new (gmyth_socket->sd); + + //GIOFlags flags = g_io_channel_get_flags (gmyth_socket->sd_io_ch); + /* unset the nonblock flag */ + //flags &= ~G_IO_FLAG_NONBLOCK; + /* unset the nonblocking stuff for some time, because GNUTLS doesn't like + * that */ + //g_io_channel_set_flags (gmyth_socket->sd_io_ch, flags, NULL); + + ret = ( ret_code == 0 ) ? TRUE : FALSE ; + return ret; +} + +/** Gets the GIOChannel associated to the given GMythSocket. + * + * @param gmyth_socket The GMythSocket instance. + */ +GIOChannel * +gmyth_socket_get_io_channel( GMythSocket *gmyth_socket ) +{ + g_return_val_if_fail( gmyth_socket != NULL, NULL ); + + return gmyth_socket->sd_io_ch; +} + +/** Verifies if the socket is able to read. + * + * @param gmyth_socket The GMythSocket instance. + * @return TRUE if the socket is able to read, FALSE if not. + */ +gboolean +gmyth_socket_is_able_to_read( GMythSocket *gmyth_socket ) +{ + gboolean ret = TRUE; + + /* verify if the input (read) buffer is ready to receive data */ + GIOCondition io_cond = g_io_channel_get_buffer_condition( gmyth_socket->sd_io_ch ); + + if ( ( io_cond & G_IO_IN ) == 0 ) { + g_warning ("[%s] IO channel is not able to send data!\n", __FUNCTION__); + ret = FALSE; + } + + return ret; + +} + +/** Verifies if the socket is able to write. + * + * @param gmyth_socket The GMythSocket instance. + * @return TRUE if the socket is able to write, FALSE if not. + */ +gboolean +gmyth_socket_is_able_to_write( GMythSocket *gmyth_socket ) +{ + gboolean ret = TRUE; + + /* verify if the input (read) buffer is ready to receive data */ + GIOCondition io_cond = g_io_channel_get_buffer_condition( gmyth_socket->sd_io_ch ); + + if ( ( ( io_cond & G_IO_OUT ) == 0 ) || ( ( io_cond & G_IO_HUP ) == 0 ) ) { + g_warning ("[%s] IO channel is not able to send data!\n", __FUNCTION__); + ret = FALSE; + } + + return ret; + +} + +/** Sends a command to the backend. + * + * @param gmyth_socket the GMythSocket instance. + * @param command The string command to be sent. + */ +gboolean +gmyth_socket_send_command(GMythSocket *gmyth_socket, GString *command) +{ + gboolean ret = TRUE; + + GIOStatus io_status = G_IO_STATUS_NORMAL; + //GIOCondition io_cond; + GError* error = NULL; + + + gchar *buffer = NULL; + + gsize bytes_written = 0; + + if( command == NULL || ( command->len <= 0 ) || command->str == NULL ) { + g_warning ("[%s] Invalid NULL command parameter!\n", __FUNCTION__); + ret = FALSE; + goto done; + } + + //g_static_mutex_lock( &mutex ); + gmyth_debug ("Sending command to backend: %s\n", command->str); + + buffer = g_strnfill( BUFLEN, ' ' ); + g_snprintf( buffer, MYTH_PROTOCOL_FIELD_SIZE+1, "%-8d", command->len); + + command = g_string_prepend(command, buffer); + + /* write bytes to socket */ + io_status = g_io_channel_write_chars( gmyth_socket->sd_io_ch, command->str, + command->len, &bytes_written, &error ); + + + if( (io_status == G_IO_STATUS_ERROR) || ( bytes_written <= 0 ) ) { + g_warning ("[%s] Error while writing to socket", __FUNCTION__); + ret = FALSE; + } else if ( bytes_written < command->len ) { + g_warning ("[%s] Not all data was written socket", __FUNCTION__); + ret = FALSE; + } + + io_status = g_io_channel_flush( gmyth_socket->sd_io_ch, &error ); + + if ( ( bytes_written != command->len ) || ( io_status == G_IO_STATUS_ERROR ) ) + { + g_warning ("[%s] Some problem occurred when sending data to the socket\n", __FUNCTION__); + + ret = TRUE; + } + + //g_static_mutex_unlock( &mutex ); +done: + if ( error != NULL ) { + g_printerr( "[%s] Error found reading data from IO channel: (%d, %s)\n", __FUNCTION__, error->code, error->message ); + ret = FALSE; + g_error_free( error ); + } + + if ( buffer!= NULL ) + g_free( buffer ); + + return ret; +} + +/** Starts Mythtv protocol level connection. Checks Mythtv protocol version + * supported by the backend and send the "ANN" command. + * + * @param gmyth_socket the GMythSocket instance. + * @param hostname_backend The backend hostname or IP address. + * @param port The backend port to connect. + * @param blocking_client A flag to choose between blocking and non-blocking + * @param with_events Sets the connection flag to receive events. + * backend connection. + */ +static gboolean +gmyth_socket_connect_to_backend_and_events (GMythSocket *gmyth_socket, + const gchar *hostname_backend, gint port, gboolean blocking_client, + gboolean with_events) +{ + if (!gmyth_socket_connect (gmyth_socket, hostname_backend, port)) { + g_warning ("[%s] Could not open socket to backend machine [%s]\n", __FUNCTION__, + hostname_backend ); + return FALSE; + } + + if ( gmyth_socket_check_protocol_version (gmyth_socket) ) { + + GString *result; + GString *base_str = g_string_new(""); + GString *hostname = NULL; + + hostname = gmyth_socket_get_local_hostname(); + if (hostname == NULL) { + g_debug ("Hostname not available, setting to n800frontend\n"); + hostname = g_strdup ("n800frontend"); + } + + g_string_printf(base_str, "ANN %s %s %u", + (blocking_client ? "Playback" : "Monitor"), + hostname->str, with_events); + + gmyth_socket_send_command (gmyth_socket, base_str); + result = gmyth_socket_receive_response (gmyth_socket); + + if (result != NULL) { + gmyth_debug ("Response received from backend: %s", result->str); + g_string_free (result, TRUE); + } + + g_string_free (hostname, TRUE); + g_string_free (base_str, TRUE); + + return TRUE; + } else { + g_warning ("[%s] GMythSocket could not connect to the backend", __FUNCTION__); + return FALSE; + } +} + +/** Starts Mythtv protocol level connection. Checks Mythtv protocol version + * supported by the backend and send the "ANN" command. + * + * @param gmyth_socket the GMythSocket instance. + * @param hostname_backend The backend hostname or IP address. + * @param port The backend port to connect. + * @param blocking_client A flag to choose between blocking and non-blocking + */ +gboolean +gmyth_socket_connect_to_backend (GMythSocket *gmyth_socket, + const gchar *hostname_backend, gint port, gboolean blocking_client) +{ + if (!gmyth_socket_connect_to_backend_and_events ( gmyth_socket, hostname_backend, port, + blocking_client, FALSE) ) { + gmyth_debug ("Could not open socket to backend machine [%s]\n", + hostname_backend ); + return FALSE; + } + + return TRUE; + +} + +/** Starts Mythtv protocol level connection. Checks Mythtv protocol version + * supported by the backend and send the "ANN" command. + * + * @param gmyth_socket the GMythSocket instance. + * @param hostname_backend The backend hostname or IP address. + * @param port The backend port to connect. + * @param blocking_client A flag to choose between blocking and non-blocking + */ +gboolean +gmyth_socket_connect_to_backend_events (GMythSocket *gmyth_socket, + const gchar *hostname_backend, gint port, gboolean blocking_client) +{ + if (!gmyth_socket_connect_to_backend_and_events ( gmyth_socket, hostname_backend, port, + blocking_client, TRUE) ) { + gmyth_debug ("Could not open socket to backend machine in order to receive events [%s]\n", + hostname_backend ); + return FALSE; + } + + return TRUE; +} + +/** Closes the socket connection to the backend. + * + * @param gmyth_socket The GMythSocket instance. + */ +void +gmyth_socket_close_connection (GMythSocket *gmyth_socket) +{ + close (gmyth_socket->sd); + gmyth_socket->sd = -1; + + if (gmyth_socket->sd_io_ch != NULL) { + g_io_channel_unref (gmyth_socket->sd_io_ch); + gmyth_socket->sd_io_ch = NULL; + } +} + + +/** Try the MythTV version numbers, and get the version returned by + * the possible REJECT message, in order to contruct a new + * MythTV version request. + * + * @param gmyth_socket The GMythSocket instance. + * @param mythtv_version The Mythtv protocol version to be tested + * + * @return The actual MythTV the client is connected to. + */ +gint +gmyth_socket_check_protocol_version_number (GMythSocket *gmyth_socket, gint mythtv_version) +{ + GString *response = NULL; + GString *payload = NULL; + gboolean res = TRUE; + gint mythtv_new_version = MYTHTV_CANNOT_NEGOTIATE_VERSION; + guint max_iterations = MYTHTV_MAX_VERSION_CHECKS; + +try_new_version: + payload = g_string_new ("MYTH_PROTO_VERSION"); + g_string_append_printf( payload, " %d", mythtv_version ); + + gmyth_socket_send_command(gmyth_socket, payload); + response = gmyth_socket_receive_response(gmyth_socket); + + if (response == NULL) { + g_warning ("[%s] Check protocol version error! Not answered!", __FUNCTION__); + res = FALSE; + goto done; + } + + res = g_str_has_prefix (response->str, "ACCEPT"); + if (!res) { + g_warning ("[%s] Protocol version request error: %s", __FUNCTION__, response->str); + /* get the version number returned by the REJECT message */ + if ( ( res = g_str_has_prefix (response->str, "REJECT") ) == TRUE ) { + gchar *new_version = NULL; + new_version = g_strrstr( response->str, "]" ); + if (new_version!=NULL) { + ++new_version; /* skip ']' character */ + if ( new_version != NULL ) { + gmyth_debug ( "[%s] got MythTV version = %s.\n", __FUNCTION__, new_version ); + mythtv_version = (gint)g_ascii_strtoull (new_version, NULL, 10 ); + /* do reconnection to the socket (socket is closed if the MythTV version was wrong) */ + gmyth_socket_connect( gmyth_socket, gmyth_socket->hostname, gmyth_socket->port ); + new_version =NULL; + if ( --max_iterations > 0 ) + goto try_new_version; + else + goto done; + } + } + } + } + + /* change the return value to a valid one */ + if ( res ) { + mythtv_new_version = mythtv_version; + gmyth_socket->mythtv_version = mythtv_new_version; + } + +done: + if ( payload != NULL ) + g_string_free (payload, TRUE); + if ( response != NULL ) + g_string_free (response, TRUE); + + return mythtv_new_version; +} + +/** Verifies if the Mythtv backend supported the GMyth supported version. + * + * @param gmyth_socket The GMythSocket instance. + * @return TRUE if supports, FALSE if not. + */ +gboolean +gmyth_socket_check_protocol_version (GMythSocket *gmyth_socket) +{ + return ( ( gmyth_socket->mythtv_version = + gmyth_socket_check_protocol_version_number ( gmyth_socket, + MYTHTV_VERSION_DEFAULT ) ) != MYTHTV_CANNOT_NEGOTIATE_VERSION ); +} + +/** Returns the Mythtv backend supported version. + * + * @param gmyth_socket The GMythSocket instance. + * @return The actual MythTV version number. + */ +gint +gmyth_socket_get_protocol_version (GMythSocket *gmyth_socket) +{ + return gmyth_socket->mythtv_version; +} + +/** Receives a backend answer after a gmyth_socket_send_command_call (). + * + * @param gmyth_socket The GMythSocket instance. + * @return The response received, or NULL if error or nothing was received. + */ +GString* +gmyth_socket_receive_response(GMythSocket *gmyth_socket) +{ + GIOStatus io_status = G_IO_STATUS_NORMAL; + GError* error = NULL; + gchar *buffer; + + GString *str = NULL; + + gsize bytes_read = 0; + gint len = 0; + GIOCondition io_cond = g_io_channel_get_buffer_condition (gmyth_socket->sd_io_ch); + + g_return_val_if_fail( gmyth_socket != NULL, NULL ); + + /* verify if the input (read) buffer is ready to receive data */ + + //g_static_mutex_lock( &mutex ); + + //buffer = g_new0 (gchar, MYTH_PROTOCOL_FIELD_SIZE); + buffer = g_strnfill (MYTH_PROTOCOL_FIELD_SIZE, ' '); + io_status = g_io_channel_read_chars (gmyth_socket->sd_io_ch, buffer, MYTH_PROTOCOL_FIELD_SIZE, &bytes_read, &error); + + /* verify if the input (read) buffer is ready to receive data */ + io_cond = g_io_channel_get_buffer_condition (gmyth_socket->sd_io_ch); + + gmyth_debug ( "[%s] Bytes read = %d\n", __FUNCTION__, bytes_read ); + + if( (io_status == G_IO_STATUS_ERROR) || (bytes_read <= 0) ) { + g_warning ("[%s] Error in mythprotocol response from backend\n", __FUNCTION__); + str = NULL; + //return NULL; + } else { + + io_status = g_io_channel_flush( gmyth_socket->sd_io_ch, &error ); + /* verify if the input (read) buffer is ready to receive data */ + io_cond = g_io_channel_get_buffer_condition( gmyth_socket->sd_io_ch ); + + //if ( ( io_cond & G_IO_IN ) != 0 ) { + //gchar *buffer_aux = NULL; + + /* removes trailing whitespace */ + //buffer_aux = g_strstrip (buffer); + len = (gint)g_ascii_strtoull ( g_strstrip (buffer), NULL, 10 ); + + if (buffer != NULL) { + g_free (buffer); + buffer = NULL; + } + + /* + if (buffer_aux != NULL) { + g_free (buffer_aux); + buffer_aux = NULL; + } + */ + + buffer = g_new0 (gchar, len+1); + + bytes_read = 0; + io_status = g_io_channel_read_chars( gmyth_socket->sd_io_ch, buffer, len, &bytes_read, &error); + buffer[bytes_read] = '\0'; + //} + } + + //g_static_mutex_unlock( &mutex ); + + gmyth_debug ("Response received from backend: {%s}\n", buffer); + + if ( ( bytes_read != len ) || ( io_status == G_IO_STATUS_ERROR ) ) + str = NULL; + else + str = g_string_new (buffer); + + if ( error != NULL ) { + g_printerr( "[%s] Error found receiving response from the IO channel: (%d, %s)\n", __FUNCTION__, error->code, error->message ); + str = NULL; + g_error_free (error); + } + + g_free (buffer); + return str; +} + +/** Format a Mythtv command from the str_list entries and send it to backend. + * + * @param gmyth_socket The GMythSocket instance. + * @param str_list The string list to form the command + * @return TRUE if command was sent, FALSE if any error happens. + */ +gboolean +gmyth_socket_write_stringlist(GMythSocket *gmyth_socket, GMythStringList* str_list) +{ + + GList *tmp_list = NULL; + GPtrArray *ptr_array = NULL; + gchar *str_array = NULL; + + g_static_mutex_lock( &mutex ); + + ptr_array = g_ptr_array_sized_new (g_list_length(str_list->glist)); + + // FIXME: change this implementation! + tmp_list = str_list->glist; + for(; tmp_list; tmp_list = tmp_list->next) { + if ( tmp_list->data != NULL ) { + g_ptr_array_add(ptr_array, ((GString*)tmp_list->data)->str); + } else { + g_ptr_array_add (ptr_array, ""); + } + } + g_ptr_array_add(ptr_array, NULL); // g_str_joinv() needs a NULL terminated string + + str_array = g_strjoinv (MYTH_SEPARATOR, (gchar **) (ptr_array->pdata)); + + g_static_mutex_unlock( &mutex ); + + gmyth_debug ( "[%s] Sending socket request: %s\n", __FUNCTION__, str_array ); + + // Sends message to backend + // TODO: implement looping to send remaining data, and add timeout testing! + GString *command = g_string_new(str_array); + gmyth_socket_send_command(gmyth_socket, command); + g_string_free (command, TRUE); + + g_free (str_array); + g_ptr_array_free (ptr_array, TRUE); + + return TRUE; +} + +/* Receives a backend command response and split it into the given string list. + * + * @param gmyth_socket The GMythSocket instance. + * @param str_list the string list to be filled. + * @return The number of received strings. + */ +gint +gmyth_socket_read_stringlist (GMythSocket *gmyth_socket, GMythStringList* str_list) +{ + GString *response; + gchar **str_array; + gint i; + + response = gmyth_socket_receive_response(gmyth_socket); + g_static_mutex_lock( &mutex ); + + gmyth_string_list_clear_all (str_list); + str_array = g_strsplit (response->str, MYTH_SEPARATOR, -1); + + for (i=0; i< g_strv_length (str_array); i++) { + gmyth_string_list_append_char_array (str_list, str_array[i] ); + } + g_static_mutex_unlock( &mutex ); + + g_string_free (response, TRUE); + g_strfreev (str_array); + + return gmyth_string_list_length (str_list); +} + +/** Formats a Mythtv protocol command based on str_list and sends it to + * the connected backend. The backend response is overwritten into str_list. + * + * @param gmyth_socket The GMythSocket instance. + * @param str_list The string list to be sent, and on which the answer + * will be written. + * @return TRUE if command was sent and an answer was received, FALSE if any + * error happens. + */ +gint +gmyth_socket_sendreceive_stringlist (GMythSocket *gmyth_socket, GMythStringList *str_list) +{ + gmyth_socket_write_stringlist (gmyth_socket, str_list); + + return gmyth_socket_read_stringlist (gmyth_socket, str_list); +} diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_socket.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_socket.h Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,130 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_socket.h + * + * @brief

MythTV socket implementation, according to the MythTV Project + * (www.mythtv.org). + * + * This component provides basic socket functionalities to interact with + * the Mythtv backend. + *

+ * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Rosfran Lins Borges + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GMYTH_SOCKET_H__ +#define __GMYTH_SOCKET_H__ + +#include + +#include +#include +#include +#include +#include + +#include "gmyth_stringlist.h" + +G_BEGIN_DECLS + +#define GMYTH_SOCKET_TYPE (gmyth_socket_get_type ()) +#define GMYTH_SOCKET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_SOCKET_TYPE, GMythSocket)) +#define GMYTH_SOCKET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_SOCKET_TYPE, GMythSocketClass)) +#define IS_GMYTH_SOCKET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_SOCKET_TYPE)) +#define IS_GMYTH_SOCKET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_SOCKET_TYPE)) +#define GMYTH_SOCKET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_SOCKET_TYPE, GMythSocketClass)) + + +typedef struct _GMythSocket GMythSocket; +typedef struct _GMythSocketClass GMythSocketClass; + +struct _GMythSocketClass +{ + GObjectClass parent_class; + + /* callbacks */ + /* no one for now */ +}; + +struct _GMythSocket +{ + GObject parent; + + /* socket descriptor */ + gint sd; + GIOChannel *sd_io_ch; + + gchar *hostname; + gint port; + gint mythtv_version; +}; + +/* used when no protocol version number was negotiated */ +#define MYTHTV_CANNOT_NEGOTIATE_VERSION 0 + +GType gmyth_socket_get_type (void); + +GMythSocket * gmyth_socket_new (); + +gboolean gmyth_socket_connect (GMythSocket *gmyth_socket, const gchar *hostname, gint port); + + +GIOChannel * gmyth_socket_get_io_channel (GMythSocket *gmyth_socket ); + +gboolean gmyth_socket_is_able_to_read (GMythSocket *gmyth_socket ); +gboolean gmyth_socket_is_able_to_write (GMythSocket *gmyth_socket ); + +gboolean gmyth_socket_send_command (GMythSocket *gmyth_socket, + GString *command); +GString * gmyth_socket_receive_response (GMythSocket *gmyth_socket); +gint gmyth_socket_sendreceive_stringlist (GMythSocket *gmyth_socket, + GMythStringList *str_list); + +gboolean gmyth_socket_connect (GMythSocket *gmyth_socket, + const gchar *hostname, gint port); +gboolean gmyth_socket_connect_with_timeout (GMythSocket *gmyth_socket, + const gchar *hostname, gint port, guint timeout); + +gboolean gmyth_socket_connect_to_backend (GMythSocket *gmyth_socket, + const gchar *hostname_backend, gint port, + gboolean blocking_client); + +gboolean gmyth_socket_connect_to_backend_events (GMythSocket *gmyth_socket, + const gchar *hostname_backend, gint port, + gboolean blocking_client); + +GString * gmyth_socket_get_local_hostname (void); + +void gmyth_socket_close_connection (GMythSocket *gmyth_socket); + +gboolean gmyth_socket_check_protocol_version (GMythSocket *gmyth_socket); +gint gmyth_socket_check_protocol_version_number (GMythSocket *gmyth_socket, + gint mythtv_version); + +gint gmyth_socket_get_protocol_version (GMythSocket *gmyth_socket); + +gboolean gmyth_socket_write_stringlist(GMythSocket *gmyth_socket, + GMythStringList* str_list); +gint gmyth_socket_read_stringlist(GMythSocket *gmyth_socket, + GMythStringList* str_list); +G_END_DECLS + +#endif /* __GMYTH_SOCKET_H__ */ diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_stringlist.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_stringlist.c Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,390 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_stringlist.c + * + * @brief

This component contains functions for dealing with the stringlist + * format of the mythprotocol. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Hallyson Luiz de Morais Melo + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gmyth_stringlist.h" + +#include "gmyth_debug.h" + +static void gmyth_string_list_class_init (GMythStringListClass *klass); +static void gmyth_string_list_init (GMythStringList *object); + +static void gmyth_string_list_dispose (GObject *object); +static void gmyth_string_list_finalize (GObject *object); + +G_DEFINE_TYPE(GMythStringList, gmyth_string_list, G_TYPE_OBJECT) + +static void +gmyth_string_list_class_init (GMythStringListClass *klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + + gobject_class->dispose = gmyth_string_list_dispose; + gobject_class->finalize = gmyth_string_list_finalize; +} + +static void +gmyth_string_list_init (GMythStringList *gmyth_string_list) +{ + gmyth_string_list->glist = NULL; +} + +static void +gmyth_string_list_dispose (GObject *object) +{ + GMythStringList *gmyth_string_list = GMYTH_STRING_LIST(object); + + if (gmyth_string_list->glist) + gmyth_string_list_clear_all(gmyth_string_list); + + G_OBJECT_CLASS (gmyth_string_list_parent_class)->dispose (object); +} + +static void +gmyth_string_list_finalize (GObject *object) +{ + //GMythStringList *gmyth_string_list = GMYTH_STRING_LIST(object); + + g_signal_handlers_destroy (object); + + G_OBJECT_CLASS (gmyth_string_list_parent_class)->finalize (object); +} + +/** Creates a new instance of GStringList. + * + * @return a new instance of GStringList. + */ +GMythStringList * +gmyth_string_list_new () +{ + GMythStringList *gmyth_string_list = GMYTH_STRING_LIST (g_object_new (GMYTH_STRING_LIST_TYPE, NULL)); + return gmyth_string_list; +} + +/** Appends a guint64 to the string list. + * + * @param strlist The GMythStringList instance. + * @param value The guint64 to be appended. + * + * @return The appended guint64 converted to a GString object. + */ +GString* +gmyth_string_list_append_int ( GMythStringList *strlist, const gint value ) +{ + GString *tmp_str = g_string_new (""); + + g_string_printf (tmp_str, "%d", value); + + gmyth_string_list_append_string (strlist, tmp_str); + + return tmp_str; +} + +/** Appends a guint64 to the string list. + * + * @param strlist The GMythStringList instance. + * @param value The guint64 to be appended. + * + * @return The appended guint64 converted to a GString object. + */ +GString* +gmyth_string_list_append_uint64 ( GMythStringList *strlist, const guint64 value) +{ + GString *tmp_str1 = g_string_new (""); + GString *tmp_str2 = g_string_new (""); + gmyth_debug ( "value = %llu.\n", value); + + gulong l2 = ( (guint64)value & 0xffffffff ); + gulong l1 = ( (guint64)value >> 32 ); + + /* high order part of guint64 value */ + g_string_printf (tmp_str1, "%lu", l1); + + gmyth_debug( "[%s] uint64 (high) = %s\n", __FUNCTION__, tmp_str1->str ); + + //gmyth_string_list_append_string (strlist, tmp_str1); + strlist->glist = g_list_append( strlist->glist, tmp_str1 ); + + /* low order part of guint64 value */ + g_string_printf (tmp_str2, "%lu", l2); + + gmyth_debug( "[%s] uint64 (low) = %s\n", __FUNCTION__, tmp_str2->str ); + + strlist->glist = g_list_append( strlist->glist, tmp_str2 ); + + //gmyth_string_list_append_string (strlist, tmp_str2); + + return tmp_str2; +} + +/** Appends a gint64 to the string list. + * + * @param strlist The GMythStringList instance. + * @param value The gint64 to be appended. + * + * @return The appended gint64 converted to a GString object. + */ +GString* +gmyth_string_list_append_int64 ( GMythStringList *strlist, const gint64 value) +{ + GString *tmp_str1 = g_string_new (""); + GString *tmp_str2 = g_string_new (""); + gmyth_debug ( "value = %lld.\n", value ); + + glong l2 = ( (gint64)value & 0xffffffff ); + glong l1 = ( (gint64)value >> 32 ); + + /* high order part of gint64 value */ + g_string_printf (tmp_str1, "%ld", l1); + + gmyth_debug( "[%s] int64 (high) = %s\n", __FUNCTION__, tmp_str1->str ); + + //gmyth_string_list_append_string (strlist, tmp_str1); + strlist->glist = g_list_append( strlist->glist, tmp_str1 ); + + /* low order part of gint64 value */ + g_string_printf (tmp_str2, "%ld", l2); + + gmyth_debug( "[%s] int64 (low) = %s\n", __FUNCTION__, tmp_str2->str ); + + strlist->glist = g_list_append( strlist->glist, tmp_str2 ); + + return tmp_str2; +} + +/** Appends a char array to the string list. + * + * @param strlist The GMythStringList instance. + * @param value The char array to be appended. + * + * @return The appended char array converted to a GString object. + */ +GString* +gmyth_string_list_append_char_array ( GMythStringList *strlist, const gchar* value ) +{ + GString *tmp_str = NULL; + + g_return_val_if_fail( strlist != NULL, NULL ); + + tmp_str = g_string_new (value); + + g_return_val_if_fail( tmp_str != NULL, NULL ); + + gmyth_string_list_append_string (strlist, tmp_str); + + return tmp_str; +} + +/** Appends a string to the string list. + * + * @param strlist The GMythStringList instance. + * @param value The string to be appended. + * + * @return The appended string itself. + */ +GString* +gmyth_string_list_append_string ( GMythStringList *strlist, GString *value ) +{ + g_return_val_if_fail( strlist != NULL, NULL ); + + strlist->glist = g_list_append (strlist->glist, value); + + return value; +} + +/** Gets an integer value from the string list at the given position. + * + * @param strlist The GMythStringList instance. + * @param index the integer position in the list, starting with zero. + * @return The integer value. + */ +gint +gmyth_string_list_get_int ( GMythStringList *strlist, const gint index ) +{ + //TODO: Create static method check_index() + GString *tmp_str = NULL; + + g_return_val_if_fail( strlist != NULL, 0 ); + + tmp_str = (GString *) g_list_nth_data (strlist->glist, index); + + g_return_val_if_fail( tmp_str != NULL && tmp_str->str != NULL, 0 ); + + return (gint) ( /* 0x00000000ffffffffL & (gint64)*/g_ascii_strtoull ( tmp_str->str, NULL, 10 ) ); +} + +/** Gets a guint64 value from the string list at the given position. + * According to the Mythtv protocol, the 64 bits value is formed by + * two strings. + * + * @param strlist The GMythStringList instance. + * @param index the index of the first string forming the 64 bits value. + * Index starts with zero. + * @return The guint64 value. + */ +guint64 +gmyth_string_list_get_uint64 ( GMythStringList *strlist, const gint index ) +{ + //TODO: Create static method check_index() + guint64 ret_value = 0; + guint64 l2 = 0; + + g_return_val_if_fail( strlist != NULL, 0 ); + + const GString *tmp_str1 = (GString *) g_list_nth_data (strlist->glist, index); + const GString *tmp_str2 = (GString *) g_list_nth_data (strlist->glist, index+1); + + if ( tmp_str1 != NULL ) + gmyth_debug ( "[%s] seek high bytes = %s\n", __FUNCTION__, tmp_str1->str ); + if ( tmp_str2 == NULL || strlen( tmp_str2->str ) > 0 ) { + } else { + gmyth_debug ( "[%s] seek low bytes = %s\n", __FUNCTION__, tmp_str2->str ); + } + + guint64 l1 = ( (guint64)g_ascii_strtoull (tmp_str1->str, NULL, 10) /*& 0xffffffff*/ ); + if ( tmp_str2 != NULL && tmp_str2->str != NULL && strlen(tmp_str2->str) > 0 ) { + l2 = ( (guint64)g_ascii_strtoull (tmp_str2->str, NULL, 10) /*& 0xffffffff*/ ); + } else { + l2 = l1; + l1 = 0; + } + + gmyth_debug ( "[%s]\t[l1 == %llu, l2 == %llu]\n", __FUNCTION__, l1, l2 ); + + ret_value = ((guint64)(l2) /*& 0xffffffff*/) | ((guint64)l1 << 32); + + gmyth_debug( "[%s] returning uint64 value = %llu\n", __FUNCTION__, ret_value ); + + return ret_value; +} + +/** Gets a gint64 value from the string list at the given position. + * According to the Mythtv protocol, the 64 bits value is formed by + * two strings. + * + * @param strlist The GMythStringList instance. + * @param index the index of the first string forming the 64 bits value. + * Index starts with zero. + * @return The gint64 value. + */ +gint64 +gmyth_string_list_get_int64 ( GMythStringList *strlist, const gint index ) +{ + //TODO: Create static method check_index() + gint64 ret_value = 0; + gint64 l2 = 0; + + g_return_val_if_fail( strlist != NULL, 0 ); + + const GString *tmp_str1 = (GString *) g_list_nth_data (strlist->glist, index); + const GString *tmp_str2 = (GString *) g_list_nth_data (strlist->glist, index+1); + + if ( tmp_str1 != NULL ) + gmyth_debug ( "[%s] seek high bytes = %s\n", __FUNCTION__, tmp_str1->str ); + if ( tmp_str2 == NULL || strlen( tmp_str2->str ) > 0 ) { + } else { + gmyth_debug ( "[%s] seek low bytes = %s\n", __FUNCTION__, tmp_str2->str ); + } + + gint64 l1 = ( (guint64)g_ascii_strtoull (tmp_str1->str, NULL, 10) /*& 0xffffffff*/ ); + if ( tmp_str2 != NULL && tmp_str2->str != NULL && strlen(tmp_str2->str) > 0 ) { + l2 = ( (gint64)g_ascii_strtoull (tmp_str2->str, NULL, 10) /*& 0xffffffff*/ ); + } else { + l2 = l1; + l1 = 0; + } + + gmyth_debug ( "[%s]\t[l1 == %lld, l2 == %lld]\n", __FUNCTION__, l1, l2 ); + + ret_value = ((gint64)(l2) /*& 0xffffffff*/) | ((gint64)l1 << 32); + + gmyth_debug( "[%s] returning int64 value = %lld\n", __FUNCTION__, ret_value ); + + return ret_value; +} + + +/** Gets a string from the string list at the given position. + * + * @param strlist The GMythStringList instance. + * @param index the string position in the list, starting with zero. + * @return A pointer to the string data. + */ +GString* +gmyth_string_list_get_string ( GMythStringList *strlist, const gint index ) +{ + if (!strlist || !(strlist->glist)) { + g_warning ("%s received Null arguments", __FUNCTION__); + return NULL; + } + + return (GString *) g_list_nth_data (strlist->glist, index); +} + + +#if 0 +static void +gmyth_string_list_clear_element( GString *str_elem, void *data_aux ) +{ + if ( str_elem != NULL ) { + g_string_free( str_elem, TRUE ); + } +} +#endif + +/** Removes all strings from the string list. + * + * @param strlist The GMythStringList instance. + */ +void +gmyth_string_list_clear_all ( GMythStringList *strlist ) +{ + if ( strlist != NULL && strlist->glist ) { + //g_list_foreach( strlist->glist, (GFunc)gmyth_string_list_clear_element, NULL ); + g_list_free (strlist->glist); + strlist->glist = NULL; + } +} + +/** Retrieves the number of elements in the string list. + * + * @param strlist The GMythStringList instance. + * @return the string list length. + */ +gint +gmyth_string_list_length ( GMythStringList *strlist ) +{ + g_return_val_if_fail( strlist != NULL && strlist->glist != NULL, 0 ); + + return g_list_length (strlist->glist); +} diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_stringlist.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_stringlist.h Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,101 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_stringlist.h + * + * @brief

This component contains functions for dealing with the stringlist + * format of the mythprotocol. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Hallyson Luiz de Morais Melo + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef GMYTH_STRING_LIST_H_ +#define GMYTH_STRING_LIST_H_ + +#include + +#include +#include +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define GMYTH_STRING_LIST_TYPE (gmyth_string_list_get_type ()) +#define GMYTH_STRING_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_STRING_LIST_TYPE, GMythStringList)) +#define GMYTH_STRING_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_STRING_LIST_TYPE, GMythStringListClass)) +#define IS_GMYTH_STRING_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_STRING_LIST_TYPE)) +#define IS_GMYTH_STRING_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_STRING_LIST_TYPE)) +#define GMYTH_STRING_LIST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_STRING_LIST_TYPE, GMythStringListClass)) + + +typedef struct _GMythStringList GMythStringList; +typedef struct _GMythStringListClass GMythStringListClass; + +struct _GMythStringListClass +{ + GObjectClass parent_class; + + /* callbacks */ + /* no one for now */ +}; + +struct _GMythStringList +{ + GObject parent; + + /* string list */ + GList *glist; +}; + + +GType gmyth_string_list_get_type (void); + +GMythStringList * gmyth_string_list_new (void); + +void gmyth_string_list_clear_all (GMythStringList *strlist); +int gmyth_string_list_length (GMythStringList *strlist); + +GString * gmyth_string_list_append_int (GMythStringList *strlist, + const gint value); +GString * gmyth_string_list_append_uint64 (GMythStringList *strlist, + const guint64 value); + +GString * gmyth_string_list_append_int64 (GMythStringList *strlist, + const gint64 value); + +GString * gmyth_string_list_append_char_array (GMythStringList *strlist, + const char* value); +GString * gmyth_string_list_append_string (GMythStringList *strlist, + GString *value); + +int gmyth_string_list_get_int (GMythStringList *strlist, const gint index); +guint64 gmyth_string_list_get_uint64 (GMythStringList *strlist, const gint index); +gint64 gmyth_string_list_get_int64 (GMythStringList *strlist, const gint index); +GString * gmyth_string_list_get_string (GMythStringList *strlist, const gint index); + +#define gmyth_string_list_get_char_array(strlist, index) \ + (gmyth_string_list_get_string(strlist, index))->str + +G_END_DECLS + +#endif /*GMYTH_STRING_LIST_H_*/ diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_tvchain.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_tvchain.c Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,390 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_tvchain.c + * + * @brief

This component contains functions for creating and accessing + * the tvchain functions for live tv playback. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Hallyson Luiz de Morais Melo + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gmyth_tvchain.h" + +#include +#include +#include +#include +#include + +#include "gmyth_epg.h" +#include "gmyth_util.h" +#include "gmyth_query.h" +#include "gmyth_scheduler.h" +#include "gmyth_debug.h" + +static void gmyth_tvchain_class_init (GMythTVChainClass *klass); +static void gmyth_tvchain_init (GMythTVChain *object); + +static void gmyth_tvchain_dispose (GObject *object); +static void gmyth_tvchain_finalize (GObject *object); + +G_DEFINE_TYPE(GMythTVChain, gmyth_tvchain, G_TYPE_OBJECT) + +static GStaticMutex mutex = G_STATIC_MUTEX_INIT; + +static void +gmyth_tvchain_class_init (GMythTVChainClass *klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + + gobject_class->dispose = gmyth_tvchain_dispose; + gobject_class->finalize = gmyth_tvchain_finalize; +} + +static void +gmyth_tvchain_init (GMythTVChain *tvchain) +{ + tvchain->tvchain_id = NULL; + + tvchain->cur_chanid = g_string_new (""); + tvchain->cur_startts = NULL; +} + +static void +gmyth_tvchain_dispose (GObject *object) +{ + GMythTVChain *tvchain = GMYTH_TVCHAIN(object); + + if ( tvchain->tvchain_id != NULL ) { + g_string_free( tvchain->tvchain_id, TRUE ); + tvchain->tvchain_id = NULL; + } + + if ( tvchain->tvchain_list != NULL ) { + g_list_free( tvchain->tvchain_list ); + tvchain->tvchain_list = NULL; + } + + if ( tvchain->cur_chanid != NULL ) { + g_string_free( tvchain->cur_chanid, TRUE ); + tvchain->cur_chanid = NULL; + } + + if ( tvchain->backend_info) { + g_object_unref (tvchain->backend_info); + tvchain->backend_info = NULL; + } + + + G_OBJECT_CLASS (gmyth_tvchain_parent_class)->dispose (object); +} + +static void +gmyth_tvchain_finalize (GObject *object) +{ + g_signal_handlers_destroy (object); + + G_OBJECT_CLASS (gmyth_tvchain_parent_class)->finalize (object); +} + +/** Initializes the tvchain and generates the tvchain id. + * + * @param tvchain The GMythTVChain instance. + * @param hostname The local hostname used to generate the tvchain id. + */ +gboolean +gmyth_tvchain_initialize (GMythTVChain *tvchain, GMythBackendInfo *backend_info) +{ + const char *hostname; + + assert (tvchain); + g_return_val_if_fail (backend_info != NULL, FALSE); + + g_object_ref (backend_info); + tvchain->backend_info = backend_info; + + hostname = gmyth_backend_info_get_hostname (backend_info); + + if (tvchain->tvchain_id == NULL) { + gchar *isodate = NULL; + GTimeVal *cur_time = g_new0( GTimeVal, 1 ); + //struct tm* gmyth_util_time_val_to_date ( const GTimeVal* time ) + + g_get_current_time(cur_time); + isodate = gmyth_util_time_to_isoformat_from_time_val_fmt ( "%Y-%m-%dT%H:%M:%S", cur_time ); + + tvchain->tvchain_id = g_string_sized_new (7 + strlen (hostname) + strlen(isodate)); + g_string_printf(tvchain->tvchain_id, + "live-%s-%s", hostname, isodate); + + gmyth_debug ("[%s] tv_chain_id: %s", __FUNCTION__, tvchain->tvchain_id->str); + + if (isodate) + g_free(isodate); + + if ( cur_time ) + g_free( cur_time ); + } else { + g_warning ("[%s] TVchain already initialized", __FUNCTION__); + } + + return TRUE; +} + +/** Gets the tvchain id. + * + * @param tvchain The GMythTVChain instance. + * @return The tvchain id. + */ +GString* +gmyth_tvchain_get_id (GMythTVChain *tvchain) +{ + g_return_val_if_fail( tvchain != NULL && tvchain->tvchain_id != NULL, NULL ); + + return g_string_new (tvchain->tvchain_id->str); +} + +/** Reloads all tvchain entries in the database. + * + * @param tvchain The GMythTVChain instance. + * @return TRUE if success, or FALSE if error. + */ +gboolean +gmyth_tvchain_reload_all (GMythTVChain *tvchain) +{ + MYSQL_ROW msql_row; + MYSQL_RES *msql_res = NULL; + GMythQuery *gmyth_query = NULL; + gboolean ret = TRUE; + GString *stmt_str = NULL; + + g_static_mutex_lock( &mutex ); + + /* gets the initial size of the TVChain entries list */ + guint prev_size = g_list_length (tvchain->tvchain_list); + + gmyth_debug ("[%s] chainid: %s", __FUNCTION__, tvchain->tvchain_id->str); + + if ( tvchain != NULL && tvchain->tvchain_list != NULL ) { + g_list_free (tvchain->tvchain_list); + tvchain->tvchain_list = NULL; + } + + // TODO: Reuse gmyth_query already connected from context + gmyth_query = gmyth_query_new (); + if (!gmyth_query_connect (gmyth_query, tvchain->backend_info)) { + g_warning ("[%s] Could not connect to db", __FUNCTION__); + g_static_mutex_unlock( &mutex ); + ret = FALSE; + goto done; + } + + stmt_str = g_string_new (""); + g_string_printf (stmt_str, + "SELECT chanid, starttime, endtime, discontinuity, " + "chainpos, hostprefix, cardtype, channame, input " + "FROM tvchain " + "WHERE chainid = \"%s\" ORDER BY chainpos;", + tvchain->tvchain_id->str); + + msql_res = gmyth_query_process_statement(gmyth_query, stmt_str->str); + if (msql_res != NULL) { + + while ((msql_row = mysql_fetch_row (msql_res)) != NULL) { + struct LiveTVChainEntry *entry = g_new0 (struct LiveTVChainEntry, 1); + entry->chanid = g_string_new (msql_row[0]); + entry->starttime = gmyth_util_string_to_time_val ((const gchar*) msql_row[1]); + entry->endtime = gmyth_util_string_to_time_val ((const gchar*) msql_row[2]); + entry->discontinuity = g_ascii_strtoull (msql_row[3], NULL, 10 ) != 0; + entry->hostprefix = g_string_new (msql_row[5]); + entry->cardtype = g_string_new (msql_row[6]); + entry->channum = g_string_new (msql_row[7]); + entry->inputname = g_string_new (msql_row[8]); + + //m_maxpos = query.value(4).toInt() + 1; + g_print( "[%s] Reading TV chain entry (channel %s): [%s, %s, %s]\n", __FUNCTION__, entry->channum->str, entry->chanid->str, + (gchar*)msql_row[1], (gchar*)msql_row[2] ); + + /* add this to get the actual start timestamp of the last recording */ + if ( tvchain->cur_startts < entry->starttime ) + tvchain->cur_startts = entry->starttime; + + tvchain->tvchain_list = g_list_append (tvchain->tvchain_list, entry); + } + } else { + g_warning ("gmyth_tvchain_reload_all query error!\n"); + g_static_mutex_unlock( &mutex ); + + ret = FALSE; + goto done; + } + + g_static_mutex_unlock( &mutex ); + + tvchain->cur_pos = gmyth_tvchain_program_is_at (tvchain, tvchain->cur_chanid, tvchain->cur_startts); + g_print( "[%s] TVChain current position = %d.\n", __FUNCTION__, tvchain->cur_pos ); + + if (tvchain->cur_pos < 0) + tvchain->cur_pos = 0; + + // if (m_switchid >= 0) + // m_switchid = ProgramIsAt(m_switchentry.chanid,m_switchentry.starttime); + + if (prev_size != g_list_length (tvchain->tvchain_list)) { + gmyth_debug ("[%s] Added new recording", __FUNCTION__); + } + +done: + if ( stmt_str != NULL ) + g_string_free (stmt_str, TRUE); + + if ( msql_res != NULL ) + mysql_free_result (msql_res); + + if ( gmyth_query != NULL ) + g_object_unref (gmyth_query); + + return ret; +} + +/** Returns the internal index for the TV chain related to the given + * channel and start time. + * + * @param tvchain The GMythTVChain instance. + * @param chanid The channel id. + * @param startts The program start time. + */ +gint +gmyth_tvchain_program_is_at (GMythTVChain *tvchain, GString *chanid, GTimeVal* startts) +{ + gint count = 0; + struct LiveTVChainEntry *entry; + GList *tmp_list = tvchain->tvchain_list; + guint list_size = g_list_length (tvchain->tvchain_list); + + g_static_mutex_lock( &mutex ); + + for (; tmp_list && ( count < list_size ); tmp_list = tvchain->tvchain_list->next, count++) + { + entry = (struct LiveTVChainEntry*) tmp_list->data; + if ( !g_strncasecmp (entry->chanid->str, chanid->str, chanid->len) + && entry->starttime == startts ) + { + g_static_mutex_unlock( &mutex ); + return count; + } + } + g_static_mutex_unlock( &mutex ); + + return -1; +} + +/** Get the program info associated to the tvchain. + * + * @param tvchain The GMythTVChain instance. + * @param index The tvchain index. + * @return The program info structure. + */ +GMythProgramInfo* +gmyth_tvchain_get_program_at (GMythTVChain *tvchain, gint index) +{ + struct LiveTVChainEntry *entry; + + entry = gmyth_tvchain_get_entry_at (tvchain, index); + + if (entry) + return gmyth_tvchain_entry_to_program (tvchain, entry); + + return NULL; +} + +/** Gets a LiveTVChainEntry associated to the tvchain by its index. + * + * @param tvchain The GMythTVChain instance. + * @param index The tvchain entry index + * @return The LiveTVchainEntry structure. + */ +struct LiveTVChainEntry* +gmyth_tvchain_get_entry_at (GMythTVChain *tvchain, gint index) +{ + struct LiveTVChainEntry* chain_entry = NULL; + + g_return_val_if_fail( tvchain != NULL && tvchain->tvchain_list != NULL, NULL ); + + g_static_mutex_lock( &mutex ); + + gint size = g_list_length (tvchain->tvchain_list); + gint new_index = (index < 0 || index >= size) ? size - 1 : index; + + if (new_index >= 0) + chain_entry = (struct LiveTVChainEntry*) g_list_nth_data (tvchain->tvchain_list, new_index); + + g_static_mutex_unlock( &mutex ); + + if ( chain_entry != NULL ) { + gmyth_debug ("[%s] Got TV Chain entry at %d.\n", __FUNCTION__, new_index ); + + } else { + g_warning ("[%s] failed to get entry at index %d", __FUNCTION__, index); + } + + return chain_entry; +} + +/** Gets the program info from backend database associated to the tv chain entry. + * + * @param tvchain The GMythTVChain instance. + * @param entry the LiveTVChainEntry to be converted. + * @return The progrma info. + */ +GMythProgramInfo* +gmyth_tvchain_entry_to_program (GMythTVChain *tvchain, struct LiveTVChainEntry *entry) +{ + GMythProgramInfo *proginfo = NULL; + + g_return_val_if_fail( tvchain != NULL, NULL ); + + if ( !entry || !tvchain ) { + g_warning ("gmyth_tvchain_entry_to_program() received NULL argument"); + return NULL; + } + + GMythScheduler *scheduler = gmyth_scheduler_new (); + + gmyth_scheduler_connect( scheduler, tvchain->backend_info ); + proginfo = gmyth_scheduler_get_recorded (scheduler, + entry->chanid, entry->starttime); + gmyth_scheduler_disconnect( scheduler ); + + if (proginfo) { + proginfo->pathname = g_string_prepend (proginfo->pathname, entry->hostprefix->str); + } else { + g_warning ("tvchain_entry_to_program( chan id = %s, starttime = %ld) failed!", entry->chanid->str, entry->starttime->tv_sec); + } + + return proginfo; +} diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_tvchain.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_tvchain.h Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,108 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_tvchain.h + * + * @brief

This component contains functions for creating and accessing + * the tvchain functions for live tv playback. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Hallyson Luiz de Morais Melo + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef LIVETVCHAIN_H_ +#define LIVETVCHAIN_H_ + +#include +#include + +#include "gmyth_common.h" +#include "gmyth_backendinfo.h" + +G_BEGIN_DECLS + +#define GMYTH_TVCHAIN_TYPE (gmyth_tvchain_get_type ()) +#define GMYTH_TVCHAIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_TVCHAIN_TYPE, GMythTVChain)) +#define GMYTH_TVCHAIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_TVCHAIN_TYPE, GMythTVChainClass)) +#define IS_GMYTH_TVCHAIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_TVCHAIN_TYPE)) +#define IS_GMYTH_TVCHAIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_TVCHAIN_TYPE)) +#define GMYTH_TVCHAIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_TVCHAIN_TYPE, GMythTVChainClass)) + + +typedef struct _GMythTVChain GMythTVChain; +typedef struct _GMythTVChainClass GMythTVChainClass; + + +struct LiveTVChainEntry +{ + GString *chanid; + + GTimeVal* starttime; + GTimeVal* endtime; + + gboolean discontinuity; // if true, can't play smooth from last entry + GString *hostprefix; + GString *cardtype; + GString *channum; + GString *inputname; +}; + + +struct _GMythTVChainClass +{ + GObjectClass parent_class; + + /* callbacks */ + /* no one for now */ +}; + +struct _GMythTVChain +{ + GObject parent; + + GString *tvchain_id; + GList *tvchain_list; + + GTimeVal* cur_startts; + GString *cur_chanid; + gint cur_pos; + + GMythBackendInfo *backend_info; +}; + + +GType gmyth_tvchain_get_type (void); + +gboolean gmyth_tvchain_initialize (GMythTVChain *tvchain, + GMythBackendInfo *backend_info); +gboolean gmyth_tvchain_reload_all (GMythTVChain *tvchain); +GString* gmyth_tvchain_get_id (GMythTVChain *tvchain); +gint gmyth_tvchain_program_is_at (GMythTVChain *tvchain, + GString *chanid, GTimeVal* startts); + +struct LiveTVChainEntry* gmyth_tvchain_get_entry_at (GMythTVChain *tvchain, + gint index); + +GMythProgramInfo* gmyth_tvchain_entry_to_program (GMythTVChain *tvchain, + struct LiveTVChainEntry *entry); +GMythProgramInfo* gmyth_tvchain_get_program_at (GMythTVChain *tvchain, gint index); + +G_END_DECLS + +#endif /*LIVETVCHAIN_H_*/ diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_uri.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_uri.c Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,404 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_uri.c + * + * @brief

GMythURI utils + * - Extracts and parses a URI char string, in according with the RFC 2396 + * [http://www.ietf.org/rfc/rfc2396.txt] + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Rosfran Borges + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gmyth_uri.h" + +#include +#include +#include + +#include "gmyth_debug.h" + +static void gmyth_uri_class_init (GMythURIClass *klass); +static void gmyth_uri_init (GMythURI *object); + +static void gmyth_uri_dispose (GObject *object); +static void gmyth_uri_finalize (GObject *object); + +G_DEFINE_TYPE(GMythURI, gmyth_uri, G_TYPE_OBJECT) + +static void +gmyth_uri_parser_setup_and_new( GMythURI *uri, const gchar *value ); + +static void +gmyth_uri_class_init (GMythURIClass *klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + + gobject_class->dispose = gmyth_uri_dispose; + gobject_class->finalize = gmyth_uri_finalize; +} + +static void +gmyth_uri_init (GMythURI *gmyth_uri) +{ +} + +static void +gmyth_uri_dispose (GObject *object) +{ + GMythURI *gmyth_uri = GMYTH_URI(object); + + if ( gmyth_uri->host != NULL ) { + g_string_free( gmyth_uri->host, TRUE ); + gmyth_uri->host = NULL; + } + + if ( gmyth_uri->protocol != NULL ) { + g_string_free( gmyth_uri->protocol, TRUE ); + gmyth_uri->protocol = NULL; + } + + if ( gmyth_uri->path != NULL ) { + g_string_free( gmyth_uri->path, TRUE ); + gmyth_uri->path = NULL; + } + + if ( gmyth_uri->fragment != NULL ) { + g_string_free( gmyth_uri->fragment, TRUE ); + gmyth_uri->fragment = NULL; + } + + if ( gmyth_uri->user != NULL ) { + g_string_free( gmyth_uri->user, TRUE ); + gmyth_uri->user = NULL; + } + + if ( gmyth_uri->password != NULL ) { + g_string_free( gmyth_uri->password, TRUE ); + gmyth_uri->password = NULL; + } + + if ( gmyth_uri->query != NULL ) { + g_string_free( gmyth_uri->query, TRUE ); + gmyth_uri->query = NULL; + } + + G_OBJECT_CLASS (gmyth_uri_parent_class)->dispose (object); +} + +static void +gmyth_uri_finalize (GObject *object) +{ + //GMythURI *gmyth_uri = GMYTH_URI(object); + + g_signal_handlers_destroy (object); + + G_OBJECT_CLASS (gmyth_uri_parent_class)->finalize (object); +} + +/** Creates a new instance of GMythURI. + * + * @return a new instance of GMythURI. + */ +GMythURI * +gmyth_uri_new (void) +{ + GMythURI *gmyth_uri = GMYTH_URI (g_object_new (GMYTH_URI_TYPE, NULL)); + + return gmyth_uri; +} + +/** Creates a new instance of GMythURI. + * + * @return a new instance of GMythURI. + */ +GMythURI * +gmyth_uri_new_with_value (const gchar *value) +{ + GMythURI *gmyth_uri = GMYTH_URI (g_object_new (GMYTH_URI_TYPE, NULL)); + + gmyth_uri_parser_setup_and_new (gmyth_uri, value); + + return gmyth_uri; +} + +static gint +gmyth_strstr (const gchar *haystack, const gchar *needle) +{ + + gchar *strPos; + + if (haystack == NULL || needle == NULL) + return -1; + strPos = strstr(haystack, needle); + if (strPos == NULL) + return -1; + + return (strPos - haystack); + +} + +static gboolean +gmyth_uri_isabsolute (const GMythURI *uri) +{ + gboolean ret = FALSE; + + g_return_val_if_fail( uri != NULL && uri->uri != NULL && uri->protocol != NULL, FALSE ); + + if ( gmyth_strstr( uri->uri->str, GMYTH_URI_PROTOCOL_DELIM ) == 0 || strlen(uri->protocol->str) > 0 ) + ret = TRUE; + + return ret; +} + +static gint +gmyth_strrchr( const gchar *str, const gchar *chars, const gint nchars ) +{ + + gint strLen; + gint i, j; + + if ( str == NULL || chars == NULL ) + return -1; + + strLen = strlen( str ); + for ( i= (strLen-1); 0 <= i; i-- ) { + for ( j=0; jstr != NULL && strlen(field->str) > 0 ) + return field->str; + else + return ""; +} + +static void +gmyth_uri_parser_setup_and_new( GMythURI *uri, const gchar *value ) +{ + + gint uriLen; + gint currIdx; + gint protoIdx; + gint atIdx; + gint colonIdx; + gint shashIdx; + gint eIdx; + gchar *host; + gint eblacketIdx; + gint hostLen; + gint sharpIdx; + /* + gint questionIdx; + gint queryLen; + */ + + uriLen = strlen(value); + uri->uri = g_string_new( value ); + + currIdx = 0; + + /*** Protocol ****/ + protoIdx = gmyth_strstr (value, GMYTH_URI_PROTOCOL_DELIM); + if (0 < protoIdx) { + uri->protocol = g_string_new_len (value, protoIdx); + currIdx += protoIdx + strlen( GMYTH_URI_PROTOCOL_DELIM ); + } + + /*** User (Password) ****/ + atIdx = gmyth_strstr( value+currIdx, GMYTH_URI_USER_DELIM ); + if ( 0 < atIdx ) { + colonIdx = gmyth_strstr( value+currIdx, GMYTH_URI_COLON_DELIM ); + + if (0 < colonIdx && colonIdx < atIdx) { + uri->user = g_string_new_len (value+currIdx, colonIdx); + uri->password = g_string_new_len (value+currIdx+colonIdx+1, atIdx - (colonIdx+1)); + } + else + uri->user = g_string_new_len (value+currIdx, atIdx - currIdx); + currIdx += atIdx + 1; + } + + /*** Host (Port) ****/ + shashIdx = gmyth_strstr( value+currIdx, GMYTH_URI_SLASH_DELIM ); + if (0 < shashIdx) + uri->host = g_string_new_len (value+currIdx, shashIdx); + else if ( gmyth_uri_isabsolute(uri) == TRUE ) + uri->host = g_string_new_len (value+currIdx, strlen (value) - currIdx); + + host = gmyth_uri_get_host(uri); + colonIdx = gmyth_strrchr (host, GMYTH_URI_COLON_DELIM, 1); + eblacketIdx = gmyth_strrchr (host, GMYTH_URI_EBLACET_DELIM, 1); + if ( ( 0 < colonIdx ) && ( eblacketIdx < colonIdx ) ) { + GString *portStr = NULL; + GString *hostStr = g_string_new (host != NULL ? host : ""); + + hostLen = hostStr->len; + /**** host ****/ + uri->host = g_string_erase (uri->host, 0, hostLen); + uri->host = g_string_insert_len (uri->host, 0, hostStr->str, colonIdx); + if (0 < hostLen) { + if (host[0] == '[' && host[hostLen-1] == ']') + uri->host = g_string_new_len (hostStr->str+1, colonIdx-2); + } + /**** port ****/ + portStr = g_string_new_len (hostStr->str+colonIdx+1, hostLen-colonIdx-1); + uri->port = (gint)g_ascii_strtoull( portStr->str, NULL, 10 ); + g_string_free (portStr, TRUE); + g_string_free (hostStr, TRUE); + } + else { + const gchar* protocol = gmyth_uri_get_protocol(uri); + uri->port = GMYTH_URI_KNKOWN_PORT; + if ( strcmp(protocol, GMYTH_URI_PROTOCOL_HTTP) == 0 ) + uri->port = GMYTH_URI_DEFAULT_HTTP_PORT; + if ( strcmp(protocol, GMYTH_URI_PROTOCOL_FTP) == 0 ) + uri->port = GMYTH_URI_DEFAULT_FTP_PORT; + } + + if (shashIdx > 0) currIdx += shashIdx; + + /* + Handle relative URL + */ + if (gmyth_uri_isabsolute(uri) == FALSE) + { + + if (shashIdx != 0) + { + /* Add slash delimiter at the beginning of the URL, + if it doesn't exist + */ + uri->path = g_string_new( GMYTH_URI_SLASH_DELIM ); + } + uri->path = g_string_append( uri->path, value ); + + } else { + /* First set path simply to the rest of URI */ + uri->path = g_string_new_len (value+currIdx, uriLen-currIdx ); + } + + gmyth_debug( "uri value: %s", value ); + uri->query = g_string_new ( g_strstr_len( value, strlen(value), GMYTH_URI_E_DELIM ) ); + + eIdx = gmyth_strstr( value+currIdx, GMYTH_URI_E_DELIM ); + + if ( 0 < eIdx ) { + uri->query = g_string_new ( g_strstr_len( value, strlen(value), GMYTH_URI_E_DELIM ) ); + gmyth_debug( "query = %s", uri->query->str ); + } + + /**** Path (Query/Fragment) ****/ + sharpIdx = gmyth_strstr(value+currIdx, GMYTH_URI_SHARP_DELIM); + if (0 < sharpIdx) { + uri->path = g_string_append_len( uri->path, value+currIdx, sharpIdx); + uri->fragment = g_string_new_len (value+currIdx+sharpIdx+1, uriLen-(currIdx+sharpIdx+1)); + } + + gmyth_debug( "[%s] GMythURI: host = %s, port = %d, path = %s, query = %s, fragment = %s, "\ + "user = %s, password = %s.\n", __FUNCTION__, gmyth_uri_print_field( uri->host ), uri->port, + gmyth_uri_print_field( uri->path ), gmyth_uri_print_field( uri->query ), gmyth_uri_print_field( uri->fragment ), + gmyth_uri_print_field ( uri->user ), gmyth_uri_print_field( uri->password ) ); + +} + +gboolean +gmyth_uri_is_equals( GMythURI* uri1, GMythURI* uri2 ) +{ + return ( g_ascii_strcasecmp( gmyth_uri_get_host( uri1 ), gmyth_uri_get_host( uri2 ) ) == 0 && + gmyth_uri_get_port( uri1 ) == gmyth_uri_get_port( uri2 ) ); +} + +gboolean +gmyth_uri_is_livetv( GMythURI* uri ) +{ + gboolean ret = FALSE; + + g_return_val_if_fail( uri != NULL && uri->uri != NULL && uri->uri->str != NULL, FALSE ); + + ret = ( g_strstr_len( uri->uri->str, strlen( uri->uri->str ), "/?" ) != NULL ); + + if ( ret ) + gmyth_debug( "This URI is a LiveTV recording..." ); + + return ret; + +} + +gchar* +gmyth_uri_get_channel_name( GMythURI* uri ) +{ + gchar* channel = NULL; + + g_return_val_if_fail( uri != NULL && uri->uri != NULL && uri->uri->str != NULL, FALSE ); + + gchar *channel_query = g_strstr_len( gmyth_uri_get_query( uri ), strlen( gmyth_uri_get_query( uri ) ), "channel" ); + + if ( channel_query != NULL ) + { + gmyth_debug( "TV Channel is in the following URI segment: %s", channel_query ); + + gchar **chan_key_value = g_strsplit( gmyth_uri_get_query( uri ), "=", 2 ); + + /* gmyth_debug( "Channel tuple is [ %s, %s ]", chan_key_value[0], chan_key_value[1] ); */ + + if ( chan_key_value[1] != NULL ) + { + channel = g_strdup( chan_key_value[1] ); + } + + if ( chan_key_value != NULL ) + g_strfreev( chan_key_value ); + } + + gmyth_debug( "Got channel decimal value from the URI: %s", channel ); + + return channel; + +} + +gint +gmyth_uri_get_channel_num( GMythURI* uri ) +{ + gchar *channel_name = gmyth_uri_get_channel_name( uri ); + + if ( channel_name != NULL ) + { + return g_ascii_strtoull( channel_name, NULL, 10 ); + } + + return -1; + +} diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_uri.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_uri.h Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,125 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_uri.h + * + * @brief

GMythURI utils + * - Extracts and parses a URI char string, in according with the RFC 2396 + * [http://www.ietf.org/rfc/rfc2396.txt] + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Rosfran Borges + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _GMYTH_URI_H_ +#define _GMYTH_URI_H_ + +#include +#include + +#include +#include +#include + +G_BEGIN_DECLS + +#define GMYTH_URI_TYPE (gmyth_uri_get_type ()) +#define GMYTH_URI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_URI_TYPE, GMythURI)) +#define GMYTH_URI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_URI_TYPE, GMythURIClass)) +#define IS_GMYTH_URI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_URI_TYPE)) +#define IS_GMYTH_URI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_URI_TYPE)) +#define GMYTH_URI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_URI_TYPE, GMythURIClass)) + +typedef struct _GMythURI GMythURI; +typedef struct _GMythURIClass GMythURIClass; + +/**************************************** +* Define +****************************************/ + +#define GMYTH_URI_KNKOWN_PORT (-1) +#define GMYTH_URI_DEFAULT_HTTP_PORT 80 +#define GMYTH_URI_DEFAULT_FTP_PORT 21 +#define GMYTH_URI_DEFAULT_PATH "/" +#define GMYTH_URI_MAXLEN 256 + +#define GMYTH_URI_PROTOCOL_DELIM "://" +#define GMYTH_URI_USER_DELIM "@" +#define GMYTH_URI_COLON_DELIM ":" +#define GMYTH_URI_SLASH_DELIM "/" +#define GMYTH_URI_SBLACET_DELIM "[" +#define GMYTH_URI_EBLACET_DELIM "]" +#define GMYTH_URI_SHARP_DELIM "#" +#define GMYTH_URI_QUESTION_DELIM "?" +#define GMYTH_URI_E_DELIM "&" +#define GMYTH_URI_ESCAPING_CHAR "%" + +#define GMYTH_URI_PROTOCOL_MYTH "myth" +#define GMYTH_URI_PROTOCOL_HTTP "http" +#define GMYTH_URI_PROTOCOL_FTP "ftp" + +/**************************************** +* Data Type +****************************************/ + +struct _GMythURIClass +{ + GObjectClass parent_class; + + /* callbacks */ + /* no one for now */ +}; + +struct _GMythURI { + + GObject parent; + + GString *uri; + GString *host; + gint port; + GString *protocol; + GString *path; + GString *fragment; + GString *user; + GString *password; + GString *query; + +}; + +GType gmyth_uri_get_type (void); +GMythURI* gmyth_uri_new (void); +GMythURI* gmyth_uri_new_with_value (const gchar *value); +gboolean gmyth_uri_is_equals ( GMythURI* uri1, GMythURI* uri2 ); +gboolean gmyth_uri_is_livetv ( GMythURI* uri ); +gint gmyth_uri_get_channel_num( GMythURI* uri ); +gchar* gmyth_uri_get_channel_name( GMythURI* uri ); + + +#define gmyth_uri_get_host(urip) ( urip->host != NULL ? urip->host->str : "" ) +#define gmyth_uri_get_port(urip) ( urip->port ) +#define gmyth_uri_get_protocol(urip) ( urip->protocol != NULL ? urip->protocol->str : "" ) +#define gmyth_uri_get_path(urip) ( urip->path != NULL ? urip->path->str : "" ) +#define gmyth_uri_get_user(urip) ( urip->user != NULL ? urip->user->str : "" ) +#define gmyth_uri_get_password(urip) ( urip->password != NULL ? urip->password->str : "" ) +#define gmyth_uri_get_fragment(urip) ( urip->fragment != NULL ? urip->fragment->str : "" ) +#define gmyth_uri_get_query(urip) ( urip->query != NULL ? urip->query->str : "" ) + +G_END_DECLS + +#endif /* _GMYTH_URI_H_ */ diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_util.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_util.c Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,647 @@ +/** +* GMyth Library +* +* @file gmyth/gmyth_util.c +* +* @brief

This component provides utility functions. +* +* Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. +* @author Hallyson Luiz de Morais Melo +* +*//* +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define _XOPEN_SOURCE +#define _XOPEN_SOURCE_EXTENDED +#define __USE_MISC + +#include +#include +#include +#include +#include + +#include "gmyth.h" + +#if !GLIB_CHECK_VERSION (2, 10, 0) +gchar * +g_time_val_to_iso8601 (GTimeVal *time_); +gboolean +g_time_val_from_iso8601 (const gchar *iso_date, + GTimeVal *time_); +void +g_date_set_time_val (GDate *date, + GTimeVal *timeval); + +#endif + +static GStaticMutex mutex = G_STATIC_MUTEX_INIT; + +/** Converts a time_t struct in a GString at ISO standard format + * (e.g. 2006-07-20T09:56:41). + * + * The returned GString memory should be deallocated from + * the calling function. + * + * @param time_value the time value to be converted + * @return GString* the converted isoformat string + */ +GString* +gmyth_util_time_to_isoformat (time_t time_value) +{ + struct tm tm_time; + GString *result; + + g_static_mutex_lock ( &mutex ); + + if (localtime_r(&time_value, &tm_time) == NULL) { + g_static_mutex_unlock ( &mutex ); + g_warning ("gmyth_util_time_to_isoformat convertion error!\n"); + return NULL; + } + + result = g_string_sized_new(20); + g_string_printf(result, "%04d-%02d-%02dT%02d:%02d:%02d", + tm_time.tm_year + 1900, tm_time.tm_mon + 1, tm_time.tm_mday, + tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec); + + gmyth_debug( "Result (ISO 8601) = %s", result->str ); + + g_static_mutex_unlock ( &mutex ); + + return result; +} + +/** Converts a time_t struct in a GString at ISO standard format + * (e.g. 2006-07-20T09:56:41). + * + * The returned GString memory should be deallocated from + * the calling function. + * + * @param time_value the GTimeValue to be converted + * @return GString* the converted isoformat string + */ +gchar* +gmyth_util_time_to_isoformat_from_time_val_fmt ( const gchar *fmt_string, const GTimeVal* time_val ) +{ + gchar *result = NULL; + struct tm *tm_time = NULL; + + gint buffer_len = 0; + + g_return_val_if_fail( fmt_string != NULL, NULL ); + + g_return_val_if_fail( time_val != NULL, NULL ); + + time_t time = time_val->tv_sec;// + (gint)( time_val->tv_usec / G_USEC_PER_SEC ); + + tm_time = g_malloc0( sizeof(struct tm) ); + + g_static_mutex_lock ( &mutex ); + + if ( NULL == localtime_r( &time, tm_time ) ) { + g_warning ("gmyth_util_time_to_isoformat convertion error!\n"); + } else { + // we first check the return of strftime to allocate a buffer of the correct size + buffer_len = strftime( NULL, SSIZE_MAX, fmt_string, tm_time ); + if ( buffer_len > 0 ) { + result = g_malloc0( buffer_len + 1 ); + if( result == NULL ){ + g_static_mutex_unlock ( &mutex ); + g_warning ("gmyth_util_time_to_isoformat convertion error!\n"); + return NULL; + } + strftime( result, buffer_len + 1, fmt_string, tm_time ); + gmyth_debug( "Dateline (ISO result): %s", result ); + } + + } + + gmyth_debug( "Result (strftime) = %s", result ); + + //strptime( result, "%Y-%m-%dT%H:%M:%SZ", tm_time ); + + //strftime( result, strlen(result), fmt_string, tm_time ); + + g_static_mutex_unlock ( &mutex ); + + gmyth_debug( "Result (ISO 8601) = %s", result ); + + return result; + +} + +/** Converts a time_t struct in a GString at ISO standard format + * (e.g. 2006-07-20 09:56:41). + * + * The returned GString memory should be deallocated from + * the calling function. + * + * @param time_value the GTimeValue to be converted + * @return GString* the converted isoformat string + */ +gchar* +gmyth_util_time_to_isoformat_from_time_val ( const GTimeVal* time ) +{ + gchar *result = gmyth_util_time_to_isoformat_from_time_val_fmt( "%Y-%m-%d %H:%M:%S", time ); + //result[10] = ' '; + //result[ strlen(result) - 1] = '\0'; + + return result; +} + +/** Converts a time_t struct in a GString at ISO standard format 2 + * (e.g. 2006-07-20T09:56:41). + * + * The returned GString memory should be deallocated from + * the calling function. + * + * @param time_value the GTimeValue to be converted + * @return GString* the converted isoformat string + */ +gchar* +gmyth_util_time_to_mythformat_from_time_val ( const GTimeVal* time ) +{ + gchar *result = gmyth_util_time_to_isoformat_from_time_val_fmt( "%Y-%m-%dT%H:%M:%S", time ); + return result; +} + +/** Converts a time_t struct in a GString at ISO standard format + * (e.g. 2006-07-20T09:56:41). + * + * The returned GString memory should be deallocated from + * the calling function. + * + * @param time_value the GTimeValue to be converted + * @return GString* the converted isoformat string + */ +gchar* +gmyth_util_time_to_string_only_date ( const GTimeVal* time ) +{ + gchar *result = gmyth_util_time_to_isoformat_from_time_val_fmt( "%Y-%m-%d", time ); + //result[10] = ' '; + //result[ strlen(result) - 1] = '\0'; + return result; +} + +/** Converts a time_t struct in a GString at ISO standard format + * (e.g. 2006-07-20T09:56:41). + * + * The returned GString memory should be deallocated from + * the calling function. + * + * @param time_value the GTimeValue to be converted + * @return GString* the converted isoformat string + */ +gchar* +gmyth_util_time_to_string_only_time ( const GTimeVal* time ) +{ + gchar *result = gmyth_util_time_to_isoformat_from_time_val_fmt( "%H:%M:%S", time ); + //result[10] = ' '; + //result[ strlen(result) - 1] = '\0'; + return result; +} + +/** Converts a time_t struct in a GString to the following + * format (e.g. 2006-07-20 09:56:41). + * + * The returned GString memory should be deallocated from + * the calling function. + * + * @param time_value the time value to be converted + * @return GString* the converted string + */ +GString* +gmyth_util_time_to_string (time_t time_value) +{ + GString *result = gmyth_util_time_to_isoformat (time_value); + result->str[10] = ' '; + result->str[ strlen(result->str) - 1] = '\0'; + + return result; +} + +/** Converts a time_t struct in a GString to the following + * format (e.g. 2006-07-20 09:56:41). + * + * The returned GString memory should be deallocated from + * the calling function. + * + * @param time_value the time value to be converted + * @return GString* the converted string + */ +gchar* +gmyth_util_time_to_string_from_time_val ( const GTimeVal *time_val ) +{ + gchar *result = gmyth_util_time_to_isoformat_from_time_val_fmt ( "%Y-%m-%d %H:%M:%S", time_val ); + //result[10] = ' '; + + return result; +} + +/** Converts a GString in the following format + * (e.g. 2006-07-20 09:56:41) to a time_t struct. + * + * @param time_str the string to be converted + * @return time_t the time converted value + */ +time_t +gmyth_util_string_to_time (GString* time_str) +{ + gint year, month, day, hour, min, sec; + + gmyth_debug( "[%s] time_str = %s. [%s]", __FUNCTION__, time_str != NULL ? + time_str->str : "[time string is NULL!]", time_str->str ); + + if ( sscanf (time_str->str, "%04d-%02d-%02d %02d:%02d:%02d", + &year, &month, &day, &hour, &min, &sec) < 3 ) { + g_warning ("GMythUtil: isoformat_to_time converter error!\n"); + return 0; + } + + g_static_mutex_lock ( &mutex ); + + struct tm* tm_time = g_malloc0( sizeof(struct tm) ); + tm_time->tm_year = year - 1900; + tm_time->tm_mon = month - 1; + tm_time->tm_mday = day; + tm_time->tm_hour = hour; + tm_time->tm_min = min; + tm_time->tm_sec = sec; + + g_static_mutex_unlock ( &mutex ); + + return mktime( tm_time ); +} + +/** Converts a GString in the following format + * (e.g. 2006-07-20 09:56:41) to a time_t struct. + * + * @param time_str the string to be converted + * @return time_t the time converted value + */ +struct tm* +gmyth_util_time_val_to_date ( const GTimeVal* time ) +{ + struct tm *date = g_malloc0( sizeof( struct tm ) ); + time_t time_micros = time->tv_sec;// + (gint)( time->tv_usec / G_USEC_PER_SEC ); + + if ( NULL == date ) { + g_warning ( "GMythUtil: GDate *gmyth_util_time_val_to_date (GTimeVal* time) - converter error!\n" ); + return NULL; + } + + if ( NULL == localtime_r( &time_micros, date ) ) { + g_warning ( "gmyth_util_time_to_isoformat convertion error!\n" ); + return NULL; + } + + gmyth_debug( "Converted from GTimeVal == %s to GDate", asctime( date ) ); + + return date; +} + +/** Converts a GString in the following format + * (e.g. 2006-07-20 09:56:41) to a time_t struct. + * + * @param time_str the string to be converted + * @return time_t the time converted value + */ +GTimeVal* +gmyth_util_string_to_time_val_fmt ( const gchar *fmt_string, const gchar* time_str ) +{ + GTimeVal *time = g_new0( GTimeVal, 1 ); + struct tm* tm_time = NULL; + time_t time_micros; + gint result; + + gmyth_debug( "[%s] time_str = %s. [%s]", time_str, time_str != NULL ? + time_str : "[time string is NULL!]", time_str ); + + if ( NULL == time_str ) + { + g_warning ("GMythUtil: isoformat_to_time converter error!\n"); + return NULL; + } + + g_static_mutex_lock ( &mutex ); + + tm_time = g_malloc0( sizeof(struct tm) ); + + /* we first check the return of strftime to allocate a buffer of the correct size */ + result = strptime( time_str, "%Y-%m-%dT%H:%M:%S", tm_time ); + if ( NULL == result ) { + /* we first check the return of strftime to allocate a buffer of the correct size */ + result = strptime( time_str, "%Y-%m-%dT%H:%M:%SZ", tm_time ); + if ( NULL == result ) { + /* we first check the return of strftime to allocate a buffer of the correct size */ + result = strptime( time_str, "%Y-%m-%d %H:%M:%S", tm_time ); + if ( NULL == result ) { + g_static_mutex_unlock ( &mutex ); + gmyth_debug( "Dateline (ISO result): %s", result ); + time = NULL; + //goto done; + } + } + } + + time_micros = mktime( tm_time ); + + time->tv_sec = time_micros; // + (gint)( time_val->tv_usec / G_USEC_PER_SEC ); + + gmyth_debug( "After mktime call... = %s", asctime(tm_time) ); + + g_static_mutex_unlock ( &mutex ); + + return time; +} + +/** Converts a GString in the following format + * (e.g. 2006-07-20 09:56:41) to a time_t struct. + * + * @param time_str the string to be converted + * @return time_t the time converted value + */ +GTimeVal* +gmyth_util_string_to_time_val ( const gchar* time_str ) +{ + GTimeVal *time = gmyth_util_string_to_time_val_fmt ( "%Y-%m-%d %H:%M:%S", time_str ); + + return time; +} + +/** Decodes a long long variable from the string list + * format of the myhtprotocol. + * + * @param strlist the string list of mythprotocol values + * @param offset the list node offset of the long long variable + * @return gint64 the long long converted value + */ +gint64 +gmyth_util_decode_long_long(GMythStringList *strlist, guint offset) +{ + + gint64 ret_value = 0LL; + + g_return_val_if_fail( strlist != NULL, ret_value ); + + if ( offset > gmyth_string_list_length( strlist )) + g_printerr( "[%s] Offset is greater than the Stringlist (offset = %d)!\n", + __FUNCTION__, offset ); + + g_return_val_if_fail( offset < gmyth_string_list_length( strlist ), ret_value ); + + gint l1 = gmyth_string_list_get_int( strlist, offset ); + gint l2 = gmyth_string_list_get_int( strlist, offset + 1 ); + + ret_value = (l2 /*& 0xffffffffLL*/) | ( (gint64)l1 << 32 ); + + return ret_value; + +} + +gboolean +gmyth_util_file_exists (GMythBackendInfo *backend_info, const gchar* filename) +{ + GMythSocket *socket; + gboolean res; + + socket = gmyth_socket_new (); + res = gmyth_socket_connect_to_backend (socket, backend_info->hostname, + backend_info->port, TRUE); + + if (res == TRUE) { + GMythStringList *slist; + GMythProgramInfo *program = NULL; + + program = gmyth_program_info_new(); + program->pathname = g_string_new (filename); + + slist = gmyth_string_list_new (); + gmyth_string_list_append_char_array (slist, "QUERY_CHECKFILE"); + + gmyth_program_info_to_string_list (program, slist); + + gmyth_socket_sendreceive_stringlist (socket, slist); + + res = (gmyth_string_list_get_int (slist, 0) == 1); + + g_object_unref (program); + + g_object_unref (slist); + + gmyth_socket_close_connection (socket); + } + g_object_unref (socket); + return res; +} + + +#if !GLIB_CHECK_VERSION (2, 10, 0) + +/* Hacked from glib 2.10 */ + +static time_t +mktime_utc (struct tm *tm) +{ + time_t retval; + +#ifndef HAVE_TIMEGM + static const gint days_before[] = + { + 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 + }; +#endif + +#ifndef HAVE_TIMEGM + if (tm->tm_mon < 0 || tm->tm_mon > 11) + return (time_t) -1; + + retval = (tm->tm_year - 70) * 365; + retval += (tm->tm_year - 68) / 4; + retval += days_before[tm->tm_mon] + tm->tm_mday - 1; + + if (tm->tm_year % 4 == 0 && tm->tm_mon < 2) + retval -= 1; + + retval = ((((retval * 24) + tm->tm_hour) * 60) + tm->tm_min) * 60 + tm->tm_sec; +#else + retval = timegm (tm); +#endif /* !HAVE_TIMEGM */ + + return retval; +} + +gboolean +g_time_val_from_iso8601 (const gchar *iso_date, + GTimeVal *time_) +{ + struct tm tm; + long val; + + g_return_val_if_fail (iso_date != NULL, FALSE); + g_return_val_if_fail (time_ != NULL, FALSE); + + val = strtoul (iso_date, (char **)&iso_date, 10); + if (*iso_date == '-') + { + /* YYYY-MM-DD */ + tm.tm_year = val - 1900; + iso_date++; + tm.tm_mon = strtoul (iso_date, (char **)&iso_date, 10) - 1; + + if (*iso_date++ != '-') + return FALSE; + + tm.tm_mday = strtoul (iso_date, (char **)&iso_date, 10); + } + else + { + /* YYYYMMDD */ + tm.tm_mday = val % 100; + tm.tm_mon = (val % 10000) / 100 - 1; + tm.tm_year = val / 10000 - 1900; + } + + if (*iso_date++ != 'T') + return FALSE; + + val = strtoul (iso_date, (char **)&iso_date, 10); + if (*iso_date == ':') + { + /* hh:mm:ss */ + tm.tm_hour = val; + iso_date++; + tm.tm_min = strtoul (iso_date, (char **)&iso_date, 10); + + if (*iso_date++ != ':') + return FALSE; + + tm.tm_sec = strtoul (iso_date, (char **)&iso_date, 10); + } + else + { + /* hhmmss */ + tm.tm_sec = val % 100; + tm.tm_min = (val % 10000) / 100; + tm.tm_hour = val / 10000; + } + + time_->tv_sec = mktime_utc (&tm); + time_->tv_usec = 1; + + if (*iso_date == '.') + time_->tv_usec = strtoul (iso_date + 1, (char **)&iso_date, 10); + + if (*iso_date == '+' || *iso_date == '-') + { + gint sign = (*iso_date == '+') ? -1 : 1; + + val = 60 * strtoul (iso_date + 1, (char **)&iso_date, 10); + + if (*iso_date == ':') + val = 60 * val + strtoul (iso_date + 1, NULL, 10); + else + val = 60 * (val / 100) + (val % 100); + + time_->tv_sec += (time_t) (val * sign); + } + + return TRUE; +} + + +gchar * +g_time_val_to_iso8601 (GTimeVal *time_) +{ + gchar *retval; + + g_return_val_if_fail (time_->tv_usec >= 0 && time_->tv_usec < G_USEC_PER_SEC, NULL); + +#define ISO_8601_LEN 21 +#define ISO_8601_FORMAT "%Y-%m-%dT%H:%M:%SZ" + retval = g_new0 (gchar, ISO_8601_LEN + 1); + + strftime (retval, ISO_8601_LEN, + ISO_8601_FORMAT, + gmtime (&(time_->tv_sec))); + + return retval; +} + + +/* Hacked from glib 2.10 */ + +void +g_date_set_time_t (GDate *date, + time_t timet) +{ + struct tm tm; + + g_return_if_fail (date != NULL); + +#ifdef HAVE_LOCALTIME_R + localtime_r (&timet, &tm); +#else + { + struct tm *ptm = localtime (&timet); + + if (ptm == NULL) + { + /* Happens at least in Microsoft's C library if you pass a + * negative time_t. Use 2000-01-01 as default date. + */ +#ifndef G_DISABLE_CHECKS + g_return_if_fail_warning (G_LOG_DOMAIN, "g_date_set_time", "ptm != NULL"); +#endif + + tm.tm_mon = 0; + tm.tm_mday = 1; + tm.tm_year = 100; + } + else + memcpy ((void *) &tm, (void *) ptm, sizeof(struct tm)); + } +#endif + + date->julian = FALSE; + + date->month = tm.tm_mon + 1; + date->day = tm.tm_mday; + date->year = tm.tm_year + 1900; + + g_return_if_fail (g_date_valid_dmy (date->day, date->month, date->year)); + + date->dmy = TRUE; +} + + +void +g_date_set_time_val (GDate *date, + GTimeVal *timeval) +{ + g_date_set_time_t (date, (time_t) timeval->tv_sec); +} + + + + +#endif diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/src/gmyth_util.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/src/gmyth_util.h Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,66 @@ +/** +* GMyth Library +* +* @file gmyth/gmyth_util.h +* +* @brief

This component provides utility functions. +* +* Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. +* @author Hallyson Luiz de Morais Melo +* +*//* +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef GMYTH_UTIL_H_ +#define GMYTH_UTIL_H_ + +#include +#include + +#include "gmyth_stringlist.h" +#include "gmyth_backendinfo.h" + +G_BEGIN_DECLS + +GString *gmyth_util_time_to_isoformat(time_t time_value); +GString *gmyth_util_time_to_string (time_t time_value); +time_t gmyth_util_string_to_time (GString* time_str); +gint64 gmyth_util_decode_long_long (GMythStringList *strlist, + guint offset); + +gchar* gmyth_util_time_to_isoformat_from_time_val_fmt ( const gchar *fmt_string, const GTimeVal* time_val ); + +GTimeVal *gmyth_util_string_to_time_val_fmt ( const gchar *fmt_string, const gchar* time_str ); + +GTimeVal *gmyth_util_string_to_time_val ( const gchar* time_str ); + +gchar *gmyth_util_time_to_isoformat_from_time_val( const GTimeVal *time); +gchar *gmyth_util_time_to_mythformat_from_time_val ( const GTimeVal* time ); + +gchar *gmyth_util_time_to_string_only_date ( const GTimeVal* time ); + +gchar *gmyth_util_time_to_string_only_time ( const GTimeVal* time ); + +gchar *gmyth_util_time_to_string_from_time_val ( const GTimeVal *time_val ); + +struct tm *gmyth_util_time_val_to_date ( const GTimeVal* time ); + +gboolean gmyth_util_file_exists (GMythBackendInfo *backend_info, const gchar* filename); + +G_END_DECLS + +#endif /*GMYTH_UTIL_H_*/ diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/tests/Makefile.am --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/tests/Makefile.am Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,18 @@ +noinst_PROGRAMS = \ + test + +TESTS = \ + test + +test_SOURCES = \ + main.c + +test_LDADD = \ + $(MYSQL_LIBS) \ + $(top_builddir)/src/libgmyth.la + +AM_CPPFLAGS = \ + -I$(top_srcdir) \ + -I$(top_srcdir)/src \ + $(MYSQL_CFLAGS) \ + $(GLIB_CFLAGS) diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/tests/compile_file_exists --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/tests/compile_file_exists Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,1 @@ +gcc -o test_file_exists test_file_exists.c -DBIG_JOINS=1 -I/usr/include/mysql -I/usr/local/include/gmyth -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -L/usr/local/lib -lmysqlclient -lz -lcrypt -lnsl -lm -lgmyth -lgobject-2.0 -lglib-2.0 diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/tests/compile_test_connection --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/tests/compile_test_connection Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,1 @@ +gcc -o gmyth_test_connection gmyth_test_connection.c `pkg-config --cflags --libs gmyth-0.1 glib-2.0` diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/tests/compile_test_recorder --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/tests/compile_test_recorder Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,1 @@ +gcc -o gmyth_test_recorder gmyth_test_recorder.c `pkg-config --cflags --libs gmyth-0.1` diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/tests/compile_test_recordings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/tests/compile_test_recordings Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,1 @@ +gcc -o gmyth_test_recordings gmyth_test_recordings.c `pkg-config --cflags --libs gmyth-0.1 glib-2.0` diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/tests/gmyth_test_connection.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/tests/gmyth_test_connection.c Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,74 @@ +#include + +#include "gmyth_uri.h" +#include "gmyth_backendinfo.h" +#include "gmyth_socket.h" +#include "gmyth_query.h" + +static gboolean +test_backend_connection1 (GMythBackendInfo *backend_info) +{ + GMythSocket *socket = gmyth_socket_new (); + if (gmyth_socket_connect_with_timeout (socket, + gmyth_backend_info_get_hostname (backend_info), + gmyth_backend_info_get_port (backend_info), 4) == TRUE) { + g_debug ("Socket connection success"); + return TRUE; + } else { + g_debug ("Connection failed"); + return FALSE; + } +} + +static gboolean +test_backend_connection2 (GMythBackendInfo *backend_info) +{ + GMythSocket *socket = gmyth_socket_new (); + if (gmyth_socket_connect_to_backend (socket, + gmyth_backend_info_get_hostname (backend_info), + gmyth_backend_info_get_port (backend_info), TRUE) == TRUE) { + + + g_debug ("Backend socket connection success"); + return TRUE; + } else { + g_debug ("Connection failed"); + return FALSE; + } +} + +static gboolean +test_mysql_connection1 (GMythBackendInfo *backend_info) +{ + GMythQuery *query = gmyth_query_new (); + + if (gmyth_query_connect_with_timeout (query, backend_info, 3) == TRUE) { + g_debug ("Mysql connection success"); + return TRUE; + } else { + g_debug ("Mysql connection failed"); + return FALSE; + } + +} + + +int +main (int args, const char **argv) +{ + const char* uri = argv[1]; + + GMythBackendInfo *backend_info; + g_type_init (); + //g_thread_init (NULL); + + backend_info = gmyth_backend_info_new_with_uri (argv[1]); + + test_backend_connection1 (backend_info); + test_backend_connection2 (backend_info); + test_mysql_connection1 (backend_info); +} + + + + diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/tests/gmyth_test_epg.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/tests/gmyth_test_epg.c Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,60 @@ + +#include "gmyth_backendinfo.h" +#include "gmyth_epg.h" + +static gboolean +test_epg_connection (GMythBackendInfo *backend_info) +{ + GMythEPG *epg = gmyth_epg_new (); + gboolean res = FALSE; + + res = gmyth_epg_connect (epg, backend_info); + + gmyth_epg_disconnect (epg); + g_object_unref (epg); + + return res; +} + + +static gboolean +test_epg_get_channels (GMythBackendInfo *backend_info) +{ + GMythEPG *epg = gmyth_epg_new (); + GList *clist; + gint i, length; + + if (!gmyth_epg_connect (epg, backend_info)) { + return FALSE; + } + + length = gmyth_epg_get_channel_list (epg, &clist); + g_print ("==== %d channels found in the EPG ====\n", length); + for (i=0; i + +#include "gmyth_backendinfo.h" +#include "gmyth_remote_util.h" +#include "gmyth_query.h" +#include "gmyth_epg.h" +#include "gmyth_common.h" + + +static gboolean +test_recorder_availability (GMythBackendInfo *backend_info) +{ + GMythRecorder* recorder; + GMythSocket *socket = gmyth_socket_new (); + + if (gmyth_socket_connect_to_backend (socket, + gmyth_backend_info_get_hostname (backend_info), + gmyth_backend_info_get_port (backend_info), TRUE) == FALSE) { + g_debug ("Test recorder failed: Connection failed"); + return FALSE; + } + + recorder = remote_request_next_free_recorder (socket, -1); + gmyth_socket_close_connection (socket); + if (recorder == NULL) { + g_debug ("Recorder not available\n"); + return FALSE; + } + + g_debug ("Recorder found (num): %d", recorder->recorder_num); + + return TRUE; +} + +static gboolean +test_recorder_setup (GMythBackendInfo *backend_info) +{ + GMythQuery *query = gmyth_query_new (); + + if (gmyth_query_connect_with_timeout (query, backend_info, 3) == TRUE) { + g_debug ("Mysql connection success"); + return TRUE; + } else { + g_debug ("Mysql connection failed"); + return FALSE; + } + +} + +static gboolean +test_recorder_check_channels (GMythBackendInfo *backend_info) +{ + GMythRecorder* recorder; + GMythSocket *socket = gmyth_socket_new (); + GMythEPG *epg = gmyth_epg_new (); + GList *clist; + gint i, length; + + // Gets the free recorder + if (gmyth_socket_connect_to_backend (socket, + gmyth_backend_info_get_hostname (backend_info), + gmyth_backend_info_get_port (backend_info), TRUE) == FALSE) { + g_debug ("Test recorder failed: Connection failed"); + return FALSE; + } + + recorder = remote_request_next_free_recorder (socket, -1); + gmyth_socket_close_connection (socket); + if (recorder == NULL) { + g_debug ("[%s] Recorder not available", __FUNCTION__); + return FALSE; + } + + // Connects the recorder socket + gmyth_recorder_setup (recorder); + + // Gets the list of channels + if (!gmyth_epg_connect (epg, backend_info)) { + g_debug ("%s: Not connected\n", __FUNCTION__); + return FALSE; + } + + length = gmyth_epg_get_channel_list (epg, &clist); + gmyth_epg_disconnect (epg); + g_object_unref (epg); + + g_print ("==== Verifying the %d channels found in the EPG ====\n", length); + for (i=0; ichannel_ID); + g_debug ("Channel %d %s", channel_info->channel_ID, res ? "Found" : "Not found"); + } + + g_list_free (clist); + +} + + +int +main (int args, const char **argv) +{ + const char* uri = argv[1]; + + GMythBackendInfo *backend_info; + g_type_init (); + g_thread_init (NULL); + + backend_info = gmyth_backend_info_new_with_uri (argv[1]); + + printf ("******** Testing recorder availability ***********\n"); + test_recorder_availability (backend_info); + + printf ("******** Testing recorder check channels function ***********\n"); + test_recorder_check_channels (backend_info); +} + + + + + diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/tests/gmyth_test_recordings.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/tests/gmyth_test_recordings.c Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,59 @@ +#include + +#include "gmyth_uri.h" +#include "gmyth_backendinfo.h" +#include "gmyth_scheduler.h" +#include "gmyth_epg.h" +#include "gmyth_common.h" + +static gboolean +test_recording_list (GMythBackendInfo *backend_info) +{ + GList *list = NULL; + gint length = 0; + GMythScheduler *scheduler = gmyth_scheduler_new (); + + if (gmyth_scheduler_connect_with_timeout (scheduler, + backend_info, 10) == TRUE) { + g_debug ("===== Scheduler connection success ====="); + } else { + g_debug ("===== Scheduler connection failed ====="); + return FALSE; + } + + length = gmyth_scheduler_get_recorded_list (scheduler, &list); + + g_debug ("===== %d Recordings found =====\n", length); + length--; + while (length >= 0) { + RecordedInfo *record = (RecordedInfo*) g_list_nth_data (list, length); + if (record == 0) { + g_debug ("===== Recorded list returned NULL pointer =====\n"); + length--; + continue; + } + g_debug ("===== Record id = %d =====\n", record->record_id); + g_debug ("===== Record name = %s =====\n", (record ? record->basename->str : "NULL")); + length--; + } + + gmyth_scheduler_disconnect (scheduler); + +} + +int +main (int args, const char **argv) +{ + const char* uri = argv[1]; + + GMythBackendInfo *backend_info; + g_type_init (); + + backend_info = gmyth_backend_info_new_with_uri (argv[1]); + + test_recording_list (backend_info); +} + + + + diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/tests/http.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/tests/http.c Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,24 @@ +#include +#include "gmyth.h" +#include + +int +main (int args, const char **argv) +{ + GMythBackendInfo *backend_info; + g_type_init(); + //g_thread_init(NULL); + + backend_info = gmyth_backend_info_new (); + + gmyth_backend_info_set_hostname (backend_info, "localhost"); + gmyth_backend_info_set_port (backend_info, 6543); + + GTimeVal* start = gmyth_util_string_to_time_val("2006-01-01T00:00"); + GTimeVal* end = gmyth_util_string_to_time_val("2007-01-01T00:00"); + GMythEpg epg; + epg = retrieve_epg(backend_info, 6544, start, end, 0, 2, "True"); + + + return 0; +} diff -r 69382cca242e -r 22a17127789e branches/gmyth-0.1b/tests/main.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/branches/gmyth-0.1b/tests/main.c Thu Feb 01 18:42:01 2007 +0000 @@ -0,0 +1,49 @@ +#include +#include "gmyth.h" + +int +main (int args, const char **argv) +{ + const char *uri = argv[1]; + GMythURI *gmyth_uri = NULL; + gboolean res; + GMythBackendInfo *backend_info; + g_type_init (); + g_thread_init (NULL); + + backend_info = gmyth_backend_info_new (); + gmyth_uri = gmyth_uri_new_with_value (uri); + + gmyth_backend_info_set_hostname (backend_info, gmyth_uri_get_host (gmyth_uri)); + gmyth_backend_info_set_port (backend_info, gmyth_uri_get_port (gmyth_uri)); + + res = gmyth_util_file_exists (backend_info, uri); + if (res == FALSE) { + g_debug ("file not exists"); + return -1; + } + GMythFileTransfer *file_transfer = gmyth_file_transfer_new (); + GString *hostname = g_string_new (uri); + res = gmyth_file_transfer_open (file_transfer, hostname); + if (res == FALSE) { + g_debug ("Fail to open server"); + return -1; + } + + guint64 filesize = gmyth_file_transfer_get_filesize (file_transfer); + if (filesize <= 0) { + g_debug ("filesize is 0"); + return -1; + } + + GByteArray *data = g_byte_array_new (); + guint num = gmyth_file_transfer_read (file_transfer, data, filesize, FALSE); + g_debug ("read %d bytes", num); + + g_byte_array_free (data, TRUE); + g_object_unref (file_transfer); + g_object_unref (gmyth_uri); + g_string_free (hostname, TRUE); + + return 0; +}