1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/gmyth/COPYING Wed Sep 20 23:45:35 2006 +0100
1.3 @@ -0,0 +1,504 @@
1.4 + GNU LESSER GENERAL PUBLIC LICENSE
1.5 + Version 2.1, February 1999
1.6 +
1.7 + Copyright (C) 1991, 1999 Free Software Foundation, Inc.
1.8 + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1.9 + Everyone is permitted to copy and distribute verbatim copies
1.10 + of this license document, but changing it is not allowed.
1.11 +
1.12 +[This is the first released version of the Lesser GPL. It also counts
1.13 + as the successor of the GNU Library Public License, version 2, hence
1.14 + the version number 2.1.]
1.15 +
1.16 + Preamble
1.17 +
1.18 + The licenses for most software are designed to take away your
1.19 +freedom to share and change it. By contrast, the GNU General Public
1.20 +Licenses are intended to guarantee your freedom to share and change
1.21 +free software--to make sure the software is free for all its users.
1.22 +
1.23 + This license, the Lesser General Public License, applies to some
1.24 +specially designated software packages--typically libraries--of the
1.25 +Free Software Foundation and other authors who decide to use it. You
1.26 +can use it too, but we suggest you first think carefully about whether
1.27 +this license or the ordinary General Public License is the better
1.28 +strategy to use in any particular case, based on the explanations below.
1.29 +
1.30 + When we speak of free software, we are referring to freedom of use,
1.31 +not price. Our General Public Licenses are designed to make sure that
1.32 +you have the freedom to distribute copies of free software (and charge
1.33 +for this service if you wish); that you receive source code or can get
1.34 +it if you want it; that you can change the software and use pieces of
1.35 +it in new free programs; and that you are informed that you can do
1.36 +these things.
1.37 +
1.38 + To protect your rights, we need to make restrictions that forbid
1.39 +distributors to deny you these rights or to ask you to surrender these
1.40 +rights. These restrictions translate to certain responsibilities for
1.41 +you if you distribute copies of the library or if you modify it.
1.42 +
1.43 + For example, if you distribute copies of the library, whether gratis
1.44 +or for a fee, you must give the recipients all the rights that we gave
1.45 +you. You must make sure that they, too, receive or can get the source
1.46 +code. If you link other code with the library, you must provide
1.47 +complete object files to the recipients, so that they can relink them
1.48 +with the library after making changes to the library and recompiling
1.49 +it. And you must show them these terms so they know their rights.
1.50 +
1.51 + We protect your rights with a two-step method: (1) we copyright the
1.52 +library, and (2) we offer you this license, which gives you legal
1.53 +permission to copy, distribute and/or modify the library.
1.54 +
1.55 + To protect each distributor, we want to make it very clear that
1.56 +there is no warranty for the free library. Also, if the library is
1.57 +modified by someone else and passed on, the recipients should know
1.58 +that what they have is not the original version, so that the original
1.59 +author's reputation will not be affected by problems that might be
1.60 +introduced by others.
1.61 +
1.62 + Finally, software patents pose a constant threat to the existence of
1.63 +any free program. We wish to make sure that a company cannot
1.64 +effectively restrict the users of a free program by obtaining a
1.65 +restrictive license from a patent holder. Therefore, we insist that
1.66 +any patent license obtained for a version of the library must be
1.67 +consistent with the full freedom of use specified in this license.
1.68 +
1.69 + Most GNU software, including some libraries, is covered by the
1.70 +ordinary GNU General Public License. This license, the GNU Lesser
1.71 +General Public License, applies to certain designated libraries, and
1.72 +is quite different from the ordinary General Public License. We use
1.73 +this license for certain libraries in order to permit linking those
1.74 +libraries into non-free programs.
1.75 +
1.76 + When a program is linked with a library, whether statically or using
1.77 +a shared library, the combination of the two is legally speaking a
1.78 +combined work, a derivative of the original library. The ordinary
1.79 +General Public License therefore permits such linking only if the
1.80 +entire combination fits its criteria of freedom. The Lesser General
1.81 +Public License permits more lax criteria for linking other code with
1.82 +the library.
1.83 +
1.84 + We call this license the "Lesser" General Public License because it
1.85 +does Less to protect the user's freedom than the ordinary General
1.86 +Public License. It also provides other free software developers Less
1.87 +of an advantage over competing non-free programs. These disadvantages
1.88 +are the reason we use the ordinary General Public License for many
1.89 +libraries. However, the Lesser license provides advantages in certain
1.90 +special circumstances.
1.91 +
1.92 + For example, on rare occasions, there may be a special need to
1.93 +encourage the widest possible use of a certain library, so that it becomes
1.94 +a de-facto standard. To achieve this, non-free programs must be
1.95 +allowed to use the library. A more frequent case is that a free
1.96 +library does the same job as widely used non-free libraries. In this
1.97 +case, there is little to gain by limiting the free library to free
1.98 +software only, so we use the Lesser General Public License.
1.99 +
1.100 + In other cases, permission to use a particular library in non-free
1.101 +programs enables a greater number of people to use a large body of
1.102 +free software. For example, permission to use the GNU C Library in
1.103 +non-free programs enables many more people to use the whole GNU
1.104 +operating system, as well as its variant, the GNU/Linux operating
1.105 +system.
1.106 +
1.107 + Although the Lesser General Public License is Less protective of the
1.108 +users' freedom, it does ensure that the user of a program that is
1.109 +linked with the Library has the freedom and the wherewithal to run
1.110 +that program using a modified version of the Library.
1.111 +
1.112 + The precise terms and conditions for copying, distribution and
1.113 +modification follow. Pay close attention to the difference between a
1.114 +"work based on the library" and a "work that uses the library". The
1.115 +former contains code derived from the library, whereas the latter must
1.116 +be combined with the library in order to run.
1.117 +
1.118 + GNU LESSER GENERAL PUBLIC LICENSE
1.119 + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
1.120 +
1.121 + 0. This License Agreement applies to any software library or other
1.122 +program which contains a notice placed by the copyright holder or
1.123 +other authorized party saying it may be distributed under the terms of
1.124 +this Lesser General Public License (also called "this License").
1.125 +Each licensee is addressed as "you".
1.126 +
1.127 + A "library" means a collection of software functions and/or data
1.128 +prepared so as to be conveniently linked with application programs
1.129 +(which use some of those functions and data) to form executables.
1.130 +
1.131 + The "Library", below, refers to any such software library or work
1.132 +which has been distributed under these terms. A "work based on the
1.133 +Library" means either the Library or any derivative work under
1.134 +copyright law: that is to say, a work containing the Library or a
1.135 +portion of it, either verbatim or with modifications and/or translated
1.136 +straightforwardly into another language. (Hereinafter, translation is
1.137 +included without limitation in the term "modification".)
1.138 +
1.139 + "Source code" for a work means the preferred form of the work for
1.140 +making modifications to it. For a library, complete source code means
1.141 +all the source code for all modules it contains, plus any associated
1.142 +interface definition files, plus the scripts used to control compilation
1.143 +and installation of the library.
1.144 +
1.145 + Activities other than copying, distribution and modification are not
1.146 +covered by this License; they are outside its scope. The act of
1.147 +running a program using the Library is not restricted, and output from
1.148 +such a program is covered only if its contents constitute a work based
1.149 +on the Library (independent of the use of the Library in a tool for
1.150 +writing it). Whether that is true depends on what the Library does
1.151 +and what the program that uses the Library does.
1.152 +
1.153 + 1. You may copy and distribute verbatim copies of the Library's
1.154 +complete source code as you receive it, in any medium, provided that
1.155 +you conspicuously and appropriately publish on each copy an
1.156 +appropriate copyright notice and disclaimer of warranty; keep intact
1.157 +all the notices that refer to this License and to the absence of any
1.158 +warranty; and distribute a copy of this License along with the
1.159 +Library.
1.160 +
1.161 + You may charge a fee for the physical act of transferring a copy,
1.162 +and you may at your option offer warranty protection in exchange for a
1.163 +fee.
1.164 +
1.165 + 2. You may modify your copy or copies of the Library or any portion
1.166 +of it, thus forming a work based on the Library, and copy and
1.167 +distribute such modifications or work under the terms of Section 1
1.168 +above, provided that you also meet all of these conditions:
1.169 +
1.170 + a) The modified work must itself be a software library.
1.171 +
1.172 + b) You must cause the files modified to carry prominent notices
1.173 + stating that you changed the files and the date of any change.
1.174 +
1.175 + c) You must cause the whole of the work to be licensed at no
1.176 + charge to all third parties under the terms of this License.
1.177 +
1.178 + d) If a facility in the modified Library refers to a function or a
1.179 + table of data to be supplied by an application program that uses
1.180 + the facility, other than as an argument passed when the facility
1.181 + is invoked, then you must make a good faith effort to ensure that,
1.182 + in the event an application does not supply such function or
1.183 + table, the facility still operates, and performs whatever part of
1.184 + its purpose remains meaningful.
1.185 +
1.186 + (For example, a function in a library to compute square roots has
1.187 + a purpose that is entirely well-defined independent of the
1.188 + application. Therefore, Subsection 2d requires that any
1.189 + application-supplied function or table used by this function must
1.190 + be optional: if the application does not supply it, the square
1.191 + root function must still compute square roots.)
1.192 +
1.193 +These requirements apply to the modified work as a whole. If
1.194 +identifiable sections of that work are not derived from the Library,
1.195 +and can be reasonably considered independent and separate works in
1.196 +themselves, then this License, and its terms, do not apply to those
1.197 +sections when you distribute them as separate works. But when you
1.198 +distribute the same sections as part of a whole which is a work based
1.199 +on the Library, the distribution of the whole must be on the terms of
1.200 +this License, whose permissions for other licensees extend to the
1.201 +entire whole, and thus to each and every part regardless of who wrote
1.202 +it.
1.203 +
1.204 +Thus, it is not the intent of this section to claim rights or contest
1.205 +your rights to work written entirely by you; rather, the intent is to
1.206 +exercise the right to control the distribution of derivative or
1.207 +collective works based on the Library.
1.208 +
1.209 +In addition, mere aggregation of another work not based on the Library
1.210 +with the Library (or with a work based on the Library) on a volume of
1.211 +a storage or distribution medium does not bring the other work under
1.212 +the scope of this License.
1.213 +
1.214 + 3. You may opt to apply the terms of the ordinary GNU General Public
1.215 +License instead of this License to a given copy of the Library. To do
1.216 +this, you must alter all the notices that refer to this License, so
1.217 +that they refer to the ordinary GNU General Public License, version 2,
1.218 +instead of to this License. (If a newer version than version 2 of the
1.219 +ordinary GNU General Public License has appeared, then you can specify
1.220 +that version instead if you wish.) Do not make any other change in
1.221 +these notices.
1.222 +
1.223 + Once this change is made in a given copy, it is irreversible for
1.224 +that copy, so the ordinary GNU General Public License applies to all
1.225 +subsequent copies and derivative works made from that copy.
1.226 +
1.227 + This option is useful when you wish to copy part of the code of
1.228 +the Library into a program that is not a library.
1.229 +
1.230 + 4. You may copy and distribute the Library (or a portion or
1.231 +derivative of it, under Section 2) in object code or executable form
1.232 +under the terms of Sections 1 and 2 above provided that you accompany
1.233 +it with the complete corresponding machine-readable source code, which
1.234 +must be distributed under the terms of Sections 1 and 2 above on a
1.235 +medium customarily used for software interchange.
1.236 +
1.237 + If distribution of object code is made by offering access to copy
1.238 +from a designated place, then offering equivalent access to copy the
1.239 +source code from the same place satisfies the requirement to
1.240 +distribute the source code, even though third parties are not
1.241 +compelled to copy the source along with the object code.
1.242 +
1.243 + 5. A program that contains no derivative of any portion of the
1.244 +Library, but is designed to work with the Library by being compiled or
1.245 +linked with it, is called a "work that uses the Library". Such a
1.246 +work, in isolation, is not a derivative work of the Library, and
1.247 +therefore falls outside the scope of this License.
1.248 +
1.249 + However, linking a "work that uses the Library" with the Library
1.250 +creates an executable that is a derivative of the Library (because it
1.251 +contains portions of the Library), rather than a "work that uses the
1.252 +library". The executable is therefore covered by this License.
1.253 +Section 6 states terms for distribution of such executables.
1.254 +
1.255 + When a "work that uses the Library" uses material from a header file
1.256 +that is part of the Library, the object code for the work may be a
1.257 +derivative work of the Library even though the source code is not.
1.258 +Whether this is true is especially significant if the work can be
1.259 +linked without the Library, or if the work is itself a library. The
1.260 +threshold for this to be true is not precisely defined by law.
1.261 +
1.262 + If such an object file uses only numerical parameters, data
1.263 +structure layouts and accessors, and small macros and small inline
1.264 +functions (ten lines or less in length), then the use of the object
1.265 +file is unrestricted, regardless of whether it is legally a derivative
1.266 +work. (Executables containing this object code plus portions of the
1.267 +Library will still fall under Section 6.)
1.268 +
1.269 + Otherwise, if the work is a derivative of the Library, you may
1.270 +distribute the object code for the work under the terms of Section 6.
1.271 +Any executables containing that work also fall under Section 6,
1.272 +whether or not they are linked directly with the Library itself.
1.273 +
1.274 + 6. As an exception to the Sections above, you may also combine or
1.275 +link a "work that uses the Library" with the Library to produce a
1.276 +work containing portions of the Library, and distribute that work
1.277 +under terms of your choice, provided that the terms permit
1.278 +modification of the work for the customer's own use and reverse
1.279 +engineering for debugging such modifications.
1.280 +
1.281 + You must give prominent notice with each copy of the work that the
1.282 +Library is used in it and that the Library and its use are covered by
1.283 +this License. You must supply a copy of this License. If the work
1.284 +during execution displays copyright notices, you must include the
1.285 +copyright notice for the Library among them, as well as a reference
1.286 +directing the user to the copy of this License. Also, you must do one
1.287 +of these things:
1.288 +
1.289 + a) Accompany the work with the complete corresponding
1.290 + machine-readable source code for the Library including whatever
1.291 + changes were used in the work (which must be distributed under
1.292 + Sections 1 and 2 above); and, if the work is an executable linked
1.293 + with the Library, with the complete machine-readable "work that
1.294 + uses the Library", as object code and/or source code, so that the
1.295 + user can modify the Library and then relink to produce a modified
1.296 + executable containing the modified Library. (It is understood
1.297 + that the user who changes the contents of definitions files in the
1.298 + Library will not necessarily be able to recompile the application
1.299 + to use the modified definitions.)
1.300 +
1.301 + b) Use a suitable shared library mechanism for linking with the
1.302 + Library. A suitable mechanism is one that (1) uses at run time a
1.303 + copy of the library already present on the user's computer system,
1.304 + rather than copying library functions into the executable, and (2)
1.305 + will operate properly with a modified version of the library, if
1.306 + the user installs one, as long as the modified version is
1.307 + interface-compatible with the version that the work was made with.
1.308 +
1.309 + c) Accompany the work with a written offer, valid for at
1.310 + least three years, to give the same user the materials
1.311 + specified in Subsection 6a, above, for a charge no more
1.312 + than the cost of performing this distribution.
1.313 +
1.314 + d) If distribution of the work is made by offering access to copy
1.315 + from a designated place, offer equivalent access to copy the above
1.316 + specified materials from the same place.
1.317 +
1.318 + e) Verify that the user has already received a copy of these
1.319 + materials or that you have already sent this user a copy.
1.320 +
1.321 + For an executable, the required form of the "work that uses the
1.322 +Library" must include any data and utility programs needed for
1.323 +reproducing the executable from it. However, as a special exception,
1.324 +the materials to be distributed need not include anything that is
1.325 +normally distributed (in either source or binary form) with the major
1.326 +components (compiler, kernel, and so on) of the operating system on
1.327 +which the executable runs, unless that component itself accompanies
1.328 +the executable.
1.329 +
1.330 + It may happen that this requirement contradicts the license
1.331 +restrictions of other proprietary libraries that do not normally
1.332 +accompany the operating system. Such a contradiction means you cannot
1.333 +use both them and the Library together in an executable that you
1.334 +distribute.
1.335 +
1.336 + 7. You may place library facilities that are a work based on the
1.337 +Library side-by-side in a single library together with other library
1.338 +facilities not covered by this License, and distribute such a combined
1.339 +library, provided that the separate distribution of the work based on
1.340 +the Library and of the other library facilities is otherwise
1.341 +permitted, and provided that you do these two things:
1.342 +
1.343 + a) Accompany the combined library with a copy of the same work
1.344 + based on the Library, uncombined with any other library
1.345 + facilities. This must be distributed under the terms of the
1.346 + Sections above.
1.347 +
1.348 + b) Give prominent notice with the combined library of the fact
1.349 + that part of it is a work based on the Library, and explaining
1.350 + where to find the accompanying uncombined form of the same work.
1.351 +
1.352 + 8. You may not copy, modify, sublicense, link with, or distribute
1.353 +the Library except as expressly provided under this License. Any
1.354 +attempt otherwise to copy, modify, sublicense, link with, or
1.355 +distribute the Library is void, and will automatically terminate your
1.356 +rights under this License. However, parties who have received copies,
1.357 +or rights, from you under this License will not have their licenses
1.358 +terminated so long as such parties remain in full compliance.
1.359 +
1.360 + 9. You are not required to accept this License, since you have not
1.361 +signed it. However, nothing else grants you permission to modify or
1.362 +distribute the Library or its derivative works. These actions are
1.363 +prohibited by law if you do not accept this License. Therefore, by
1.364 +modifying or distributing the Library (or any work based on the
1.365 +Library), you indicate your acceptance of this License to do so, and
1.366 +all its terms and conditions for copying, distributing or modifying
1.367 +the Library or works based on it.
1.368 +
1.369 + 10. Each time you redistribute the Library (or any work based on the
1.370 +Library), the recipient automatically receives a license from the
1.371 +original licensor to copy, distribute, link with or modify the Library
1.372 +subject to these terms and conditions. You may not impose any further
1.373 +restrictions on the recipients' exercise of the rights granted herein.
1.374 +You are not responsible for enforcing compliance by third parties with
1.375 +this License.
1.376 +
1.377 + 11. If, as a consequence of a court judgment or allegation of patent
1.378 +infringement or for any other reason (not limited to patent issues),
1.379 +conditions are imposed on you (whether by court order, agreement or
1.380 +otherwise) that contradict the conditions of this License, they do not
1.381 +excuse you from the conditions of this License. If you cannot
1.382 +distribute so as to satisfy simultaneously your obligations under this
1.383 +License and any other pertinent obligations, then as a consequence you
1.384 +may not distribute the Library at all. For example, if a patent
1.385 +license would not permit royalty-free redistribution of the Library by
1.386 +all those who receive copies directly or indirectly through you, then
1.387 +the only way you could satisfy both it and this License would be to
1.388 +refrain entirely from distribution of the Library.
1.389 +
1.390 +If any portion of this section is held invalid or unenforceable under any
1.391 +particular circumstance, the balance of the section is intended to apply,
1.392 +and the section as a whole is intended to apply in other circumstances.
1.393 +
1.394 +It is not the purpose of this section to induce you to infringe any
1.395 +patents or other property right claims or to contest validity of any
1.396 +such claims; this section has the sole purpose of protecting the
1.397 +integrity of the free software distribution system which is
1.398 +implemented by public license practices. Many people have made
1.399 +generous contributions to the wide range of software distributed
1.400 +through that system in reliance on consistent application of that
1.401 +system; it is up to the author/donor to decide if he or she is willing
1.402 +to distribute software through any other system and a licensee cannot
1.403 +impose that choice.
1.404 +
1.405 +This section is intended to make thoroughly clear what is believed to
1.406 +be a consequence of the rest of this License.
1.407 +
1.408 + 12. If the distribution and/or use of the Library is restricted in
1.409 +certain countries either by patents or by copyrighted interfaces, the
1.410 +original copyright holder who places the Library under this License may add
1.411 +an explicit geographical distribution limitation excluding those countries,
1.412 +so that distribution is permitted only in or among countries not thus
1.413 +excluded. In such case, this License incorporates the limitation as if
1.414 +written in the body of this License.
1.415 +
1.416 + 13. The Free Software Foundation may publish revised and/or new
1.417 +versions of the Lesser General Public License from time to time.
1.418 +Such new versions will be similar in spirit to the present version,
1.419 +but may differ in detail to address new problems or concerns.
1.420 +
1.421 +Each version is given a distinguishing version number. If the Library
1.422 +specifies a version number of this License which applies to it and
1.423 +"any later version", you have the option of following the terms and
1.424 +conditions either of that version or of any later version published by
1.425 +the Free Software Foundation. If the Library does not specify a
1.426 +license version number, you may choose any version ever published by
1.427 +the Free Software Foundation.
1.428 +
1.429 + 14. If you wish to incorporate parts of the Library into other free
1.430 +programs whose distribution conditions are incompatible with these,
1.431 +write to the author to ask for permission. For software which is
1.432 +copyrighted by the Free Software Foundation, write to the Free
1.433 +Software Foundation; we sometimes make exceptions for this. Our
1.434 +decision will be guided by the two goals of preserving the free status
1.435 +of all derivatives of our free software and of promoting the sharing
1.436 +and reuse of software generally.
1.437 +
1.438 + NO WARRANTY
1.439 +
1.440 + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
1.441 +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
1.442 +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
1.443 +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
1.444 +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
1.445 +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1.446 +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
1.447 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
1.448 +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
1.449 +
1.450 + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
1.451 +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
1.452 +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
1.453 +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
1.454 +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
1.455 +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
1.456 +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
1.457 +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
1.458 +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
1.459 +DAMAGES.
1.460 +
1.461 + END OF TERMS AND CONDITIONS
1.462 +
1.463 + How to Apply These Terms to Your New Libraries
1.464 +
1.465 + If you develop a new library, and you want it to be of the greatest
1.466 +possible use to the public, we recommend making it free software that
1.467 +everyone can redistribute and change. You can do so by permitting
1.468 +redistribution under these terms (or, alternatively, under the terms of the
1.469 +ordinary General Public License).
1.470 +
1.471 + To apply these terms, attach the following notices to the library. It is
1.472 +safest to attach them to the start of each source file to most effectively
1.473 +convey the exclusion of warranty; and each file should have at least the
1.474 +"copyright" line and a pointer to where the full notice is found.
1.475 +
1.476 + <one line to give the library's name and a brief idea of what it does.>
1.477 + Copyright (C) <year> <name of author>
1.478 +
1.479 + This library is free software; you can redistribute it and/or
1.480 + modify it under the terms of the GNU Lesser General Public
1.481 + License as published by the Free Software Foundation; either
1.482 + version 2.1 of the License, or (at your option) any later version.
1.483 +
1.484 + This library is distributed in the hope that it will be useful,
1.485 + but WITHOUT ANY WARRANTY; without even the implied warranty of
1.486 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1.487 + Lesser General Public License for more details.
1.488 +
1.489 + You should have received a copy of the GNU Lesser General Public
1.490 + License along with this library; if not, write to the Free Software
1.491 + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1.492 +
1.493 +Also add information on how to contact you by electronic and paper mail.
1.494 +
1.495 +You should also get your employer (if you work as a programmer) or your
1.496 +school, if any, to sign a "copyright disclaimer" for the library, if
1.497 +necessary. Here is a sample; alter the names:
1.498 +
1.499 + Yoyodyne, Inc., hereby disclaims all copyright interest in the
1.500 + library `Frob' (a library for tweaking knobs) written by James Random Hacker.
1.501 +
1.502 + <signature of Ty Coon>, 1 April 1990
1.503 + Ty Coon, President of Vice
1.504 +
1.505 +That's all there is to it!
1.506 +
1.507 +
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/gmyth/ChangeLog Wed Sep 20 23:45:35 2006 +0100
2.3 @@ -0,0 +1,24 @@
2.4 +2006-08-17 Rosfran Borges <rosfran.borges@indt.org.br>
2.5 + * Added the correct gstreamer-base package (GSTBASE) at the configure.ac;
2.6 + GSTBASE_CFLAGS and GSTBASE_LIBS variables had the same values from
2.7 + the GST_CFLAGS/GST_LIBS.
2.8 +
2.9 +2006-08-16 Rosfran Borges <rosfran.borges@indt.org.br>
2.10 + * Fixed some installation issues, regarding lib-installing to the
2.11 + correct directory, and copying the header files to the destination
2.12 + dir (make install).
2.13 + * Put 'pkg-config' resource to the Maemo Myth library. The name of the
2.14 + PKG-CONFIG resource is 'maemo-myth', plus the minor and major version.
2.15 + Actually, the version is '0.1', so the library config file is:
2.16 + 'maemo-myth-0.1.pc'. You can type: 'pkg-config --cflags --libs
2.17 + maemo-myth-0.1'.
2.18 + * Many adjustments in the automake/autoconf configuration files
2.19 + (configure.ac, Makefile.am) - some autotools misusage fixed.
2.20 + * Added the MythURI structure, and the URI parsing utility functions
2.21 + (missing in the GLib).
2.22 + * Some functions were exported (myth_socket, mmyth_context), that's
2.23 + why many ther modules need to use them.
2.24 + * Fixed some library dependencies.
2.25 + * Prepared to be used inside the GStreamer (linking with the MythTV
2.26 + plug-in).
2.27 +
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/gmyth/INSTALL Wed Sep 20 23:45:35 2006 +0100
3.3 @@ -0,0 +1,182 @@
3.4 +Basic Installation
3.5 +==================
3.6 +
3.7 + These are generic installation instructions.
3.8 +
3.9 + The `configure' shell script attempts to guess correct values for
3.10 +various system-dependent variables used during compilation. It uses
3.11 +those values to create a `Makefile' in each directory of the package.
3.12 +It may also create one or more `.h' files containing system-dependent
3.13 +definitions. Finally, it creates a shell script `config.status' that
3.14 +you can run in the future to recreate the current configuration, a file
3.15 +`config.cache' that saves the results of its tests to speed up
3.16 +reconfiguring, and a file `config.log' containing compiler output
3.17 +(useful mainly for debugging `configure').
3.18 +
3.19 + If you need to do unusual things to compile the package, please try
3.20 +to figure out how `configure' could check whether to do them, and mail
3.21 +diffs or instructions to the address given in the `README' so they can
3.22 +be considered for the next release. If at some point `config.cache'
3.23 +contains results you don't want to keep, you may remove or edit it.
3.24 +
3.25 + The file `configure.in' is used to create `configure' by a program
3.26 +called `autoconf'. You only need `configure.in' if you want to change
3.27 +it or regenerate `configure' using a newer version of `autoconf'.
3.28 +
3.29 +The simplest way to compile this package is:
3.30 +
3.31 + 1. `cd' to the directory containing the package's source code and type
3.32 + `./configure' to configure the package for your system. If you're
3.33 + using `csh' on an old version of System V, you might need to type
3.34 + `sh ./configure' instead to prevent `csh' from trying to execute
3.35 + `configure' itself.
3.36 +
3.37 + Running `configure' takes awhile. While running, it prints some
3.38 + messages telling which features it is checking for.
3.39 +
3.40 + 2. Type `make' to compile the package.
3.41 +
3.42 + 3. Optionally, type `make check' to run any self-tests that come with
3.43 + the package.
3.44 +
3.45 + 4. Type `make install' to install the programs and any data files and
3.46 + documentation.
3.47 +
3.48 + 5. You can remove the program binaries and object files from the
3.49 + source code directory by typing `make clean'. To also remove the
3.50 + files that `configure' created (so you can compile the package for
3.51 + a different kind of computer), type `make distclean'. There is
3.52 + also a `make maintainer-clean' target, but that is intended mainly
3.53 + for the package's developers. If you use it, you may have to get
3.54 + all sorts of other programs in order to regenerate files that came
3.55 + with the distribution.
3.56 +
3.57 +Compilers and Options
3.58 +=====================
3.59 +
3.60 + Some systems require unusual options for compilation or linking that
3.61 +the `configure' script does not know about. You can give `configure'
3.62 +initial values for variables by setting them in the environment. Using
3.63 +a Bourne-compatible shell, you can do that on the command line like
3.64 +this:
3.65 + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
3.66 +
3.67 +Or on systems that have the `env' program, you can do it like this:
3.68 + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
3.69 +
3.70 +Compiling For Multiple Architectures
3.71 +====================================
3.72 +
3.73 + You can compile the package for more than one kind of computer at the
3.74 +same time, by placing the object files for each architecture in their
3.75 +own directory. To do this, you must use a version of `make' that
3.76 +supports the `VPATH' variable, such as GNU `make'. `cd' to the
3.77 +directory where you want the object files and executables to go and run
3.78 +the `configure' script. `configure' automatically checks for the
3.79 +source code in the directory that `configure' is in and in `..'.
3.80 +
3.81 + If you have to use a `make' that does not supports the `VPATH'
3.82 +variable, you have to compile the package for one architecture at a time
3.83 +in the source code directory. After you have installed the package for
3.84 +one architecture, use `make distclean' before reconfiguring for another
3.85 +architecture.
3.86 +
3.87 +Installation Names
3.88 +==================
3.89 +
3.90 + By default, `make install' will install the package's files in
3.91 +`/usr/local/bin', `/usr/local/man', etc. You can specify an
3.92 +installation prefix other than `/usr/local' by giving `configure' the
3.93 +option `--prefix=PATH'.
3.94 +
3.95 + You can specify separate installation prefixes for
3.96 +architecture-specific files and architecture-independent files. If you
3.97 +give `configure' the option `--exec-prefix=PATH', the package will use
3.98 +PATH as the prefix for installing programs and libraries.
3.99 +Documentation and other data files will still use the regular prefix.
3.100 +
3.101 + In addition, if you use an unusual directory layout you can give
3.102 +options like `--bindir=PATH' to specify different values for particular
3.103 +kinds of files. Run `configure --help' for a list of the directories
3.104 +you can set and what kinds of files go in them.
3.105 +
3.106 + If the package supports it, you can cause programs to be installed
3.107 +with an extra prefix or suffix on their names by giving `configure' the
3.108 +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
3.109 +
3.110 +Optional Features
3.111 +=================
3.112 +
3.113 + Some packages pay attention to `--enable-FEATURE' options to
3.114 +`configure', where FEATURE indicates an optional part of the package.
3.115 +They may also pay attention to `--with-PACKAGE' options, where PACKAGE
3.116 +is something like `gnu-as' or `x' (for the X Window System). The
3.117 +`README' should mention any `--enable-' and `--with-' options that the
3.118 +package recognizes.
3.119 +
3.120 + For packages that use the X Window System, `configure' can usually
3.121 +find the X include and library files automatically, but if it doesn't,
3.122 +you can use the `configure' options `--x-includes=DIR' and
3.123 +`--x-libraries=DIR' to specify their locations.
3.124 +
3.125 +Specifying the System Type
3.126 +==========================
3.127 +
3.128 + There may be some features `configure' can not figure out
3.129 +automatically, but needs to determine by the type of host the package
3.130 +will run on. Usually `configure' can figure that out, but if it prints
3.131 +a message saying it can not guess the host type, give it the
3.132 +`--host=TYPE' option. TYPE can either be a short name for the system
3.133 +type, such as `sun4', or a canonical name with three fields:
3.134 + CPU-COMPANY-SYSTEM
3.135 +
3.136 +See the file `config.sub' for the possible values of each field. If
3.137 +`config.sub' isn't included in this package, then this package doesn't
3.138 +need to know the host type.
3.139 +
3.140 + If you are building compiler tools for cross-compiling, you can also
3.141 +use the `--target=TYPE' option to select the type of system they will
3.142 +produce code for and the `--build=TYPE' option to select the type of
3.143 +system on which you are compiling the package.
3.144 +
3.145 +Sharing Defaults
3.146 +================
3.147 +
3.148 + If you want to set default values for `configure' scripts to share,
3.149 +you can create a site shell script called `config.site' that gives
3.150 +default values for variables like `CC', `cache_file', and `prefix'.
3.151 +`configure' looks for `PREFIX/share/config.site' if it exists, then
3.152 +`PREFIX/etc/config.site' if it exists. Or, you can set the
3.153 +`CONFIG_SITE' environment variable to the location of the site script.
3.154 +A warning: not all `configure' scripts look for a site script.
3.155 +
3.156 +Operation Controls
3.157 +==================
3.158 +
3.159 + `configure' recognizes the following options to control how it
3.160 +operates.
3.161 +
3.162 +`--cache-file=FILE'
3.163 + Use and save the results of the tests in FILE instead of
3.164 + `./config.cache'. Set FILE to `/dev/null' to disable caching, for
3.165 + debugging `configure'.
3.166 +
3.167 +`--help'
3.168 + Print a summary of the options to `configure', and exit.
3.169 +
3.170 +`--quiet'
3.171 +`--silent'
3.172 +`-q'
3.173 + Do not print messages saying which checks are being made. To
3.174 + suppress all normal output, redirect it to `/dev/null' (any error
3.175 + messages will still be shown).
3.176 +
3.177 +`--srcdir=DIR'
3.178 + Look for the package's source code in directory DIR. Usually
3.179 + `configure' can determine that directory automatically.
3.180 +
3.181 +`--version'
3.182 + Print the version of Autoconf used to generate the `configure'
3.183 + script, and exit.
3.184 +
3.185 +`configure' also accepts some other, not widely useful, options.
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/gmyth/Makefile.am Wed Sep 20 23:45:35 2006 +0100
4.3 @@ -0,0 +1,23 @@
4.4 +SUBDIRS= src pixmaps
4.5 +
4.6 +### all of the standard pc files we need to generate
4.7 +pcfiles = gmyth-@GMYTH_MAJORMINOR@.pc
4.8 +
4.9 +all-local: $(pcfiles)
4.10 +
4.11 +### how to generate pc files
4.12 +%-@GMYTH_MAJORMINOR@.pc: %.pc
4.13 + cp $< $@
4.14 +
4.15 +pkgconfigdir = $(libdir)/pkgconfig
4.16 +pkgconfig_DATA = $(pcfiles)
4.17 +
4.18 +include aminclude.am
4.19 +
4.20 +EXTRA_DIST = \
4.21 + autogen.sh \
4.22 + gmyth.pc.in \
4.23 + AUTHORS \
4.24 + COPYING \
4.25 + README
4.26 +
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/gmyth/aminclude.am Wed Sep 20 23:45:35 2006 +0100
5.3 @@ -0,0 +1,186 @@
5.4 +# Copyright (C) 2004 Oren Ben-Kiki
5.5 +# This file is distributed under the same terms as the Automake macro files.
5.6 +
5.7 +# Generate automatic documentation using Doxygen. Goals and variables values
5.8 +# are controlled by the various DX_COND_??? conditionals set by autoconf.
5.9 +#
5.10 +# The provided goals are:
5.11 +# doxygen-doc: Generate all doxygen documentation.
5.12 +# doxygen-run: Run doxygen, which will generate some of the documentation
5.13 +# (HTML, CHM, CHI, MAN, RTF, XML) but will not do the post
5.14 +# processing required for the rest of it (PS, PDF, and some MAN).
5.15 +# doxygen-man: Rename some doxygen generated man pages.
5.16 +# doxygen-ps: Generate doxygen PostScript documentation.
5.17 +# doxygen-pdf: Generate doxygen PDF documentation.
5.18 +#
5.19 +# Note that by default these are not integrated into the automake goals. If
5.20 +# doxygen is used to generate man pages, you can achieve this integration by
5.21 +# setting man3_MANS to the list of man pages generated and then adding the
5.22 +# dependency:
5.23 +#
5.24 +# $(man3_MANS): doxygen-doc
5.25 +#
5.26 +# This will cause make to run doxygen and generate all the documentation.
5.27 +#
5.28 +# The following variable is intended for use in Makefile.am:
5.29 +#
5.30 +# DX_CLEANFILES = everything to clean.
5.31 +#
5.32 +# This is usually added to MOSTLYCLEANFILES.
5.33 +
5.34 +## --------------------------------- ##
5.35 +## Format-independent Doxygen rules. ##
5.36 +## --------------------------------- ##
5.37 +
5.38 +if DX_COND_doc
5.39 +
5.40 +## ------------------------------- ##
5.41 +## Rules specific for HTML output. ##
5.42 +## ------------------------------- ##
5.43 +
5.44 +if DX_COND_html
5.45 +
5.46 +DX_CLEAN_HTML = @DX_DOCDIR@/html
5.47 +
5.48 +endif DX_COND_html
5.49 +
5.50 +## ------------------------------ ##
5.51 +## Rules specific for CHM output. ##
5.52 +## ------------------------------ ##
5.53 +
5.54 +if DX_COND_chm
5.55 +
5.56 +DX_CLEAN_CHM = @DX_DOCDIR@/chm
5.57 +
5.58 +if DX_COND_chi
5.59 +
5.60 +DX_CLEAN_CHI = @DX_DOCDIR@/@PACKAGE@.chi
5.61 +
5.62 +endif DX_COND_chi
5.63 +
5.64 +endif DX_COND_chm
5.65 +
5.66 +## ------------------------------ ##
5.67 +## Rules specific for MAN output. ##
5.68 +## ------------------------------ ##
5.69 +
5.70 +if DX_COND_man
5.71 +
5.72 +DX_CLEAN_MAN = @DX_DOCDIR@/man
5.73 +
5.74 +endif DX_COND_man
5.75 +
5.76 +## ------------------------------ ##
5.77 +## Rules specific for RTF output. ##
5.78 +## ------------------------------ ##
5.79 +
5.80 +if DX_COND_rtf
5.81 +
5.82 +DX_CLEAN_RTF = @DX_DOCDIR@/rtf
5.83 +
5.84 +endif DX_COND_rtf
5.85 +
5.86 +## ------------------------------ ##
5.87 +## Rules specific for XML output. ##
5.88 +## ------------------------------ ##
5.89 +
5.90 +if DX_COND_xml
5.91 +
5.92 +DX_CLEAN_XML = @DX_DOCDIR@/xml
5.93 +
5.94 +endif DX_COND_xml
5.95 +
5.96 +## ----------------------------- ##
5.97 +## Rules specific for PS output. ##
5.98 +## ----------------------------- ##
5.99 +
5.100 +if DX_COND_ps
5.101 +
5.102 +DX_CLEAN_PS = @DX_DOCDIR@/@PACKAGE@.ps
5.103 +
5.104 +DX_PS_GOAL = doxygen-ps
5.105 +
5.106 +doxygen-ps: @DX_DOCDIR@/@PACKAGE@.ps
5.107 +
5.108 +@DX_DOCDIR@/@PACKAGE@.ps: @DX_DOCDIR@/@PACKAGE@.tag
5.109 + cd @DX_DOCDIR@/latex; \
5.110 + rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \
5.111 + $(DX_LATEX) refman.tex; \
5.112 + $(MAKEINDEX_PATH) refman.idx; \
5.113 + $(DX_LATEX) refman.tex; \
5.114 + countdown=5; \
5.115 + while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \
5.116 + refman.log > /dev/null 2>&1 \
5.117 + && test $$countdown -gt 0; do \
5.118 + $(DX_LATEX) refman.tex; \
5.119 + countdown=`expr $$countdown - 1`; \
5.120 + done; \
5.121 + $(DX_DVIPS) -o ../@PACKAGE@.ps refman.dvi
5.122 +
5.123 +endif DX_COND_ps
5.124 +
5.125 +## ------------------------------ ##
5.126 +## Rules specific for PDF output. ##
5.127 +## ------------------------------ ##
5.128 +
5.129 +if DX_COND_pdf
5.130 +
5.131 +DX_CLEAN_PDF = @DX_DOCDIR@/@PACKAGE@.pdf
5.132 +
5.133 +DX_PDF_GOAL = doxygen-pdf
5.134 +
5.135 +doxygen-pdf: @DX_DOCDIR@/@PACKAGE@.pdf
5.136 +
5.137 +@DX_DOCDIR@/@PACKAGE@.pdf: @DX_DOCDIR@/@PACKAGE@.tag
5.138 + cd @DX_DOCDIR@/latex; \
5.139 + rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \
5.140 + $(DX_PDFLATEX) refman.tex; \
5.141 + $(DX_MAKEINDEX) refman.idx; \
5.142 + $(DX_PDFLATEX) refman.tex; \
5.143 + countdown=5; \
5.144 + while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \
5.145 + refman.log > /dev/null 2>&1 \
5.146 + && test $$countdown -gt 0; do \
5.147 + $(DX_PDFLATEX) refman.tex; \
5.148 + countdown=`expr $$countdown - 1`; \
5.149 + done; \
5.150 + mv refman.pdf ../@PACKAGE@.pdf
5.151 +
5.152 +endif DX_COND_pdf
5.153 +
5.154 +## ------------------------------------------------- ##
5.155 +## Rules specific for LaTeX (shared for PS and PDF). ##
5.156 +## ------------------------------------------------- ##
5.157 +
5.158 +if DX_COND_latex
5.159 +
5.160 +DX_CLEAN_LATEX = @DX_DOCDIR@/latex
5.161 +
5.162 +endif DX_COND_latex
5.163 +
5.164 +.PHONY: doxygen-run doxygen-doc $(DX_PS_GOAL) $(DX_PDF_GOAL)
5.165 +
5.166 +.INTERMEDIATE: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL)
5.167 +
5.168 +doxygen-run: @DX_DOCDIR@/@PACKAGE@.tag
5.169 +
5.170 +doxygen-doc: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL)
5.171 +
5.172 +@DX_DOCDIR@/@PACKAGE@.tag: $(DX_CONFIG) $(pkginclude_HEADERS)
5.173 + rm -rf @DX_DOCDIR@
5.174 + $(DX_ENV) $(DX_DOXYGEN) $(srcdir)/$(DX_CONFIG)
5.175 +
5.176 +DX_CLEANFILES = \
5.177 + @DX_DOCDIR@/@PACKAGE@.tag \
5.178 + -r \
5.179 + $(DX_CLEAN_HTML) \
5.180 + $(DX_CLEAN_CHM) \
5.181 + $(DX_CLEAN_CHI) \
5.182 + $(DX_CLEAN_MAN) \
5.183 + $(DX_CLEAN_RTF) \
5.184 + $(DX_CLEAN_XML) \
5.185 + $(DX_CLEAN_PS) \
5.186 + $(DX_CLEAN_PDF) \
5.187 + $(DX_CLEAN_LATEX)
5.188 +
5.189 +endif DX_COND_doc
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/gmyth/autogen.sh Wed Sep 20 23:45:35 2006 +0100
6.3 @@ -0,0 +1,99 @@
6.4 +#!/bin/sh
6.5 +# Run this to generate all the initial makefiles, etc.
6.6 +
6.7 +DIE=0
6.8 +package=gmyth
6.9 +srcfile=configure.ac
6.10 +
6.11 +# a quick cvs co if necessary to alleviate the pain - may remove this
6.12 +# when developers get a clue ;)
6.13 +if test ! -d common;
6.14 +then
6.15 + echo "+ getting common/ from svn"
6.16 + svn co common
6.17 +fi
6.18 +
6.19 +# source helper functions
6.20 +if test ! -f common/autogen-helper.sh;
6.21 +then
6.22 + echo There is something wrong with your source tree.
6.23 + echo You are missing common/autogen-helper.sh
6.24 + exit 1
6.25 +fi
6.26 +. common/autogen-helper.sh
6.27 +
6.28 +CONFIGURE_DEF_OPT='--enable-maintainer-mode'
6.29 +
6.30 +autogen_options
6.31 +
6.32 +echo -n "+ check for build tools"
6.33 +if test ! -z "$NOCHECK"; then echo " skipped"; else echo; fi
6.34 +version_check "autoconf" "$AUTOCONF autoconf autoconf-2.54 autoconf-2.53" \
6.35 + "ftp://ftp.gnu.org/pub/gnu/autoconf/" 2 53 || DIE=1
6.36 +version_check "automake" "$AUTOMAKE automake automake-1.9 automake-1.8 automake-1.7 automake-1.6" \
6.37 + "ftp://ftp.gnu.org/pub/gnu/automake/" 1 6 || DIE=1
6.38 +version_check "libtoolize" "$LIBTOOLIZE libtoolize" \
6.39 + "ftp://ftp.gnu.org/pub/gnu/libtool/" 1 5 0 || DIE=1
6.40 +version_check "pkg-config" "" \
6.41 + "http://www.freedesktop.org/software/pkgconfig" 0 8 0 || DIE=1
6.42 +
6.43 +die_check $DIE
6.44 +
6.45 +aclocal_check || DIE=1
6.46 +autoheader_check || DIE=1
6.47 +
6.48 +die_check $DIE
6.49 +
6.50 +# if no arguments specified then this will be printed
6.51 +if test -z "$*"; then
6.52 + echo "+ checking for autogen.sh options"
6.53 + echo " This autogen script will automatically run ./configure as:"
6.54 + echo " ./configure $CONFIGURE_DEF_OPT"
6.55 + echo " To pass any additional options, please specify them on the $0"
6.56 + echo " command line."
6.57 +fi
6.58 +
6.59 +toplevel_check $srcfile
6.60 +
6.61 +tool_run "$aclocal" "-I m4 $ACLOCAL_FLAGS"
6.62 +tool_run "$libtoolize" "--copy --force"
6.63 +tool_run "$autoheader"
6.64 +
6.65 +# touch the stamp-h.in build stamp so we don't re-run autoheader in maintainer mode -- wingo
6.66 +echo timestamp > stamp-h.in 2> /dev/null
6.67 +
6.68 +tool_run "$autoconf"
6.69 +tool_run "$automake" "-a -c"
6.70 +
6.71 +# if enable exists, add an -enable option for each of the lines in that file
6.72 +if test -f enable; then
6.73 + for a in `cat enable`; do
6.74 + CONFIGURE_FILE_OPT="--enable-$a"
6.75 + done
6.76 +fi
6.77 +
6.78 +# if disable exists, add an -disable option for each of the lines in that file
6.79 +if test -f disable; then
6.80 + for a in `cat disable`; do
6.81 + CONFIGURE_FILE_OPT="$CONFIGURE_FILE_OPT --disable-$a"
6.82 + done
6.83 +fi
6.84 +
6.85 +test -n "$NOCONFIGURE" && {
6.86 + echo "+ skipping configure stage for package $package, as requested."
6.87 + echo "+ autogen.sh done."
6.88 + exit 0
6.89 +}
6.90 +
6.91 +echo "+ running configure ... "
6.92 +test ! -z "$CONFIGURE_DEF_OPT" && echo " ./configure default flags: $CONFIGURE_DEF_OPT"
6.93 +test ! -z "$CONFIGURE_EXT_OPT" && echo " ./configure external flags: $CONFIGURE_EXT_OPT"
6.94 +test ! -z "$CONFIGURE_FILE_OPT" && echo " ./configure enable/disable flags: $CONFIGURE_FILE_OPT"
6.95 +echo
6.96 +
6.97 +./configure $CONFIGURE_DEF_OPT $CONFIGURE_EXT_OPT $CONFIGURE_FILE_OPT || {
6.98 + echo " configure failed"
6.99 + exit 1
6.100 +}
6.101 +
6.102 +echo "Now type 'make' to compile $package."
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/gmyth/common/Makefile.am Wed Sep 20 23:45:35 2006 +0100
7.3 @@ -0,0 +1,1 @@
7.4 +EXTRA_DIST = autogen-helper.sh
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/gmyth/common/autogen-helper.sh Wed Sep 20 23:45:35 2006 +0100
8.3 @@ -0,0 +1,302 @@
8.4 +# a silly hack that generates autoregen.sh but it's handy
8.5 +echo "#!/bin/sh" > autoregen.sh
8.6 +echo "./autogen.sh $@ \$@" >> autoregen.sh
8.7 +chmod +x autoregen.sh
8.8 +
8.9 +# helper functions for autogen.sh
8.10 +
8.11 +debug ()
8.12 +# print out a debug message if DEBUG is a defined variable
8.13 +{
8.14 + if test ! -z "$DEBUG"
8.15 + then
8.16 + echo "DEBUG: $1"
8.17 + fi
8.18 +}
8.19 +
8.20 +version_check ()
8.21 +# check the version of a package
8.22 +# first argument : package name (executable)
8.23 +# second argument : optional path where to look for it instead
8.24 +# third argument : source download url
8.25 +# rest of arguments : major, minor, micro version
8.26 +# all consecutive ones : suggestions for binaries to use
8.27 +# (if not specified in second argument)
8.28 +{
8.29 + PACKAGE=$1
8.30 + PKG_PATH=$2
8.31 + URL=$3
8.32 + MAJOR=$4
8.33 + MINOR=$5
8.34 + MICRO=$6
8.35 +
8.36 + # for backwards compatibility, we let PKG_PATH=PACKAGE when PKG_PATH null
8.37 + if test -z "$PKG_PATH"; then PKG_PATH=$PACKAGE; fi
8.38 + debug "major $MAJOR minor $MINOR micro $MICRO"
8.39 + VERSION=$MAJOR
8.40 + if test ! -z "$MINOR"; then VERSION=$VERSION.$MINOR; else MINOR=0; fi
8.41 + if test ! -z "$MICRO"; then VERSION=$VERSION.$MICRO; else MICRO=0; fi
8.42 +
8.43 + debug "major $MAJOR minor $MINOR micro $MICRO"
8.44 +
8.45 + for SUGGESTION in $PKG_PATH; do
8.46 + COMMAND="$SUGGESTION"
8.47 +
8.48 + # don't check if asked not to
8.49 + test -z "$NOCHECK" && {
8.50 + echo -n " checking for $COMMAND >= $VERSION ... "
8.51 + } || {
8.52 + # we set a var with the same name as the package, but stripped of
8.53 + # unwanted chars
8.54 + VAR=`echo $PACKAGE | sed 's/-//g'`
8.55 + debug "setting $VAR"
8.56 + eval $VAR="$COMMAND"
8.57 + return 0
8.58 + }
8.59 +
8.60 + debug "checking version with $COMMAND"
8.61 + ($COMMAND --version) < /dev/null > /dev/null 2>&1 ||
8.62 + {
8.63 + echo "not found."
8.64 + continue
8.65 + }
8.66 + # strip everything that's not a digit, then use cut to get the first field
8.67 + pkg_version=`$COMMAND --version|head -n 1|sed 's/^[^0-9]*//'|cut -d' ' -f1`
8.68 + debug "pkg_version $pkg_version"
8.69 + # remove any non-digit characters from the version numbers to permit numeric
8.70 + # comparison
8.71 + pkg_major=`echo $pkg_version | cut -d. -f1 | sed s/[a-zA-Z\-].*//g`
8.72 + pkg_minor=`echo $pkg_version | cut -d. -f2 | sed s/[a-zA-Z\-].*//g`
8.73 + pkg_micro=`echo $pkg_version | cut -d. -f3 | sed s/[a-zA-Z\-].*//g`
8.74 + test -z "$pkg_major" && pkg_major=0
8.75 + test -z "$pkg_minor" && pkg_minor=0
8.76 + test -z "$pkg_micro" && pkg_micro=0
8.77 + debug "found major $pkg_major minor $pkg_minor micro $pkg_micro"
8.78 +
8.79 + #start checking the version
8.80 + debug "version check"
8.81 +
8.82 + # reset check
8.83 + WRONG=
8.84 +
8.85 + if [ ! "$pkg_major" -gt "$MAJOR" ]; then
8.86 + debug "major: $pkg_major <= $MAJOR"
8.87 + if [ "$pkg_major" -lt "$MAJOR" ]; then
8.88 + debug "major: $pkg_major < $MAJOR"
8.89 + WRONG=1
8.90 + elif [ ! "$pkg_minor" -gt "$MINOR" ]; then
8.91 + debug "minor: $pkg_minor <= $MINOR"
8.92 + if [ "$pkg_minor" -lt "$MINOR" ]; then
8.93 + debug "minor: $pkg_minor < $MINOR"
8.94 + WRONG=1
8.95 + elif [ "$pkg_micro" -lt "$MICRO" ]; then
8.96 + debug "micro: $pkg_micro < $MICRO"
8.97 + WRONG=1
8.98 + fi
8.99 + fi
8.100 + fi
8.101 +
8.102 + if test ! -z "$WRONG"; then
8.103 + echo "found $pkg_version, not ok !"
8.104 + continue
8.105 + else
8.106 + echo "found $pkg_version, ok."
8.107 + # we set a var with the same name as the package, but stripped of
8.108 + # unwanted chars
8.109 + VAR=`echo $PACKAGE | sed 's/-//g'`
8.110 + debug "setting $VAR"
8.111 + eval $VAR="$COMMAND"
8.112 + return 0
8.113 + fi
8.114 + done
8.115 +
8.116 + echo "not found !"
8.117 + echo "You must have $PACKAGE installed to compile $package."
8.118 + echo "Download the appropriate package for your distribution,"
8.119 + echo "or get the source tarball at $URL"
8.120 + return 1;
8.121 +}
8.122 +
8.123 +aclocal_check ()
8.124 +{
8.125 + # normally aclocal is part of automake
8.126 + # so we expect it to be in the same place as automake
8.127 + # so if a different automake is supplied, we need to adapt as well
8.128 + # so how's about replacing automake with aclocal in the set var,
8.129 + # and saving that in $aclocal ?
8.130 + # note, this will fail if the actual automake isn't called automake*
8.131 + # or if part of the path before it contains it
8.132 + if [ -z "$automake" ]; then
8.133 + echo "Error: no automake variable set !"
8.134 + return 1
8.135 + else
8.136 + aclocal=`echo $automake | sed s/automake/aclocal/`
8.137 + debug "aclocal: $aclocal"
8.138 + if [ "$aclocal" != "aclocal" ];
8.139 + then
8.140 + CONFIGURE_DEF_OPT="$CONFIGURE_DEF_OPT --with-aclocal=$aclocal"
8.141 + fi
8.142 + if [ ! -x `which $aclocal` ]; then
8.143 + echo "Error: cannot execute $aclocal !"
8.144 + return 1
8.145 + fi
8.146 + fi
8.147 +}
8.148 +
8.149 +autoheader_check ()
8.150 +{
8.151 + # same here - autoheader is part of autoconf
8.152 + # use the same voodoo
8.153 + if [ -z "$autoconf" ]; then
8.154 + echo "Error: no autoconf variable set !"
8.155 + return 1
8.156 + else
8.157 + autoheader=`echo $autoconf | sed s/autoconf/autoheader/`
8.158 + debug "autoheader: $autoheader"
8.159 + if [ "$autoheader" != "autoheader" ];
8.160 + then
8.161 + CONFIGURE_DEF_OPT="$CONFIGURE_DEF_OPT --with-autoheader=$autoheader"
8.162 + fi
8.163 + if [ ! -x `which $autoheader` ]; then
8.164 + echo "Error: cannot execute $autoheader !"
8.165 + return 1
8.166 + fi
8.167 + fi
8.168 +
8.169 +}
8.170 +
8.171 +autoconf_2_52d_check ()
8.172 +{
8.173 + # autoconf 2.52d has a weird issue involving a yes:no error
8.174 + # so don't allow it's use
8.175 + test -z "$NOCHECK" && {
8.176 + ac_version=`$autoconf --version|head -n 1|sed 's/^[a-zA-Z\.\ ()]*//;s/ .*$//'`
8.177 + if test "$ac_version" = "2.52d"; then
8.178 + echo "autoconf 2.52d has an issue with our current build."
8.179 + echo "We don't know who's to blame however. So until we do, get a"
8.180 + echo "regular version. RPM's of a working version are on the gstreamer site."
8.181 + exit 1
8.182 + fi
8.183 + }
8.184 + return 0
8.185 +}
8.186 +
8.187 +die_check ()
8.188 +{
8.189 + # call with $DIE
8.190 + # if set to 1, we need to print something helpful then die
8.191 + DIE=$1
8.192 + if test "x$DIE" = "x1";
8.193 + then
8.194 + echo
8.195 + echo "- Please get the right tools before proceeding."
8.196 + echo "- Alternatively, if you're sure we're wrong, run with --nocheck."
8.197 + exit 1
8.198 + fi
8.199 +}
8.200 +
8.201 +autogen_options ()
8.202 +{
8.203 + if test "x$1" = "x"; then
8.204 + return 0
8.205 + fi
8.206 +
8.207 + while test "x$1" != "x" ; do
8.208 + optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
8.209 + case "$1" in
8.210 + --noconfigure)
8.211 + NOCONFIGURE=defined
8.212 + AUTOGEN_EXT_OPT="$AUTOGEN_EXT_OPT --noconfigure"
8.213 + echo "+ configure run disabled"
8.214 + shift
8.215 + ;;
8.216 + --nocheck)
8.217 + AUTOGEN_EXT_OPT="$AUTOGEN_EXT_OPT --nocheck"
8.218 + NOCHECK=defined
8.219 + echo "+ autotools version check disabled"
8.220 + shift
8.221 + ;;
8.222 + --debug)
8.223 + DEBUG=defined
8.224 + AUTOGEN_EXT_OPT="$AUTOGEN_EXT_OPT --debug"
8.225 + echo "+ debug output enabled"
8.226 + shift
8.227 + ;;
8.228 + --prefix=*)
8.229 + CONFIGURE_EXT_OPT="$CONFIGURE_EXT_OPT --prefix=$optarg"
8.230 + echo "+ passing --prefix=$optarg to configure"
8.231 + shift
8.232 + ;;
8.233 + --prefix)
8.234 + shift
8.235 + echo "DEBUG: $1"
8.236 + CONFIGURE_EXT_OPT="$CONFIGURE_EXT_OPT --prefix=$1"
8.237 + echo "+ passing --prefix=$1 to configure"
8.238 + shift
8.239 + ;;
8.240 + -h|--help)
8.241 + echo "autogen.sh (autogen options) -- (configure options)"
8.242 + echo "autogen.sh help options: "
8.243 + echo " --noconfigure don't run the configure script"
8.244 + echo " --nocheck don't do version checks"
8.245 + echo " --debug debug the autogen process"
8.246 + echo " --prefix will be passed on to configure"
8.247 + echo
8.248 + echo " --with-autoconf PATH use autoconf in PATH"
8.249 + echo " --with-automake PATH use automake in PATH"
8.250 + echo
8.251 + echo "to pass options to configure, put them as arguments after -- "
8.252 + exit 1
8.253 + ;;
8.254 + --with-automake=*)
8.255 + AUTOMAKE=$optarg
8.256 + echo "+ using alternate automake in $optarg"
8.257 + CONFIGURE_DEF_OPT="$CONFIGURE_DEF_OPT --with-automake=$AUTOMAKE"
8.258 + shift
8.259 + ;;
8.260 + --with-autoconf=*)
8.261 + AUTOCONF=$optarg
8.262 + echo "+ using alternate autoconf in $optarg"
8.263 + CONFIGURE_DEF_OPT="$CONFIGURE_DEF_OPT --with-autoconf=$AUTOCONF"
8.264 + shift
8.265 + ;;
8.266 + --disable*|--enable*|--with*)
8.267 + echo "+ passing option $1 to configure"
8.268 + CONFIGURE_EXT_OPT="$CONFIGURE_EXT_OPT $1"
8.269 + shift
8.270 + ;;
8.271 + --) shift ; break ;;
8.272 + *) echo "- ignoring unknown autogen.sh argument $1"; shift ;;
8.273 + esac
8.274 + done
8.275 +
8.276 + for arg do CONFIGURE_EXT_OPT="$CONFIGURE_EXT_OPT $arg"; done
8.277 + if test ! -z "$CONFIGURE_EXT_OPT"
8.278 + then
8.279 + echo "+ options passed to configure: $CONFIGURE_EXT_OPT"
8.280 + fi
8.281 +}
8.282 +
8.283 +toplevel_check ()
8.284 +{
8.285 + srcfile=$1
8.286 + test -f $srcfile || {
8.287 + echo "You must run this script in the top-level $package directory"
8.288 + exit 1
8.289 + }
8.290 +}
8.291 +
8.292 +
8.293 +tool_run ()
8.294 +{
8.295 + tool=$1
8.296 + options=$2
8.297 + run_if_fail=$3
8.298 + echo "+ running $tool $options..."
8.299 + $tool $options || {
8.300 + echo
8.301 + echo $tool failed
8.302 + eval $run_if_fail
8.303 + exit 1
8.304 + }
8.305 +}
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/gmyth/configure.ac Wed Sep 20 23:45:35 2006 +0100
9.3 @@ -0,0 +1,224 @@
9.4 +# -*- Autoconf -*-
9.5 +# Process this file with autoconf to produce a configure script.
9.6 +
9.7 +AC_PREREQ(2.50)
9.8 +
9.9 +AC_INIT([gmyth],[0.1])
9.10 +
9.11 +dnl AC_CONFIG_SRCDIR([src/mmyth_main.c])
9.12 +AC_CONFIG_HEADER(config.h)
9.13 +
9.14 +dnl when going to/from release please set the nano (fourth number) right !
9.15 +dnl releases only do Wall, SVN and prerelease does Werror too
9.16 +AS_VERSION(gmyth, GMYTH, 0, 1, 0, 3, GMYTH_SVN="no", GMYTH_SVN="yes")
9.17 +
9.18 +GMYTH_MAJORMINOR=$GMYTH_MAJOR_VERSION.$GMYTH_MINOR_VERSION
9.19 +
9.20 +AC_SUBST(GMYTH_MAJORMINOR)
9.21 +
9.22 +dnl AM_MAINTAINER_MODE provides the option to enable maintainer mode
9.23 +AM_MAINTAINER_MODE
9.24 +dnl make aclocal work in maintainer mode
9.25 +AC_SUBST(ACLOCAL_AMFLAGS, "-I m4")
9.26 +
9.27 +# Checks for programs.
9.28 +# check for tools
9.29 +# Make sure CFLAGS is defined to stop AC_PROC_CC adding -g
9.30 +CFLAGS="$CFLAGS -Wall"
9.31 +AC_PROG_CC
9.32 +AC_PROG_LIBTOOL
9.33 +
9.34 +dnl Generate doxygen documentation
9.35 +DX_HTML_FEATURE(ON)
9.36 +DX_CHM_FEATURE(OFF)
9.37 +DX_CHI_FEATURE(OFF)
9.38 +DX_MAN_FEATURE(OFF)
9.39 +DX_RTF_FEATURE(OFF)
9.40 +DX_XML_FEATURE(OFF)
9.41 +DX_PDF_FEATURE(OFF)
9.42 +DX_PS_FEATURE(OFF)
9.43 +DX_INIT_DOXYGEN(gmyth, doxygen.cfg, docs)
9.44 +
9.45 +
9.46 +# Checks for libraries.
9.47 +
9.48 +# Checks for header files.
9.49 +AC_HEADER_STDC
9.50 +AC_CHECK_HEADERS([fcntl.h stdint.h stdlib.h string.h sys/ioctl.h sys/socket.h unistd.h])
9.51 +
9.52 +# Checks for typedefs, structures, and compiler characteristics.
9.53 +AC_C_CONST
9.54 +AC_TYPE_PID_T
9.55 +AC_STRUCT_TM
9.56 +
9.57 +# Checks for library functions.
9.58 +AC_FUNC_FORK
9.59 +AC_PROG_GCC_TRADITIONAL
9.60 +AC_FUNC_MALLOC
9.61 +AC_FUNC_MKTIME
9.62 +AC_FUNC_VPRINTF
9.63 +AC_CHECK_FUNCS([memset socket stime strstr strtoul])
9.64 +
9.65 +AM_INIT_AUTOMAKE($PACKAGE, $VERSION)
9.66 +
9.67 +# Checks required packages
9.68 +
9.69 +dnl Test if --disable-debug given
9.70 +AC_ARG_ENABLE(debug,
9.71 + [AC_HELP_STRING([--disable-debug], [disable debugging mode])],
9.72 + enable_debug="$enableval",
9.73 + enable_debug=yes)
9.74 +
9.75 +if test "x$enable_debug" = "xyes" ; then
9.76 + CFLAGS="$CFLAGS -g"
9.77 +else
9.78 + AC_DEFINE( NDEBUG, 1, [disable debug messages] )
9.79 + CFLAGS="$CFLAGS -O2 -DG_DISABLE_CHECKS -DNDEBUG"
9.80 +fi
9.81 +
9.82 +AM_CONDITIONAL( NDEBUG, test "x$enable_debug" = "xyes" )
9.83 +
9.84 +# Check for pkgconfig
9.85 +AC_CHECK_PROG(HAVE_PKGCONFIG, pkg-config, yes, no)
9.86 +# Give error and exit if we don't have pkgconfig
9.87 +if test "x$HAVE_PKGCONFIG" = "xno"; then
9.88 + AC_MSG_ERROR(you need to have pkgconfig installed !)
9.89 +fi
9.90 +
9.91 +# Check for Glib2.0
9.92 +PKG_CHECK_MODULES(GLIB, glib-2.0, HAVE_GLIB=yes,HAVE_GLIB=no)
9.93 +
9.94 +# Give error and exit if we don't have glib
9.95 +if test "x$HAVE_GLIB" = "xno"; then
9.96 + AC_MSG_ERROR(you need glib-2.0 installed)
9.97 +fi
9.98 +
9.99 +# make GLIB_CFLAGS and GLIB_LIBS available
9.100 +AC_SUBST(GLIB_CFLAGS)
9.101 +AC_SUBST(GLIB_LIBS)
9.102 +
9.103 +# Check for GObject2.0
9.104 +PKG_CHECK_MODULES(GOBJECT,
9.105 + gobject-2.0,
9.106 + HAVE_GOBJECT=yes, HAVE_GOBJECT=no)
9.107 +
9.108 +# Give error and exit if we don't have gobject
9.109 +if test "x$HAVE_GOBJECT" = "xno"; then
9.110 + AC_MSG_ERROR(you need gobject-2.0 installed)
9.111 +fi
9.112 +
9.113 +# make GOBJECT_CFLAGS and GOBJECT_LIBS available
9.114 +AC_SUBST(GOBJECT_CFLAGS)
9.115 +AC_SUBST(GOBJECT_LIBS)
9.116 +
9.117 +# Check for GTK+-2.0
9.118 +PKG_CHECK_MODULES(GTK, gtk+-2.0, HAVE_GTK=yes,HAVE_GTK=no)
9.119 +
9.120 +# Give error and exit if we don't have gtk
9.121 +if test "x$HAVE_GTK" = "xyes"; then
9.122 + AC_DEFINE(WITH_GTK, 1, [build with GTK+ related stuff])
9.123 + dnl AC_MSG_ERROR(you need gtk+-2.0 installed)
9.124 +else
9.125 + AC_MSG_RESULT(no)
9.126 +fi
9.127 +
9.128 +AM_CONDITIONAL(WITH_GTK, test "x$HAVE_GTK" = "xyes" )
9.129 +
9.130 +# make GTK_CFLAGS and GTK_LIBS available
9.131 +AC_SUBST(GTK_CFLAGS)
9.132 +AC_SUBST(GTK_LIBS)
9.133 +
9.134 +dnl ========== Check for Hildon Libraries
9.135 +PKG_CHECK_MODULES(HILDON,
9.136 + hildon-lgpl libosso hildon-status-bar-lib libhildonmenu hildon-base-lib hildon-control-panel hildon-libs,
9.137 + HAVE_HILDON=yes, HAVE_HILDON=no)
9.138 +
9.139 +if test "x$HAVE_HILDON" = "xyes"; then
9.140 + AC_DEFINE(MAEMO_PLATFORM, 1, [build with hildon libs])
9.141 + HILDON_CFLAGS="$HILDON_CFLAGS -DMAEMO_PLATFORM=1"
9.142 +else
9.143 + AC_MSG_RESULT(no)
9.144 +fi
9.145 +
9.146 +AM_CONDITIONAL(MAEMO_PLATFORM, test "x$HAVE_HILDON" = "xyes")
9.147 +
9.148 +dnl make HILDON_CFLAGS and HILDON_LIBS available
9.149 +AC_SUBST(HILDON_CFLAGS)
9.150 +AC_SUBST(HILDON_LIBS)
9.151 +
9.152 +# Check for libxml-2.0
9.153 +PKG_CHECK_MODULES(LIBXML, libxml-2.0, HAVE_LIBXML=yes,HAVE_LIBXML=no)
9.154 +
9.155 +# Give error and exit if we don't have gtk
9.156 +if test "x$HAVE_LIBXML" = "xno"; then
9.157 + AC_MSG_ERROR(you need libxml-2.0 installed)
9.158 +fi
9.159 +
9.160 +# make LIBXML_CFLAGS and LIBXML_LIBS available
9.161 +AC_SUBST(LIBXML_CFLAGS)
9.162 +AC_SUBST(LIBXML_LIBS)
9.163 +
9.164 +
9.165 +# check for gstreamer development files
9.166 +GST_REQUIRED=0.10
9.167 +GST_MAJORMINOR=0.10
9.168 +PKG_CHECK_MODULES(GST, \
9.169 + gstreamer-$GST_MAJORMINOR >= $GST_REQUIRED,
9.170 + HAVE_GST=yes, HAVE_GST=no)
9.171 +
9.172 +# Give error and exit if we don't have gstreamer
9.173 +if test "x$HAVE_GST" = "xno"; then
9.174 + AC_MSG_ERROR(you need gstreamer development packages installed !)
9.175 +fi
9.176 +
9.177 +# make GST_CFLAGS and GST_LIBS available
9.178 +AC_SUBST(GST_CFLAGS)
9.179 +AC_SUBST(GST_LIBS)
9.180 +
9.181 +# check for gstreamer-base plugins (xoverlay interface)
9.182 +GSTBASE_REQUIRED=0.10
9.183 +GSTBASE_MAJORMINOR=0.10
9.184 +PKG_CHECK_MODULES(GSTBASE, \
9.185 + gstreamer-base-$GSTBASE_MAJORMINOR >= $GSTBASE_REQUIRED,
9.186 + HAVE_GSTBASE=yes, HAVE_GSTBASE=no)
9.187 +
9.188 +# Give error and exit if we don't have gstreamer base libraries
9.189 +if test "x$HAVE_GSTBASE" = "xno"; then
9.190 + AC_MSG_ERROR(you need gstreamer base development packages installed !)
9.191 +fi
9.192 +
9.193 +# make GSTBASE_CFLAGS and GSTBASE_LIBS available
9.194 +AC_SUBST(GSTBASE_CFLAGS)
9.195 +AC_SUBST(GSTBASE_LIBS)
9.196 +
9.197 +
9.198 +# make GST_MAJORMINOR available in Makefile.am
9.199 +AC_SUBST(GST_MAJORMINOR)
9.200 +
9.201 +#
9.202 +# mysql libraries
9.203 +#
9.204 +AC_CHECK_PROG(MYSQL_CFLAGS,mysql_config,`mysql_config --cflags`)
9.205 +if test -z "$MYSQL_CFLAGS"; then
9.206 + AC_MSG_ERROR([Could not find mysql_config script. Make sure the mysql client libraries are installed])
9.207 +fi
9.208 +AC_SUBST(MYSQL_CFLAGS)
9.209 +
9.210 +
9.211 +AC_CHECK_PROG(MYSQL_LIBS,mysql_config,`mysql_config --libs`)
9.212 +if test -z "$MYSQL_LIBS"; then
9.213 + AC_MSG_ERROR([Could not find mysql_config script. Make sure the mysql client libraries are installed])
9.214 +fi
9.215 +AC_SUBST(MYSQL_LIBS)
9.216 +
9.217 +#dnl Enable gtk-doc
9.218 +#GTK_DOC_CHECK(1.4)
9.219 +
9.220 +
9.221 +AC_CONFIG_FILES([Makefile
9.222 + pixmaps/Makefile
9.223 + src/Makefile
9.224 + src/libgmyth/Makefile
9.225 + src/gui/Makefile
9.226 + gmyth.pc])
9.227 +AC_OUTPUT
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/gmyth/data/settings/history.dat Wed Sep 20 23:45:35 2006 +0100
10.3 @@ -0,0 +1,3 @@
10.4 +# MIPTV history file
10.5 +# Stores the last network frequency used
10.6 +602000000
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/gmyth/debian/changelog Wed Sep 20 23:45:35 2006 +0100
11.3 @@ -0,0 +1,6 @@
11.4 +mmyth (0.1-indt1) unstable; urgency=low
11.5 +
11.6 + * Initial Maemo Package.
11.7 +
11.8 + -- Hallyson Melo <hallyson.melo@indt.org.br> Fri, 15 Sep 2006 10:26:16 -0300
11.9 +
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/gmyth/debian/compat Wed Sep 20 23:45:35 2006 +0100
12.3 @@ -0,0 +1,1 @@
12.4 +4
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/gmyth/debian/control Wed Sep 20 23:45:35 2006 +0100
13.3 @@ -0,0 +1,17 @@
13.4 +Source: mmyth
13.5 +Section: user/accessories
13.6 +Priority: optional
13.7 +Maintainer: Hallyson Melo <hallyson.melo@indt.org.br>
13.8 +Build-Depends: debhelper, libgtk2.0-dev (>= 2.4.0),
13.9 + libosso-dev, hildon-libs-dev, hildon-fm-dev
13.10 +Standards-Version: 3.6.2
13.11 +
13.12 +Package: mmyth
13.13 +Architecture: any
13.14 +Depends: ${shlibs:Depends}, ${misc:Depends}, maemo-select-menu-location
13.15 +Provides: MythTV
13.16 +Description: MythTV frontend
13.17 + NONONONONONONONONONONONONONONONONO
13.18 + NONONONONONONONONONONo
13.19 + .
13.20 + NONNONONONON
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/gmyth/debian/control.in Wed Sep 20 23:45:35 2006 +0100
14.3 @@ -0,0 +1,17 @@
14.4 +Source: mmyth
14.5 +Section: user/accessories
14.6 +Priority: optional
14.7 +Maintainer: Hallyson Melo <hallyson.melo@indt.org.br>
14.8 +Build-Depends: debhelper, libgtk2.0-dev (>= 2.4.0),
14.9 + libosso-dev, hildon-libs-dev, hildon-fm-dev
14.10 +Standards-Version: 3.6.2
14.11 +
14.12 +Package: mmyth
14.13 +Architecture: any
14.14 +Depends: ${shlibs:Depends}, ${misc:Depends}, maemo-select-menu-location
14.15 +Provides: MythTV
14.16 +Description: MythTV frontend
14.17 + NONONONONONONONONONONONONONONONONO
14.18 + NONONONONONONONONONONo
14.19 + .
14.20 + NONNONONONON
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/gmyth/debian/mmyth.desktop Wed Sep 20 23:45:35 2006 +0100
15.3 @@ -0,0 +1,10 @@
15.4 +[Desktop Entry]
15.5 +Encoding=UTF-8
15.6 +Version=0.1
15.7 +Type=Application
15.8 +Name=Maemo Myth
15.9 +Exec=/usr/bin/mmyth
15.10 +Terminal=false
15.11 +X-HildonDesk-ShowInToolbar=true
15.12 +X-Osso-Type=application/x-executable
15.13 +StartupWMClass=mmyth
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/gmyth/debian/mmyth.dirs Wed Sep 20 23:45:35 2006 +0100
16.3 @@ -0,0 +1,3 @@
16.4 +usr/share/pixmaps
16.5 +usr/share/applications/hildon
16.6 +usr/share/dbus-1/services
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
17.2 +++ b/gmyth/debian/mmyth.postinst Wed Sep 20 23:45:35 2006 +0100
17.3 @@ -0,0 +1,5 @@
17.4 +#! /bin/sh
17.5 +
17.6 +maemo-select-menu-location mmyth.desktop tana_fi_extras
17.7 +
17.8 +exit 0
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
18.2 +++ b/gmyth/debian/mmyth.service Wed Sep 20 23:45:35 2006 +0100
18.3 @@ -0,0 +1,3 @@
18.4 +[D-BUS Service]
18.5 +Name=com.nokia.xournal
18.6 +Exec=/usr/bin/xournal
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
19.2 +++ b/gmyth/debian/rules Wed Sep 20 23:45:35 2006 +0100
19.3 @@ -0,0 +1,15 @@
19.4 +#!/usr/bin/make -f
19.5 +# -*- mode: makefile; coding: utf-8 -*-
19.6 +
19.7 +include /usr/share/cdbs/1/rules/debhelper.mk
19.8 +include /usr/share/cdbs/1/class/gnome.mk
19.9 +include /usr/share/cdbs/1/rules/simple-patchsys.mk
19.10 +include /usr/share/gnome-pkg-tools/1/rules/uploaders.mk
19.11 +
19.12 +DEB_CONFIGURE_EXTRA_FLAGS := --prefix=/usr
19.13 +
19.14 +binary-install/mmyth::
19.15 +# /usr/bin/install -p -m 644 debian/mmyth.png `pwd`/debian/mmyth/usr/share/pixmaps
19.16 + /usr/bin/install -p -m 644 debian/mmyth.desktop `pwd`/debian/mmyth/usr/share/applications/hildon
19.17 +# /usr/bin/install -p -m 644 debian/mmyth.service `pwd`/debian/mmyth/usr/share/dbus-1/services
19.18 +
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
20.2 +++ b/gmyth/doxygen.cfg Wed Sep 20 23:45:35 2006 +0100
20.3 @@ -0,0 +1,212 @@
20.4 +# Doxyfile 1.4.2
20.5 +
20.6 +#---------------------------------------------------------------------------
20.7 +# Project related configuration options
20.8 +#---------------------------------------------------------------------------
20.9 +PROJECT_NAME = $(PROJECT)-$(VERSION)
20.10 +PROJECT_NUMBER =
20.11 +OUTPUT_DIRECTORY = $(DOCDIR)
20.12 +CREATE_SUBDIRS = NO
20.13 +OUTPUT_LANGUAGE = English
20.14 +USE_WINDOWS_ENCODING = NO
20.15 +BRIEF_MEMBER_DESC = YES
20.16 +REPEAT_BRIEF = YES
20.17 +ABBREVIATE_BRIEF = YES
20.18 +ALWAYS_DETAILED_SEC = NO
20.19 +INLINE_INHERITED_MEMB = NO
20.20 +STRIP_FROM_INC_PATH = $(SRCDIR)/src/libgmyth
20.21 +FULL_PATH_NAMES = YES
20.22 +STRIP_FROM_PATH = $(SRCDIR)/src/libgmyth
20.23 +SHORT_NAMES = YES
20.24 +JAVADOC_AUTOBRIEF = YES
20.25 +MULTILINE_CPP_IS_BRIEF = NO
20.26 +DETAILS_AT_TOP = YES
20.27 +INHERIT_DOCS = YES
20.28 +DISTRIBUTE_GROUP_DOC = NO
20.29 +TAB_SIZE = 8
20.30 +ALIASES =
20.31 +OPTIMIZE_OUTPUT_FOR_C = YES
20.32 +OPTIMIZE_OUTPUT_JAVA = NO
20.33 +SUBGROUPING = YES
20.34 +#---------------------------------------------------------------------------
20.35 +# Build related configuration options
20.36 +#---------------------------------------------------------------------------
20.37 +EXTRACT_ALL = YES
20.38 +EXTRACT_PRIVATE = NO
20.39 +EXTRACT_STATIC = NO
20.40 +EXTRACT_LOCAL_CLASSES = YES
20.41 +EXTRACT_LOCAL_METHODS = YES
20.42 +HIDE_UNDOC_MEMBERS = NO
20.43 +HIDE_UNDOC_CLASSES = NO
20.44 +HIDE_FRIEND_COMPOUNDS = NO
20.45 +HIDE_IN_BODY_DOCS = NO
20.46 +INTERNAL_DOCS = NO
20.47 +CASE_SENSE_NAMES = NO
20.48 +HIDE_SCOPE_NAMES = NO
20.49 +SHOW_INCLUDE_FILES = YES
20.50 +INLINE_INFO = YES
20.51 +SORT_MEMBER_DOCS = YES
20.52 +SORT_BRIEF_DOCS = NO
20.53 +SORT_BY_SCOPE_NAME = NO
20.54 +GENERATE_TODOLIST = YES
20.55 +GENERATE_TESTLIST = YES
20.56 +GENERATE_BUGLIST = YES
20.57 +GENERATE_DEPRECATEDLIST= YES
20.58 +ENABLED_SECTIONS =
20.59 +MAX_INITIALIZER_LINES = 30
20.60 +SHOW_USED_FILES = YES
20.61 +#---------------------------------------------------------------------------
20.62 +# configuration options related to warning and progress messages
20.63 +#---------------------------------------------------------------------------
20.64 +QUIET = YES
20.65 +WARNINGS = YES
20.66 +WARN_IF_UNDOCUMENTED = YES
20.67 +WARN_IF_DOC_ERROR = YES
20.68 +WARN_FORMAT = "$file:$line: $text"
20.69 +WARN_LOGFILE =
20.70 +#---------------------------------------------------------------------------
20.71 +# configuration options related to the input files
20.72 +#---------------------------------------------------------------------------
20.73 +INPUT = $(SRCDIR)/src/libgmyth
20.74 +FILE_PATTERNS = *.c *.h
20.75 +RECURSIVE = YES
20.76 +EXCLUDE =
20.77 +EXCLUDE_SYMLINKS = NO
20.78 +EXCLUDE_PATTERNS =
20.79 +EXAMPLE_PATH = $(SRCDIR)/src/gui
20.80 +EXAMPLE_PATTERNS =
20.81 +EXAMPLE_RECURSIVE = NO
20.82 +IMAGE_PATH =
20.83 +INPUT_FILTER =
20.84 +FILTER_SOURCE_FILES = NO
20.85 +#---------------------------------------------------------------------------
20.86 +# configuration options related to source browsing
20.87 +#---------------------------------------------------------------------------
20.88 +SOURCE_BROWSER = YES
20.89 +INLINE_SOURCES = NO
20.90 +STRIP_CODE_COMMENTS = YES
20.91 +REFERENCED_BY_RELATION = YES
20.92 +REFERENCES_RELATION = YES
20.93 +VERBATIM_HEADERS = YES
20.94 +#---------------------------------------------------------------------------
20.95 +# configuration options related to the alphabetical class index
20.96 +#---------------------------------------------------------------------------
20.97 +ALPHABETICAL_INDEX = NO
20.98 +COLS_IN_ALPHA_INDEX = 5
20.99 +IGNORE_PREFIX =
20.100 +#---------------------------------------------------------------------------
20.101 +# configuration options related to the HTML output
20.102 +#---------------------------------------------------------------------------
20.103 +GENERATE_HTML = $(GENERATE_HTML)
20.104 +HTML_OUTPUT = html
20.105 +HTML_FILE_EXTENSION = .html
20.106 +HTML_HEADER =
20.107 +HTML_FOOTER =
20.108 +HTML_STYLESHEET =
20.109 +HTML_ALIGN_MEMBERS = YES
20.110 +GENERATE_HTMLHELP = $(GENERATE_CHM)
20.111 +CHM_FILE = ../$(PROJECT).chm
20.112 +HHC_LOCATION = $(HHC_PATH)
20.113 +GENERATE_CHI = $(GENERATE_CHI)
20.114 +BINARY_TOC = YES
20.115 +TOC_EXPAND = YES
20.116 +DISABLE_INDEX = NO
20.117 +ENUM_VALUES_PER_LINE = 4
20.118 +GENERATE_TREEVIEW = YES
20.119 +TREEVIEW_WIDTH = 250
20.120 +#---------------------------------------------------------------------------
20.121 +# configuration options related to the LaTeX output
20.122 +#---------------------------------------------------------------------------
20.123 +GENERATE_LATEX = $(GENERATE_LATEX)
20.124 +LATEX_OUTPUT = latex
20.125 +LATEX_CMD_NAME = latex
20.126 +MAKEINDEX_CMD_NAME = makeindex
20.127 +COMPACT_LATEX = NO
20.128 +PAPER_TYPE = $(PAPER_SIZE)
20.129 +EXTRA_PACKAGES =
20.130 +LATEX_HEADER =
20.131 +PDF_HYPERLINKS = NO
20.132 +USE_PDFLATEX = NO
20.133 +LATEX_BATCHMODE = YES
20.134 +LATEX_HIDE_INDICES = NO
20.135 +#---------------------------------------------------------------------------
20.136 +# configuration options related to the RTF output
20.137 +#---------------------------------------------------------------------------
20.138 +GENERATE_RTF = $(GENERATE_RTF)
20.139 +RTF_OUTPUT = rtf
20.140 +COMPACT_RTF = NO
20.141 +RTF_HYPERLINKS = NO
20.142 +RTF_STYLESHEET_FILE =
20.143 +RTF_EXTENSIONS_FILE =
20.144 +#---------------------------------------------------------------------------
20.145 +# configuration options related to the man page output
20.146 +#---------------------------------------------------------------------------
20.147 +GENERATE_MAN = $(GENERATE_MAN)
20.148 +MAN_OUTPUT = man
20.149 +MAN_EXTENSION = .1
20.150 +MAN_LINKS = NO
20.151 +#---------------------------------------------------------------------------
20.152 +# configuration options related to the XML output
20.153 +#---------------------------------------------------------------------------
20.154 +GENERATE_XML = $(GENERATE_XML)
20.155 +XML_OUTPUT = xml
20.156 +XML_SCHEMA =
20.157 +XML_DTD =
20.158 +XML_PROGRAMLISTING = YES
20.159 +#---------------------------------------------------------------------------
20.160 +# configuration options for the AutoGen Definitions output
20.161 +#---------------------------------------------------------------------------
20.162 +GENERATE_AUTOGEN_DEF = NO
20.163 +#---------------------------------------------------------------------------
20.164 +# configuration options related to the Perl module output
20.165 +#---------------------------------------------------------------------------
20.166 +GENERATE_PERLMOD = NO
20.167 +PERLMOD_LATEX = NO
20.168 +PERLMOD_PRETTY = YES
20.169 +PERLMOD_MAKEVAR_PREFIX =
20.170 +#---------------------------------------------------------------------------
20.171 +# Configuration options related to the preprocessor
20.172 +#---------------------------------------------------------------------------
20.173 +ENABLE_PREPROCESSING = YES
20.174 +MACRO_EXPANSION = NO
20.175 +EXPAND_ONLY_PREDEF = NO
20.176 +SEARCH_INCLUDES = YES
20.177 +INCLUDE_PATH =
20.178 +INCLUDE_FILE_PATTERNS =
20.179 +PREDEFINED =
20.180 +EXPAND_AS_DEFINED =
20.181 +SKIP_FUNCTION_MACROS = YES
20.182 +#---------------------------------------------------------------------------
20.183 +# Configuration::additions related to external references
20.184 +#---------------------------------------------------------------------------
20.185 +TAGFILES =
20.186 +GENERATE_TAGFILE = $(DOCDIR)/$(PROJECT).tag
20.187 +ALLEXTERNALS = NO
20.188 +EXTERNAL_GROUPS = YES
20.189 +PERL_PATH = $(PERL_PATH)
20.190 +#---------------------------------------------------------------------------
20.191 +# Configuration options related to the dot tool
20.192 +#---------------------------------------------------------------------------
20.193 +CLASS_DIAGRAMS = YES
20.194 +HIDE_UNDOC_RELATIONS = YES
20.195 +HAVE_DOT = $(HAVE_DOT)
20.196 +CLASS_GRAPH = YES
20.197 +COLLABORATION_GRAPH = YES
20.198 +UML_LOOK = NO
20.199 +TEMPLATE_RELATIONS = NO
20.200 +INCLUDE_GRAPH = YES
20.201 +INCLUDED_BY_GRAPH = YES
20.202 +CALL_GRAPH = NO
20.203 +GRAPHICAL_HIERARCHY = YES
20.204 +DOT_IMAGE_FORMAT = png
20.205 +DOT_PATH = $(DOT_PATH)
20.206 +DOTFILE_DIRS =
20.207 +MAX_DOT_GRAPH_WIDTH = 1024
20.208 +MAX_DOT_GRAPH_HEIGHT = 1024
20.209 +MAX_DOT_GRAPH_DEPTH = 0
20.210 +GENERATE_LEGEND = YES
20.211 +DOT_CLEANUP = YES
20.212 +#---------------------------------------------------------------------------
20.213 +# Configuration::additions related to the search engine
20.214 +#---------------------------------------------------------------------------
20.215 +SEARCHENGINE = NO
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
21.2 +++ b/gmyth/gmyth.pc.in Wed Sep 20 23:45:35 2006 +0100
21.3 @@ -0,0 +1,12 @@
21.4 +prefix=@prefix@
21.5 +exec_prefix=@exec_prefix@
21.6 +libdir=@libdir@
21.7 +includedir=@includedir@
21.8 +
21.9 +Name: gmyth
21.10 +Description: Myth TV library based upon GLib/GObject paradigm
21.11 +Version: @VERSION@
21.12 +Requires: gobject-2.0 glib-2.0 gtk+-2.0
21.13 +
21.14 +Libs: @MYSQL_LIBS@ -L${libdir} -lgmyth
21.15 +Cflags: @MYSQL_CFLAGS@ -I${includedir}/gmyth
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
22.2 +++ b/gmyth/m4/Makefile.am Wed Sep 20 23:45:35 2006 +0100
22.3 @@ -0,0 +1,7 @@
22.4 +EXTRA_DIST = \
22.5 + ac_doxygen.m4 \
22.6 + as-compiler-flag.m4 \
22.7 + as-expand.m4 \
22.8 + as-version.m4 \
22.9 + as-gtk-doc.m4
22.10 +
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
23.2 +++ b/gmyth/m4/ac_doxygen.m4 Wed Sep 20 23:45:35 2006 +0100
23.3 @@ -0,0 +1,312 @@
23.4 +# This file is part of Autoconf. -*- Autoconf -*-
23.5 +
23.6 +# Copyright (C) 2004 Oren Ben-Kiki
23.7 +# This file is distributed under the same terms as the Autoconf macro files.
23.8 +
23.9 +# Generate automatic documentation using Doxygen. Works in concert with the
23.10 +# aminclude.m4 file and a compatible doxygen configuration file. Defines the
23.11 +# following public macros:
23.12 +#
23.13 +# DX_???_FEATURE(ON|OFF) - control the default setting fo a Doxygen feature.
23.14 +# Supported features are 'DOXYGEN' itself, 'DOT' for generating graphics,
23.15 +# 'HTML' for plain HTML, 'CHM' for compressed HTML help (for MS users), 'CHI'
23.16 +# for generating a seperate .chi file by the .chm file, and 'MAN', 'RTF',
23.17 +# 'XML', 'PDF' and 'PS' for the appropriate output formats. The environment
23.18 +# variable DOXYGEN_PAPER_SIZE may be specified to override the default 'a4wide'
23.19 +# paper size.
23.20 +#
23.21 +# By default, HTML, PDF and PS documentation is generated as this seems to be
23.22 +# the most popular and portable combination. MAN pages created by Doxygen are
23.23 +# usually problematic, though by picking an appropriate subset and doing some
23.24 +# massaging they might be better than nothing. CHM and RTF are specific for MS
23.25 +# (note that you can't generate both HTML and CHM at the same time). The XML is
23.26 +# rather useless unless you apply specialized post-processing to it.
23.27 +#
23.28 +# The macro mainly controls the default state of the feature. The use can
23.29 +# override the default by specifying --enable or --disable. The macros ensure
23.30 +# that contradictory flags are not given (e.g., --enable-doxygen-html and
23.31 +# --enable-doxygen-chm, --enable-doxygen-anything with --disable-doxygen, etc.)
23.32 +# Finally, each feature will be automatically disabled (with a warning) if the
23.33 +# required programs are missing.
23.34 +#
23.35 +# Once all the feature defaults have been specified, call DX_INIT_DOXYGEN with
23.36 +# the following parameters: a one-word name for the project for use as a
23.37 +# filename base etc., an optional configuration file name (the default is
23.38 +# 'Doxyfile', the same as Doxygen's default), and an optional output directory
23.39 +# name (the default is 'doxygen-doc').
23.40 +
23.41 +## ----------##
23.42 +## Defaults. ##
23.43 +## ----------##
23.44 +
23.45 +DX_ENV=""
23.46 +AC_DEFUN([DX_FEATURE_doc], ON)
23.47 +AC_DEFUN([DX_FEATURE_dot], ON)
23.48 +AC_DEFUN([DX_FEATURE_man], OFF)
23.49 +AC_DEFUN([DX_FEATURE_html], ON)
23.50 +AC_DEFUN([DX_FEATURE_chm], OFF)
23.51 +AC_DEFUN([DX_FEATURE_chi], OFF)
23.52 +AC_DEFUN([DX_FEATURE_rtf], OFF)
23.53 +AC_DEFUN([DX_FEATURE_xml], OFF)
23.54 +AC_DEFUN([DX_FEATURE_pdf], ON)
23.55 +AC_DEFUN([DX_FEATURE_ps], ON)
23.56 +
23.57 +## --------------- ##
23.58 +## Private macros. ##
23.59 +## --------------- ##
23.60 +
23.61 +# DX_ENV_APPEND(VARIABLE, VALUE)
23.62 +# ------------------------------
23.63 +# Append VARIABLE="VALUE" to DX_ENV for invoking doxygen.
23.64 +AC_DEFUN([DX_ENV_APPEND], [AC_SUBST([DX_ENV], ["$DX_ENV $1='$2'"])])
23.65 +
23.66 +# DX_DIRNAME_EXPR
23.67 +# ---------------
23.68 +# Expand into a shell expression prints the directory part of a path.
23.69 +AC_DEFUN([DX_DIRNAME_EXPR],
23.70 + [[expr ".$1" : '\(\.\)[^/]*$' \| "x$1" : 'x\(.*\)/[^/]*$']])
23.71 +
23.72 +# DX_IF_FEATURE(FEATURE, IF-ON, IF-OFF)
23.73 +# -------------------------------------
23.74 +# Expands according to the M4 (static) status of the feature.
23.75 +AC_DEFUN([DX_IF_FEATURE], [ifelse(DX_FEATURE_$1, ON, [$2], [$3])])
23.76 +
23.77 +# DX_REQUIRE_PROG(VARIABLE, PROGRAM)
23.78 +# ----------------------------------
23.79 +# Require the specified program to be found for the DX_CURRENT_FEATURE to work.
23.80 +AC_DEFUN([DX_REQUIRE_PROG], [
23.81 +AC_PATH_TOOL([$1], [$2])
23.82 +if test "$DX_FLAG_[]DX_CURRENT_FEATURE$$1" = 1; then
23.83 + AC_MSG_WARN([$2 not found - will not DX_CURRENT_DESCRIPTION])
23.84 + AC_SUBST([DX_FLAG_[]DX_CURRENT_FEATURE], 0)
23.85 +fi
23.86 +])
23.87 +
23.88 +# DX_TEST_FEATURE(FEATURE)
23.89 +# ------------------------
23.90 +# Expand to a shell expression testing whether the feature is active.
23.91 +AC_DEFUN([DX_TEST_FEATURE], [test "$DX_FLAG_$1" = 1])
23.92 +
23.93 +# DX_CHECK_DEPEND(REQUIRED_FEATURE, REQUIRED_STATE)
23.94 +# -------------------------------------------------
23.95 +# Verify that a required features has the right state before trying to turn on
23.96 +# the DX_CURRENT_FEATURE.
23.97 +AC_DEFUN([DX_CHECK_DEPEND], [
23.98 +test "$DX_FLAG_$1" = "$2" \
23.99 +|| AC_MSG_ERROR([doxygen-DX_CURRENT_FEATURE ifelse([$2], 1,
23.100 + requires, contradicts) doxygen-DX_CURRENT_FEATURE])
23.101 +])
23.102 +
23.103 +# DX_CLEAR_DEPEND(FEATURE, REQUIRED_FEATURE, REQUIRED_STATE)
23.104 +# ----------------------------------------------------------
23.105 +# Turn off the DX_CURRENT_FEATURE if the required feature is off.
23.106 +AC_DEFUN([DX_CLEAR_DEPEND], [
23.107 +test "$DX_FLAG_$1" = "$2" || AC_SUBST([DX_FLAG_[]DX_CURRENT_FEATURE], 0)
23.108 +])
23.109 +
23.110 +# DX_FEATURE_ARG(FEATURE, DESCRIPTION,
23.111 +# CHECK_DEPEND, CLEAR_DEPEND,
23.112 +# REQUIRE, DO-IF-ON, DO-IF-OFF)
23.113 +# --------------------------------------------
23.114 +# Parse the command-line option controlling a feature. CHECK_DEPEND is called
23.115 +# if the user explicitly turns the feature on (and invokes DX_CHECK_DEPEND),
23.116 +# otherwise CLEAR_DEPEND is called to turn off the default state if a required
23.117 +# feature is disabled (using DX_CLEAR_DEPEND). REQUIRE performs additional
23.118 +# requirement tests (DX_REQUIRE_PROG). Finally, an automake flag is set and
23.119 +# DO-IF-ON or DO-IF-OFF are called according to the final state of the feature.
23.120 +AC_DEFUN([DX_ARG_ABLE], [
23.121 + AC_DEFUN([DX_CURRENT_FEATURE], [$1])
23.122 + AC_DEFUN([DX_CURRENT_DESCRIPTION], [$2])
23.123 + AC_ARG_ENABLE(doxygen-$1,
23.124 + [AS_HELP_STRING(DX_IF_FEATURE([$1], [--disable-doxygen-$1],
23.125 + [--enable-doxygen-$1]),
23.126 + DX_IF_FEATURE([$1], [don't $2], [$2]))],
23.127 + [
23.128 +case "$enableval" in
23.129 +#(
23.130 +y|Y|yes|Yes|YES)
23.131 + AC_SUBST([DX_FLAG_$1], 1)
23.132 + $3
23.133 +;; #(
23.134 +n|N|no|No|NO)
23.135 + AC_SUBST([DX_FLAG_$1], 0)
23.136 +;; #(
23.137 +*)
23.138 + AC_MSG_ERROR([invalid value '$enableval' given to doxygen-$1])
23.139 +;;
23.140 +esac
23.141 +], [
23.142 +AC_SUBST([DX_FLAG_$1], [DX_IF_FEATURE([$1], 1, 0)])
23.143 +$4
23.144 +])
23.145 +if DX_TEST_FEATURE([$1]); then
23.146 + $5
23.147 + :
23.148 +fi
23.149 +if DX_TEST_FEATURE([$1]); then
23.150 + AM_CONDITIONAL(DX_COND_$1, :)
23.151 + $6
23.152 + :
23.153 +else
23.154 + AM_CONDITIONAL(DX_COND_$1, false)
23.155 + $7
23.156 + :
23.157 +fi
23.158 +])
23.159 +
23.160 +## -------------- ##
23.161 +## Public macros. ##
23.162 +## -------------- ##
23.163 +
23.164 +# DX_XXX_FEATURE(DEFAULT_STATE)
23.165 +# -----------------------------
23.166 +AC_DEFUN([DX_DOXYGEN_FEATURE], [AC_DEFUN([DX_FEATURE_doc], [$1])])
23.167 +AC_DEFUN([DX_MAN_FEATURE], [AC_DEFUN([DX_FEATURE_man], [$1])])
23.168 +AC_DEFUN([DX_HTML_FEATURE], [AC_DEFUN([DX_FEATURE_html], [$1])])
23.169 +AC_DEFUN([DX_CHM_FEATURE], [AC_DEFUN([DX_FEATURE_chm], [$1])])
23.170 +AC_DEFUN([DX_CHI_FEATURE], [AC_DEFUN([DX_FEATURE_chi], [$1])])
23.171 +AC_DEFUN([DX_RTF_FEATURE], [AC_DEFUN([DX_FEATURE_rtf], [$1])])
23.172 +AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])])
23.173 +AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])])
23.174 +AC_DEFUN([DX_PDF_FEATURE], [AC_DEFUN([DX_FEATURE_pdf], [$1])])
23.175 +AC_DEFUN([DX_PS_FEATURE], [AC_DEFUN([DX_FEATURE_ps], [$1])])
23.176 +
23.177 +# DX_INIT_DOXYGEN(PROJECT, [CONFIG-FILE], [OUTPUT-DOC-DIR])
23.178 +# ---------------------------------------------------------
23.179 +# PROJECT also serves as the base name for the documentation files.
23.180 +# The default CONFIG-FILE is "Doxyfile" and OUTPUT-DOC-DIR is "doxygen-doc".
23.181 +AC_DEFUN([DX_INIT_DOXYGEN], [
23.182 +
23.183 +# Files:
23.184 +AC_SUBST([DX_PROJECT], [$1])
23.185 +AC_SUBST([DX_CONFIG], [ifelse([$2], [], Doxyfile, [$2])])
23.186 +AC_SUBST([DX_DOCDIR], [ifelse([$3], [], doxygen-doc, [$3])])
23.187 +
23.188 +# Environment variables used inside doxygen.cfg:
23.189 +DX_ENV_APPEND(SRCDIR, $srcdir)
23.190 +DX_ENV_APPEND(PROJECT, $DX_PROJECT)
23.191 +DX_ENV_APPEND(DOCDIR, $DX_DOCDIR)
23.192 +DX_ENV_APPEND(VERSION, $PACKAGE_VERSION)
23.193 +
23.194 +# Doxygen itself:
23.195 +DX_ARG_ABLE(doc, [generate any doxygen documentation],
23.196 + [],
23.197 + [],
23.198 + [DX_REQUIRE_PROG([DX_DOXYGEN], doxygen)
23.199 + DX_REQUIRE_PROG([DX_PERL], perl)],
23.200 + [DX_ENV_APPEND(PERL_PATH, $DX_PERL)])
23.201 +
23.202 +# Dot for graphics:
23.203 +DX_ARG_ABLE(dot, [generate graphics for doxygen documentation],
23.204 + [DX_CHECK_DEPEND(doc, 1)],
23.205 + [DX_CLEAR_DEPEND(doc, 1)],
23.206 + [DX_REQUIRE_PROG([DX_DOT], dot)],
23.207 + [DX_ENV_APPEND(HAVE_DOT, YES)
23.208 + DX_ENV_APPEND(DOT_PATH, [`DX_DIRNAME_EXPR($DX_DOT)`])],
23.209 + [DX_ENV_APPEND(HAVE_DOT, NO)])
23.210 +
23.211 +# Man pages generation:
23.212 +DX_ARG_ABLE(man, [generate doxygen manual pages],
23.213 + [DX_CHECK_DEPEND(doc, 1)],
23.214 + [DX_CLEAR_DEPEND(doc, 1)],
23.215 + [],
23.216 + [DX_ENV_APPEND(GENERATE_MAN, YES)],
23.217 + [DX_ENV_APPEND(GENERATE_MAN, NO)])
23.218 +
23.219 +# RTF file generation:
23.220 +DX_ARG_ABLE(rtf, [generate doxygen RTF documentation],
23.221 + [DX_CHECK_DEPEND(doc, 1)],
23.222 + [DX_CLEAR_DEPEND(doc, 1)],
23.223 + [],
23.224 + [DX_ENV_APPEND(GENERATE_RTF, YES)],
23.225 + [DX_ENV_APPEND(GENERATE_RTF, NO)])
23.226 +
23.227 +# XML file generation:
23.228 +DX_ARG_ABLE(xml, [generate doxygen XML documentation],
23.229 + [DX_CHECK_DEPEND(doc, 1)],
23.230 + [DX_CLEAR_DEPEND(doc, 1)],
23.231 + [],
23.232 + [DX_ENV_APPEND(GENERATE_XML, YES)],
23.233 + [DX_ENV_APPEND(GENERATE_XML, NO)])
23.234 +
23.235 +# (Compressed) HTML help generation:
23.236 +DX_ARG_ABLE(chm, [generate doxygen compressed HTML help documentation],
23.237 + [DX_CHECK_DEPEND(doc, 1)],
23.238 + [DX_CLEAR_DEPEND(doc, 1)],
23.239 + [DX_REQUIRE_PROG([DX_HHC], hhc)],
23.240 + [DX_ENV_APPEND(HHC_PATH, $DX_HHC)
23.241 + DX_ENV_APPEND(GENERATE_HTML, YES)
23.242 + DX_ENV_APPEND(GENERATE_HTMLHELP, YES)],
23.243 + [DX_ENV_APPEND(GENERATE_HTMLHELP, NO)])
23.244 +
23.245 +# Seperate CHI file generation.
23.246 +DX_ARG_ABLE(chi, [generate doxygen seperate compressed HTML help index file],
23.247 + [DX_CHECK_DEPEND(chm, 1)],
23.248 + [DX_CLEAR_DEPEND(chm, 1)],
23.249 + [],
23.250 + [DX_ENV_APPEND(GENERATE_CHI, YES)],
23.251 + [DX_ENV_APPEND(GENERATE_CHI, NO)])
23.252 +
23.253 +# Plain HTML pages generation:
23.254 +DX_ARG_ABLE(html, [generate doxygen plain HTML documentation],
23.255 + [DX_CHECK_DEPEND(doc, 1) DX_CHECK_DEPEND(chm, 0)],
23.256 + [DX_CLEAR_DEPEND(doc, 1) DX_CLEAR_DEPEND(chm, 0)],
23.257 + [],
23.258 + [DX_ENV_APPEND(GENERATE_HTML, YES)],
23.259 + [DX_TEST_FEATURE(chm) || DX_ENV_APPEND(GENERATE_HTML, NO)])
23.260 +
23.261 +# PostScript file generation:
23.262 +DX_ARG_ABLE(ps, [generate doxygen PostScript documentation],
23.263 + [DX_CHECK_DEPEND(doc, 1)],
23.264 + [DX_CLEAR_DEPEND(doc, 1)],
23.265 + [DX_REQUIRE_PROG([DX_LATEX], latex)
23.266 + DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex)
23.267 + DX_REQUIRE_PROG([DX_DVIPS], dvips)
23.268 + DX_REQUIRE_PROG([DX_EGREP], egrep)])
23.269 +
23.270 +# PDF file generation:
23.271 +DX_ARG_ABLE(pdf, [generate doxygen PDF documentation],
23.272 + [DX_CHECK_DEPEND(doc, 1)],
23.273 + [DX_CLEAR_DEPEND(doc, 1)],
23.274 + [DX_REQUIRE_PROG([DX_PDFLATEX], pdflatex)
23.275 + DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex)
23.276 + DX_REQUIRE_PROG([DX_EGREP], egrep)])
23.277 +
23.278 +# LaTeX generation for PS and/or PDF:
23.279 +if DX_TEST_FEATURE(ps) || DX_TEST_FEATURE(pdf); then
23.280 + AM_CONDITIONAL(DX_COND_latex, :)
23.281 + DX_ENV_APPEND(GENERATE_LATEX, YES)
23.282 +else
23.283 + AM_CONDITIONAL(DX_COND_latex, false)
23.284 + DX_ENV_APPEND(GENERATE_LATEX, NO)
23.285 +fi
23.286 +
23.287 +# Paper size for PS and/or PDF:
23.288 +AC_ARG_VAR(DOXYGEN_PAPER_SIZE,
23.289 + [a4wide (default), a4, letter, legal or executive])
23.290 +case "$DOXYGEN_PAPER_SIZE" in
23.291 +#(
23.292 +"")
23.293 + AC_SUBST(DOXYGEN_PAPER_SIZE, "")
23.294 +;; #(
23.295 +a4wide|a4|letter|legal|executive)
23.296 + DX_ENV_APPEND(PAPER_SIZE, $DOXYGEN_PAPER_SIZE)
23.297 +;; #(
23.298 +*)
23.299 + AC_MSG_ERROR([unknown DOXYGEN_PAPER_SIZE='$DOXYGEN_PAPER_SIZE'])
23.300 +;;
23.301 +esac
23.302 +
23.303 +#For debugging:
23.304 +#echo DX_FLAG_doc=$DX_FLAG_doc
23.305 +#echo DX_FLAG_dot=$DX_FLAG_dot
23.306 +#echo DX_FLAG_man=$DX_FLAG_man
23.307 +#echo DX_FLAG_html=$DX_FLAG_html
23.308 +#echo DX_FLAG_chm=$DX_FLAG_chm
23.309 +#echo DX_FLAG_chi=$DX_FLAG_chi
23.310 +#echo DX_FLAG_rtf=$DX_FLAG_rtf
23.311 +#echo DX_FLAG_xml=$DX_FLAG_xml
23.312 +#echo DX_FLAG_pdf=$DX_FLAG_pdf
23.313 +#echo DX_FLAG_ps=$DX_FLAG_ps
23.314 +#echo DX_ENV=$DX_ENV
23.315 +])
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
24.2 +++ b/gmyth/m4/as-compiler-flag.m4 Wed Sep 20 23:45:35 2006 +0100
24.3 @@ -0,0 +1,33 @@
24.4 +dnl as-compiler-flag.m4 0.1.0
24.5 +
24.6 +dnl autostars m4 macro for detection of compiler flags
24.7 +
24.8 +dnl David Schleef <ds@schleef.org>
24.9 +
24.10 +dnl $Id: as-compiler-flag.m4,v 1.1.1.1 2005/08/26 00:42:44 andrunko Exp $
24.11 +
24.12 +dnl AS_COMPILER_FLAG(CFLAGS, ACTION-IF-ACCEPTED, [ACTION-IF-NOT-ACCEPTED])
24.13 +dnl Tries to compile with the given CFLAGS.
24.14 +dnl Runs ACTION-IF-ACCEPTED if the compiler can compile with the flags,
24.15 +dnl and ACTION-IF-NOT-ACCEPTED otherwise.
24.16 +
24.17 +AC_DEFUN([AS_COMPILER_FLAG],
24.18 +[
24.19 + AC_MSG_CHECKING([to see if compiler understands $1])
24.20 +
24.21 + save_CFLAGS="$CFLAGS"
24.22 + CFLAGS="$CFLAGS $1"
24.23 +
24.24 + AC_TRY_COMPILE([ ], [], [flag_ok=yes], [flag_ok=no])
24.25 + CFLAGS="$save_CFLAGS"
24.26 +
24.27 + if test "X$flag_ok" = Xyes ; then
24.28 + $2
24.29 + true
24.30 + else
24.31 + $3
24.32 + true
24.33 + fi
24.34 + AC_MSG_RESULT([$flag_ok])
24.35 +])
24.36 +
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
25.2 +++ b/gmyth/m4/as-expand.m4 Wed Sep 20 23:45:35 2006 +0100
25.3 @@ -0,0 +1,40 @@
25.4 +dnl AS_AC_EXPAND(VAR, CONFIGURE_VAR)
25.5 +dnl
25.6 +dnl example
25.7 +dnl AS_AC_EXPAND(SYSCONFDIR, $sysconfdir)
25.8 +dnl will set SYSCONFDIR to /usr/local/etc if prefix=/usr/local
25.9 +
25.10 +AC_DEFUN([AS_AC_EXPAND],
25.11 +[
25.12 + EXP_VAR=[$1]
25.13 + FROM_VAR=[$2]
25.14 +
25.15 + dnl first expand prefix and exec_prefix if necessary
25.16 + prefix_save=$prefix
25.17 + exec_prefix_save=$exec_prefix
25.18 +
25.19 + dnl if no prefix given, then use /usr/local, the default prefix
25.20 + if test "x$prefix" = "xNONE"; then
25.21 + prefix=$ac_default_prefix
25.22 + fi
25.23 + dnl if no exec_prefix given, then use prefix
25.24 + if test "x$exec_prefix" = "xNONE"; then
25.25 + exec_prefix=$prefix
25.26 + fi
25.27 +
25.28 + full_var="$FROM_VAR"
25.29 + dnl loop until it doesn't change anymore
25.30 + while true; do
25.31 + new_full_var="`eval echo $full_var`"
25.32 + if test "x$new_full_var"="x$full_var"; then break; fi
25.33 + full_var=$new_full_var
25.34 + done
25.35 +
25.36 + dnl clean up
25.37 + full_var=$new_full_var
25.38 + AC_SUBST([$1], "$full_var")
25.39 +
25.40 + dnl restore prefix and exec_prefix
25.41 + prefix=$prefix_save
25.42 + exec_prefix=$exec_prefix_save
25.43 +])
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
26.2 +++ b/gmyth/m4/as-version.m4 Wed Sep 20 23:45:35 2006 +0100
26.3 @@ -0,0 +1,59 @@
26.4 +dnl version.m4 0.0.5
26.5 +dnl autostars m4 macro for versioning
26.6 +dnl thomas@apestaart.org
26.7 +dnl
26.8 +dnl AS_VERSION(PACKAGE, PREFIX, MAJOR, MINOR, MICRO, NANO, ACTION_IF_NO_NANO, ACTION_IF_NANO)
26.9 +dnl example
26.10 +dnl AS_VERSION(gstreamer, GST_VERSION, 0, 3, 2,)
26.11 +dnl for a 0.3.2 release version
26.12 +dnl
26.13 +dnl this macro
26.14 +dnl - defines [$PREFIX]_MAJOR, MINOR and MICRO
26.15 +dnl - if NANO is empty, then we're in release mode, else in cvs/dev mode
26.16 +dnl - defines [$PREFIX], VERSION, and [$PREFIX]_RELEASE
26.17 +dnl - executes the relevant action
26.18 +dnl - AC_SUBST's PACKAGE, VERSION, [$PREFIX] and [$PREFIX]_RELEASE
26.19 +dnl as well as the little ones
26.20 +dnl - doesn't call AM_INIT_AUTOMAKE anymore because it prevents
26.21 +dnl maintainer mode from running ok
26.22 +dnl
26.23 +dnl don't forget to put #undef [$2] and [$2]_RELEASE in acconfig.h
26.24 +
26.25 +AC_DEFUN([AS_VERSION],
26.26 +[
26.27 + PACKAGE=[$1]
26.28 + [$2]_MAJOR_VERSION=[$3]
26.29 + [$2]_MINOR_VERSION=[$4]
26.30 + [$2]_MICRO_VERSION=[$5]
26.31 + NANO=[$6]
26.32 + [$2]_NANO_VERSION=$NANO
26.33 + if test "x$NANO" = "x" || test "x$NANO" = "x0";
26.34 + then
26.35 + AC_MSG_NOTICE(configuring [$1] for release)
26.36 + VERSION=[$3].[$4].[$5]
26.37 + [$2]_RELEASE=1
26.38 + dnl execute action
26.39 + ifelse([$7], , :, [$7])
26.40 + else
26.41 + AC_MSG_NOTICE(configuring [$1] for development with nano $NANO)
26.42 + VERSION=[$3].[$4].[$5].$NANO
26.43 + [$2]_RELEASE=`date +%Y%m%d_%H%M%S`
26.44 + dnl execute action
26.45 + ifelse([$8], , :, [$8])
26.46 + fi
26.47 +
26.48 + [$2]_VERSION=$VERSION
26.49 + AC_DEFINE_UNQUOTED([$2]_VERSION, "$[$2]_VERSION", [Define the version])
26.50 + AC_SUBST([$2]_VERSION)
26.51 +
26.52 + AC_SUBST([$2]_RELEASE)
26.53 +
26.54 + AC_SUBST([$2]_MAJOR_VERSION)
26.55 + AC_SUBST([$2]_MINOR_VERSION)
26.56 + AC_SUBST([$2]_MICRO_VERSION)
26.57 + AC_SUBST([$2]_NANO_VERSION)
26.58 + AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Define the package name])
26.59 + AC_SUBST(PACKAGE)
26.60 + AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Define the version])
26.61 + AC_SUBST(VERSION)
26.62 +])
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
27.2 +++ b/gmyth/pixmaps/Makefile.am Wed Sep 20 23:45:35 2006 +0100
27.3 @@ -0,0 +1,11 @@
27.4 +# Adding the application icon
27.5 +#icondir = $(datadir)/miptv/pixmaps
27.6 +#icon_DATA = \
27.7 +# miptv.png
27.8 +
27.9 +
27.10 +# Adding the application resources
27.11 +pixmapdir = $(pkgdatadir)/pixmaps
27.12 +pixmap_DATA = mmyth_logo.png
27.13 +
27.14 +EXTRA_DIST = $(pixmap_DATA)
28.1 Binary file gmyth/pixmaps/main_logo.gif has changed
29.1 Binary file gmyth/pixmaps/mmyth_logo.png has changed
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
30.2 +++ b/gmyth/src/Makefile.am Wed Sep 20 23:45:35 2006 +0100
30.3 @@ -0,0 +1,29 @@
30.4 +SUBDIRS = libgmyth gui .
30.5 +
30.6 +bin_PROGRAMS = mmyth
30.7 +
30.8 +mmyth_SOURCES = mmyth_main.c
30.9 +
30.10 +mmyth_CFLAGS = \
30.11 + $(GTK_CFLAGS) \
30.12 + $(GLIB_CFLAGS) \
30.13 + $(GST_CFLAGS) \
30.14 + $(MYSQL_CFLAGS) \
30.15 + -g3 -O0 \
30.16 + -I$(top_srcdir)/src/libgmyth \
30.17 + -I$(top_srcdir)/src/gui \
30.18 + -DDATA_DIR=\""$(pkgdatadir)"\" \
30.19 + -DPIX_DIR=\""$(pkgdatadir)/pixmaps/"\" \
30.20 + -DESG_DIR=\""$(pkgdatadir)/pixmaps/"\" \
30.21 + -DICON_DIR=\""$(pkgdatadir)/pixmaps/"\"
30.22 +
30.23 +mmyth_LDFLAGS =
30.24 +
30.25 +mmyth_LDADD = \
30.26 + $(GTK_LIBS) \
30.27 + $(GLIB_LIBS) \
30.28 + $(GST_LIBS) \
30.29 + $(GSTBASE_LIBS) \
30.30 + $(HILDON_LIBS) \
30.31 + $(top_srcdir)/src/libgmyth/libgmyth.la \
30.32 + $(top_srcdir)/src/gui/libmmythgui.la
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
31.2 +++ b/gmyth/src/gui/Makefile.am Wed Sep 20 23:45:35 2006 +0100
31.3 @@ -0,0 +1,29 @@
31.4 +noinst_LTLIBRARIES = libmmythgui.la
31.5 +
31.6 +libmmythgui_la_SOURCES = \
31.7 + mmyth_ui.c \
31.8 + mmyth_uicommon.c \
31.9 + mmyth_epg_grid_view.c \
31.10 + mmyth_epg_grid_widget.c \
31.11 + mmyth_recordui.c \
31.12 + mmyth_uisettings.c \
31.13 + mmyth_schedulerui.c
31.14 +
31.15 +libmmythgui_la_CFLAGS = \
31.16 + $(GTK_CFLAGS) \
31.17 + $(GLIB_CFLAGS) \
31.18 + $(GST_CFLAGS) \
31.19 + $(MYSQL_CFLAGS) \
31.20 + -I$(top_srcdir)/src/libgmyth \
31.21 + -I$(top_srcdir)/src \
31.22 + -DDATA_DIR=\""$(pkgdatadir)"\" \
31.23 + -DPIX_DIR=\""$(pkgdatadir)/pixmaps/"\" \
31.24 + -DICON_DIR=\""$(datadir)/pixmaps/"\" \
31.25 + -g3 -O0
31.26 +
31.27 +libmmythgui_la_LIBADD = \
31.28 + $(top_srcdir)/src/libgmyth/libgmyth.la
31.29 +
31.30 +libmmythgui_la_LDFLAGS = -export-dynamic
31.31 +
31.32 +
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
32.2 +++ b/gmyth/src/gui/mmyth_epg_grid_view.c Wed Sep 20 23:45:35 2006 +0100
32.3 @@ -0,0 +1,213 @@
32.4 +#include <string.h>
32.5 +#include <stdlib.h>
32.6 +#include <gtk/gtk.h>
32.7 +#include <gdk/gdkkeysyms.h>
32.8 +#include <time.h>
32.9 +
32.10 +#include "mmyth_epg_grid_view.h"
32.11 +#include "mmyth_epg_grid_widget.h"
32.12 +
32.13 +/* Service genre */
32.14 +#define GENRE_MIN 0
32.15 +#define GENRE_MAX 10
32.16 +#define GENRE_UNDEFINED 0
32.17 +#define GENRE_MOVIE 1
32.18 +#define GENRE_NEWS 2
32.19 +#define GENRE_SHOW 3
32.20 +#define GENRE_SPORTS 4
32.21 +#define GENRE_CHILDREN 5
32.22 +#define GENRE_MUSIC 6
32.23 +#define GENRE_CULTURE 7
32.24 +#define GENRE_SOCIAL 8
32.25 +#define GENRE_EDUCATION 9
32.26 +#define GENRE_LEISURE 10
32.27 +
32.28 +#define NRO_HOURS 3
32.29 +
32.30 +/* Function prototypes*/
32.31 +static void update_service_details(MMythEpgGridWidget *object,
32.32 + gpointer arg1, gpointer user_data);
32.33 +static gboolean key_press_epg_grid_view(GtkWidget * widget,
32.34 + GdkEventKey * event,
32.35 + gpointer user_data);
32.36 +
32.37 +static GtkWidget *mmyth_epg_grid_widget = NULL;
32.38 +
32.39 +/* is a GtkEventBox */
32.40 +static GtkWidget *program_details_area = NULL;
32.41 +static GtkWidget *details_main_hbox = NULL;
32.42 +static GtkWidget *details_vbox = NULL;
32.43 +static GtkWidget *details_logo_vbox = NULL;
32.44 +
32.45 +/* update signal callback from MMythEpgGridWidget */
32.46 +static void
32.47 +update_service_details(MMythEpgGridWidget *object, gpointer arg1, gpointer user_data)
32.48 +{
32.49 + g_return_if_fail(arg1 != NULL);
32.50 +
32.51 + EpgGridItem *epg_grid_item = (EpgGridItem *) arg1;
32.52 +
32.53 + gchar sel_prog_desc[100] = "<big><b>";
32.54 + gchar time_buffer[50];
32.55 +
32.56 + /* FIXME: get first content from content_list*/
32.57 + GMythProgramInfo *proginfo = (GMythProgramInfo *) epg_grid_item->proginfo;
32.58 +
32.59 + if(proginfo) {
32.60 + GString *prog_name = proginfo->title;
32.61 + GString *service_name = proginfo->chanid;
32.62 +
32.63 + if(details_vbox != NULL)
32.64 + gtk_container_remove (GTK_CONTAINER (details_main_hbox), details_vbox);
32.65 +
32.66 + /* update service description */
32.67 + strcat(sel_prog_desc, service_name->str);
32.68 + strcat(sel_prog_desc, "</b></big>");
32.69 +
32.70 + GtkWidget *fst_line_lbl = gtk_label_new(NULL);
32.71 + gtk_misc_set_alignment (GTK_MISC(fst_line_lbl), 0.0, 0.0);
32.72 + gtk_label_set_markup(GTK_LABEL(fst_line_lbl), sel_prog_desc);
32.73 +
32.74 + /* freeing char[] */
32.75 + sel_prog_desc[0] = 0;
32.76 + strcat(sel_prog_desc, "\t");
32.77 + strcat(sel_prog_desc, prog_name->str);
32.78 +
32.79 + struct tm loctime_start, loctime_end;
32.80 +
32.81 + // Convert it to local time representation.
32.82 + /* FIXME: conversion from time to localtime is different
32.83 + in different machines */
32.84 + long int schedule_start_time = proginfo->startts;
32.85 + long int schedule_end_time = proginfo->endts;
32.86 +
32.87 + if (localtime_r(&schedule_start_time, &loctime_start) == NULL) {
32.88 + g_warning ("localtime_r error in mmyth_epg_grid_view!\n");
32.89 + }
32.90 +
32.91 + #if 0
32.92 + fprintf (stderr, asctime (loctime_start));
32.93 + #endif
32.94 +
32.95 + strftime (time_buffer, 100, " %H:%M - ", &loctime_start);
32.96 + strcat(sel_prog_desc, time_buffer );
32.97 +
32.98 + if (localtime_r(&schedule_end_time, &loctime_end) == NULL) {
32.99 + g_warning ("localtime_r error in mmyth_epg_grid_view!\n");
32.100 + }
32.101 +
32.102 + #if 0
32.103 + fprintf (stderr, asctime (loctime_end));
32.104 + #endif
32.105 +
32.106 + strftime (time_buffer, 100, "%H:%M\n", &loctime_end);
32.107 + strcat(sel_prog_desc, time_buffer );
32.108 +
32.109 + GtkWidget *snd_line_lbl = gtk_label_new(NULL);
32.110 + gtk_misc_set_alignment (GTK_MISC(snd_line_lbl), 0.0, 0.0);
32.111 + gtk_label_set_markup(GTK_LABEL(snd_line_lbl), sel_prog_desc);
32.112 +
32.113 + // add the current selected program description to the label
32.114 + details_vbox = gtk_vbox_new(FALSE, 0);
32.115 + GtkWidget *fst_line_hbox = gtk_hbox_new(FALSE, 0);
32.116 +
32.117 + gtk_box_pack_start (GTK_BOX (fst_line_hbox),
32.118 + fst_line_lbl, FALSE, FALSE, 6);
32.119 + gtk_box_pack_start (GTK_BOX (details_vbox),
32.120 + fst_line_hbox, FALSE, FALSE, 0);
32.121 + gtk_box_pack_start (GTK_BOX (details_vbox),
32.122 + snd_line_lbl, FALSE, FALSE, 0);
32.123 + gtk_box_pack_start (GTK_BOX (details_main_hbox),
32.124 + details_vbox, FALSE, FALSE, 0);
32.125 +
32.126 + gtk_widget_show_all(details_main_hbox);
32.127 + }
32.128 +}
32.129 +
32.130 +/* Callback for hardware keys */
32.131 +static gboolean
32.132 +key_press_epg_grid_view(GtkWidget * widget,
32.133 + GdkEventKey * event, gpointer user_data)
32.134 +{
32.135 + MMythEpgGridWidget *mmyth_epg_grid_widget = (MMythEpgGridWidget *) user_data;
32.136 +
32.137 + return mmyth_epg_grid_widget_key_press(mmyth_epg_grid_widget, widget, event);
32.138 +}
32.139 +
32.140 +GtkWidget *
32.141 +epg_grid_view_new (MMythUi* mmyth_ui)
32.142 +{
32.143 + GtkWidget *scrolled_window;
32.144 + scrolled_window = gtk_scrolled_window_new (NULL, NULL);
32.145 + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
32.146 + GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
32.147 +
32.148 + gtk_widget_modify_bg(scrolled_window, GTK_STATE_NORMAL, &main_bg_color);
32.149 +
32.150 + GtkWidget *main_vbox = gtk_vbox_new (FALSE, 0);
32.151 + //gtk_container_set_border_width(main_vbox, 4);
32.152 +
32.153 + GtkWidget *details_event_box = gtk_event_box_new();
32.154 + gtk_widget_modify_bg(details_event_box, GTK_STATE_NORMAL, &main_bg_color);
32.155 +
32.156 + program_details_area = gtk_vbox_new (FALSE, 0);
32.157 + gtk_container_add (GTK_CONTAINER (details_event_box),
32.158 + program_details_area);
32.159 + gtk_container_set_border_width(GTK_CONTAINER (program_details_area), 4);
32.160 +
32.161 + details_main_hbox = gtk_hbox_new (FALSE, 10);
32.162 +
32.163 + gtk_box_pack_start (GTK_BOX (program_details_area),
32.164 + details_main_hbox, FALSE, FALSE, 0);
32.165 +
32.166 + details_logo_vbox = gtk_vbox_new (FALSE, 0);
32.167 +
32.168 + GtkWidget *details_desc_vbox = gtk_vbox_new (FALSE, 0);
32.169 +
32.170 + gtk_box_pack_start (GTK_BOX (details_main_hbox),
32.171 + details_desc_vbox, FALSE, FALSE, 0);
32.172 + gtk_box_pack_start (GTK_BOX (details_main_hbox),
32.173 + details_logo_vbox, FALSE, FALSE, 0);
32.174 +
32.175 + gtk_widget_set_size_request (program_details_area, -1, 120);
32.176 +
32.177 + mmyth_epg_grid_widget = mmyth_epg_grid_widget_new();
32.178 + g_signal_connect(mmyth_epg_grid_widget, "selection_updated",
32.179 + G_CALLBACK (update_service_details), NULL);
32.180 +
32.181 + /* select by default the first service */
32.182 + /* depends on mount services */
32.183 + if (MMYTH_EPG_GRID_WIDGET(mmyth_epg_grid_widget)->epg_view_model) {
32.184 + GList *fst_service = (GList *)
32.185 + MMYTH_EPG_GRID_WIDGET(mmyth_epg_grid_widget)->epg_view_model->data;
32.186 + mmyth_epg_grid_widget_update_service(MMYTH_EPG_GRID_WIDGET(mmyth_epg_grid_widget),
32.187 + fst_service);
32.188 + }
32.189 +
32.190 + gtk_box_pack_start (GTK_BOX (main_vbox),
32.191 + details_event_box, FALSE, FALSE, 0);
32.192 + gtk_box_pack_start (GTK_BOX (main_vbox),
32.193 + gtk_hseparator_new(), FALSE, FALSE, 0);
32.194 + gtk_box_pack_start (GTK_BOX (main_vbox),
32.195 + mmyth_epg_grid_widget, FALSE, FALSE, 0);
32.196 +
32.197 + gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window),
32.198 + main_vbox);
32.199 +
32.200 + /* Add hardware button listener to application */
32.201 + g_signal_connect(mmyth_ui->main_window, "key_press_event",
32.202 + G_CALLBACK (key_press_epg_grid_view), mmyth_epg_grid_widget);
32.203 +
32.204 + gtk_widget_show_all (scrolled_window);
32.205 +
32.206 + return scrolled_window;
32.207 +}
32.208 +
32.209 +/*
32.210 +DVBHScheduleEvent *
32.211 +mmyth_epg_grid_view_get_selected_schedule()
32.212 +{
32.213 + return mmyth_epg_grid_get_selected_schedule
32.214 + (MMYTH_EPG_GRID_WIDGET(mmyth_epg_grid_widget));
32.215 +}
32.216 +*/
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
33.2 +++ b/gmyth/src/gui/mmyth_epg_grid_view.h Wed Sep 20 23:45:35 2006 +0100
33.3 @@ -0,0 +1,8 @@
33.4 +#ifndef MMYTH_ESG_GRID_VIEW_H_
33.5 +#define MMYTH_ESG_GRID_VIEW_H_
33.6 +
33.7 +#include "mmyth_ui.h"
33.8 +
33.9 +GtkWidget *epg_grid_view_new(MMythUi * mmyth_ui);
33.10 +
33.11 +#endif /* MMYTH_ESG_GRID_VIEW_H_ */
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
34.2 +++ b/gmyth/src/gui/mmyth_epg_grid_widget.c Wed Sep 20 23:45:35 2006 +0100
34.3 @@ -0,0 +1,622 @@
34.4 +#include <gtk/gtksignal.h>
34.5 +#include <gdk/gdkevents.h>
34.6 +#include <gdk/gdkkeysyms.h>
34.7 +
34.8 +#include "mmyth_uicommon.h"
34.9 +#include "mmyth_epg_grid_widget.h"
34.10 +
34.11 +#include "gmyth_util.h"
34.12 +#include "gmyth_epg.h"
34.13 +
34.14 +#define PIXELS_HOUR 105
34.15 +#define PROGRAM_SEPARATION 2
34.16 +
34.17 +enum {
34.18 + SELECTION_UPDATED_SIGNAL,
34.19 + LAST_SIGNAL
34.20 +};
34.21 +
34.22 +struct _MMythEpgGridWidgetPrivate {
34.23 + /* private widget components */
34.24 + GtkWidget *epg_channels_vbox;
34.25 + GtkWidget *epg_programs_vbox;
34.26 +
34.27 + GHashTable *service_model_hash;
34.28 +
34.29 + /* guidegrid attributes */
34.30 + gboolean show_favorites;
34.31 + gint current_start_channel_id;
34.32 +
34.33 + time_t current_start_time;
34.34 + time_t current_end_time;
34.35 +
34.36 + guint selected_channel_index;
34.37 +
34.38 + /* GList of ProgramInfo for each Channel */
34.39 + GList * program_list[MAX_DISPLAY_CHANS];
34.40 + GList * channel_list;
34.41 +
34.42 + GMythEPG *mmyth_epg;
34.43 +
34.44 + gint DISPLAY_CHANS;
34.45 +};
34.46 +
34.47 +static void mmyth_epg_grid_widget_class_init (MMythEpgGridWidgetClass *klass);
34.48 +static void mmyth_epg_grid_widget_init (MMythEpgGridWidget *object);
34.49 +static void mmyth_epg_grid_widget_private_init (MMythEpgGridWidgetPrivate *private);
34.50 +static void mmyth_epg_grid_widget_mount_services (MMythEpgGridWidget *object,
34.51 + int start_time, int end_time);
34.52 +static void mmyth_epg_grid_widget_mount_header (MMythEpgGridWidget *object);
34.53 +static void mmyth_epg_grid_widget_clicked (GtkWidget* widget,
34.54 + GdkEventExpose *event,
34.55 + gpointer data);
34.56 +static GtkWidget *create_event_box_lbl (gchar *str, int width,
34.57 + const GdkColor *bg_color,
34.58 + const GdkColor *fg_color);
34.59 +
34.60 +static void mmyth_epg_grid_widget_fill_programinfos(MMythEpgGridWidgetPrivate *private);
34.61 +static void mmyth_epg_grid_widget_fill_program_row_infos(
34.62 + MMythEpgGridWidgetPrivate *private,
34.63 + unsigned int chanNum, unsigned int row);
34.64 +
34.65 +static gint mmyth_epg_grid_widget_signals[LAST_SIGNAL] = { 0 };
34.66 +
34.67 +G_DEFINE_TYPE(MMythEpgGridWidget, mmyth_epg_grid_widget, GTK_TYPE_EVENT_BOX)
34.68 +
34.69 +static void
34.70 +mmyth_epg_grid_widget_class_init (MMythEpgGridWidgetClass *klass)
34.71 +{
34.72 + g_type_class_add_private (klass, sizeof (MMythEpgGridWidgetPrivate));
34.73 +
34.74 + mmyth_epg_grid_widget_signals[SELECTION_UPDATED_SIGNAL] = g_signal_new (
34.75 + "selection_updated",
34.76 + G_TYPE_FROM_CLASS(klass),
34.77 + G_SIGNAL_RUN_FIRST,
34.78 + 0,
34.79 + NULL,
34.80 + NULL,
34.81 + g_cclosure_marshal_VOID__POINTER,
34.82 + G_TYPE_NONE,
34.83 + 1,
34.84 + G_TYPE_POINTER);
34.85 +}
34.86 +
34.87 +static void
34.88 +mmyth_epg_grid_widget_private_init (MMythEpgGridWidgetPrivate *private)
34.89 +{
34.90 + time_t cur_time;
34.91 +
34.92 + g_return_if_fail(private != NULL);
34.93 +
34.94 + private->epg_channels_vbox = NULL;
34.95 + private->epg_programs_vbox = NULL;
34.96 + private->service_model_hash = NULL;
34.97 +
34.98 + private->show_favorites = FALSE;
34.99 + private->current_start_channel_id = -1;
34.100 +
34.101 + /* Selected the first diplayable channel initially */
34.102 + private->selected_channel_index = 0;
34.103 +
34.104 + /* TODO fix the current start/end time */
34.105 + private->current_start_time = time(&cur_time);
34.106 + private->current_end_time = time(&cur_time) + 10800;
34.107 +
34.108 + private->DISPLAY_CHANS = MAX_DISPLAY_CHANS;
34.109 +
34.110 + // TODO: Close the epg and unref it in dispose call
34.111 + private->mmyth_epg = gmyth_epg_new ();
34.112 + if (!gmyth_epg_connect (private->mmyth_epg)) {
34.113 + g_warning ("[%s] Could not connect mysql handler to db", __FUNCTION__);
34.114 + g_object_unref (private->mmyth_epg);
34.115 + private->mmyth_epg = NULL;
34.116 + }
34.117 +}
34.118 +
34.119 +static void
34.120 +mmyth_epg_grid_widget_init (MMythEpgGridWidget *mmyth_epg_grid_widget)
34.121 +{
34.122 + MMythEpgGridWidgetPrivate *private =
34.123 + MMYTH_EPG_GRID_WIDGET_GET_PRIVATE(mmyth_epg_grid_widget);
34.124 +
34.125 + /* init private fields */
34.126 + mmyth_epg_grid_widget_private_init(private);
34.127 +
34.128 + mmyth_epg_grid_widget->epg_view_model = NULL;
34.129 + mmyth_epg_grid_widget->selected_grid_item = NULL;
34.130 +
34.131 + GtkWidget *epg_event_box = GTK_WIDGET(mmyth_epg_grid_widget);
34.132 + gtk_widget_modify_bg(epg_event_box, GTK_STATE_NORMAL, &main_bg_color);
34.133 + gtk_widget_set_size_request (epg_event_box, 0, 125);
34.134 +
34.135 + GtkWidget *epg_main_hbox = gtk_hbox_new (FALSE, 10);
34.136 + gtk_container_set_border_width(GTK_CONTAINER (epg_main_hbox), 10);
34.137 +
34.138 + gtk_container_add (GTK_CONTAINER (epg_event_box),
34.139 + epg_main_hbox);
34.140 +
34.141 + /* channels vbox */
34.142 + GtkWidget *epg_channels_vbox = gtk_vbox_new (FALSE, 3);
34.143 + private->epg_channels_vbox = epg_channels_vbox;
34.144 +
34.145 + /* programs vbox */
34.146 + GtkWidget *epg_programs_vbox = gtk_vbox_new (FALSE, 3);
34.147 + private->epg_programs_vbox = epg_programs_vbox;
34.148 +
34.149 + /* packing start */
34.150 + gtk_box_pack_start (GTK_BOX (epg_main_hbox),
34.151 + epg_channels_vbox, FALSE, FALSE, 0);
34.152 + gtk_box_pack_start (GTK_BOX (epg_main_hbox),
34.153 + epg_programs_vbox, FALSE, FALSE, 0);
34.154 +
34.155 + /* table header (first line) */
34.156 + mmyth_epg_grid_widget_mount_header(mmyth_epg_grid_widget);
34.157 +
34.158 + /* service programs */
34.159 + /* mount service programs with current time */
34.160 + mmyth_epg_grid_widget_mount_services(mmyth_epg_grid_widget,
34.161 + private->current_start_time,
34.162 + private->current_end_time);
34.163 +}
34.164 +
34.165 +GtkWidget*
34.166 +mmyth_epg_grid_widget_new ()
34.167 +{
34.168 + return GTK_WIDGET ( gtk_type_new (mmyth_epg_grid_widget_get_type ()));
34.169 +}
34.170 +
34.171 +static void
34.172 +mmyth_epg_grid_widget_mount_services(MMythEpgGridWidget *mmyth_epg_grid_widget,
34.173 + int start_time, int end_time)
34.174 +{
34.175 + GList *proglist;
34.176 + GList *channel_list = NULL;
34.177 + GMythChannelInfo *channel_info;
34.178 +
34.179 + int chanid;
34.180 + MMythEpgGridWidgetPrivate *private =
34.181 + MMYTH_EPG_GRID_WIDGET_GET_PRIVATE(mmyth_epg_grid_widget);
34.182 +
34.183 + // update view_model
34.184 + /* FIXME shallow free or recursive? */
34.185 + if(mmyth_epg_grid_widget->epg_view_model != NULL) {
34.186 + g_list_free(mmyth_epg_grid_widget->epg_view_model);
34.187 + mmyth_epg_grid_widget->epg_view_model = NULL;
34.188 + }
34.189 +
34.190 + if(private->service_model_hash != NULL) {
34.191 + g_hash_table_destroy(private->service_model_hash);
34.192 + }
34.193 +
34.194 + private->service_model_hash = g_hash_table_new(NULL, NULL);
34.195 +
34.196 + /* fill program infos from db */
34.197 + mmyth_epg_grid_widget_fill_programinfos(private);
34.198 +
34.199 + channel_list = private->channel_list;
34.200 +
34.201 + /* for each channel get_programs() */
34.202 + for (chanid=0; channel_list &&
34.203 + chanid < private->DISPLAY_CHANS; chanid++) {
34.204 + proglist = (GList *) private->program_list[chanid];
34.205 +
34.206 + channel_info = (GMythChannelInfo *) channel_list->data;
34.207 + channel_list = g_list_next(channel_list);
34.208 +
34.209 + /* Service Title*/
34.210 + GString *name = NULL;
34.211 + if (channel_info->channel_name)
34.212 + name = g_string_new (channel_info->channel_name->str);
34.213 +
34.214 + GdkColor title_bg_color;
34.215 + title_bg_color.red = 5000;
34.216 + title_bg_color.green = 9000;
34.217 + title_bg_color.blue = 40000;
34.218 +
34.219 + GdkColor title_fg_color;
34.220 + title_fg_color.red = 60000;
34.221 + title_fg_color.green = 60000;
34.222 + title_fg_color.blue = 60000;
34.223 +
34.224 + GtkWidget *event_box_channel = create_event_box_lbl(
34.225 + name->str, 90,
34.226 + &title_bg_color,
34.227 + &title_fg_color);
34.228 +
34.229 + gtk_box_pack_start (GTK_BOX (private->epg_channels_vbox),
34.230 + event_box_channel, FALSE, FALSE, 0);
34.231 +
34.232 + GtkWidget *epg_line_hbox = gtk_hbox_new (FALSE, 0);
34.233 +
34.234 + GdkColor bg_color;
34.235 + bg_color.red = 5000;
34.236 + bg_color.green = 30000;
34.237 + bg_color.blue = 60000;
34.238 +
34.239 + GdkColor fg_color;
34.240 + fg_color.red = 60000;
34.241 + fg_color.green = 60000;
34.242 + fg_color.blue = 60000;
34.243 +
34.244 + /* Content parsing */
34.245 + GList *epg_grid_list = NULL;
34.246 +
34.247 + GMythProgramInfo *proginfo;
34.248 + int pixel_count = 0;
34.249 + for (; proglist; proglist = proglist->next) {
34.250 + proginfo = (GMythProgramInfo *) proglist->data;
34.251 +
34.252 + GString *content_name = proginfo->title;
34.253 +
34.254 + int initial_time, last_time, duration;
34.255 +
34.256 + int schedule_start_time = proginfo->startts;
34.257 + int schedule_end_time = proginfo->endts;
34.258 +
34.259 + initial_time =
34.260 + (schedule_start_time < start_time) ? start_time : schedule_start_time;
34.261 + last_time = (schedule_end_time > end_time) ? end_time : schedule_end_time;
34.262 + duration = last_time - initial_time;
34.263 +
34.264 + // Verify program time
34.265 + #if 0
34.266 + g_debug ("ServiceID: %d, ScheduleID: %d\n", service->id, schedule->id);
34.267 + fprintf (stderr, "program time\nfrom = %d, to = %d\n",
34.268 + schedule->validFrom, schedule->validTo);
34.269 +
34.270 + struct tm loctime;
34.271 +
34.272 + /* Convert it to local time representation. */
34.273 + if (localtime_r((time_t *)&schedule->validFrom, &loctime) == NULL) {
34.274 + g_warning ("localtime_r error in mmyth_epg_grid_widget!\n");
34.275 + return NULL;
34.276 + }
34.277 + fprintf (stderr, asctime (&loctime));
34.278 +
34.279 + if (localtime_r((time_t *)&schedule->validTo, &loctime) == NULL) {
34.280 + g_warning ("localtime_r error in mmyth_epg_grid_widget!\n");
34.281 + return NULL;
34.282 + }
34.283 + fprintf (stderr, asctime (&loctime));
34.284 + #endif
34.285 +
34.286 + /* fprintf(stderr, "duration = %d\n", duration); */
34.287 + double duration_hour = duration / (double) 3600.0;
34.288 + /* fprintf(stderr, "duration_hour = %lf\n", duration_hour); */
34.289 +
34.290 + int size = PIXELS_HOUR * duration_hour;
34.291 +
34.292 + /* complete hour */
34.293 + /* FIXME: UGLY WRONG HACK TO ALIGN PROGRAM TIME!!!*/
34.294 + if(last_time%3600 != 0) {
34.295 + size -= PROGRAM_SEPARATION;
34.296 + }
34.297 + if(initial_time%3600 != 0) {
34.298 + size -= PROGRAM_SEPARATION;
34.299 + }
34.300 +
34.301 + pixel_count += size + PROGRAM_SEPARATION;
34.302 + GtkWidget *event_box = create_event_box_lbl(content_name->str,
34.303 + size, &bg_color,
34.304 + &fg_color);
34.305 + gtk_widget_add_events(event_box,
34.306 + GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
34.307 +
34.308 + /* create EpgGridItem */
34.309 + EpgGridItem *epg_grid_item = g_new(EpgGridItem, 1);
34.310 + epg_grid_item->proginfo = proginfo;
34.311 + epg_grid_item->event_box = event_box;
34.312 + epg_grid_item->object = mmyth_epg_grid_widget;
34.313 +
34.314 + epg_grid_list = g_list_prepend(epg_grid_list, (gpointer) epg_grid_item);
34.315 +
34.316 + gtk_box_pack_start (GTK_BOX (epg_line_hbox),
34.317 + event_box, FALSE, FALSE, PROGRAM_SEPARATION);
34.318 +
34.319 + g_signal_connect (G_OBJECT (event_box), "button-press-event",
34.320 + G_CALLBACK (mmyth_epg_grid_widget_clicked),
34.321 + (gpointer*) epg_grid_list);
34.322 + }
34.323 +#if 0
34.324 + printf("chaind = %d!!!!" chanid);fflush(stdout);
34.325 +#endif
34.326 +
34.327 + if(!epg_grid_list) {
34.328 + /* No programs for current channel */
34.329 + /* FIXME: size HARDCODED */
34.330 + GtkWidget *event_box = create_event_box_lbl("No program list available",
34.331 + PIXELS_HOUR * 3, &bg_color,
34.332 + &fg_color);
34.333 + gtk_widget_add_events(event_box,
34.334 + GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
34.335 +
34.336 + /* create EpgGridItem */
34.337 + EpgGridItem *epg_grid_item = g_new(EpgGridItem, 1);
34.338 + epg_grid_item->proginfo = NULL;
34.339 + epg_grid_item->event_box = event_box;
34.340 + epg_grid_item->object = mmyth_epg_grid_widget;
34.341 +
34.342 + epg_grid_list = g_list_prepend(epg_grid_list, (gpointer) epg_grid_item);
34.343 +
34.344 + gtk_box_pack_start (GTK_BOX (epg_line_hbox),
34.345 + event_box, FALSE, FALSE, PROGRAM_SEPARATION);
34.346 +
34.347 + g_signal_connect (G_OBJECT (event_box), "button-press-event",
34.348 + G_CALLBACK (mmyth_epg_grid_widget_clicked),
34.349 + (gpointer*) epg_grid_list);
34.350 + }
34.351 +
34.352 + epg_grid_list = g_list_reverse(epg_grid_list);
34.353 + mmyth_epg_grid_widget->epg_view_model =
34.354 + g_list_append(mmyth_epg_grid_widget->epg_view_model, epg_grid_list);
34.355 +
34.356 + gtk_box_pack_start (GTK_BOX (private->epg_programs_vbox),
34.357 + epg_line_hbox, FALSE, FALSE, 0);
34.358 + }
34.359 +}
34.360 +
34.361 +static void
34.362 +mmyth_epg_grid_widget_mount_header(MMythEpgGridWidget *mmyth_epg_grid_widget)
34.363 +{
34.364 + MMythEpgGridWidgetPrivate *private =
34.365 + MMYTH_EPG_GRID_WIDGET_GET_PRIVATE(mmyth_epg_grid_widget);
34.366 +
34.367 + struct tm hour_tm;
34.368 + const gchar name_title[] = "Today";
34.369 + GtkWidget * lbl_title = gtk_label_new(name_title);
34.370 +
34.371 + gtk_misc_set_alignment (GTK_MISC(lbl_title), 0.0, 0.5);
34.372 +
34.373 + gtk_box_pack_start (GTK_BOX (private->epg_channels_vbox),
34.374 + lbl_title, FALSE, FALSE, 0);
34.375 +
34.376 + /* hours title line */
34.377 + GtkWidget *epg_programs_hours_hbox = gtk_hbox_new (TRUE, 0);
34.378 +
34.379 + if (localtime_r((time_t *)&private->current_start_time, &hour_tm) == NULL) {
34.380 + g_warning ("localtime_r error in mmyth_epg_grid_widget!\n");
34.381 + return NULL;
34.382 + }
34.383 +
34.384 + if (hour_tm.tm_min>30) {
34.385 + hour_tm.tm_min = 30;
34.386 + } else if (hour_tm.tm_min>0) {
34.387 + hour_tm.tm_min = 0;
34.388 + }
34.389 +
34.390 + gchar hour1_str[10];
34.391 + strftime(hour1_str, 8, "%H:%M", &hour_tm);
34.392 + GtkWidget * lbl_hour1 = gtk_label_new(hour1_str);
34.393 + gtk_misc_set_alignment (GTK_MISC(lbl_hour1), 0.0, 0.5);
34.394 +
34.395 + hour_tm.tm_hour++;
34.396 + gchar hour2_str[10];
34.397 + strftime(hour2_str, 8, "%H:%M", &hour_tm);
34.398 + GtkWidget * lbl_hour2 = gtk_label_new(hour2_str);
34.399 + gtk_misc_set_alignment (GTK_MISC(lbl_hour2), 0.0, 0.5);
34.400 +
34.401 + hour_tm.tm_hour++;
34.402 + gchar hour3_str[10];
34.403 + strftime(hour3_str, 8, "%H:%M", &hour_tm);
34.404 + GtkWidget * lbl_hour3 = gtk_label_new(hour3_str);
34.405 + gtk_misc_set_alignment (GTK_MISC(lbl_hour3), 0.0, 0.5);
34.406 +
34.407 + gtk_box_pack_start (GTK_BOX (epg_programs_hours_hbox),
34.408 + lbl_hour1, TRUE, TRUE, 0);
34.409 + gtk_box_pack_start (GTK_BOX (epg_programs_hours_hbox),
34.410 + lbl_hour2, TRUE, TRUE, 0);
34.411 + gtk_box_pack_start (GTK_BOX (epg_programs_hours_hbox),
34.412 + lbl_hour3, TRUE, TRUE, 0);
34.413 +
34.414 + gtk_box_pack_start (GTK_BOX (private->epg_programs_vbox),
34.415 + epg_programs_hours_hbox, FALSE, FALSE, 0);
34.416 +}
34.417 +
34.418 +/******************************************************************************
34.419 + * INTERNAL CALLBACKS FOR STATE CHANGE *
34.420 + *****************************************************************************/
34.421 +static void
34.422 +mmyth_epg_grid_widget_deselect_service(MMythEpgGridWidget *mmyth_epg_grid_widget)
34.423 +{
34.424 + EpgGridItem *epg_grid_item;
34.425 +
34.426 + /* deselect*/
34.427 + if(mmyth_epg_grid_widget->selected_grid_item != NULL) {
34.428 + epg_grid_item =
34.429 + (EpgGridItem*) mmyth_epg_grid_widget->selected_grid_item->data;
34.430 + gtk_widget_set_state(GTK_WIDGET(epg_grid_item->event_box), GTK_STATE_NORMAL);
34.431 + }
34.432 +}
34.433 +
34.434 +static void
34.435 +mmyth_epg_grid_widget_clicked (GtkWidget* widget,
34.436 + GdkEventExpose *event, gpointer data)
34.437 +{
34.438 + g_return_if_fail(data != NULL);
34.439 +
34.440 + GList *epg_grid_item_list = (GList *) data;
34.441 + EpgGridItem *epg_grid_item = (EpgGridItem *) epg_grid_item_list->data;
34.442 +
34.443 + /* update the selected service */
34.444 + mmyth_epg_grid_widget_update_service( epg_grid_item->object, (GList*) data );
34.445 +}
34.446 +
34.447 +void
34.448 +mmyth_epg_grid_widget_update_service(MMythEpgGridWidget * object,
34.449 + GList *selected_grid_list)
34.450 +{
34.451 + g_return_if_fail(object != NULL);
34.452 + g_return_if_fail(selected_grid_list != NULL);
34.453 +
34.454 + EpgGridItem *epg_grid_item = (EpgGridItem *) selected_grid_list->data;
34.455 +
34.456 + mmyth_epg_grid_widget_deselect_service(epg_grid_item->object);
34.457 +
34.458 + /* updating current selected schedule_item and schedule_list*/
34.459 + object->selected_grid_item = selected_grid_list;
34.460 +
34.461 + /* set state of the event box */
34.462 + gtk_widget_set_state(GTK_WIDGET(epg_grid_item->event_box), GTK_STATE_SELECTED);
34.463 + /* emit update signal for listeners */
34.464 + g_signal_emit(object,
34.465 + mmyth_epg_grid_widget_signals[SELECTION_UPDATED_SIGNAL],
34.466 + 0,
34.467 + (gpointer) epg_grid_item);
34.468 +}
34.469 +
34.470 +static GtkWidget *
34.471 +create_event_box_lbl(gchar *str, int width, const GdkColor *bg_color,
34.472 + const GdkColor *fg_color)
34.473 +{
34.474 + GtkWidget *event_box = gtk_event_box_new();
34.475 + GtkWidget *lbl = gtk_label_new(str);
34.476 + gtk_label_set_ellipsize(GTK_LABEL(lbl), PANGO_ELLIPSIZE_END);
34.477 +
34.478 + gtk_widget_modify_bg(event_box, GTK_STATE_NORMAL, bg_color);
34.479 + gtk_widget_modify_fg(lbl, GTK_STATE_NORMAL, fg_color);
34.480 +
34.481 + /* selected colors are const*/
34.482 + GdkColor selected_bg_color;
34.483 + selected_bg_color.red = 100;
34.484 + selected_bg_color.green = 40000;
34.485 + selected_bg_color.blue = 100;
34.486 +
34.487 + GdkColor selected_fg_color;
34.488 + selected_fg_color.red = 100;
34.489 + selected_fg_color.green = 100;
34.490 + selected_fg_color.blue = 100;
34.491 +
34.492 + gtk_widget_modify_bg(event_box, GTK_STATE_SELECTED, &selected_bg_color);
34.493 + gtk_widget_modify_fg(lbl, GTK_STATE_SELECTED, &selected_fg_color);
34.494 +
34.495 + gtk_misc_set_alignment (GTK_MISC(lbl), 0.0, 0.5);
34.496 + gtk_container_add (GTK_CONTAINER (event_box),
34.497 + lbl);
34.498 + gtk_widget_set_size_request(event_box, width, -1);
34.499 +
34.500 + return event_box;
34.501 +}
34.502 +
34.503 +/******************************************************************************
34.504 + * METHODS *
34.505 + *****************************************************************************/
34.506 +
34.507 +/* Callback for hardware keys */
34.508 +gboolean
34.509 +mmyth_epg_grid_widget_key_press (MMythEpgGridWidget * object,
34.510 + GtkWidget * widget, GdkEventKey * event)
34.511 +{
34.512 + MMythEpgGridWidgetPrivate *private =
34.513 + MMYTH_EPG_GRID_WIDGET_GET_PRIVATE(object);
34.514 +
34.515 + EpgGridItem *epg_grid_item;
34.516 + GList *tmp;
34.517 +
34.518 + /* List of selected_grid_item */
34.519 + GList *selected_view_model;
34.520 +
34.521 + gint channel_index;
34.522 +
34.523 + if(object->selected_grid_item == NULL) {
34.524 + g_warning ("No program selected");
34.525 + return FALSE;
34.526 + }
34.527 +
34.528 + epg_grid_item = (EpgGridItem*) object->selected_grid_item->data;
34.529 +
34.530 + channel_index = private->selected_channel_index;
34.531 +
34.532 + switch (event->keyval) {
34.533 + case GDK_Up:
34.534 + selected_view_model = g_list_nth( object->epg_view_model, channel_index - 1 );
34.535 + if(selected_view_model != NULL) {
34.536 + private->selected_channel_index = channel_index - 1;
34.537 + tmp = (GList *) selected_view_model->data;
34.538 + /* TODO: select a better centralized item
34.539 + currently is picking the 1st or last item */
34.540 + if(g_list_next(object->selected_grid_item) == NULL &&
34.541 + g_list_previous(object->selected_grid_item) != NULL) {
34.542 + /* in this case the new selected will be the last */
34.543 + tmp = g_list_last(tmp);
34.544 + }
34.545 +
34.546 + /* update the selected service */
34.547 + mmyth_epg_grid_widget_update_service( object, tmp );
34.548 + }
34.549 + return TRUE;
34.550 + case GDK_Down:
34.551 + selected_view_model = g_list_nth( object->epg_view_model, channel_index + 1 );
34.552 + if(selected_view_model != NULL) {
34.553 + private->selected_channel_index = channel_index + 1;
34.554 + tmp = (GList *) selected_view_model->data;
34.555 + /* TODO: select a better centralized item
34.556 + currently is picking the 1st or last item */
34.557 + if(g_list_next(object->selected_grid_item) == NULL &&
34.558 + g_list_previous(object->selected_grid_item) != NULL) {
34.559 + /* in this case the new selected will be the last */
34.560 + tmp = g_list_last(tmp);
34.561 + }
34.562 +
34.563 + /* update the selected service */
34.564 + mmyth_epg_grid_widget_update_service( object, tmp );
34.565 + }
34.566 + return TRUE;
34.567 + case GDK_Left:
34.568 + tmp = g_list_previous( object->selected_grid_item );
34.569 + if(tmp != NULL) {
34.570 + /* update the selected service */
34.571 + mmyth_epg_grid_widget_update_service( object, tmp );
34.572 + }
34.573 + return TRUE;
34.574 + case GDK_Right:
34.575 + tmp = g_list_next( object->selected_grid_item );
34.576 + if(tmp != NULL) {
34.577 + /* update the selected service */
34.578 + mmyth_epg_grid_widget_update_service( object, tmp );
34.579 + }
34.580 + return TRUE;
34.581 + default:
34.582 + return TRUE;
34.583 + }
34.584 +
34.585 + return FALSE;
34.586 +}
34.587 +
34.588 +static void
34.589 +mmyth_epg_grid_widget_fill_programinfos (MMythEpgGridWidgetPrivate *private)
34.590 +{
34.591 + GList *channels_list = NULL;
34.592 + int y;
34.593 +
34.594 + if ((private->mmyth_epg != NULL) &&
34.595 + (gmyth_epg_get_channel_list (private->mmyth_epg, &channels_list) < 0 )) {
34.596 + private->channel_list = NULL;
34.597 + return;
34.598 + }
34.599 +
34.600 + private->channel_list = channels_list;
34.601 +
34.602 + for (y = 0; y < private->DISPLAY_CHANS && channels_list; y++) {
34.603 + GMythChannelInfo *channel_info = (GMythChannelInfo *) channels_list->data;
34.604 +
34.605 + mmyth_epg_grid_widget_fill_program_row_infos(
34.606 + private, channel_info->channel_ID, y);
34.607 +
34.608 + channels_list = g_list_next (channels_list);
34.609 + }
34.610 +}
34.611 +
34.612 +static void
34.613 +mmyth_epg_grid_widget_fill_program_row_infos(MMythEpgGridWidgetPrivate *private,
34.614 + guint chanNum, guint row)
34.615 +{
34.616 + gint res = gmyth_epg_get_program_list (private->mmyth_epg,
34.617 + &(private->program_list[row]),
34.618 + chanNum, private->current_start_time,
34.619 + private->current_end_time);
34.620 +
34.621 + if (res < 0) {
34.622 + g_warning ("[%s] Error while retrieving epg programs", __FUNCTION__);
34.623 + }
34.624 +}
34.625 +
35.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
35.2 +++ b/gmyth/src/gui/mmyth_epg_grid_widget.h Wed Sep 20 23:45:35 2006 +0100
35.3 @@ -0,0 +1,74 @@
35.4 +#ifndef __MMYTH_EPG_GRID_WIDGET_H__
35.5 +#define __MMYTH_EPG_GRID_WIDGET_H__
35.6 +
35.7 +#include <glib-object.h>
35.8 +#include <gdk/gdk.h>
35.9 +#include <gtk/gtkvbox.h>
35.10 +#include <gtk/gtkeventbox.h>
35.11 +
35.12 +#include "gmyth_common.h"
35.13 +
35.14 +#define MAX_DISPLAY_CHANS 4
35.15 +
35.16 +#define G_BEGIN_DECLS
35.17 +
35.18 +#define MMYTH_EPG_GRID_WIDGET_TYPE (mmyth_epg_grid_widget_get_type ())
35.19 +#define MMYTH_EPG_GRID_WIDGET(obj) (GTK_CHECK_CAST ((obj), MMYTH_EPG_GRID_WIDGET_TYPE, MMythEpgGridWidget))
35.20 +#define MMYTH_EPG_GRID_WIDGET_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), MMYTH_EPG_GRID_WIDGET_TYPE, MMythEpgGridWidgetClass))
35.21 +#define IS_MMYTH_EPG_GRID_WIDGET(obj) (GTK_CHECK_TYPE ((obj), MMYTH_EPG_GRID_WIDGET_TYPE))
35.22 +#define IS_MMYTH_EPG_GRID_WIDGET_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), MMYTH_EPG_GRID_WIDGET_TYPE))
35.23 +#define MMYTH_EPG_GRID_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MMYTH_EPG_GRID_WIDGET_TYPE, MMythEpgGridWidgetClass))
35.24 +#define MMYTH_EPG_GRID_WIDGET_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), MMYTH_EPG_GRID_WIDGET_TYPE, MMythEpgGridWidgetPrivate))
35.25 +
35.26 +
35.27 +typedef struct _MMythEpgGridWidget MMythEpgGridWidget;
35.28 +typedef struct _MMythEpgGridWidgetClass MMythEpgGridWidgetClass;
35.29 +typedef struct _MMythEpgGridWidgetPrivate MMythEpgGridWidgetPrivate;
35.30 +
35.31 +struct _MMythEpgGridWidgetClass
35.32 +{
35.33 + GtkEventBoxClass parent_class;
35.34 +
35.35 + /* callbacks */
35.36 + /* no one for now */
35.37 +};
35.38 +
35.39 +struct _MMythEpgGridWidget
35.40 +{
35.41 + GtkEventBox event_box;
35.42 +
35.43 + /* Selected Widgets Logic*/
35.44 + /* List os Service Model in the current view
35.45 + * the data of this list are GList for the programs
35.46 + * of each service */
35.47 + GList *epg_view_model;
35.48 +
35.49 + /* Selected Schedule Item*/
35.50 + GList *selected_grid_item;
35.51 +};
35.52 +
35.53 +
35.54 +GType mmyth_epg_grid_widget_get_type (void);
35.55 +GtkWidget* mmyth_epg_grid_widget_new (void);
35.56 +/*DVBHScheduleEvent* mmyth_epg_grid_get_selected_schedule (MMythEpgGridWidget * object);*/
35.57 +void mmyth_epg_grid_widget_update_service (MMythEpgGridWidget * object,
35.58 + GList *epg_grid_item_node);
35.59 +gboolean mmyth_epg_grid_widget_key_press (MMythEpgGridWidget * object,
35.60 + GtkWidget * widget,
35.61 + GdkEventKey * event);
35.62 +
35.63 +typedef struct _EpgGridItem EpgGridItem;
35.64 +
35.65 +/* FIXME: auxiliary struct */
35.66 +struct _EpgGridItem {
35.67 +
35.68 + GMythProgramInfo *proginfo;
35.69 + GtkWidget *event_box;
35.70 +
35.71 + /* for callback purposes */
35.72 + MMythEpgGridWidget *object;
35.73 +};
35.74 +
35.75 +#define G_END_DECLS
35.76 +
35.77 +#endif /* __MMYTH_EPG_GRID_WIDGET_H__ */
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
36.2 +++ b/gmyth/src/gui/mmyth_recordui.c Wed Sep 20 23:45:35 2006 +0100
36.3 @@ -0,0 +1,332 @@
36.4 +#include<gtk/gtk.h>
36.5 +#include<glib.h>
36.6 +#include <sys/types.h>
36.7 +#include <sys/stat.h>
36.8 +#include <unistd.h>
36.9 +#include <string.h>
36.10 +#include <stdio.h>
36.11 +#include <stdlib.h>
36.12 +
36.13 +#include "mmyth_ui.h"
36.14 +#include "mmyth_recordui.h"
36.15 +
36.16 +/* GMyth library includes */
36.17 +#include "gmyth_scheduler.h"
36.18 +#include "gmyth_util.h"
36.19 +
36.20 +enum {
36.21 + START_DATE_COLUMN = 0,
36.22 + TITLE_COLUMN,
36.23 + CHAN_ID_COLUMN,
36.24 + END_TIME_COLUMN,
36.25 + RECORD_ID_COLUMN,
36.26 + BASENAME_COLUMN,
36.27 + N_COLUMNS
36.28 +};
36.29 +
36.30 +gboolean
36.31 +mmyth_recordui_reload_all (MMythRecordUI *recordui)
36.32 +{
36.33 + gboolean res = FALSE;
36.34 +
36.35 + res = mmyth_recordui_reload_schedule (recordui);
36.36 +
36.37 + res = res & mmyth_recordui_reload_record (recordui);
36.38 +
36.39 +
36.40 + if (!res)
36.41 + g_warning ("[%s] Error while reloading schedule and recording content", __FUNCTION__);
36.42 +
36.43 + return res;
36.44 +}
36.45 +
36.46 +gboolean
36.47 +mmyth_recordui_reload_schedule (MMythRecordUI *recordui)
36.48 +{
36.49 + gint new_row = 0;
36.50 + ScheduleInfo *schedule_info;
36.51 + GList *schedule_list;
36.52 + GtkTreeIter iter;
36.53 + GString *start_date_time = NULL;
36.54 + GString *end_date_time = NULL;
36.55 + GString *str_aux = g_string_new("");
36.56 + gint res;
36.57 +
36.58 + gtk_tree_store_clear(recordui->sch_tree_store);
36.59 +
36.60 + res = gmyth_scheduler_get_schedule_list(recordui->scheduler, &(schedule_list));
36.61 + if (res < 0) {
36.62 + g_warning ("[%s] Retrieved NULL list of scheduled data from database",
36.63 + __FUNCTION__);
36.64 + return FALSE;
36.65 + }
36.66 +
36.67 + for ( ; schedule_list; schedule_list = schedule_list->next) {
36.68 + schedule_info = (ScheduleInfo*) schedule_list->data;
36.69 +
36.70 + gtk_tree_store_insert(recordui->sch_tree_store, &iter, NULL, new_row++);
36.71 +
36.72 + start_date_time = gmyth_util_time_to_string(schedule_info->start_time);
36.73 + end_date_time = gmyth_util_time_to_string(schedule_info->end_time);
36.74 +
36.75 + g_string_printf(str_aux, "%d", schedule_info->channel_id);
36.76 +
36.77 + gtk_tree_store_set(recordui->sch_tree_store, &iter,
36.78 + START_DATE_COLUMN, start_date_time->str,
36.79 + TITLE_COLUMN, schedule_info->title->str,
36.80 + CHAN_ID_COLUMN, str_aux->str,
36.81 + END_TIME_COLUMN, end_date_time->str, //It doesn't appear
36.82 + RECORD_ID_COLUMN, schedule_info->record_id,
36.83 + -1); //the last line is a hidden item to be used in searching tasks
36.84 + }
36.85 +
36.86 + g_debug ("[%s] %d lines added to schedule list UI", __FUNCTION__, new_row);
36.87 +
36.88 + /* free allocated memory */
36.89 + if(!start_date_time)
36.90 + g_string_free(start_date_time, FALSE);
36.91 + if(!end_date_time)
36.92 + g_string_free(end_date_time, FALSE);
36.93 + g_string_free(str_aux, FALSE);
36.94 +
36.95 + return TRUE;
36.96 +}
36.97 +
36.98 +gboolean
36.99 +mmyth_recordui_reload_record (MMythRecordUI *recordui)
36.100 +{
36.101 + gint new_row = 0;
36.102 + RecordedInfo *recorded_info;
36.103 + GList *record_list = NULL;
36.104 + GtkTreeIter iter;
36.105 + GString *start_date_time = NULL;
36.106 + GString *end_date_time = NULL;
36.107 + GString *str_aux = g_string_new("");
36.108 + gint res;
36.109 +
36.110 + gtk_tree_store_clear(recordui->rec_tree_store);
36.111 +
36.112 + res = gmyth_scheduler_get_recorded_list(recordui->scheduler, &record_list);
36.113 + if (res < 0) {
36.114 + g_warning ("[%s] Retrieved NULL list of recorded data from database", __FUNCTION__);
36.115 + return FALSE;
36.116 + }
36.117 +
36.118 + for (; record_list; record_list = record_list->next) {
36.119 + recorded_info = (RecordedInfo*) record_list->data;
36.120 +
36.121 + gtk_tree_store_insert(recordui->rec_tree_store, &iter, NULL, new_row++);
36.122 +
36.123 + start_date_time = gmyth_util_time_to_string(recorded_info->start_time);
36.124 + end_date_time = gmyth_util_time_to_string(recorded_info->end_time);
36.125 +
36.126 + g_string_printf(str_aux, "%d", recorded_info->channel_id);
36.127 +
36.128 + gtk_tree_store_set(recordui->rec_tree_store, &iter,
36.129 + START_DATE_COLUMN, start_date_time->str,
36.130 + TITLE_COLUMN, recorded_info->title->str,
36.131 + CHAN_ID_COLUMN, str_aux->str,
36.132 + END_TIME_COLUMN, end_date_time->str, //It doesn't appear
36.133 + RECORD_ID_COLUMN, recorded_info->record_id,
36.134 + BASENAME_COLUMN, recorded_info->basename->str, -1);
36.135 + //the last line is a hidden item to be used in searching tasks
36.136 + }
36.137 +
36.138 + g_debug ("[%s] %d lines added to record list UI", __FUNCTION__, new_row);
36.139 +
36.140 + return TRUE;
36.141 +}
36.142 +
36.143 +
36.144 +MMythRecordUI*
36.145 +mmyth_recordui_new(void)
36.146 +{
36.147 + MMythRecordUI *recordui = g_new0 (MMythRecordUI, 1);
36.148 +
36.149 + recordui->scrolled_window = gtk_scrolled_window_new (NULL, NULL);
36.150 + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (recordui->scrolled_window),
36.151 + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
36.152 +
36.153 + recordui->viewport = gtk_viewport_new (NULL, NULL);
36.154 + gtk_container_add (GTK_CONTAINER (recordui->scrolled_window), recordui->viewport);
36.155 +
36.156 + recordui->notebook = gtk_notebook_new ();
36.157 + gtk_container_set_border_width (GTK_CONTAINER (recordui->notebook), 1);
36.158 + gtk_notebook_set_scrollable (GTK_NOTEBOOK (recordui->notebook), TRUE);
36.159 + gtk_notebook_popup_enable (GTK_NOTEBOOK (recordui->notebook));
36.160 + gtk_container_add (GTK_CONTAINER (recordui->viewport), recordui->notebook);
36.161 + gtk_notebook_popup_disable(GTK_NOTEBOOK (recordui->notebook));
36.162 +
36.163 + /* Schedule tab */
36.164 + recordui->sch_scrolled_window = gtk_scrolled_window_new (NULL, NULL);
36.165 + gtk_container_add (GTK_CONTAINER (recordui->notebook), recordui->sch_scrolled_window);
36.166 + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (recordui->sch_scrolled_window),
36.167 + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
36.168 + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (recordui->sch_scrolled_window),
36.169 + GTK_SHADOW_IN);
36.170 +
36.171 + /* The basename column in the sched_tree_store is not being used*/
36.172 + recordui->sch_tree_store =
36.173 + gtk_tree_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING,
36.174 + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING );
36.175 +
36.176 + recordui->sch_treeview =
36.177 + gtk_tree_view_new_with_model(GTK_TREE_MODEL(recordui->sch_tree_store));
36.178 + gtk_container_add (GTK_CONTAINER (recordui->sch_scrolled_window),
36.179 + recordui->sch_treeview);
36.180 + recordui->sch_renderer = gtk_cell_renderer_text_new();
36.181 + //g_object_set(G_OBJECT(renderer1), "foreground", "green", "background", "black", NULL);
36.182 + recordui->sch_column1 =
36.183 + gtk_tree_view_column_new_with_attributes("Start time", recordui->sch_renderer,
36.184 + "text", START_DATE_COLUMN, NULL);
36.185 + gtk_tree_view_append_column(GTK_TREE_VIEW(recordui->sch_treeview),
36.186 + recordui->sch_column1);
36.187 + recordui->sch_column2 =
36.188 + gtk_tree_view_column_new_with_attributes("Title", recordui->sch_renderer,
36.189 + "text", TITLE_COLUMN, NULL);
36.190 + gtk_tree_view_append_column(GTK_TREE_VIEW(recordui->sch_treeview),
36.191 + recordui->sch_column2);
36.192 + recordui->sch_column3 =
36.193 + gtk_tree_view_column_new_with_attributes("Channel", recordui->sch_renderer,
36.194 + "text", CHAN_ID_COLUMN, NULL);
36.195 + gtk_tree_view_append_column(GTK_TREE_VIEW(recordui->sch_treeview),
36.196 + recordui->sch_column3);
36.197 + gtk_tree_view_column_set_resizable(recordui->sch_column1, TRUE);
36.198 + gtk_tree_view_column_set_resizable(recordui->sch_column2, TRUE);
36.199 + gtk_tree_view_column_set_resizable(recordui->sch_column3, TRUE);
36.200 + gtk_tree_view_column_set_reorderable(recordui->sch_column1, TRUE);
36.201 + gtk_tree_view_column_set_reorderable(recordui->sch_column2, TRUE);
36.202 + gtk_tree_view_column_set_reorderable(recordui->sch_column3, TRUE);
36.203 +// recordui->sch_column4 =
36.204 +// gtk_tree_view_column_new_with_attributes("", recordui->sch_renderer, "text", END_TIME_COLUMN, NULL);
36.205 +// gtk_tree_view_append_column(GTK_TREE_VIEW(recordui->sch_treeview),
36.206 +// recordui->sch_column4);
36.207 +
36.208 + recordui->sch_label = gtk_label_new (("Schedule"));
36.209 + gtk_notebook_set_tab_label (GTK_NOTEBOOK (recordui->notebook),
36.210 + gtk_notebook_get_nth_page (
36.211 + GTK_NOTEBOOK (recordui->notebook), 0),
36.212 + recordui->sch_label);
36.213 +
36.214 + // Record items tab
36.215 + // g_object_set(G_OBJECT(renderer2), "foreground", "blue", NULL);
36.216 + recordui->rec_scrolled_window = gtk_scrolled_window_new (NULL, NULL);
36.217 + gtk_container_add (GTK_CONTAINER (recordui->notebook),
36.218 + recordui->rec_scrolled_window);
36.219 + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (recordui->rec_scrolled_window),
36.220 + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
36.221 + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (recordui->rec_scrolled_window),
36.222 + GTK_SHADOW_IN);
36.223 +
36.224 + recordui->rec_tree_store =
36.225 + gtk_tree_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING,
36.226 + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING);
36.227 + recordui->rec_treeview =
36.228 + gtk_tree_view_new_with_model(GTK_TREE_MODEL(recordui->rec_tree_store));
36.229 + gtk_container_add (GTK_CONTAINER (recordui->rec_scrolled_window),
36.230 + recordui->rec_treeview);
36.231 + recordui->rec_renderer = gtk_cell_renderer_text_new();
36.232 + //g_object_set(G_OBJECT(renderer1), "foreground", "green", "background", "black", NULL);
36.233 +
36.234 + recordui->rec_column1 =
36.235 + gtk_tree_view_column_new_with_attributes("Start time", recordui->rec_renderer,
36.236 + "text", START_DATE_COLUMN, NULL);
36.237 + gtk_tree_view_append_column(GTK_TREE_VIEW(recordui->rec_treeview),
36.238 + recordui->rec_column1);
36.239 + recordui->rec_column2 =
36.240 + gtk_tree_view_column_new_with_attributes("Title", recordui->rec_renderer,
36.241 + "text", TITLE_COLUMN, NULL);
36.242 + gtk_tree_view_append_column(GTK_TREE_VIEW(recordui->rec_treeview),
36.243 + recordui->rec_column2);
36.244 + recordui->rec_column3 =
36.245 + gtk_tree_view_column_new_with_attributes("Channel", recordui->rec_renderer,
36.246 + "text", CHAN_ID_COLUMN, NULL);
36.247 + gtk_tree_view_append_column(GTK_TREE_VIEW(recordui->rec_treeview),
36.248 + recordui->rec_column3);
36.249 + gtk_tree_view_column_set_resizable(recordui->rec_column1, TRUE);
36.250 + gtk_tree_view_column_set_resizable(recordui->rec_column2, TRUE);
36.251 + gtk_tree_view_column_set_resizable(recordui->rec_column3, TRUE);
36.252 + gtk_tree_view_column_set_reorderable(recordui->rec_column1, TRUE);
36.253 + gtk_tree_view_column_set_reorderable(recordui->rec_column2, TRUE);
36.254 + gtk_tree_view_column_set_reorderable(recordui->rec_column3, TRUE);
36.255 +// recordui->rec_column4 = gtk_tree_view_column_new_with_attributes("", recordui->rec_renderer, "text", END_TIME_COLUMN, NULL);
36.256 +// gtk_tree_view_append_column(GTK_TREE_VIEW(recordui->rec_treeview), recordui->rec_column4);
36.257 +
36.258 + recordui->rec_label = gtk_label_new (("Recorded"));
36.259 + gtk_notebook_set_tab_label (GTK_NOTEBOOK (recordui->notebook),
36.260 + gtk_notebook_get_nth_page (
36.261 + GTK_NOTEBOOK (recordui->notebook), 1),
36.262 + recordui->rec_label);
36.263 +
36.264 + // Gets the mmyth scheduler manager
36.265 + recordui->scheduler = gmyth_scheduler_new ();
36.266 +
36.267 + /* init connection to the backend */
36.268 + gmyth_scheduler_connect (recordui->scheduler);
36.269 +
36.270 + return recordui;
36.271 +}
36.272 +
36.273 +void
36.274 +mmyth_recordui_free (MMythRecordUI *recordui)
36.275 +{
36.276 + // FIXME: Release memory here!
36.277 + /* close connection to the backend */
36.278 + gmyth_scheduler_disconnect (recordui->scheduler);
36.279 +}
36.280 +
36.281 +void
36.282 +mmyth_recordui_delete_selected (GtkButton *button, MMythRecordUI *recordui)
36.283 +{
36.284 + GtkTreeSelection *selection;
36.285 + GtkTreeModel *list_store;
36.286 + GtkTreeIter iter;
36.287 + int index;
36.288 + int curr_page = 0;
36.289 +
36.290 + curr_page = gtk_notebook_get_current_page(GTK_NOTEBOOK(recordui->notebook));
36.291 +
36.292 + if ( curr_page == 0) {
36.293 + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(recordui->sch_treeview));
36.294 + if (selection != NULL) {
36.295 + gtk_tree_selection_get_selected(selection, &list_store, &iter);
36.296 + gtk_tree_model_get(list_store, &iter, RECORD_ID_COLUMN, &index, -1);
36.297 + gmyth_scheduler_delete_schedule(recordui->scheduler, index);
36.298 + mmyth_recordui_reload_schedule (recordui);
36.299 + return;
36.300 + }
36.301 +
36.302 + } else if (curr_page == 1) {
36.303 + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(recordui->rec_treeview));
36.304 + if (selection != NULL) {
36.305 + gtk_tree_selection_get_selected(selection, &list_store, &iter);
36.306 + gtk_tree_model_get(list_store, &iter, RECORD_ID_COLUMN, &index, -1);
36.307 + gmyth_scheduler_delete_recorded(recordui->scheduler, index);
36.308 + mmyth_recordui_reload_record (recordui);
36.309 + return;
36.310 + }
36.311 + }
36.312 +
36.313 + g_warning ("[%s] None element was removed from the list", __FUNCTION__);
36.314 +}
36.315 +
36.316 +/* FIXME: change this function name, it is returning the
36.317 + * basename_column that represents the nuv filename of
36.318 + * the recorded content */
36.319 +gchar*
36.320 +mmyth_recordui_get_selected_recorded (MMythRecordUI *recordui)
36.321 +{
36.322 + GtkTreeSelection *selection = NULL;
36.323 + GtkTreeModel *list_store = NULL;
36.324 + GtkTreeIter iter;
36.325 + gchar *path = NULL;
36.326 +
36.327 + /* returning nuv filename, basename_column */
36.328 + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(recordui->rec_treeview));
36.329 + if (gtk_tree_selection_get_selected (selection, &list_store, &iter)) {
36.330 + gtk_tree_model_get(list_store, &iter, BASENAME_COLUMN, &path, -1);
36.331 + }
36.332 +
36.333 + // FIXME: MOVE THIS TO OTHER PLACE
36.334 + return path;
36.335 +}
37.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
37.2 +++ b/gmyth/src/gui/mmyth_recordui.h Wed Sep 20 23:45:35 2006 +0100
37.3 @@ -0,0 +1,48 @@
37.4 +#ifndef MMYTH_RECORD_H_
37.5 +#define MMYTH_RECORD_H_
37.6 +
37.7 +#include "gmyth_scheduler.h"
37.8 +
37.9 +typedef struct _MMythRecordUI
37.10 +{
37.11 + GtkWidget *scrolled_window;
37.12 + GtkWidget *viewport;
37.13 + GtkWidget *notebook;
37.14 +
37.15 + GtkWidget *rec_scrolled_window;
37.16 + GtkWidget *sch_scrolled_window;
37.17 + GtkWidget *rec_treeview;
37.18 + GtkWidget *sch_treeview;
37.19 + GtkWidget *rec_label;
37.20 + GtkWidget *sch_label;
37.21 +
37.22 + GtkTreeViewColumn *rec_column1;
37.23 + GtkTreeViewColumn *rec_column2;
37.24 + GtkTreeViewColumn *rec_column3;
37.25 + GtkTreeViewColumn *rec_column4;
37.26 + GtkTreeViewColumn *sch_column1;
37.27 + GtkTreeViewColumn *sch_column2;
37.28 + GtkTreeViewColumn *sch_column3;
37.29 + GtkTreeViewColumn *sch_column4;
37.30 +
37.31 + GtkCellRenderer *rec_renderer;
37.32 + GtkCellRenderer *sch_renderer;
37.33 +
37.34 + GtkTreeStore *sch_tree_store;
37.35 + GtkTreeStore *rec_tree_store;
37.36 +
37.37 + GMythScheduler *scheduler;
37.38 +
37.39 +} MMythRecordUI;
37.40 +
37.41 +MMythRecordUI* mmyth_recordui_new(void);
37.42 +void mmyth_recordui_free (MMythRecordUI *recordui);
37.43 +
37.44 +void mmyth_recordui_delete_selected (GtkButton *button, MMythRecordUI *recordui);
37.45 +gboolean mmyth_recordui_reload_all (MMythRecordUI *recordui);
37.46 +gboolean mmyth_recordui_reload_schedule (MMythRecordUI *recordui);
37.47 +gboolean mmyth_recordui_reload_record (MMythRecordUI *recordui);
37.48 +
37.49 +gchar* mmyth_recordui_get_selected_recorded (MMythRecordUI *recordui);
37.50 +
37.51 +#endif /*MMYTH_RECORD_H_*/
38.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
38.2 +++ b/gmyth/src/gui/mmyth_schedulerui.c Wed Sep 20 23:45:35 2006 +0100
38.3 @@ -0,0 +1,368 @@
38.4 +#include <gtk/gtk.h>
38.5 +#include <glib.h>
38.6 +#include <glib/gprintf.h>
38.7 +#include <sys/types.h>
38.8 +#include <sys/stat.h>
38.9 +#include <unistd.h>
38.10 +#include <string.h>
38.11 +#include <stdio.h>
38.12 +
38.13 +#include "mmyth_ui.h"
38.14 +#include "mmyth_uicommon.h"
38.15 +#include "mmyth_recordui.h"
38.16 +#include "mmyth_schedulerui.h"
38.17 +
38.18 +/* GMyth library includes */
38.19 +#include "gmyth_scheduler.h"
38.20 +#include "gmyth_common.h"
38.21 +#include "gmyth_epg.h"
38.22 +
38.23 +static void run_calendar_dialog (GtkButton *button, gpointer data);
38.24 +
38.25 +static void add_channel_field (MMythSchedulerUI *scheduler_ui, GtkWidget *vbox);
38.26 +static void add_time_field (MMythSchedulerUI *scheduler_ui, GtkWidget *vbox);
38.27 +static void add_date_field (MMythSchedulerUI *scheduler_ui, GtkWidget *vbox);
38.28 +static void add_duration_field (MMythSchedulerUI *scheduler_ui, GtkWidget *vbox);
38.29 +static void add_frequency_field (MMythSchedulerUI *scheduler_ui, GtkWidget *vbox);
38.30 +static void add_title_field (MMythSchedulerUI *scheduler_ui, GtkWidget *vbox);
38.31 +
38.32 +MMythSchedulerUI*
38.33 +mmyth_schedulerui_new (void)
38.34 +{
38.35 + GtkWidget *scrolledwindow;
38.36 + GtkWidget *viewport;
38.37 + GtkWidget *head_hbox;
38.38 + GtkWidget *fields_vbox;
38.39 + GtkWidget *hseparator;
38.40 + GtkWidget *label;
38.41 +
38.42 + MMythSchedulerUI *scheduler_ui = g_new0 (MMythSchedulerUI, 1);
38.43 +
38.44 + scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
38.45 + scheduler_ui->main_widget = scrolledwindow;
38.46 + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
38.47 + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
38.48 +
38.49 + //Is this needed?
38.50 + viewport = gtk_viewport_new (NULL, NULL);
38.51 + gtk_container_add (GTK_CONTAINER (scrolledwindow), viewport);
38.52 +
38.53 + //Is this needed?
38.54 + head_hbox = gtk_hbox_new (FALSE, 0);
38.55 + gtk_container_add (GTK_CONTAINER (viewport), head_hbox);
38.56 +
38.57 + fields_vbox = gtk_vbox_new (FALSE, 0);
38.58 + gtk_box_pack_start (GTK_BOX (head_hbox), fields_vbox, TRUE, TRUE, 0);
38.59 + gtk_container_set_border_width (GTK_CONTAINER (fields_vbox), 10);
38.60 +
38.61 + label = gtk_label_new_with_mnemonic (("Manual Schedule Recording"));
38.62 + gtk_box_pack_start (GTK_BOX (fields_vbox), label, FALSE, FALSE, 0);
38.63 + gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
38.64 +
38.65 + hseparator = gtk_hseparator_new ();
38.66 + gtk_box_pack_start (GTK_BOX (fields_vbox), hseparator, FALSE, TRUE, 0);
38.67 +
38.68 + add_channel_field (scheduler_ui, fields_vbox);
38.69 + add_time_field (scheduler_ui, fields_vbox);
38.70 + add_date_field (scheduler_ui, fields_vbox);
38.71 + add_duration_field (scheduler_ui, fields_vbox);
38.72 + add_frequency_field (scheduler_ui, fields_vbox);
38.73 + add_title_field (scheduler_ui, fields_vbox);
38.74 +
38.75 + return scheduler_ui;
38.76 +}
38.77 +
38.78 +static void
38.79 +set_date_from_calendar (GtkCalendar *calendar, gpointer data)
38.80 +{
38.81 + char sched_date[24];
38.82 +
38.83 + MMythSchedulerUI *scheduler_ui = (MMythSchedulerUI*) data;
38.84 +
38.85 + // FIXME: Change this, save another value instead of month_temp, day_temp, ...
38.86 + gtk_calendar_get_date(GTK_CALENDAR(calendar),
38.87 + &(scheduler_ui->year_temp), &(scheduler_ui->month_temp), &(scheduler_ui->day_temp));
38.88 +
38.89 + sched_date[23]='\0';
38.90 + g_sprintf(sched_date, "%04d %02d %02d (yyyy mm dd)",
38.91 + scheduler_ui->year_temp, scheduler_ui->month_temp+1, scheduler_ui->day_temp);
38.92 +
38.93 + gtk_button_set_label(GTK_BUTTON(scheduler_ui->date_button), sched_date);
38.94 +
38.95 + gtk_widget_destroy(scheduler_ui->calendar_dialog);
38.96 + scheduler_ui->calendar_dialog = NULL;
38.97 + scheduler_ui->calendar = NULL;
38.98 +}
38.99 +
38.100 +//calendar
38.101 +static void
38.102 +run_calendar_dialog (GtkButton *button, gpointer data)
38.103 +{
38.104 +
38.105 + GtkWidget *dialog_vbox;
38.106 + MMythSchedulerUI *scheduler_ui = (MMythSchedulerUI*) data;
38.107 +
38.108 + // calendar_dialog and calendar are been released at set_date_from_calendar ()
38.109 + scheduler_ui->calendar_dialog = gtk_dialog_new ();
38.110 + gtk_container_set_border_width (GTK_CONTAINER (scheduler_ui->calendar_dialog), 1);
38.111 + gtk_window_set_title (GTK_WINDOW (scheduler_ui->calendar_dialog), "Select starting date");
38.112 + gtk_window_set_position (GTK_WINDOW (scheduler_ui->calendar_dialog), GTK_WIN_POS_CENTER);
38.113 + gtk_window_set_decorated (GTK_WINDOW (scheduler_ui->calendar_dialog), FALSE);
38.114 +
38.115 + dialog_vbox = GTK_DIALOG (scheduler_ui->calendar_dialog)->vbox;
38.116 +
38.117 + scheduler_ui->calendar = gtk_calendar_new ();
38.118 +
38.119 + gtk_box_pack_start (GTK_BOX (dialog_vbox), scheduler_ui->calendar, TRUE, TRUE, 0);
38.120 + gtk_calendar_display_options (GTK_CALENDAR (scheduler_ui->calendar),
38.121 + GTK_CALENDAR_SHOW_HEADING | GTK_CALENDAR_SHOW_DAY_NAMES);
38.122 +
38.123 + gtk_widget_show_all (scheduler_ui->calendar_dialog);
38.124 +
38.125 + g_signal_connect (G_OBJECT (scheduler_ui->calendar), "day-selected-double-click",
38.126 + G_CALLBACK (set_date_from_calendar), data);
38.127 +}
38.128 +
38.129 +
38.130 +gboolean
38.131 +mmyth_schedulerui_save (MMythSchedulerUI *scheduler_ui)
38.132 +{
38.133 + GMythScheduler *scheduler;
38.134 + ScheduleInfo *schedule_info;
38.135 + GMythChannelInfo *channel_info;
38.136 +
38.137 + GList *clist;
38.138 + gint index, duration;
38.139 + gint frequency;
38.140 + struct tm start_tm;
38.141 +
38.142 + schedule_info = g_new0(ScheduleInfo, 1);
38.143 + if(schedule_info == NULL) {
38.144 + g_warning ("Error allocating memory");
38.145 + return FALSE;
38.146 + }
38.147 +
38.148 + clist = scheduler_ui->channel_list;
38.149 +
38.150 + index = gtk_combo_box_get_active(GTK_COMBO_BOX(scheduler_ui->channel_combobox));
38.151 +
38.152 + if (clist != NULL)
38.153 + clist = g_list_nth(clist, index);
38.154 +
38.155 + if (clist) {
38.156 + g_debug ("[%s] New schedule: %d", __FUNCTION__, index);
38.157 + } else {
38.158 + g_warning ("[%s] Error when adding new schedule", __FUNCTION__);
38.159 + return FALSE;
38.160 + }
38.161 +
38.162 + channel_info = clist->data;
38.163 +
38.164 + /* initialize schedule_info */
38.165 + schedule_info->channel_id = channel_info->channel_ID;
38.166 +
38.167 + start_tm.tm_hour =
38.168 + (int)gtk_spin_button_get_value(GTK_SPIN_BUTTON(scheduler_ui->hour_spinbutton));
38.169 + start_tm.tm_min =
38.170 + (int)gtk_spin_button_get_value(GTK_SPIN_BUTTON(scheduler_ui->min_spinbutton));
38.171 + start_tm.tm_sec = 0;
38.172 +
38.173 + start_tm.tm_mday = (gint)scheduler_ui->day_temp;
38.174 + start_tm.tm_mon = (gint)scheduler_ui->month_temp;
38.175 + start_tm.tm_year = (gint)scheduler_ui->year_temp - 1900; //years since 1900
38.176 +
38.177 + schedule_info->start_time = timelocal(&start_tm);
38.178 + if (schedule_info->start_time == (time_t)(-1)) {
38.179 + g_warning ("timelocal error!\n");
38.180 + return FALSE;
38.181 + }
38.182 +
38.183 + duration = (gint) gtk_spin_button_get_value(
38.184 + GTK_SPIN_BUTTON(scheduler_ui->duration_spinbutton));
38.185 + schedule_info->end_time = schedule_info->start_time + (duration*60);
38.186 +
38.187 + /* TODO: frequency is not implemented yet */
38.188 + frequency = gtk_combo_box_get_active(GTK_COMBO_BOX(scheduler_ui->freq_combobox));
38.189 +
38.190 + schedule_info->title = g_string_new("");
38.191 + g_string_printf(schedule_info->title, "%s",
38.192 + gtk_entry_get_text(GTK_ENTRY(scheduler_ui->title_entry)));
38.193 +
38.194 + /* FIXME: Architecture change to reuse the scheduler created in the recordui! */
38.195 + scheduler = gmyth_scheduler_new ();
38.196 +
38.197 + gmyth_scheduler_connect(scheduler);
38.198 +
38.199 + /* FIXME: set record_id = -1 to add a new schedule */
38.200 + schedule_info->record_id = -1;
38.201 + gmyth_scheduler_add_schedule (scheduler, schedule_info);
38.202 +
38.203 + gmyth_scheduler_disconnect(scheduler);
38.204 +
38.205 + /* free allocated memory */
38.206 + g_object_unref (scheduler);
38.207 + g_free (schedule_info);
38.208 +
38.209 + return TRUE;
38.210 +}
38.211 +
38.212 +static GtkWidget*
38.213 +add_line (GtkWidget *vbox, const gchar *str)
38.214 +{
38.215 + GtkWidget *label;
38.216 + GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
38.217 +
38.218 + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
38.219 + gtk_container_set_border_width (GTK_CONTAINER (hbox), 3);
38.220 +
38.221 + label = gtk_label_new (str);
38.222 + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
38.223 + gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
38.224 +
38.225 + return hbox;
38.226 +}
38.227 +
38.228 +static void
38.229 +add_channel_field (MMythSchedulerUI *scheduler_ui, GtkWidget *vbox)
38.230 +{
38.231 + GtkWidget *combobox;
38.232 +
38.233 + GtkWidget *hbox = add_line (vbox, "Channel: ");
38.234 +
38.235 + combobox = gtk_combo_box_new_text ();
38.236 +
38.237 + scheduler_ui->channel_combobox = combobox;
38.238 + gtk_box_pack_start (GTK_BOX (hbox), combobox, FALSE, FALSE, 0);
38.239 +
38.240 + GMythEPG *mmyth_epg = gmyth_epg_new ();
38.241 + if (!gmyth_epg_connect (mmyth_epg)) {
38.242 + // FIXME: Without this list the scheduler UI should not be shown!
38.243 + g_warning ("[%s] Error when getting list of channels", __FUNCTION__);
38.244 + }
38.245 +
38.246 + if (gmyth_epg_get_channel_list (mmyth_epg, &(scheduler_ui->channel_list)) < 0) {
38.247 + g_debug ("[%s] Error while trying to retrieve channel list", __FUNCTION__);
38.248 + } else {
38.249 + GList *clist = scheduler_ui->channel_list;
38.250 + GMythChannelInfo *channel_info;
38.251 +
38.252 + while (clist != NULL) {
38.253 + channel_info = clist->data;
38.254 + clist = clist->next;
38.255 + gtk_combo_box_append_text (GTK_COMBO_BOX (scheduler_ui->channel_combobox),
38.256 + (channel_info->channel_name->str));
38.257 + }
38.258 +
38.259 + gtk_combo_box_set_active(GTK_COMBO_BOX (scheduler_ui->channel_combobox), 0);
38.260 + }
38.261 +}
38.262 +
38.263 +static void
38.264 +add_time_field (MMythSchedulerUI *scheduler_ui, GtkWidget *vbox)
38.265 +{
38.266 + GtkWidget *label;
38.267 + GtkObject *spinbutton_adj;
38.268 + GtkWidget *hbox = add_line (vbox, "Time: ");
38.269 +
38.270 + time_t real_time;
38.271 + struct tm sched_time;
38.272 +
38.273 + time(&real_time);
38.274 +
38.275 + if (localtime_r((time_t *)&real_time, &sched_time) == NULL) {
38.276 + g_warning ("localtime_r error in mmyth_epg_grid_view!\n");
38.277 + return NULL;
38.278 + }
38.279 +
38.280 + if (sched_time.tm_min>30){
38.281 + sched_time.tm_hour = sched_time.tm_hour+1;
38.282 + sched_time.tm_min = 0;
38.283 + } else if (sched_time.tm_min>0) {
38.284 + sched_time.tm_min = 30;
38.285 + }
38.286 +
38.287 + scheduler_ui->year_temp = (guint)sched_time.tm_year + 1900;
38.288 + scheduler_ui->month_temp = (guint)sched_time.tm_mon;
38.289 + scheduler_ui->day_temp = (guint)sched_time.tm_mday;
38.290 +
38.291 + //hour entry
38.292 + spinbutton_adj = gtk_adjustment_new (sched_time.tm_hour, 00, 23, 1, 10, 10);
38.293 + scheduler_ui->hour_spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton_adj), 1, 0);
38.294 + gtk_box_pack_start (GTK_BOX (hbox), scheduler_ui->hour_spinbutton, FALSE, FALSE, 0);
38.295 +
38.296 + label = gtk_label_new ((" : "));
38.297 + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
38.298 + gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_RIGHT);
38.299 + gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
38.300 +
38.301 + //minute entry
38.302 + spinbutton_adj = gtk_adjustment_new (sched_time.tm_min, 0, 59, 1, 10, 10);
38.303 + scheduler_ui->min_spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton_adj), 1, 0);
38.304 + gtk_box_pack_start (GTK_BOX (hbox), scheduler_ui->min_spinbutton, FALSE, FALSE, 0);
38.305 +
38.306 + label = gtk_label_new ((" (hh:mm)"));
38.307 +
38.308 + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
38.309 +
38.310 +}
38.311 +
38.312 +static void
38.313 +add_date_field (MMythSchedulerUI *scheduler_ui, GtkWidget *vbox)
38.314 +{
38.315 + char sched_date[24];
38.316 + GtkWidget *hbox = add_line (vbox, "Date: ");
38.317 +
38.318 + //sched_date = ctime(&real_time);
38.319 + g_sprintf (sched_date, "%04d %02d %02d (yyyy mm dd)", scheduler_ui->year_temp, scheduler_ui->month_temp+1, scheduler_ui->day_temp);
38.320 + sched_date[23]='\0';
38.321 +
38.322 + scheduler_ui->date_button = gtk_button_new_with_label (sched_date);
38.323 + gtk_box_pack_start (GTK_BOX (hbox), scheduler_ui->date_button, FALSE, FALSE, 0);
38.324 + gtk_button_set_relief (GTK_BUTTON (scheduler_ui->date_button), GTK_RELIEF_NONE);
38.325 +
38.326 + g_signal_connect (G_OBJECT (scheduler_ui->date_button), "clicked",
38.327 + G_CALLBACK (run_calendar_dialog), scheduler_ui);
38.328 +
38.329 +}
38.330 +
38.331 +static void
38.332 +add_duration_field (MMythSchedulerUI *scheduler_ui, GtkWidget *vbox)
38.333 +{
38.334 + GtkWidget *hbox = add_line (vbox, "Duration: ");
38.335 + GtkWidget *label;
38.336 + GtkObject *spinbutton_adj;
38.337 +
38.338 + spinbutton_adj = gtk_adjustment_new (60, 5, 360, 5, 60, 60);
38.339 + scheduler_ui->duration_spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton_adj), 1, 0);
38.340 + gtk_box_pack_start (GTK_BOX (hbox), scheduler_ui->duration_spinbutton, FALSE, TRUE, 0);
38.341 + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (scheduler_ui->duration_spinbutton), TRUE);
38.342 +
38.343 + label = gtk_label_new ((" (minutes) "));
38.344 + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
38.345 +}
38.346 +
38.347 +static void
38.348 +add_frequency_field (MMythSchedulerUI *scheduler_ui, GtkWidget *vbox)
38.349 +{
38.350 +
38.351 + GtkWidget *hbox = add_line (vbox, "Frequency: ");
38.352 +
38.353 + scheduler_ui->freq_combobox = gtk_combo_box_new_text ();
38.354 + gtk_box_pack_start (GTK_BOX (hbox), scheduler_ui->freq_combobox, FALSE, FALSE, 0);
38.355 + gtk_combo_box_append_text (GTK_COMBO_BOX (scheduler_ui->freq_combobox), ("Only this day "));
38.356 + gtk_combo_box_append_text (GTK_COMBO_BOX (scheduler_ui->freq_combobox), ("Daily "));
38.357 + gtk_combo_box_append_text (GTK_COMBO_BOX (scheduler_ui->freq_combobox), ("Weekly "));
38.358 + gtk_combo_box_set_active(GTK_COMBO_BOX (scheduler_ui->freq_combobox), 0);
38.359 +
38.360 +}
38.361 +
38.362 +static void
38.363 +add_title_field (MMythSchedulerUI *scheduler_ui, GtkWidget *vbox)
38.364 +{
38.365 + GtkWidget *hbox = add_line (vbox, "Title: ");
38.366 +
38.367 + scheduler_ui->title_entry = gtk_entry_new ();
38.368 + gtk_box_pack_start (GTK_BOX (hbox), scheduler_ui->title_entry, FALSE, FALSE, 0);
38.369 + gtk_entry_set_text (GTK_ENTRY (scheduler_ui->title_entry), "(Optional)");
38.370 +
38.371 +}
39.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
39.2 +++ b/gmyth/src/gui/mmyth_schedulerui.h Wed Sep 20 23:45:35 2006 +0100
39.3 @@ -0,0 +1,45 @@
39.4 +#ifndef MMYTH_SCHEDULERECORDING_H_
39.5 +#define MMYTH_SCHEDULERECORDING_H_
39.6 +
39.7 +#include <glib.h>
39.8 +
39.9 +typedef struct _MMythSchedulerUI {
39.10 +
39.11 + GList *channel_list;
39.12 +
39.13 + GtkWidget *main_widget;
39.14 +
39.15 + GtkWidget *channel_combobox;
39.16 + GtkWidget *freq_combobox;
39.17 + GtkWidget *hour_spinbutton;
39.18 + GtkWidget *min_spinbutton;
39.19 + GtkWidget *duration_spinbutton;
39.20 + GtkWidget *title_entry;
39.21 + GtkWidget *date_button;
39.22 +
39.23 + GtkWidget *calendar_dialog;
39.24 + GtkWidget *calendar;
39.25 +
39.26 + guint year_temp, month_temp, day_temp;
39.27 +} MMythSchedulerUI;
39.28 +
39.29 +typedef struct {
39.30 + long int channel_id;
39.31 +
39.32 + struct tm start_tm;
39.33 +
39.34 + int duration;
39.35 + int frequency;
39.36 +
39.37 + GString *title;
39.38 +
39.39 +} ScheduleEntry;
39.40 +
39.41 +MMythSchedulerUI* mmyth_schedulerui_new (void);
39.42 +
39.43 +gboolean mmyth_schedulerui_save (MMythSchedulerUI *scheduler_ui);
39.44 +
39.45 +void mmyth_schedulerui_cb_schedule_button (GtkButton * button, gpointer user_data);
39.46 +
39.47 +
39.48 +#endif /*MMYTH_SCHEDULERECORDING_H_*/
40.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
40.2 +++ b/gmyth/src/gui/mmyth_ui.c Wed Sep 20 23:45:35 2006 +0100
40.3 @@ -0,0 +1,814 @@
40.4 +
40.5 +#include <glib-object.h>
40.6 +#include <sys/types.h>
40.7 +#include <sys/stat.h>
40.8 +#include <unistd.h>
40.9 +#include <string.h>
40.10 +#include <stdio.h>
40.11 +#include <gtk/gtk.h>
40.12 +#include <gdk/gdkx.h>
40.13 +#include <gst/interfaces/xoverlay.h>
40.14 +#include <assert.h>
40.15 +
40.16 +#include "mmyth_ui.h"
40.17 +#include "mmyth_uicommon.h"
40.18 +#include "mmyth_schedulerui.h"
40.19 +#include "mmyth_recordui.h"
40.20 +#include "mmyth_uisettings.h"
40.21 +#include "mmyth_epg_grid_view.h"
40.22 +
40.23 +/* GMyth library includes */
40.24 +#include "gmyth_context.h"
40.25 +#include "gmyth_tvplayer.h"
40.26 +
40.27 +#ifndef MAEMO_PLATFORM
40.28 +static gint button_press_handler (GtkWidget *widget, GdkEvent *event);
40.29 +#endif
40.30 +
40.31 +static MMythUiCommon *create_main_view (MMythUi * mmyth_ui);
40.32 +static MMythUiCommon *create_video_view (MMythUi * mmyth_ui);
40.33 +static MMythUiCommon *create_epg_grid_view (MMythUi * mmyth_ui);
40.34 +static MMythUiCommon *create_record_view (MMythUi * mmyth_ui);
40.35 +static MMythUiCommon *create_schedule_view (MMythUi * mmyth_ui);
40.36 +
40.37 +static void cb_video_close_button (GtkButton * button, gpointer user_data);
40.38 +static void cb_record_button (GtkButton * button, gpointer user_data);
40.39 +static void cb_menu_item_settings (GtkMenuItem *menuitem, gpointer user_data);
40.40 +
40.41 +/* main box from button box separator*/
40.42 +static GtkWidget *main_vseparator = NULL;
40.43 +
40.44 +GdkPixbuf *icon_sports, *icon_news,
40.45 + *icon_movies, *icon_shows, *icon_default;
40.46 +
40.47 +#ifndef MAEMO_PLATFORM
40.48 +/* FIXME: */
40.49 +static MMythUi *popup_mmyth_ui;
40.50 +#endif
40.51 +
40.52 +MMythUi *
40.53 +mmyth_ui_initialize (
40.54 +#ifdef MAEMO_PLATFORM
40.55 + HildonProgram *program,
40.56 +#endif
40.57 + GtkWidget * main_window)
40.58 +{
40.59 + MMythUi *mmyth_ui;
40.60 +
40.61 + mmyth_ui = g_new0 (MMythUi, 1);
40.62 +
40.63 + mmyth_ui->main_window = main_window;
40.64 + mmyth_ui->videow = NULL;
40.65 + mmyth_ui->mmyth_recordui = NULL;
40.66 + mmyth_ui->mmyth_schedulerui = NULL;
40.67 +
40.68 + /* Horizontal box that divides the view into control and video area */
40.69 + mmyth_ui->main_hbox = gtk_hbox_new (FALSE, 0);
40.70 + gtk_widget_show (mmyth_ui->main_hbox);
40.71 + g_object_ref (mmyth_ui->main_hbox);
40.72 +
40.73 + main_bg_color.red = 65000;
40.74 + main_bg_color.green = 65000;
40.75 + main_bg_color.blue = 65000;
40.76 +
40.77 +
40.78 +#ifndef MAEMO_PLATFORM
40.79 + /* Popup menu */
40.80 + popup_mmyth_ui = mmyth_ui;
40.81 + g_signal_connect (G_OBJECT (mmyth_ui->main_hbox), "event",
40.82 + G_CALLBACK (button_press_handler),
40.83 + G_OBJECT (mmyth_ui->main_hbox));
40.84 +
40.85 +#else // #ifdef MAEMO
40.86 +
40.87 + mmyth_ui->main_menu = GTK_MENU(gtk_menu_new());
40.88 + hildon_program_set_common_menu(program, mmyth_ui->main_menu);
40.89 +
40.90 + mmyth_ui->menu_setup = gtk_menu_item_new_with_label("Setup");
40.91 + gtk_widget_set_size_request (GTK_WIDGET (mmyth_ui->menu_setup), 150, 40);
40.92 + gtk_menu_append(mmyth_ui->main_menu, mmyth_ui->menu_setup);
40.93 +
40.94 + g_signal_connect(G_OBJECT(mmyth_ui->menu_setup), "activate", G_CALLBACK(cb_menu_item_settings), mmyth_ui);
40.95 +
40.96 + gtk_widget_show_all (GTK_WIDGET (mmyth_ui->main_menu));
40.97 +#endif
40.98 +
40.99 + // Main widget is mmyth_ui->main_hbox
40.100 + mmyth_ui->main_uicommon = create_main_view (mmyth_ui);
40.101 +
40.102 + gtk_container_add (GTK_CONTAINER (mmyth_ui->main_window),
40.103 + mmyth_ui->main_hbox);
40.104 +
40.105 + mmyth_ui_set_widget (mmyth_ui, mmyth_ui->main_uicommon);
40.106 +
40.107 + return mmyth_ui;
40.108 +}
40.109 +
40.110 +void
40.111 +mmyth_ui_finalize (MMythUi * mmyth_ui)
40.112 +{
40.113 + if (mmyth_ui != NULL) {
40.114 + if (mmyth_ui->main_uicommon)
40.115 + mmyth_uicommon_free (mmyth_ui->main_uicommon);
40.116 + if (mmyth_ui->video_uicommon)
40.117 + mmyth_uicommon_free (mmyth_ui->video_uicommon);
40.118 + if (mmyth_ui->epg_grid_uicommon)
40.119 + mmyth_uicommon_free (mmyth_ui->epg_grid_uicommon);
40.120 + if (mmyth_ui->record_uicommon)
40.121 + mmyth_uicommon_free (mmyth_ui->record_uicommon);
40.122 + if (mmyth_ui->schedule_uicommon)
40.123 + mmyth_uicommon_free (mmyth_ui->schedule_uicommon);
40.124 +
40.125 + g_free (mmyth_ui);
40.126 + }
40.127 +}
40.128 +
40.129 +void
40.130 +mmyth_ui_set_widget (MMythUi * mmyth_ui, MMythUiCommon * new_uicommon)
40.131 +{
40.132 + if (new_uicommon == NULL) {
40.133 + g_warning ("MMythUI setting a NULL UI_Common as current display\n");
40.134 + return;
40.135 + }
40.136 +
40.137 + if (mmyth_ui->current_uicommon) {
40.138 + if (mmyth_ui->current_uicommon == mmyth_ui->video_uicommon) {
40.139 + gtk_widget_hide (mmyth_ui->current_uicommon->main_widget);
40.140 + gtk_widget_hide (mmyth_ui->videow);
40.141 + }
40.142 + else {
40.143 + gtk_container_remove (GTK_CONTAINER (mmyth_ui->main_hbox),
40.144 + mmyth_ui->current_uicommon->main_widget);
40.145 + }
40.146 +
40.147 + gtk_container_remove (GTK_CONTAINER (mmyth_ui->main_hbox),
40.148 + mmyth_ui->current_uicommon->event_box);
40.149 + gtk_container_remove (GTK_CONTAINER (mmyth_ui->main_hbox),
40.150 + main_vseparator);
40.151 +
40.152 + }
40.153 +
40.154 + if (new_uicommon->main_widget == mmyth_ui->video_alignment) {
40.155 + //gst_player_video_show (GST_PLAYER_VIDEO(mmyth_ui->videow));
40.156 + gtk_widget_show (mmyth_ui->video_alignment);
40.157 + gtk_widget_show (mmyth_ui->videow);
40.158 + }
40.159 + else {
40.160 + /* FIXME: Fst call is NULL when mmyth_player_init fails */
40.161 + if(mmyth_ui->video_alignment != NULL)
40.162 + gtk_widget_hide (mmyth_ui->video_alignment);
40.163 + /* FIXME: Fst call is NULL when mmyth_player_init fails */
40.164 + if(mmyth_ui->videow != NULL)
40.165 + gtk_widget_hide (mmyth_ui->videow);
40.166 +
40.167 + gtk_box_pack_start (GTK_BOX (mmyth_ui->main_hbox),
40.168 + new_uicommon->main_widget, TRUE, TRUE, 0);
40.169 + }
40.170 +
40.171 + if(main_vseparator == NULL) {
40.172 + /* FIXME: should free this variable*/
40.173 + main_vseparator = gtk_vseparator_new();
40.174 + g_object_ref (main_vseparator);
40.175 + }
40.176 + gtk_box_pack_start (GTK_BOX (mmyth_ui->main_hbox),
40.177 + main_vseparator, FALSE, FALSE, 0);
40.178 + gtk_widget_show (main_vseparator);
40.179 +
40.180 + gtk_box_pack_end (GTK_BOX (mmyth_ui->main_hbox), new_uicommon->event_box, FALSE,
40.181 + FALSE, 0);
40.182 +
40.183 + mmyth_ui->current_uicommon = new_uicommon;
40.184 +
40.185 +}
40.186 +
40.187 +/* The close callback is the same for all windows*/
40.188 +static void
40.189 +cb_not_impl_button (GtkButton * button, gpointer user_data)
40.190 +{
40.191 + MMythUi *mmyth_ui = (MMythUi *) user_data;
40.192 +
40.193 + GtkWidget *msg_dialog = gtk_message_dialog_new (
40.194 + GTK_WINDOW(mmyth_ui->main_window),
40.195 + GTK_DIALOG_MODAL |
40.196 + GTK_DIALOG_DESTROY_WITH_PARENT,
40.197 + GTK_MESSAGE_INFO,
40.198 + GTK_BUTTONS_OK,
40.199 + "Feature not implemented");
40.200 + gtk_widget_set_size_request (msg_dialog, 350, 120);
40.201 +
40.202 + gtk_dialog_run (GTK_DIALOG (msg_dialog));
40.203 +
40.204 + gtk_widget_destroy(GTK_WIDGET(msg_dialog));
40.205 +}
40.206 +
40.207 +/******************************************************************************
40.208 + * POPUP MENU WIDGET METHODS *
40.209 + *****************************************************************************/
40.210 +
40.211 +static void
40.212 +cb_menu_item_settings (GtkMenuItem *menuitem,
40.213 + gpointer user_data)
40.214 +{
40.215 +
40.216 + MMythUi *mmyth_ui = (MMythUi*) user_data;
40.217 +
40.218 + if (mmyth_uisettings_run (GTK_WINDOW (mmyth_ui->main_window))) {
40.219 + // If user changes the settings, we restart the context
40.220 + g_debug ("[%s] Restarting mmyth_context to new settings", __FUNCTION__);
40.221 + gmyth_context_initialize();
40.222 + }
40.223 +}
40.224 +
40.225 +#ifndef MAEMO_PLATFORM
40.226 +
40.227 +static void
40.228 +detacher (GtkWidget *attach_widget,GtkMenu *menu)
40.229 +{
40.230 +
40.231 +}
40.232 +
40.233 +static void
40.234 +do_popup_menu (GtkWidget *my_widget, GdkEventButton *event)
40.235 +{
40.236 + GtkWidget *popup;
40.237 +
40.238 + int button, event_time;
40.239 +
40.240 + GtkWidget *item_general;
40.241 + GtkWidget *image;
40.242 +
40.243 + popup = gtk_menu_new ();
40.244 +
40.245 + item_general = gtk_image_menu_item_new_with_mnemonic ("Setup");
40.246 + gtk_widget_show (item_general);
40.247 + gtk_container_add (GTK_CONTAINER (popup), item_general);
40.248 +
40.249 + image = gtk_image_new_from_stock ("gtk-edit", GTK_ICON_SIZE_MENU);
40.250 + gtk_widget_show (image);
40.251 + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item_general), image);
40.252 +
40.253 + g_signal_connect (G_OBJECT(item_general), "activate", G_CALLBACK (cb_menu_item_settings), popup_mmyth_ui);
40.254 +
40.255 + if (event) {
40.256 + button = event->button;
40.257 + event_time = event->time;
40.258 + } else {
40.259 + button = 0;
40.260 + event_time = gtk_get_current_event_time ();
40.261 + }
40.262 +
40.263 + gtk_menu_attach_to_widget (GTK_MENU (popup), my_widget, detacher);
40.264 + gtk_menu_popup (GTK_MENU (popup), NULL, NULL, NULL, NULL,
40.265 + button, event_time);
40.266 + gtk_widget_show_all(popup);
40.267 +}
40.268 +
40.269 +/* Respond to a button-press by posting a menu passed in as widget.
40.270 + *
40.271 + * Note that the "widget" argument is the menu being posted, NOT
40.272 + * the button that was pressed.
40.273 + */
40.274 +static gint
40.275 +button_press_handler (GtkWidget *widget, GdkEvent *event)
40.276 +{
40.277 +
40.278 + if (event->type == GDK_BUTTON_PRESS) {
40.279 + GdkEventButton *bevent = (GdkEventButton *) event;
40.280 + /* Ignore double-clicks and triple-clicks */
40.281 + if (bevent->button == 3)
40.282 + {
40.283 + do_popup_menu (widget, bevent);
40.284 + return TRUE;
40.285 + }
40.286 + }
40.287 +
40.288 + /* Tell calling code that we have not handled this event; pass it on. */
40.289 + return FALSE;
40.290 +}
40.291 +#endif
40.292 +
40.293 +/******************************************************************************
40.294 + * MAIN APP VIEW METHODS *
40.295 + *****************************************************************************/
40.296 +
40.297 +static void
40.298 +cb_close_button (GtkButton * button, gpointer user_data)
40.299 +{
40.300 + MMythUi *mmyth_ui = (MMythUi *) user_data;
40.301 +
40.302 + mmyth_ui_set_widget (mmyth_ui, mmyth_ui->main_uicommon);
40.303 +}
40.304 +
40.305 +static void
40.306 +cb_watch_tv_button (GtkButton * button, gpointer user_data)
40.307 +{
40.308 + MMythUi *mmyth_ui = (MMythUi *) user_data;
40.309 + gboolean res = FALSE;
40.310 +
40.311 + if (!(mmyth_ui->video_uicommon))
40.312 + mmyth_ui->video_uicommon = create_video_view (mmyth_ui);
40.313 +
40.314 + // Creates the tv player that will retrieve the mythtv content, decode and show it
40.315 + mmyth_ui->tvplayer = gmyth_tvplayer_new ();
40.316 + /* choose here if this is a LiveTV session */
40.317 + mmyth_ui->tvplayer->is_livetv = TRUE;
40.318 +
40.319 + res = gmyth_tvplayer_initialize (mmyth_ui->tvplayer);
40.320 +
40.321 + if (!res) {
40.322 + g_warning ("[%s] Could not initialize tvplayer", __FUNCTION__);
40.323 +
40.324 + g_object_unref (mmyth_ui->tvplayer);
40.325 + mmyth_ui->tvplayer = NULL;
40.326 +
40.327 + GtkWidget *dialog = gtk_message_dialog_new (
40.328 + GTK_WINDOW(mmyth_ui->main_window),
40.329 + GTK_DIALOG_DESTROY_WITH_PARENT,
40.330 + GTK_MESSAGE_ERROR,
40.331 + GTK_BUTTONS_CLOSE,
40.332 + "MMyth found errors while starting TV Player, please check "
40.333 + "the GStreamer installation");
40.334 +
40.335 + gtk_dialog_run (GTK_DIALOG (dialog));
40.336 + gtk_widget_destroy (dialog);
40.337 +
40.338 + return;
40.339 + }
40.340 + //res = mmyth_tvplayer_livetv_setup (mmyth_ui->tvplayer);
40.341 + //
40.342 + if (mmyth_ui && mmyth_ui->tvplayer && res) {
40.343 + gmyth_tvplayer_set_widget (mmyth_ui->tvplayer, mmyth_ui->videow);
40.344 + gmyth_tvplayer_start_playing (mmyth_ui->tvplayer);
40.345 + } else {
40.346 + // TODO: Show Alert with error description!
40.347 + g_warning ("[%s] MMythUI can't initialize tv_player", __FUNCTION__);
40.348 + g_object_unref (mmyth_ui->tvplayer);
40.349 + mmyth_ui->tvplayer = NULL;
40.350 + // FIXME: Show the exact error that happened
40.351 + GtkWidget *dialog = gtk_message_dialog_new (
40.352 + GTK_WINDOW(mmyth_ui->main_window),
40.353 + GTK_DIALOG_DESTROY_WITH_PARENT,
40.354 + GTK_MESSAGE_ERROR,
40.355 + GTK_BUTTONS_CLOSE,
40.356 + "Error while starting TV Player, please check if the backend"
40.357 + " is running properly and a tv card is available!");
40.358 + gtk_dialog_run (GTK_DIALOG (dialog));
40.359 + gtk_widget_destroy (dialog);
40.360 + return;
40.361 + }
40.362 + mmyth_ui_set_widget (mmyth_ui, mmyth_ui->video_uicommon);
40.363 +
40.364 +}
40.365 +
40.366 +static void
40.367 +cb_epg_button (GtkButton * button, gpointer user_data)
40.368 +{
40.369 + MMythUi *mmyth_ui = (MMythUi *) user_data;
40.370 +
40.371 + if (!(mmyth_ui->epg_grid_uicommon))
40.372 + mmyth_ui->epg_grid_uicommon = create_epg_grid_view(mmyth_ui);
40.373 +
40.374 + mmyth_ui_set_widget (mmyth_ui, mmyth_ui->epg_grid_uicommon);
40.375 +}
40.376 +
40.377 +static MMythUiCommon *
40.378 +create_main_view (MMythUi * mmyth_ui)
40.379 +{
40.380 + MMythUiCommon *ui_common;
40.381 + GtkWidget *main_widget;
40.382 + GtkWidget *image;
40.383 +
40.384 + g_debug ("Creating Main UI Common");
40.385 +
40.386 + // FIXME: file path
40.387 +#ifdef MMYTH_DEV
40.388 + image = gtk_image_new_from_file ("../pixmaps/mmyth_logo.png");
40.389 +#else
40.390 + image = gtk_image_new_from_file ( PIX_DIR "mmyth_logo.png");
40.391 +#endif
40.392 +
40.393 + main_widget = gtk_event_box_new();
40.394 +
40.395 + gtk_container_add (GTK_CONTAINER (main_widget),
40.396 + image);
40.397 +
40.398 +
40.399 + gtk_widget_show_all (main_widget);
40.400 + g_object_ref (main_widget);
40.401 +
40.402 + ui_common = mmyth_uicommon_new (main_widget,
40.403 + "Watch TV", "EPG", "Recording");
40.404 +
40.405 + /* Button signals */
40.406 + // FIXME
40.407 + g_signal_connect (G_OBJECT (ui_common->button1), "clicked",
40.408 + G_CALLBACK (cb_watch_tv_button), mmyth_ui);
40.409 + g_signal_connect (G_OBJECT (ui_common->button2), "clicked",
40.410 + G_CALLBACK (cb_epg_button), mmyth_ui);
40.411 + g_signal_connect (G_OBJECT (ui_common->button3), "clicked",
40.412 + G_CALLBACK (cb_record_button), mmyth_ui);
40.413 +
40.414 + return ui_common;
40.415 +
40.416 +}
40.417 +
40.418 +/******************************************************************************
40.419 + * epg GRID VIEW METHODS *
40.420 + *****************************************************************************/
40.421 +
40.422 +static MMythUiCommon *
40.423 +create_epg_grid_view (MMythUi * mmyth_ui)
40.424 +{
40.425 + MMythUiCommon *ui_common;
40.426 +
40.427 + g_debug ("Creating EPG Grid UI Common");
40.428 +
40.429 + GtkWidget *epg_grid_view = GTK_WIDGET (epg_grid_view_new (mmyth_ui));
40.430 +
40.431 + ui_common = mmyth_uicommon_new (epg_grid_view,
40.432 + "Play", "Record",
40.433 + "Close");
40.434 +
40.435 + /* Button signals */
40.436 + g_signal_connect (G_OBJECT (ui_common->button1), "clicked",
40.437 + G_CALLBACK (cb_not_impl_button), mmyth_ui);
40.438 + g_signal_connect (G_OBJECT (ui_common->button2), "clicked",
40.439 + G_CALLBACK (cb_record_button), mmyth_ui);
40.440 + g_signal_connect (G_OBJECT (ui_common->button3), "clicked",
40.441 + G_CALLBACK (cb_close_button), mmyth_ui);
40.442 +
40.443 + return ui_common;
40.444 +}
40.445 +/******************************************************************************
40.446 + * SCHEDULE VIEW METHODS *
40.447 + ******************************************************************************/
40.448 +
40.449 +static void
40.450 +cb_save_new_schedule (GtkButton *button, gpointer user_data)
40.451 +{
40.452 + MMythUi *mmyth_ui = (MMythUi *) user_data;
40.453 +
40.454 + if (!(mmyth_ui->schedule_uicommon))
40.455 + mmyth_ui->schedule_uicommon = create_schedule_view(mmyth_ui);
40.456 +
40.457 + mmyth_schedulerui_save (mmyth_ui->mmyth_schedulerui);
40.458 +
40.459 + mmyth_recordui_reload_schedule (mmyth_ui->mmyth_recordui);
40.460 +
40.461 + mmyth_ui_set_widget (mmyth_ui, mmyth_ui->record_uicommon);
40.462 +
40.463 +}
40.464 +
40.465 +static void
40.466 +cb_edit_scheduled (GtkTreeView * tree_view, GtkTreePath *path,
40.467 + GtkTreeViewColumn *column, gpointer user_data)
40.468 +{
40.469 + MMythUi *mmyth_ui = (MMythUi *) user_data;
40.470 + GtkTreeSelection *selection;
40.471 + GtkTreeModel *list_store;
40.472 + GtkTreeIter iter;
40.473 + int index;
40.474 + //gint new_row = 0, record_id = 0;
40.475 + ScheduleInfo *schedule_info;
40.476 + GList *schedule_list;
40.477 + //GtkTreeIter iter;
40.478 + gint res;
40.479 +
40.480 + //gtk_tree_store_clear(recordui->sch_tree_store);
40.481 +
40.482 + res = gmyth_scheduler_get_schedule_list(mmyth_ui->mmyth_recordui->scheduler, &(schedule_list));
40.483 + if (res < 0) {
40.484 + g_warning ("[%s] Retrieved NULL list of scheduled data from database", __FUNCTION__);
40.485 + //return FALSE;
40.486 + }
40.487 + printf("\nX %d", res); fflush(stdout);
40.488 +
40.489 + selection =
40.490 + gtk_tree_view_get_selection(GTK_TREE_VIEW(mmyth_ui->mmyth_recordui->sch_treeview));
40.491 +
40.492 + gtk_tree_selection_get_selected(selection, &list_store, &iter);
40.493 + gtk_tree_model_get(list_store, &iter, 4, &index, -1);
40.494 +
40.495 + mmyth_ui_set_widget (mmyth_ui, mmyth_ui->schedule_uicommon);
40.496 +
40.497 + if (!(mmyth_ui->schedule_uicommon))
40.498 + mmyth_ui->schedule_uicommon = create_schedule_view(mmyth_ui);
40.499 +
40.500 + schedule_list = g_list_nth(schedule_list, atoi(gtk_tree_path_to_string(path)));
40.501 + schedule_info = (ScheduleInfo*) schedule_list->data;
40.502 +
40.503 + printf("\nstarttime: %ld", schedule_info->start_time); fflush(stdout);
40.504 +}
40.505 +
40.506 +static MMythUiCommon *
40.507 +create_schedule_view (MMythUi * mmyth_ui)
40.508 +{
40.509 + MMythUiCommon *ui_common;
40.510 + GtkWidget *schedule_widget;
40.511 +
40.512 + g_debug ("Creating Schedule UI Common");
40.513 +
40.514 + mmyth_ui->mmyth_schedulerui = mmyth_schedulerui_new ();
40.515 + if (mmyth_ui->mmyth_schedulerui == NULL) {
40.516 + g_warning ("[%s] Error while creating scheduler ui", __FUNCTION__);
40.517 + return NULL;
40.518 + }
40.519 +
40.520 + schedule_widget = mmyth_ui->mmyth_schedulerui->main_widget;
40.521 +
40.522 + gtk_widget_show_all (schedule_widget);
40.523 + g_object_ref (schedule_widget);
40.524 +
40.525 + ui_common = mmyth_uicommon_new (schedule_widget,
40.526 + "Save", "Clear",
40.527 + "Cancel");
40.528 +
40.529 + /* Button signals */
40.530 + g_signal_connect (G_OBJECT (ui_common->button1), "clicked",
40.531 + G_CALLBACK (cb_save_new_schedule), mmyth_ui);
40.532 + g_signal_connect (G_OBJECT (ui_common->button2), "clicked",
40.533 + G_CALLBACK (cb_not_impl_button), mmyth_ui);
40.534 + g_signal_connect (G_OBJECT (ui_common->button3), "clicked",
40.535 + G_CALLBACK (cb_record_button), mmyth_ui);
40.536 +
40.537 + return ui_common;
40.538 +}
40.539 +/******************************************************************************
40.540 + * RECORD VIEW METHODS *
40.541 + ******************************************************************************/
40.542 +static void
40.543 +cb_record_button (GtkButton * button, gpointer user_data)
40.544 +{
40.545 + MMythUi *mmyth_ui = (MMythUi *) user_data;
40.546 +
40.547 + if (!(mmyth_ui->record_uicommon)) {
40.548 + mmyth_ui->record_uicommon = create_record_view (mmyth_ui);
40.549 + mmyth_ui->schedule_uicommon = create_schedule_view (mmyth_ui);
40.550 + }
40.551 +
40.552 + mmyth_recordui_reload_all (mmyth_ui->mmyth_recordui);
40.553 +
40.554 + mmyth_ui_set_widget (mmyth_ui, mmyth_ui->record_uicommon);
40.555 +
40.556 +}
40.557 +
40.558 +static void
40.559 +cb_record_close_button (GtkButton * button, gpointer user_data)
40.560 +{
40.561 + MMythUi *mmyth_ui = (MMythUi *) user_data;
40.562 +
40.563 + mmyth_ui_set_widget(mmyth_ui, mmyth_ui->main_uicommon);
40.564 +
40.565 + mmyth_recordui_free(mmyth_ui->mmyth_recordui);
40.566 +
40.567 + if (mmyth_ui->record_uicommon) {
40.568 + gtk_widget_destroy (mmyth_ui->record_uicommon->main_widget);
40.569 + mmyth_uicommon_free(mmyth_ui->record_uicommon);
40.570 + mmyth_ui->record_uicommon = NULL;
40.571 + }
40.572 +
40.573 + if (mmyth_ui->schedule_uicommon) {
40.574 + // mmyth_uicommon_free(mmyth_ui->schedule_uicommon);
40.575 + }
40.576 +}
40.577 +
40.578 +
40.579 +
40.580 +
40.581 +static void
40.582 +play_selected_recorded (gpointer user_data)
40.583 +{
40.584 + MMythUi *mmyth_ui = (MMythUi *) user_data;
40.585 + gboolean res = FALSE;
40.586 +
40.587 + gchar *path = mmyth_recordui_get_selected_recorded (mmyth_ui->mmyth_recordui);
40.588 +
40.589 + if (path == NULL) {
40.590 + // This should never happens. Play button is just activated when
40.591 + // a recording is selected.
40.592 + g_warning ("[%s] Play button pressed while none recorded is selected", __FUNCTION__);
40.593 + return;
40.594 + }
40.595 +
40.596 + if (!(mmyth_ui->video_uicommon))
40.597 + mmyth_ui->video_uicommon = create_video_view (mmyth_ui);
40.598 +
40.599 + // Creates the tv player that will retrieve the mythtv content, decode and show it
40.600 + mmyth_ui->tvplayer = gmyth_tvplayer_new ();
40.601 + g_debug ("[%s] New TV Player created: %d\n", __FUNCTION__, (int) (mmyth_ui->tvplayer));
40.602 + res = gmyth_tvplayer_initialize (mmyth_ui->tvplayer);
40.603 + if (!res) {
40.604 + g_warning ("[%s] Could not initialize tvplayer", __FUNCTION__);
40.605 +
40.606 + g_object_unref (mmyth_ui->tvplayer);
40.607 + mmyth_ui->tvplayer = NULL;
40.608 +
40.609 + GtkWidget *dialog = gtk_message_dialog_new (
40.610 + GTK_WINDOW(mmyth_ui->main_window),
40.611 + GTK_DIALOG_DESTROY_WITH_PARENT,
40.612 + GTK_MESSAGE_ERROR,
40.613 + GTK_BUTTONS_CLOSE,
40.614 + "MMyth found errors while starting TV Player, please check "
40.615 + "the GStreamer installation");
40.616 +
40.617 + gtk_dialog_run (GTK_DIALOG (dialog));
40.618 + gtk_widget_destroy (dialog);
40.619 +
40.620 + return;
40.621 + }
40.622 +
40.623 + res = gmyth_tvplayer_record_setup (mmyth_ui->tvplayer, path);
40.624 +
40.625 + if (mmyth_ui && mmyth_ui->tvplayer && res) {
40.626 + gmyth_tvplayer_set_widget (mmyth_ui->tvplayer, mmyth_ui->videow);
40.627 + gmyth_tvplayer_start_playing (mmyth_ui->tvplayer);
40.628 + } else {
40.629 + // TODO: Show Alert with error description!
40.630 + g_warning ("[%s] MMythUI can't initialize tv_player", __FUNCTION__);
40.631 + g_object_unref (mmyth_ui->tvplayer);
40.632 + mmyth_ui->tvplayer = NULL;
40.633 + // FIXME: Show the exact error that happened
40.634 + GtkWidget *dialog = gtk_message_dialog_new (
40.635 + GTK_WINDOW(mmyth_ui->main_window),
40.636 + GTK_DIALOG_DESTROY_WITH_PARENT,
40.637 + GTK_MESSAGE_ERROR,
40.638 + GTK_BUTTONS_CLOSE,
40.639 + "Error while starting TV Player, please check if the backend"
40.640 + " is running properly and a tv card is available!");
40.641 + gtk_dialog_run (GTK_DIALOG (dialog));
40.642 + gtk_widget_destroy (dialog);
40.643 + return;
40.644 + }
40.645 +
40.646 + mmyth_ui_set_widget (mmyth_ui, mmyth_ui->video_uicommon);
40.647 +}
40.648 +
40.649 +static void
40.650 +cb_play_clicked_recorded (GtkTreeView * tree_view, GtkTreePath *path,
40.651 + GtkTreeViewColumn *column, gpointer user_data)
40.652 +{
40.653 + play_selected_recorded (user_data);
40.654 +}
40.655 +
40.656 +static void
40.657 +cb_play_selected (GtkButton * button, gpointer user_data)
40.658 +{
40.659 + play_selected_recorded (user_data);
40.660 +}
40.661 +
40.662 +static void
40.663 +cb_schedule_button (GtkButton * button, gpointer user_data)
40.664 +{
40.665 + MMythUi *mmyth_ui = (MMythUi *) user_data;
40.666 +
40.667 + mmyth_ui_set_widget (mmyth_ui, mmyth_ui->schedule_uicommon);
40.668 +}
40.669 +
40.670 +void
40.671 +cb_switch_page (GtkNotebook *notebook, GtkNotebookPage *page,
40.672 + guint page_num, gpointer user_data)
40.673 +{
40.674 + MMythUi *mmyth_ui = (MMythUi *) user_data;
40.675 + MMythUiCommon *ui_common;
40.676 +
40.677 + assert (mmyth_ui);
40.678 + assert (mmyth_ui->record_uicommon);
40.679 +
40.680 + ui_common = mmyth_ui->record_uicommon;
40.681 +
40.682 + if (page_num == 0) { // Switched to Schedule list
40.683 + gtk_button_set_label (GTK_BUTTON (ui_common->button1), "New");
40.684 + g_signal_handlers_disconnect_by_func (
40.685 + G_OBJECT (ui_common->button1), G_CALLBACK (cb_play_selected), mmyth_ui);
40.686 + g_signal_connect (G_OBJECT (ui_common->button1), "clicked",
40.687 + G_CALLBACK (cb_schedule_button), mmyth_ui);
40.688 + } else if (page_num == 1) {
40.689 + gtk_button_set_label (GTK_BUTTON (ui_common->button1), "Play");
40.690 + g_signal_handlers_disconnect_by_func (
40.691 + G_OBJECT (ui_common->button1), G_CALLBACK (cb_schedule_button), mmyth_ui);
40.692 + g_signal_connect (G_OBJECT (ui_common->button1), "clicked",
40.693 + G_CALLBACK (cb_play_selected), mmyth_ui);
40.694 + }
40.695 +}
40.696 +
40.697 +
40.698 +static MMythUiCommon *
40.699 +create_record_view (MMythUi * mmyth_ui)
40.700 +{
40.701 + MMythUiCommon *ui_common;
40.702 +
40.703 + g_debug ("Creating Record UI Common");
40.704 +
40.705 + mmyth_ui->mmyth_recordui = mmyth_recordui_new ();
40.706 +
40.707 + // FIXME: Change MMythRecordUI to a GtkWidget child and avoid this call!
40.708 + gtk_widget_show_all (mmyth_ui->mmyth_recordui->scrolled_window);
40.709 +
40.710 + ui_common = mmyth_uicommon_new (mmyth_ui->mmyth_recordui->scrolled_window, "New", "Delete", "<<Back");
40.711 + g_object_ref (mmyth_ui->mmyth_recordui->scrolled_window);
40.712 +
40.713 + /* Button signals */
40.714 + g_signal_connect (G_OBJECT (ui_common->button1), "clicked",
40.715 + G_CALLBACK (cb_schedule_button), mmyth_ui);
40.716 + g_signal_connect (G_OBJECT (ui_common->button2), "clicked",
40.717 + G_CALLBACK (mmyth_recordui_delete_selected), mmyth_ui->mmyth_recordui);
40.718 + g_signal_connect (G_OBJECT (ui_common->button3), "clicked",
40.719 + G_CALLBACK (cb_record_close_button), mmyth_ui);
40.720 + g_signal_connect (G_OBJECT (mmyth_ui->mmyth_recordui->notebook),
40.721 + "switch-page", G_CALLBACK (cb_switch_page), mmyth_ui);
40.722 + g_signal_connect (G_OBJECT (mmyth_ui->mmyth_recordui->rec_treeview),
40.723 + "row-activated", G_CALLBACK (cb_play_clicked_recorded), mmyth_ui);
40.724 + g_signal_connect (G_OBJECT (mmyth_ui->mmyth_recordui->sch_treeview),
40.725 + "row-activated", G_CALLBACK (cb_edit_scheduled), mmyth_ui);
40.726 + return ui_common;
40.727 +}
40.728 +
40.729 +
40.730 +/******************************************************************************
40.731 + * GST VIDEO WIDGET METHODS *
40.732 + *****************************************************************************/
40.733 +
40.734 +static void
40.735 +cb_video_close_button (GtkButton * button, gpointer user_data)
40.736 +{
40.737 + MMythUi *mmyth_ui = (MMythUi *) user_data;
40.738 +
40.739 + g_debug ("MMythUI video close button pressed");
40.740 +
40.741 + if (mmyth_ui && mmyth_ui->tvplayer) {
40.742 + gmyth_tvplayer_stop_playing (mmyth_ui->tvplayer);
40.743 +
40.744 + g_object_unref (mmyth_ui->tvplayer);
40.745 + mmyth_ui->tvplayer = NULL;
40.746 + } else {
40.747 + g_warning ("cb_video_close_button called with NULL pointer\n");
40.748 + }
40.749 +
40.750 + mmyth_ui_set_widget (mmyth_ui, mmyth_ui->main_uicommon);
40.751 +}
40.752 +
40.753 +
40.754 +static MMythUiCommon *
40.755 +create_video_view (MMythUi * mmyth_ui)
40.756 +{
40.757 +
40.758 + MMythUiCommon *ui_common;
40.759 +
40.760 + g_debug ("Creating Video UI Common");
40.761 +
40.762 + /* Creates widget to be user by MMythTVPlayer to draw the video */
40.763 + mmyth_ui->videow = gtk_drawing_area_new ();
40.764 + // FIXME: Get the widget size from settings
40.765 + gtk_widget_set_size_request (mmyth_ui->videow, 300, 240);
40.766 +
40.767 + //mmiptv_ui->logo = gdk_pixbuf_new_from_file ("logo.png", NULL);
40.768 +
40.769 + // Creates an alignment to place the video widget inside
40.770 + mmyth_ui->video_alignment = gtk_alignment_new (0.5, 0.5, 1, 1);
40.771 + gtk_widget_hide (mmyth_ui->video_alignment);
40.772 +
40.773 + gtk_container_add (GTK_CONTAINER (mmyth_ui->video_alignment),
40.774 + mmyth_ui->videow);
40.775 +
40.776 + /* Add the gst video widget to hbox. It should never be removed. */
40.777 + /* FIXME: mmyth_ui->video_alignment == NULL when mmyth_player_init fails */
40.778 + if((mmyth_ui->main_hbox != NULL) && (mmyth_ui->video_alignment != NULL)) {
40.779 + gtk_box_pack_start (GTK_BOX (mmyth_ui->main_hbox),
40.780 + mmyth_ui->video_alignment, TRUE, TRUE, 0);
40.781 + } else {
40.782 + g_warning ("[%s] Error while adding video_alignment to main widget", __FUNCTION__);
40.783 + }
40.784 +
40.785 + g_object_ref (mmyth_ui->videow);
40.786 + g_object_ref (mmyth_ui->video_alignment);
40.787 +
40.788 + ui_common = mmyth_uicommon_new (mmyth_ui->video_alignment,
40.789 + " Full\nScreen", "Other\nServices",
40.790 + "Close");
40.791 +
40.792 +
40.793 + g_signal_connect (G_OBJECT (ui_common->button1), "clicked",
40.794 + G_CALLBACK (cb_not_impl_button), mmyth_ui);
40.795 + g_signal_connect (G_OBJECT (ui_common->button2), "clicked",
40.796 + G_CALLBACK (cb_not_impl_button), mmyth_ui);
40.797 + g_signal_connect (G_OBJECT (ui_common->button3), "clicked",
40.798 + G_CALLBACK (cb_video_close_button), mmyth_ui);
40.799 +
40.800 + if (ui_common)
40.801 + g_debug ("Video UI_Common sucessfull created");
40.802 +
40.803 + return ui_common;
40.804 +}
40.805 +
40.806 +
40.807 +
40.808 +GtkWidget*
40.809 +mmyth_ui_get_video_widget (MMythUi *mmyth_ui) {
40.810 +
40.811 + if (mmyth_ui && mmyth_ui->videow) {
40.812 +
40.813 + return mmyth_ui->videow;
40.814 + }
40.815 +
40.816 + return NULL;
40.817 +}
41.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
41.2 +++ b/gmyth/src/gui/mmyth_ui.c.mine Wed Sep 20 23:45:35 2006 +0100
41.3 @@ -0,0 +1,451 @@
41.4 +
41.5 +#include <gtk/gtk.h>
41.6 +#include <gdk/gdkx.h>
41.7 +#include <gst/interfaces/xoverlay.h>
41.8 +
41.9 +#include "mmyth_ui.h"
41.10 +#include "mmyth_uicommon.h"
41.11 +/* FIXME
41.12 +#include "mmyth_videoplayer.h"
41.13 +*/
41.14 +#include "mmyth_esg_grid_view.h"
41.15 +
41.16 +static gint button_press_handler (GtkWidget *widget, GdkEvent *event);
41.17 +
41.18 +MMythUiCommon *create_main_view (MMythUi * mmyth_ui);
41.19 +MMythUiCommon *create_video_view (MMythUi * mmyth_ui);
41.20 +MMythUiCommon *create_esg_grid_view (MMythUi * mmyth_ui);
41.21 +static void cb_video_close_button (GtkButton * button, gpointer user_data);
41.22 +
41.23 +/* main box from button box separator*/
41.24 +static GtkWidget *main_vseparator = NULL;
41.25 +
41.26 +GdkPixbuf *icon_sports, *icon_news,
41.27 + *icon_movies, *icon_shows, *icon_default;
41.28 +
41.29 +/* FIXME: UGLY HACK */
41.30 +MMythUi *popup_mmyth_ui;
41.31 +
41.32 +void
41.33 +mmyth_ui_initialize_icons ()
41.34 +{
41.35 + GError *error = NULL;
41.36 +
41.37 +#ifdef MMYTH_DEVEL
41.38 + icon_sports =
41.39 + gdk_pixbuf_new_from_file ("../pixmaps/ico_sports.png", &error);
41.40 +#else
41.41 + icon_sports = gdk_pixbuf_new_from_file (PIX_DIR "ico_sports.png", &error);
41.42 +#endif
41.43 +
41.44 + if (error) {
41.45 + g_warning ("Could not load icon sports: %s\n", error->message);
41.46 + g_error_free (error);
41.47 + error = NULL;
41.48 + }
41.49 +
41.50 +#ifdef MMYTH_DEVEL
41.51 + icon_news = gdk_pixbuf_new_from_file ("../pixmaps/ico_news.png", &error);
41.52 +#else
41.53 + icon_news = gdk_pixbuf_new_from_file (PIX_DIR "ico_news.png", &error);
41.54 +#endif
41.55 +
41.56 + if (error) {
41.57 + g_warning ("Could not load icon news: %s\n", error->message);
41.58 + g_error_free (error);
41.59 + error = NULL;
41.60 + }
41.61 +
41.62 +#ifdef MMYTH_DEVEL
41.63 + icon_movies =
41.64 + gdk_pixbuf_new_from_file ("../pixmaps/ico_movies.png", &error);
41.65 +#else
41.66 + icon_movies = gdk_pixbuf_new_from_file (PIX_DIR "ico_movies.png", &error);
41.67 +#endif
41.68 + if (error) {
41.69 + g_warning ("Could not load icon movies: %s\n", error->message);
41.70 + g_error_free (error);
41.71 + error = NULL;
41.72 + }
41.73 +
41.74 +#ifdef MMYTH_DEVEL
41.75 + icon_shows = gdk_pixbuf_new_from_file ("../pixmaps/ico_shows.png", &error);
41.76 +#else
41.77 + icon_shows = gdk_pixbuf_new_from_file (PIX_DIR "ico_shows.png", &error);
41.78 +#endif
41.79 + if (error) {
41.80 + g_warning ("Could not load icon shows: %s\n", error->message);
41.81 + g_error_free (error);
41.82 + error = NULL;
41.83 + }
41.84 +
41.85 +#ifdef MMYTH_DEVEL
41.86 + icon_default =
41.87 + gdk_pixbuf_new_from_file ("../pixmaps/ico_default.png", &error);
41.88 +#else
41.89 + icon_default = gdk_pixbuf_new_from_file (PIX_DIR "ico_default.png", &error);
41.90 +#endif
41.91 +
41.92 + if (error) {
41.93 + g_warning ("Could not load icon default: %s\n", error->message);
41.94 + g_error_free (error);
41.95 + error = NULL;
41.96 + }
41.97 +
41.98 +}
41.99 +
41.100 +MMythUi *
41.101 +mmyth_ui_initialize (GtkWidget * main_window)
41.102 +{
41.103 + MMythUi *mmyth_ui;
41.104 +
41.105 + // FIXME: REMOVE ME
41.106 + //mmyth_settings_load ( );
41.107 +
41.108 + mmyth_ui = g_new0 (MMythUi, 1);
41.109 +
41.110 + mmyth_ui->main_window = main_window;
41.111 +
41.112 + /* Horizontal box that divides the view into control and video area */
41.113 + mmyth_ui->main_hbox = gtk_hbox_new (FALSE, 0);
41.114 + gtk_widget_show (mmyth_ui->main_hbox);
41.115 + g_object_ref (mmyth_ui->main_hbox);
41.116 +
41.117 + mmyth_ui_initialize_icons ();
41.118 +
41.119 + main_bg_color.red = 65000;
41.120 + main_bg_color.green = 65000;
41.121 + main_bg_color.blue = 65000;
41.122 +
41.123 + // Main widget is mmyth_ui->main_hbox
41.124 + mmyth_ui->main_uicommon = create_main_view (mmyth_ui);
41.125 + mmyth_ui->video_uicommon = create_video_view (mmyth_ui);
41.126 + mmyth_ui->esg_grid_uicommon = create_esg_grid_view (mmyth_ui);
41.127 +
41.128 + /* Popup menu */
41.129 + /* FIXME: URGENT ugly, ugly hack */
41.130 + popup_mmyth_ui = mmyth_ui;
41.131 + g_signal_connect (G_OBJECT (mmyth_ui->main_hbox), "event",
41.132 + G_CALLBACK (button_press_handler),
41.133 + G_OBJECT (mmyth_ui->main_hbox));
41.134 +
41.135 + gtk_container_add (GTK_CONTAINER (mmyth_ui->main_window),
41.136 + mmyth_ui->main_hbox);
41.137 +
41.138 + /* Add the gst video widget to hbox. It should never be removed. */
41.139 + /* FIXME: mmyth_ui->video_alignment == NULL when mmyth_player_init fails */
41.140 + if(mmyth_ui->video_alignment != NULL)
41.141 + gtk_box_pack_start (GTK_BOX (mmyth_ui->main_hbox),
41.142 + mmyth_ui->video_alignment, TRUE, TRUE, 0);
41.143 +
41.144 + mmyth_ui_set_widget (mmyth_ui, mmyth_ui->main_uicommon);
41.145 +
41.146 + return mmyth_ui;
41.147 +}
41.148 +
41.149 +void
41.150 +mmyth_ui_finalize (MMythUi * mmyth_ui)
41.151 +{
41.152 + if (mmyth_ui != NULL)
41.153 + g_free (mmyth_ui);
41.154 +
41.155 + mmyth_uicommon_unref_all (mmyth_ui->main_uicommon);
41.156 + mmyth_uicommon_unref_all (mmyth_ui->video_uicommon);
41.157 + mmyth_uicommon_unref_all (mmyth_ui->esgcurrent_uicommon);
41.158 +}
41.159 +
41.160 +void
41.161 +mmyth_ui_set_widget (MMythUi * mmyth_ui, MMythUiCommon * new_uicommon)
41.162 +{
41.163 + if (mmyth_ui->current_uicommon) {
41.164 + if (mmyth_ui->current_uicommon == mmyth_ui->video_uicommon) {
41.165 + gtk_widget_hide (mmyth_ui->current_uicommon->main_widget);
41.166 + gtk_widget_hide (mmyth_ui->videow);
41.167 + }
41.168 + else {
41.169 + gtk_container_remove (GTK_CONTAINER (mmyth_ui->main_hbox),
41.170 + mmyth_ui->current_uicommon->main_widget);
41.171 + }
41.172 +
41.173 + gtk_container_remove (GTK_CONTAINER (mmyth_ui->main_hbox),
41.174 + mmyth_ui->current_uicommon->event_box);
41.175 + gtk_container_remove (GTK_CONTAINER (mmyth_ui->main_hbox),
41.176 + main_vseparator);
41.177 +
41.178 + }
41.179 +
41.180 + if (new_uicommon->main_widget == mmyth_ui->video_alignment) {
41.181 + //gst_player_video_show (GST_PLAYER_VIDEO(mmyth_ui->videow));
41.182 + gtk_widget_show (mmyth_ui->video_alignment);
41.183 + gtk_widget_show (mmyth_ui->videow);
41.184 + }
41.185 + else {
41.186 + /* FIXME: Fst call is NULL when mmyth_player_init fails */
41.187 + if(mmyth_ui->video_alignment != NULL)
41.188 + gtk_widget_hide (mmyth_ui->video_alignment);
41.189 + /* FIXME: Fst call is NULL when mmyth_player_init fails */
41.190 + if(mmyth_ui->videow != NULL)
41.191 + gtk_widget_hide (mmyth_ui->videow);
41.192 +
41.193 + gtk_box_pack_start (GTK_BOX (mmyth_ui->main_hbox),
41.194 + new_uicommon->main_widget, TRUE, TRUE, 0);
41.195 + }
41.196 +
41.197 + if(main_vseparator == NULL) {
41.198 + /* FIXME: should free this variable*/
41.199 + main_vseparator = gtk_vseparator_new();
41.200 + g_object_ref (main_vseparator);
41.201 + }
41.202 + gtk_box_pack_start (GTK_BOX (mmyth_ui->main_hbox),
41.203 + main_vseparator, FALSE, FALSE, 0);
41.204 + gtk_widget_show (main_vseparator);
41.205 +
41.206 + gtk_box_pack_end (GTK_BOX (mmyth_ui->main_hbox), new_uicommon->event_box, FALSE,
41.207 + FALSE, 0);
41.208 +
41.209 + mmyth_ui->current_uicommon = new_uicommon;
41.210 +
41.211 +}
41.212 +
41.213 +/* The close callback is the same for all windows*/
41.214 +static void
41.215 +cb_not_impl_button (GtkButton * button, gpointer user_data)
41.216 +{
41.217 + MMythUi *mmyth_ui = (MMythUi *) user_data;
41.218 +
41.219 + GtkWidget *msg_dialog = gtk_message_dialog_new (
41.220 + GTK_WINDOW(mmyth_ui->main_window),
41.221 + GTK_DIALOG_MODAL |
41.222 + GTK_DIALOG_DESTROY_WITH_PARENT,
41.223 + GTK_MESSAGE_INFO,
41.224 + GTK_BUTTONS_OK,
41.225 + "Feature not implemented yet");
41.226 + gtk_widget_set_size_request (msg_dialog, 300, 120);
41.227 +
41.228 + gtk_dialog_run (GTK_DIALOG (msg_dialog));
41.229 +
41.230 + gtk_widget_destroy(GTK_WIDGET(msg_dialog));
41.231 +}
41.232 +
41.233 +/******************************************************************************
41.234 + * POPUP MENU WIDGET METHODS *
41.235 + *****************************************************************************/
41.236 +
41.237 +void
41.238 +detacher (GtkWidget *attach_widget,GtkMenu *menu)
41.239 +{
41.240 +}
41.241 +
41.242 +void
41.243 +menu_item_settings_cb (GtkMenuItem *menuitem,
41.244 + gpointer user_data)
41.245 +{
41.246 + /* MMythUi *mmyth_ui = (MMythUi *) user_data; */
41.247 +
41.248 + /* FIXME
41.249 + MMythUi *mmyth_ui = popup_mmyth_ui;
41.250 +
41.251 + settings_show_dialog (GTK_WINDOW (mmyth_ui->main_window));
41.252 + */
41.253 +}
41.254 +
41.255 +static void
41.256 +do_popup_menu (GtkWidget *my_widget, GdkEventButton *event)
41.257 +{
41.258 + GtkWidget *popup;
41.259 + int button, event_time;
41.260 +
41.261 + popup = gtk_menu_new ();
41.262 +
41.263 + /* ... add menu items ... */
41.264 + GtkWidget *menu_item = gtk_menu_item_new_with_label("Settings");
41.265 + gtk_menu_append(popup, menu_item);
41.266 +
41.267 + g_signal_connect (G_OBJECT(menu_item), "activate",
41.268 + G_CALLBACK (menu_item_settings_cb), NULL);
41.269 +
41.270 + if (event)
41.271 + {
41.272 + button = event->button;
41.273 + event_time = event->time;
41.274 + }
41.275 + else
41.276 + {
41.277 + button = 0;
41.278 + event_time = gtk_get_current_event_time ();
41.279 + }
41.280 +
41.281 + //gtk_menu_attach_to_widget (GTK_MENU (popup), my_widget, detacher);
41.282 + gtk_menu_popup (GTK_MENU (popup), NULL, NULL, NULL, NULL,
41.283 + button, event_time);
41.284 + gtk_widget_show_all(popup);
41.285 +}
41.286 +
41.287 +/* Respond to a button-press by posting a menu passed in as widget.
41.288 + *
41.289 + * Note that the "widget" argument is the menu being posted, NOT
41.290 + * the button that was pressed.
41.291 + */
41.292 +
41.293 +static gint
41.294 +button_press_handler (GtkWidget *widget, GdkEvent *event)
41.295 +{
41.296 +
41.297 + if (event->type == GDK_BUTTON_PRESS) {
41.298 + GdkEventButton *bevent = (GdkEventButton *) event;
41.299 + /* Ignore double-clicks and triple-clicks */
41.300 + if (bevent->button == 3)
41.301 + {
41.302 + do_popup_menu (widget, bevent);
41.303 + return TRUE;
41.304 + }
41.305 + }
41.306 +
41.307 + /* Tell calling code that we have not handled this event; pass it on. */
41.308 + return FALSE;
41.309 +}
41.310 +
41.311 +
41.312 +/******************************************************************************
41.313 + * MAIN APP VIEW METHODS *
41.314 + *****************************************************************************/
41.315 +
41.316 +/* The close callback is the same for all windows*/
41.317 +static void
41.318 +cb_close_button (GtkButton * button, gpointer user_data)
41.319 +{
41.320 + MMythUi *mmyth_ui = (MMythUi *) user_data;
41.321 +
41.322 + mmyth_ui_set_widget (mmyth_ui, mmyth_ui->main_uicommon);
41.323 +}
41.324 +
41.325 +static void
41.326 +cb_esg_today_button (GtkButton * button, gpointer user_data)
41.327 +{
41.328 + MMythUi *mmyth_ui = (MMythUi *) user_data;
41.329 +
41.330 + mmyth_ui_set_widget (mmyth_ui, mmyth_ui->esg_grid_uicommon);
41.331 +}
41.332 +
41.333 +MMythUiCommon *
41.334 +create_main_view (MMythUi * mmyth_ui)
41.335 +{
41.336 + MMythUiCommon *ui_common;
41.337 + GtkWidget *main_widget;
41.338 + GtkWidget *image;
41.339 +
41.340 + // FIXME: file path
41.341 +#ifdef MMYTH_DEV
41.342 + image = gtk_image_new_from_file ("../pixmaps/main_logo.gif");
41.343 +#else
41.344 + image = gtk_image_new_from_file ("../pixmaps/main_logo.gif");
41.345 +#endif
41.346 +
41.347 + main_widget = gtk_event_box_new();
41.348 +
41.349 + gtk_container_add (GTK_CONTAINER (main_widget),
41.350 + image);
41.351 +
41.352 +
41.353 + gtk_widget_show_all (main_widget);
41.354 + g_object_ref (main_widget);
41.355 +
41.356 + ui_common = mmyth_uicommon_new (main_widget,
41.357 + "Channels", "Current", "Today");
41.358 +
41.359 + /* Button signals */
41.360 + /* FIXME
41.361 + g_signal_connect (G_OBJECT (ui_common->button1), "clicked",
41.362 + G_CALLBACK (cb_channels_button), mmyth_ui);
41.363 + g_signal_connect (G_OBJECT (ui_common->button2), "clicked",
41.364 + G_CALLBACK (cb_esg_current_button), mmyth_ui);
41.365 + */
41.366 + g_signal_connect (G_OBJECT (ui_common->button3), "clicked",
41.367 + G_CALLBACK (cb_esg_today_button), mmyth_ui);
41.368 +
41.369 + return ui_common;
41.370 +
41.371 +}
41.372 +
41.373 +/******************************************************************************
41.374 + * ESG GRID VIEW METHODS *
41.375 + *****************************************************************************/
41.376 +
41.377 +static void
41.378 +cb_esg_grid_view_button (GtkButton * button, gpointer user_data)
41.379 +{
41.380 + /* FIXME
41.381 + MMythUi *mmyth_ui = (MMythUi *) user_data;
41.382 + guint32 service_id = -1;
41.383 +
41.384 + // Retrieves the user selected service ID
41.385 + DVBHScheduleEvent *schedule = (DVBHScheduleEvent *) mmyth_esg_grid_view_get_selected_schedule();
41.386 +
41.387 + if(schedule != NULL) {
41.388 + service_id = schedule->service->number;
41.389 + mmyth_play_channel (mmyth_ui, service_id);
41.390 + }
41.391 + */
41.392 +}
41.393 +
41.394 +MMythUiCommon *
41.395 +create_esg_grid_view (MMythUi * mmyth_ui)
41.396 +{
41.397 + MMythUiCommon *ui_common;
41.398 + GtkWidget *esg_grid_view = GTK_WIDGET (esg_grid_view_new (mmyth_ui));
41.399 +
41.400 +
41.401 + ui_common = mmyth_uicommon_new (esg_grid_view,
41.402 + "View", "Remind",
41.403 + "Close");
41.404 +
41.405 + /* Button signals */
41.406 + g_signal_connect (G_OBJECT (ui_common->button1), "clicked",
41.407 + G_CALLBACK (cb_esg_grid_view_button), mmyth_ui);
41.408 + g_signal_connect (G_OBJECT (ui_common->button2), "clicked",
41.409 + G_CALLBACK (cb_not_impl_button), mmyth_ui);
41.410 + g_signal_connect (G_OBJECT (ui_common->button3), "clicked",
41.411 + G_CALLBACK (cb_close_button), mmyth_ui);
41.412 +
41.413 + return ui_common;
41.414 +}
41.415 +
41.416 +/******************************************************************************
41.417 + * GST VIDEO WIDGET METHODS *
41.418 + *****************************************************************************/
41.419 +
41.420 +static void
41.421 +cb_video_close_button (GtkButton * button, gpointer user_data)
41.422 +{
41.423 + MMythUi *mmyth_ui = (MMythUi *) user_data;
41.424 +
41.425 + /* FIXME
41.426 + mmyth_player_stop (mmyth_ui);
41.427 + */
41.428 +
41.429 + mmyth_ui_set_widget (mmyth_ui, mmyth_ui->main_uicommon);
41.430 +}
41.431 +
41.432 +MMythUiCommon *
41.433 +create_video_view (MMythUi * mmyth_ui)
41.434 +{
41.435 +
41.436 + MMythUiCommon *ui_common;
41.437 +
41.438 + /* FIXME
41.439 + mmyth_player_init (mmyth_ui);
41.440 + */
41.441 +
41.442 + ui_common = mmyth_uicommon_new (mmyth_ui->video_alignment,
41.443 + " Full\nScreen", "Other\nServices",
41.444 + "Close");
41.445 +
41.446 + g_signal_connect (G_OBJECT (ui_common->button1), "clicked",
41.447 + G_CALLBACK (cb_not_impl_button), mmyth_ui);
41.448 + g_signal_connect (G_OBJECT (ui_common->button2), "clicked",
41.449 + G_CALLBACK (cb_not_impl_button), mmyth_ui);
41.450 + g_signal_connect (G_OBJECT (ui_common->button3), "clicked",
41.451 + G_CALLBACK (cb_video_close_button), mmyth_ui);
41.452 +
41.453 + return ui_common;
41.454 +}
42.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
42.2 +++ b/gmyth/src/gui/mmyth_ui.c.r2518 Wed Sep 20 23:45:35 2006 +0100
42.3 @@ -0,0 +1,456 @@
42.4 +
42.5 +#include <gtk/gtk.h>
42.6 +#include <gdk/gdkx.h>
42.7 +#include <gst/interfaces/xoverlay.h>
42.8 +
42.9 +#include "mmyth_ui.h"
42.10 +#include "mmyth_uicommon.h"
42.11 +/* FIXME
42.12 +#include "mmyth_videoplayer.h"
42.13 +#include "mmyth_esg_grid_view.h"
42.14 +#include "mmyth_common.h"
42.15 +*/
42.16 +
42.17 +static gint button_press_handler (GtkWidget *widget, GdkEvent *event);
42.18 +
42.19 +MMythUiCommon *create_main_view (MMythUi * mmyth_ui);
42.20 +MMythUiCommon *create_video_view (MMythUi * mmyth_ui);
42.21 +MMythUiCommon *create_esg_grid_view (MMythUi * mmyth_ui);
42.22 +static void cb_video_close_button (GtkButton * button, gpointer user_data);
42.23 +
42.24 +/* main box from button box separator*/
42.25 +static GtkWidget *main_vseparator = NULL;
42.26 +
42.27 +GdkPixbuf *icon_sports, *icon_news,
42.28 + *icon_movies, *icon_shows, *icon_default;
42.29 +
42.30 +/* FIXME: UGLY HACK */
42.31 +MMythUi *popup_mmyth_ui;
42.32 +
42.33 +void
42.34 +mmyth_ui_initialize_icons ()
42.35 +{
42.36 + GError *error = NULL;
42.37 +
42.38 +#ifdef MMYTH_DEVEL
42.39 + icon_sports =
42.40 + gdk_pixbuf_new_from_file ("../pixmaps/ico_sports.png", &error);
42.41 +#else
42.42 + icon_sports = gdk_pixbuf_new_from_file (PIX_DIR "ico_sports.png", &error);
42.43 +#endif
42.44 +
42.45 + if (error) {
42.46 + g_warning ("Could not load icon sports: %s\n", error->message);
42.47 + g_error_free (error);
42.48 + error = NULL;
42.49 + }
42.50 +
42.51 +#ifdef MMYTH_DEVEL
42.52 + icon_news = gdk_pixbuf_new_from_file ("../pixmaps/ico_news.png", &error);
42.53 +#else
42.54 + icon_news = gdk_pixbuf_new_from_file (PIX_DIR "ico_news.png", &error);
42.55 +#endif
42.56 +
42.57 + if (error) {
42.58 + g_warning ("Could not load icon news: %s\n", error->message);
42.59 + g_error_free (error);
42.60 + error = NULL;
42.61 + }
42.62 +
42.63 +#ifdef MMYTH_DEVEL
42.64 + icon_movies =
42.65 + gdk_pixbuf_new_from_file ("../pixmaps/ico_movies.png", &error);
42.66 +#else
42.67 + icon_movies = gdk_pixbuf_new_from_file (PIX_DIR "ico_movies.png", &error);
42.68 +#endif
42.69 + if (error) {
42.70 + g_warning ("Could not load icon movies: %s\n", error->message);
42.71 + g_error_free (error);
42.72 + error = NULL;
42.73 + }
42.74 +
42.75 +#ifdef MMYTH_DEVEL
42.76 + icon_shows = gdk_pixbuf_new_from_file ("../pixmaps/ico_shows.png", &error);
42.77 +#else
42.78 + icon_shows = gdk_pixbuf_new_from_file (PIX_DIR "ico_shows.png", &error);
42.79 +#endif
42.80 + if (error) {
42.81 + g_warning ("Could not load icon shows: %s\n", error->message);
42.82 + g_error_free (error);
42.83 + error = NULL;
42.84 + }
42.85 +
42.86 +#ifdef MMYTH_DEVEL
42.87 + icon_default =
42.88 + gdk_pixbuf_new_from_file ("../pixmaps/ico_default.png", &error);
42.89 +#else
42.90 + icon_default = gdk_pixbuf_new_from_file (PIX_DIR "ico_default.png", &error);
42.91 +#endif
42.92 +
42.93 + if (error) {
42.94 + g_warning ("Could not load icon default: %s\n", error->message);
42.95 + g_error_free (error);
42.96 + error = NULL;
42.97 + }
42.98 +
42.99 +}
42.100 +
42.101 +MMythUi *
42.102 +mmyth_ui_initialize (GtkWidget * main_window)
42.103 +{
42.104 + MMythUi *mmyth_ui;
42.105 +
42.106 + // FIXME: REMOVE ME
42.107 + //mmyth_settings_load ( );
42.108 +
42.109 + mmyth_ui = g_new0 (MMythUi, 1);
42.110 +
42.111 + mmyth_ui->main_window = main_window;
42.112 +
42.113 + /* Horizontal box that divides the view into control and video area */
42.114 + mmyth_ui->main_hbox = gtk_hbox_new (FALSE, 0);
42.115 + gtk_widget_show (mmyth_ui->main_hbox);
42.116 + g_object_ref (mmyth_ui->main_hbox);
42.117 +
42.118 + mmyth_ui_initialize_icons ();
42.119 +
42.120 + main_bg_color.red = 65000;
42.121 + main_bg_color.green = 65000;
42.122 + main_bg_color.blue = 65000;
42.123 +
42.124 + // Main widget is mmyth_ui->main_hbox
42.125 + mmyth_ui->main_uicommon = create_main_view (mmyth_ui);
42.126 + mmyth_ui->video_uicommon = create_video_view (mmyth_ui);
42.127 + mmyth_ui->esg_grid_uicommon = create_esg_grid_view (mmyth_ui);
42.128 +
42.129 + /* Popup menu */
42.130 + /* FIXME: URGENT ugly, ugly hack */
42.131 + popup_mmyth_ui = mmyth_ui;
42.132 + g_signal_connect (G_OBJECT (mmyth_ui->main_hbox), "event",
42.133 + G_CALLBACK (button_press_handler),
42.134 + G_OBJECT (mmyth_ui->main_hbox));
42.135 +
42.136 + gtk_container_add (GTK_CONTAINER (mmyth_ui->main_window),
42.137 + mmyth_ui->main_hbox);
42.138 +
42.139 + /* Add the gst video widget to hbox. It should never be removed. */
42.140 + /* FIXME: mmyth_ui->video_alignment == NULL when mmyth_player_init fails */
42.141 + if(mmyth_ui->video_alignment != NULL)
42.142 + gtk_box_pack_start (GTK_BOX (mmyth_ui->main_hbox),
42.143 + mmyth_ui->video_alignment, TRUE, TRUE, 0);
42.144 +
42.145 + mmyth_ui_set_widget (mmyth_ui, mmyth_ui->main_uicommon);
42.146 +
42.147 + return mmyth_ui;
42.148 +}
42.149 +
42.150 +void
42.151 +mmyth_ui_finalize (MMythUi * mmyth_ui)
42.152 +{
42.153 + if (mmyth_ui != NULL)
42.154 + g_free (mmyth_ui);
42.155 +
42.156 + mmyth_uicommon_unref_all (mmyth_ui->main_uicommon);
42.157 + mmyth_uicommon_unref_all (mmyth_ui->video_uicommon);
42.158 + mmyth_uicommon_unref_all (mmyth_ui->esgcurrent_uicommon);
42.159 +}
42.160 +
42.161 +void
42.162 +mmyth_ui_set_widget (MMythUi * mmyth_ui, MMythUiCommon * new_uicommon)
42.163 +{
42.164 + if (mmyth_ui->current_uicommon) {
42.165 + if (mmyth_ui->current_uicommon == mmyth_ui->video_uicommon) {
42.166 + gtk_widget_hide (mmyth_ui->current_uicommon->main_widget);
42.167 + gtk_widget_hide (mmyth_ui->videow);
42.168 + }
42.169 + else {
42.170 + gtk_container_remove (GTK_CONTAINER (mmyth_ui->main_hbox),
42.171 + mmyth_ui->current_uicommon->main_widget);
42.172 + }
42.173 +
42.174 + gtk_container_remove (GTK_CONTAINER (mmyth_ui->main_hbox),
42.175 + mmyth_ui->current_uicommon->event_box);
42.176 + gtk_container_remove (GTK_CONTAINER (mmyth_ui->main_hbox),
42.177 + main_vseparator);
42.178 +
42.179 + }
42.180 +
42.181 + if (new_uicommon->main_widget == mmyth_ui->video_alignment) {
42.182 + //gst_player_video_show (GST_PLAYER_VIDEO(mmyth_ui->videow));
42.183 + gtk_widget_show (mmyth_ui->video_alignment);
42.184 + gtk_widget_show (mmyth_ui->videow);
42.185 + }
42.186 + else {
42.187 + /* FIXME: Fst call is NULL when mmyth_player_init fails */
42.188 + if(mmyth_ui->video_alignment != NULL)
42.189 + gtk_widget_hide (mmyth_ui->video_alignment);
42.190 + /* FIXME: Fst call is NULL when mmyth_player_init fails */
42.191 + if(mmyth_ui->videow != NULL)
42.192 + gtk_widget_hide (mmyth_ui->videow);
42.193 +
42.194 + gtk_box_pack_start (GTK_BOX (mmyth_ui->main_hbox),
42.195 + new_uicommon->main_widget, TRUE, TRUE, 0);
42.196 + }
42.197 +
42.198 + if(main_vseparator == NULL) {
42.199 + /* FIXME: should free this variable*/
42.200 + main_vseparator = gtk_vseparator_new();
42.201 + g_object_ref (main_vseparator);
42.202 + }
42.203 + gtk_box_pack_start (GTK_BOX (mmyth_ui->main_hbox),
42.204 + main_vseparator, FALSE, FALSE, 0);
42.205 + gtk_widget_show (main_vseparator);
42.206 +
42.207 + gtk_box_pack_end (GTK_BOX (mmyth_ui->main_hbox), new_uicommon->event_box, FALSE,
42.208 + FALSE, 0);
42.209 +
42.210 + mmyth_ui->current_uicommon = new_uicommon;
42.211 +
42.212 +}
42.213 +
42.214 +/* The close callback is the same for all windows*/
42.215 +static void
42.216 +cb_not_impl_button (GtkButton * button, gpointer user_data)
42.217 +{
42.218 + MMythUi *mmyth_ui = (MMythUi *) user_data;
42.219 +
42.220 + GtkWidget *msg_dialog = gtk_message_dialog_new (
42.221 + GTK_WINDOW(mmyth_ui->main_window),
42.222 + GTK_DIALOG_MODAL |
42.223 + GTK_DIALOG_DESTROY_WITH_PARENT,
42.224 + GTK_MESSAGE_INFO,
42.225 + GTK_BUTTONS_OK,
42.226 + "Feature not implemented yet");
42.227 + gtk_widget_set_size_request (msg_dialog, 300, 120);
42.228 +
42.229 + gtk_dialog_run (GTK_DIALOG (msg_dialog));
42.230 +
42.231 + gtk_widget_destroy(GTK_WIDGET(msg_dialog));
42.232 +}
42.233 +
42.234 +/******************************************************************************
42.235 + * POPUP MENU WIDGET METHODS *
42.236 + *****************************************************************************/
42.237 +
42.238 +void
42.239 +detacher (GtkWidget *attach_widget,GtkMenu *menu)
42.240 +{
42.241 +}
42.242 +
42.243 +void
42.244 +menu_item_settings_cb (GtkMenuItem *menuitem,
42.245 + gpointer user_data)
42.246 +{
42.247 + /* MMythUi *mmyth_ui = (MMythUi *) user_data; */
42.248 +
42.249 + /* FIXME
42.250 + MMythUi *mmyth_ui = popup_mmyth_ui;
42.251 +
42.252 + settings_show_dialog (GTK_WINDOW (mmyth_ui->main_window));
42.253 + */
42.254 +}
42.255 +
42.256 +static void
42.257 +do_popup_menu (GtkWidget *my_widget, GdkEventButton *event)
42.258 +{
42.259 + GtkWidget *popup;
42.260 + int button, event_time;
42.261 +
42.262 + popup = gtk_menu_new ();
42.263 +
42.264 + /* ... add menu items ... */
42.265 + GtkWidget *menu_item = gtk_menu_item_new_with_label("Settings");
42.266 + gtk_menu_append(popup, menu_item);
42.267 +
42.268 + g_signal_connect (G_OBJECT(menu_item), "activate",
42.269 + G_CALLBACK (menu_item_settings_cb), NULL);
42.270 +
42.271 + if (event)
42.272 + {
42.273 + button = event->button;
42.274 + event_time = event->time;
42.275 + }
42.276 + else
42.277 + {
42.278 + button = 0;
42.279 + event_time = gtk_get_current_event_time ();
42.280 + }
42.281 +
42.282 + //gtk_menu_attach_to_widget (GTK_MENU (popup), my_widget, detacher);
42.283 + gtk_menu_popup (GTK_MENU (popup), NULL, NULL, NULL, NULL,
42.284 + button, event_time);
42.285 + gtk_widget_show_all(popup);
42.286 +}
42.287 +
42.288 +/* Respond to a button-press by posting a menu passed in as widget.
42.289 + *
42.290 + * Note that the "widget" argument is the menu being posted, NOT
42.291 + * the button that was pressed.
42.292 + */
42.293 +
42.294 +static gint
42.295 +button_press_handler (GtkWidget *widget, GdkEvent *event)
42.296 +{
42.297 +
42.298 + if (event->type == GDK_BUTTON_PRESS) {
42.299 + GdkEventButton *bevent = (GdkEventButton *) event;
42.300 + /* Ignore double-clicks and triple-clicks */
42.301 + if (bevent->button == 3)
42.302 + {
42.303 + do_popup_menu (widget, bevent);
42.304 + return TRUE;
42.305 + }
42.306 + }
42.307 +
42.308 + /* Tell calling code that we have not handled this event; pass it on. */
42.309 + return FALSE;
42.310 +}
42.311 +
42.312 +
42.313 +/******************************************************************************
42.314 + * MAIN APP VIEW METHODS *
42.315 + *****************************************************************************/
42.316 +
42.317 +/* The close callback is the same for all windows*/
42.318 +static void
42.319 +cb_close_button (GtkButton * button, gpointer user_data)
42.320 +{
42.321 + MMythUi *mmyth_ui = (MMythUi *) user_data;
42.322 +
42.323 + mmyth_ui_set_widget (mmyth_ui, mmyth_ui->main_uicommon);
42.324 +}
42.325 +
42.326 +/* FIXME
42.327 +static void
42.328 +cb_esg_today_button (GtkButton * button, gpointer user_data)
42.329 +{
42.330 + MMythUi *mmyth_ui = (MMythUi *) user_data;
42.331 +
42.332 + mmyth_ui_set_widget (mmyth_ui, mmyth_ui->esg_grid_uicommon);
42.333 +}
42.334 +*/
42.335 +
42.336 +MMythUiCommon *
42.337 +create_main_view (MMythUi * mmyth_ui)
42.338 +{
42.339 + MMythUiCommon *ui_common;
42.340 + GtkWidget *main_widget;
42.341 + GtkWidget *image;
42.342 +
42.343 + // FIXME: file path
42.344 +#ifdef MMYTH_DEV
42.345 + image = gtk_image_new_from_file ("../pixmaps/main_logo.gif");
42.346 +#else
42.347 + image = gtk_image_new_from_file ("../pixmaps/main_logo.gif");
42.348 +#endif
42.349 +
42.350 + main_widget = gtk_event_box_new();
42.351 +
42.352 + gtk_container_add (GTK_CONTAINER (main_widget),
42.353 + image);
42.354 +
42.355 +
42.356 + gtk_widget_show_all (main_widget);
42.357 + g_object_ref (main_widget);
42.358 +
42.359 + ui_common = mmyth_uicommon_new (main_widget,
42.360 + "Channels", "Current", "Today");
42.361 +
42.362 + /* Button signals */
42.363 + /* FIXME
42.364 + g_signal_connect (G_OBJECT (ui_common->button1), "clicked",
42.365 + G_CALLBACK (cb_channels_button), mmyth_ui);
42.366 + g_signal_connect (G_OBJECT (ui_common->button2), "clicked",
42.367 + G_CALLBACK (cb_esg_current_button), mmyth_ui);
42.368 + g_signal_connect (G_OBJECT (ui_common->button3), "clicked",
42.369 + G_CALLBACK (cb_esg_today_button), mmyth_ui);
42.370 + */
42.371 +
42.372 + return ui_common;
42.373 +
42.374 +}
42.375 +
42.376 +/******************************************************************************
42.377 + * ESG GRID VIEW METHODS *
42.378 + *****************************************************************************/
42.379 +
42.380 +static void
42.381 +cb_esg_grid_view_button (GtkButton * button, gpointer user_data)
42.382 +{
42.383 + /* FIXME
42.384 + MMythUi *mmyth_ui = (MMythUi *) user_data;
42.385 + guint32 service_id = -1;
42.386 +
42.387 + // Retrieves the user selected service ID
42.388 + DVBHScheduleEvent *schedule = (DVBHScheduleEvent *) mmyth_esg_grid_view_get_selected_schedule();
42.389 +
42.390 + if(schedule != NULL) {
42.391 + service_id = schedule->service->number;
42.392 + mmyth_play_channel (mmyth_ui, service_id);
42.393 + }
42.394 + */
42.395 +}
42.396 +
42.397 +MMythUiCommon *
42.398 +create_esg_grid_view (MMythUi * mmyth_ui)
42.399 +{
42.400 + MMythUiCommon *ui_common;
42.401 + /* FIXME
42.402 + GtkWidget *esg_grid_view = GTK_WIDGET (esg_grid_view_new (mmyth_ui));
42.403 +
42.404 +
42.405 + ui_common = mmyth_uicommon_new (esg_grid_view,
42.406 + "View", "Remind",
42.407 + "Close");
42.408 + */
42.409 +
42.410 + /* Button signals */
42.411 + g_signal_connect (G_OBJECT (ui_common->button1), "clicked",
42.412 + G_CALLBACK (cb_esg_grid_view_button), mmyth_ui);
42.413 + g_signal_connect (G_OBJECT (ui_common->button2), "clicked",
42.414 + G_CALLBACK (cb_not_impl_button), mmyth_ui);
42.415 + g_signal_connect (G_OBJECT (ui_common->button3), "clicked",
42.416 + G_CALLBACK (cb_close_button), mmyth_ui);
42.417 +
42.418 + return ui_common;
42.419 +}
42.420 +
42.421 +/******************************************************************************
42.422 + * GST VIDEO WIDGET METHODS *
42.423 + *****************************************************************************/
42.424 +
42.425 +static void
42.426 +cb_video_close_button (GtkButton * button, gpointer user_data)
42.427 +{
42.428 + MMythUi *mmyth_ui = (MMythUi *) user_data;
42.429 +
42.430 + /* FIXME
42.431 + mmyth_player_stop (mmyth_ui);
42.432 + */
42.433 +
42.434 + mmyth_ui_set_widget (mmyth_ui, mmyth_ui->main_uicommon);
42.435 +}
42.436 +
42.437 +MMythUiCommon *
42.438 +create_video_view (MMythUi * mmyth_ui)
42.439 +{
42.440 +
42.441 + MMythUiCommon *ui_common;
42.442 +
42.443 + /* FIXME
42.444 + mmyth_player_init (mmyth_ui);
42.445 + */
42.446 +
42.447 + ui_common = mmyth_uicommon_new (mmyth_ui->video_alignment,
42.448 + " Full\nScreen", "Other\nServices",
42.449 + "Close");
42.450 +
42.451 + g_signal_connect (G_OBJECT (ui_common->button1), "clicked",
42.452 + G_CALLBACK (cb_not_impl_button), mmyth_ui);
42.453 + g_signal_connect (G_OBJECT (ui_common->button2), "clicked",
42.454 + G_CALLBACK (cb_not_impl_button), mmyth_ui);
42.455 + g_signal_connect (G_OBJECT (ui_common->button3), "clicked",
42.456 + G_CALLBACK (cb_video_close_button), mmyth_ui);
42.457 +
42.458 + return ui_common;
42.459 +}
43.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
43.2 +++ b/gmyth/src/gui/mmyth_ui.c.r2535 Wed Sep 20 23:45:35 2006 +0100
43.3 @@ -0,0 +1,567 @@
43.4 +#include <gtk/gtk.h>
43.5 +#include <gdk/gdkx.h>
43.6 +#include <gst/interfaces/xoverlay.h>
43.7 +
43.8 +#include "mmyth_ui.h"
43.9 +#include "mmyth_uicommon.h"
43.10 +#include "mmyth_uischedulerecording.h"
43.11 +#include "mmyth_uirecord.h"
43.12 +/* FIXME
43.13 +#include "mmyth_videoplayer.h"
43.14 +#include "mmyth_esg_grid_view.h"
43.15 +#include "mmyth_common.h"
43.16 +*/
43.17 +
43.18 +static gint button_press_handler (GtkWidget *widget, GdkEvent *event);
43.19 +
43.20 +MMythUiCommon *create_main_view (MMythUi * mmyth_ui);
43.21 +MMythUiCommon *create_video_view (MMythUi * mmyth_ui);
43.22 +MMythUiCommon *create_esg_grid_view (MMythUi * mmyth_ui);
43.23 +MMythUiCommon *create_record_view (MMythUi * mmyth_ui);
43.24 +MMythUiCommon *create_schedule_view (MMythUi * mmyth_ui);
43.25 +static void cb_video_close_button (GtkButton * button, gpointer user_data);
43.26 +static void cb_record_button (GtkButton * button, gpointer user_data);
43.27 +
43.28 +/* main box from button box separator*/
43.29 +static GtkWidget *main_vseparator = NULL;
43.30 +
43.31 +GdkPixbuf *icon_sports, *icon_news,
43.32 + *icon_movies, *icon_shows, *icon_default;
43.33 +
43.34 +/* FIXME: UGLY HACK */
43.35 +MMythUi *popup_mmyth_ui;
43.36 +
43.37 +void
43.38 +mmyth_ui_initialize_icons ()
43.39 +{
43.40 + GError *error = NULL;
43.41 +
43.42 +#ifdef MMYTH_DEVEL
43.43 + icon_sports =
43.44 + gdk_pixbuf_new_from_file ("../pixmaps/ico_sports.png", &error);
43.45 +#else
43.46 + icon_sports = gdk_pixbuf_new_from_file (PIX_DIR "ico_sports.png", &error);
43.47 +#endif
43.48 +
43.49 + if (error) {
43.50 + g_warning ("Could not load icon sports: %s\n", error->message);
43.51 + g_error_free (error);
43.52 + error = NULL;
43.53 + }
43.54 +
43.55 +#ifdef MMYTH_DEVEL
43.56 + icon_news = gdk_pixbuf_new_from_file ("../pixmaps/ico_news.png", &error);
43.57 +#else
43.58 + icon_news = gdk_pixbuf_new_from_file (PIX_DIR "ico_news.png", &error);
43.59 +#endif
43.60 +
43.61 + if (error) {
43.62 + g_warning ("Could not load icon news: %s\n", error->message);
43.63 + g_error_free (error);
43.64 + error = NULL;
43.65 + }
43.66 +
43.67 +#ifdef MMYTH_DEVEL
43.68 + icon_movies =
43.69 + gdk_pixbuf_new_from_file ("../pixmaps/ico_movies.png", &error);
43.70 +#else
43.71 + icon_movies = gdk_pixbuf_new_from_file (PIX_DIR "ico_movies.png", &error);
43.72 +#endif
43.73 + if (error) {
43.74 + g_warning ("Could not load icon movies: %s\n", error->message);
43.75 + g_error_free (error);
43.76 + error = NULL;
43.77 + }
43.78 +
43.79 +#ifdef MMYTH_DEVEL
43.80 + icon_shows = gdk_pixbuf_new_from_file ("../pixmaps/ico_shows.png", &error);
43.81 +#else
43.82 + icon_shows = gdk_pixbuf_new_from_file (PIX_DIR "ico_shows.png", &error);
43.83 +#endif
43.84 + if (error) {
43.85 + g_warning ("Could not load icon shows: %s\n", error->message);
43.86 + g_error_free (error);
43.87 + error = NULL;
43.88 + }
43.89 +
43.90 +#ifdef MMYTH_DEVEL
43.91 + icon_default =
43.92 + gdk_pixbuf_new_from_file ("../pixmaps/ico_default.png", &error);
43.93 +#else
43.94 + icon_default = gdk_pixbuf_new_from_file (PIX_DIR "ico_default.png", &error);
43.95 +#endif
43.96 +
43.97 + if (error) {
43.98 + g_warning ("Could not load icon default: %s\n", error->message);
43.99 + g_error_free (error);
43.100 + error = NULL;
43.101 + }
43.102 +
43.103 +}
43.104 +
43.105 +MMythUi *
43.106 +mmyth_ui_initialize (GtkWidget * main_window)
43.107 +{
43.108 + MMythUi *mmyth_ui;
43.109 +
43.110 + // FIXME: REMOVE ME
43.111 + //mmyth_settings_load ( );
43.112 +
43.113 + mmyth_ui = g_new0 (MMythUi, 1);
43.114 +
43.115 + mmyth_ui->main_window = main_window;
43.116 +
43.117 + /* Horizontal box that divides the view into control and video area */
43.118 + mmyth_ui->main_hbox = gtk_hbox_new (FALSE, 0);
43.119 + gtk_widget_show (mmyth_ui->main_hbox);
43.120 + g_object_ref (mmyth_ui->main_hbox);
43.121 +
43.122 + mmyth_ui_initialize_icons ();
43.123 +
43.124 + main_bg_color.red = 65000;
43.125 + main_bg_color.green = 65000;
43.126 + main_bg_color.blue = 65000;
43.127 +
43.128 + // Main widget is mmyth_ui->main_hbox
43.129 + mmyth_ui->main_uicommon = create_main_view (mmyth_ui);
43.130 + mmyth_ui->video_uicommon = create_video_view (mmyth_ui);
43.131 + mmyth_ui->esg_grid_uicommon = create_esg_grid_view (mmyth_ui);
43.132 + mmyth_ui->record_uicommon = create_record_view (mmyth_ui);
43.133 + mmyth_ui->schedule_uicommon = create_schedule_view (mmyth_ui);
43.134 + /* Popup menu */
43.135 + /* FIXME: URGENT ugly, ugly hack */
43.136 + popup_mmyth_ui = mmyth_ui;
43.137 + g_signal_connect (G_OBJECT (mmyth_ui->main_hbox), "event",
43.138 + G_CALLBACK (button_press_handler),
43.139 + G_OBJECT (mmyth_ui->main_hbox));
43.140 +
43.141 + gtk_container_add (GTK_CONTAINER (mmyth_ui->main_window),
43.142 + mmyth_ui->main_hbox);
43.143 +
43.144 + /* Add the gst video widget to hbox. It should never be removed. */
43.145 + /* FIXME: mmyth_ui->video_alignment == NULL when mmyth_player_init fails */
43.146 + if(mmyth_ui->video_alignment != NULL)
43.147 + gtk_box_pack_start (GTK_BOX (mmyth_ui->main_hbox),
43.148 + mmyth_ui->video_alignment, TRUE, TRUE, 0);
43.149 +
43.150 + mmyth_ui_set_widget (mmyth_ui, mmyth_ui->main_uicommon);
43.151 +
43.152 + return mmyth_ui;
43.153 +}
43.154 +
43.155 +void
43.156 +mmyth_ui_finalize (MMythUi * mmyth_ui)
43.157 +{
43.158 + if (mmyth_ui != NULL)
43.159 + g_free (mmyth_ui);
43.160 +
43.161 + mmyth_uicommon_unref_all (mmyth_ui->main_uicommon);
43.162 + mmyth_uicommon_unref_all (mmyth_ui->video_uicommon);
43.163 + mmyth_uicommon_unref_all (mmyth_ui->esgcurrent_uicommon);
43.164 +}
43.165 +
43.166 +void
43.167 +mmyth_ui_set_widget (MMythUi * mmyth_ui, MMythUiCommon * new_uicommon)
43.168 +{
43.169 + if (mmyth_ui->current_uicommon) {
43.170 + if (mmyth_ui->current_uicommon == mmyth_ui->video_uicommon) {
43.171 + gtk_widget_hide (mmyth_ui->current_uicommon->main_widget);
43.172 + gtk_widget_hide (mmyth_ui->videow);
43.173 + }
43.174 + else {
43.175 + gtk_container_remove (GTK_CONTAINER (mmyth_ui->main_hbox),
43.176 + mmyth_ui->current_uicommon->main_widget);
43.177 + }
43.178 +
43.179 + gtk_container_remove (GTK_CONTAINER (mmyth_ui->main_hbox),
43.180 + mmyth_ui->current_uicommon->event_box);
43.181 + gtk_container_remove (GTK_CONTAINER (mmyth_ui->main_hbox),
43.182 + main_vseparator);
43.183 +
43.184 + }
43.185 +
43.186 + if (new_uicommon->main_widget == mmyth_ui->video_alignment) {
43.187 + //gst_player_video_show (GST_PLAYER_VIDEO(mmyth_ui->videow));
43.188 + gtk_widget_show (mmyth_ui->video_alignment);
43.189 + gtk_widget_show (mmyth_ui->videow);
43.190 + }
43.191 + else {
43.192 + /* FIXME: Fst call is NULL when mmyth_player_init fails */
43.193 + if(mmyth_ui->video_alignment != NULL)
43.194 + gtk_widget_hide (mmyth_ui->video_alignment);
43.195 + /* FIXME: Fst call is NULL when mmyth_player_init fails */
43.196 + if(mmyth_ui->videow != NULL)
43.197 + gtk_widget_hide (mmyth_ui->videow);
43.198 +
43.199 + gtk_box_pack_start (GTK_BOX (mmyth_ui->main_hbox),
43.200 + new_uicommon->main_widget, TRUE, TRUE, 0);
43.201 + }
43.202 +
43.203 + if(main_vseparator == NULL) {
43.204 + /* FIXME: should free this variable*/
43.205 + main_vseparator = gtk_vseparator_new();
43.206 + g_object_ref (main_vseparator);
43.207 + }
43.208 + gtk_box_pack_start (GTK_BOX (mmyth_ui->main_hbox),
43.209 + main_vseparator, FALSE, FALSE, 0);
43.210 + gtk_widget_show (main_vseparator);
43.211 +
43.212 + gtk_box_pack_end (GTK_BOX (mmyth_ui->main_hbox), new_uicommon->event_box, FALSE,
43.213 + FALSE, 0);
43.214 +
43.215 + mmyth_ui->current_uicommon = new_uicommon;
43.216 +
43.217 +}
43.218 +
43.219 +/* The close callback is the same for all windows*/
43.220 +static void
43.221 +cb_not_impl_button (GtkButton * button, gpointer user_data)
43.222 +{
43.223 + MMythUi *mmyth_ui = (MMythUi *) user_data;
43.224 +
43.225 + GtkWidget *msg_dialog = gtk_message_dialog_new (
43.226 + GTK_WINDOW(mmyth_ui->main_window),
43.227 + GTK_DIALOG_MODAL |
43.228 + GTK_DIALOG_DESTROY_WITH_PARENT,
43.229 + GTK_MESSAGE_INFO,
43.230 + GTK_BUTTONS_OK,
43.231 + "Feature not implemented yet");
43.232 + gtk_widget_set_size_request (msg_dialog, 300, 120);
43.233 +
43.234 + gtk_dialog_run (GTK_DIALOG (msg_dialog));
43.235 +
43.236 + gtk_widget_destroy(GTK_WIDGET(msg_dialog));
43.237 +}
43.238 +
43.239 +/******************************************************************************
43.240 + * POPUP MENU WIDGET METHODS *
43.241 + *****************************************************************************/
43.242 +
43.243 +void
43.244 +detacher (GtkWidget *attach_widget,GtkMenu *menu)
43.245 +{
43.246 +}
43.247 +
43.248 +void
43.249 +menu_item_settings_cb (GtkMenuItem *menuitem,
43.250 + gpointer user_data)
43.251 +{
43.252 + /* MMythUi *mmyth_ui = (MMythUi *) user_data; */
43.253 +
43.254 + /* FIXME
43.255 + MMythUi *mmyth_ui = popup_mmyth_ui;
43.256 +
43.257 + settings_show_dialog (GTK_WINDOW (mmyth_ui->main_window));
43.258 + */
43.259 +}
43.260 +
43.261 +static void
43.262 +do_popup_menu (GtkWidget *my_widget, GdkEventButton *event)
43.263 +{
43.264 + GtkWidget *popup;
43.265 + int button, event_time;
43.266 +
43.267 + popup = gtk_menu_new ();
43.268 +
43.269 + /* ... add menu items ... */
43.270 + GtkWidget *menu_item = gtk_menu_item_new_with_label("Settings");
43.271 + gtk_menu_append(popup, menu_item);
43.272 +
43.273 + g_signal_connect (G_OBJECT(menu_item), "activate",
43.274 + G_CALLBACK (menu_item_settings_cb), NULL);
43.275 +
43.276 + if (event)
43.277 + {
43.278 + button = event->button;
43.279 + event_time = event->time;
43.280 + }
43.281 + else
43.282 + {
43.283 + button = 0;
43.284 + event_time = gtk_get_current_event_time ();
43.285 + }
43.286 +
43.287 + //gtk_menu_attach_to_widget (GTK_MENU (popup), my_widget, detacher);
43.288 + gtk_menu_popup (GTK_MENU (popup), NULL, NULL, NULL, NULL,
43.289 + button, event_time);
43.290 + gtk_widget_show_all(popup);
43.291 +}
43.292 +
43.293 +/* Respond to a button-press by posting a menu passed in as widget.
43.294 + *
43.295 + * Note that the "widget" argument is the menu being posted, NOT
43.296 + * the button that was pressed.
43.297 + */
43.298 +
43.299 +static gint
43.300 +button_press_handler (GtkWidget *widget, GdkEvent *event)
43.301 +{
43.302 +
43.303 + if (event->type == GDK_BUTTON_PRESS) {
43.304 + GdkEventButton *bevent = (GdkEventButton *) event;
43.305 + /* Ignore double-clicks and triple-clicks */
43.306 + if (bevent->button == 3)
43.307 + {
43.308 + do_popup_menu (widget, bevent);
43.309 + return TRUE;
43.310 + }
43.311 + }
43.312 +
43.313 + /* Tell calling code that we have not handled this event; pass it on. */
43.314 + return FALSE;
43.315 +}
43.316 +
43.317 +
43.318 +/******************************************************************************
43.319 + * MAIN APP VIEW METHODS *
43.320 + *****************************************************************************/
43.321 +
43.322 +/* The close callback is the same for all windows*/
43.323 +static void
43.324 +cb_close_button (GtkButton * button, gpointer user_data)
43.325 +{
43.326 + MMythUi *mmyth_ui = (MMythUi *) user_data;
43.327 +
43.328 + mmyth_ui_set_widget (mmyth_ui, mmyth_ui->main_uicommon);
43.329 +}
43.330 +
43.331 +// FIXME
43.332 +//static void
43.333 +//cb_record_button (GtkButton * button, gpointer user_data)
43.334 +//{
43.335 +// MMythUi *mmyth_ui = (MMythUi *) user_data;
43.336 +//
43.337 +// mmyth_ui_set_widget (mmyth_ui, mmyth_ui->record_uicommon);
43.338 +//}
43.339 +
43.340 +
43.341 +MMythUiCommon *
43.342 +create_main_view (MMythUi * mmyth_ui)
43.343 +{
43.344 + MMythUiCommon *ui_common;
43.345 + GtkWidget *main_widget;
43.346 + GtkWidget *image;
43.347 +
43.348 + // FIXME: file path
43.349 +#ifdef MMYTH_DEV
43.350 + image = gtk_image_new_from_file ("../pixmaps/main_logo.gif");
43.351 +#else
43.352 + image = gtk_image_new_from_file ("../pixmaps/main_logo.gif");
43.353 +#endif
43.354 +
43.355 + main_widget = gtk_event_box_new();
43.356 +
43.357 + gtk_container_add (GTK_CONTAINER (main_widget),
43.358 + image);
43.359 +
43.360 +
43.361 + gtk_widget_show_all (main_widget);
43.362 + g_object_ref (main_widget);
43.363 +
43.364 + ui_common = mmyth_uicommon_new (main_widget,
43.365 + "Channels", "Current", "Recording");
43.366 +
43.367 + /* Button signals */
43.368 + // FIXME
43.369 + g_signal_connect (G_OBJECT (ui_common->button1), "clicked",
43.370 + G_CALLBACK (cb_record_button), mmyth_ui);
43.371 + g_signal_connect (G_OBJECT (ui_common->button2), "clicked",
43.372 + G_CALLBACK (cb_record_button), mmyth_ui);
43.373 + g_signal_connect (G_OBJECT (ui_common->button3), "clicked",
43.374 + G_CALLBACK (cb_record_button), mmyth_ui);
43.375 +
43.376 +
43.377 + return ui_common;
43.378 +
43.379 +}
43.380 +
43.381 +/******************************************************************************
43.382 + * ESG GRID VIEW METHODS *
43.383 + *****************************************************************************/
43.384 +
43.385 +static void
43.386 +cb_esg_grid_view_button (GtkButton * button, gpointer user_data)
43.387 +{
43.388 + /* FIXME
43.389 + MMythUi *mmyth_ui = (MMythUi *) user_data;
43.390 + guint32 service_id = -1;
43.391 +
43.392 + // Retrieves the user selected service ID
43.393 + DVBHScheduleEvent *schedule = (DVBHScheduleEvent *) mmyth_esg_grid_view_get_selected_schedule();
43.394 +
43.395 + if(schedule != NULL) {
43.396 + service_id = schedule->service->number;
43.397 + mmyth_play_channel (mmyth_ui, service_id);
43.398 + }
43.399 + */
43.400 +}
43.401 +
43.402 +MMythUiCommon *
43.403 +create_esg_grid_view (MMythUi * mmyth_ui)
43.404 +{
43.405 + MMythUiCommon *ui_common;
43.406 + /* FIXME
43.407 + GtkWidget *esg_grid_view = GTK_WIDGET (esg_grid_view_new (mmyth_ui));
43.408 +
43.409 +
43.410 + ui_common = mmyth_uicommon_new (esg_grid_view,
43.411 + "View", "Remind",
43.412 + "Close");
43.413 + */
43.414 +
43.415 + /* Button signals */
43.416 + g_signal_connect (G_OBJECT (ui_common->button1), "clicked",
43.417 + G_CALLBACK (cb_esg_grid_view_button), mmyth_ui);
43.418 + g_signal_connect (G_OBJECT (ui_common->button2), "clicked",
43.419 + G_CALLBACK (cb_not_impl_button), mmyth_ui);
43.420 + g_signal_connect (G_OBJECT (ui_common->button3), "clicked",
43.421 + G_CALLBACK (cb_close_button), mmyth_ui);
43.422 +
43.423 + return ui_common;
43.424 +}
43.425 +/******************************************************************************
43.426 + * SCHEDULE VIEW METHODS *
43.427 + ******************************************************************************/
43.428 +
43.429 +static void
43.430 +cb_schedule_button (GtkButton * button, gpointer user_data)
43.431 +{
43.432 + MMythUi *mmyth_ui = (MMythUi *) user_data;
43.433 +
43.434 + mmyth_ui_set_widget (mmyth_ui, mmyth_ui->schedule_uicommon);
43.435 + /* FIXME
43.436 + MMythUi *mmyth_ui = (MMythUi *) user_data;
43.437 + guint32 service_id = -1;
43.438 +
43.439 + // Retrieves the user selected service ID
43.440 + DVBHScheduleEvent *schedule = (DVBHScheduleEvent *) mmyth_esg_grid_view_get_selected_schedule();
43.441 +
43.442 + if(schedule != NULL) {
43.443 + service_id = schedule->service->number;
43.444 + mmyth_play_channel (mmyth_ui, service_id);
43.445 + }
43.446 + */
43.447 +}
43.448 +
43.449 +MMythUiCommon *
43.450 +create_schedule_view (MMythUi * mmyth_ui)
43.451 +{
43.452 + MMythUiCommon *ui_common;
43.453 +
43.454 + GtkWidget *schedule_view = GTK_WIDGET (schedule_view_new ());
43.455 + //record_view = gtk_event_box_new();
43.456 +
43.457 +
43.458 + gtk_widget_show_all (schedule_view);
43.459 + g_object_ref (schedule_view);
43.460 +
43.461 + ui_common = mmyth_uicommon_new (schedule_view,
43.462 + "Save", "Clear",
43.463 + "Cancel");
43.464 +
43.465 + //ui->
43.466 +
43.467 + /* Button signals */
43.468 + g_signal_connect (G_OBJECT (ui_common->button1), "clicked",
43.469 + G_CALLBACK (cb_not_impl_button), mmyth_ui);
43.470 + g_signal_connect (G_OBJECT (ui_common->button2), "clicked",
43.471 + G_CALLBACK (cb_not_impl_button), mmyth_ui);
43.472 + g_signal_connect (G_OBJECT (ui_common->button3), "clicked",
43.473 + G_CALLBACK (cb_close_button), mmyth_ui);
43.474 +
43.475 + return ui_common;
43.476 +}
43.477 +/******************************************************************************
43.478 + * RECORD VIEW METHODS *
43.479 + ******************************************************************************/
43.480 +
43.481 +static void
43.482 +cb_record_button (GtkButton * button, gpointer user_data)
43.483 +{
43.484 + MMythUi *mmyth_ui = (MMythUi *) user_data;
43.485 +
43.486 + mmyth_ui_set_widget (mmyth_ui, mmyth_ui->record_uicommon);
43.487 + /* FIXME
43.488 + MMythUi *mmyth_ui = (MMythUi *) user_data;
43.489 + guint32 service_id = -1;
43.490 +
43.491 + // Retrieves the user selected service ID
43.492 + DVBHScheduleEvent *schedule = (DVBHScheduleEvent *) mmyth_esg_grid_view_get_selected_schedule();
43.493 +
43.494 + if(schedule != NULL) {
43.495 + service_id = schedule->service->number;
43.496 + mmyth_play_channel (mmyth_ui, service_id);
43.497 + }
43.498 + */
43.499 +}
43.500 +
43.501 +MMythUiCommon *
43.502 +create_record_view (MMythUi * mmyth_ui)
43.503 +{
43.504 + MMythUiCommon *ui_common;
43.505 +
43.506 + GtkWidget *record_view = GTK_WIDGET (record_view_new ());
43.507 + //record_view = gtk_event_box_new();
43.508 +
43.509 +
43.510 +
43.511 +
43.512 + gtk_widget_show_all (record_view);
43.513 + g_object_ref (record_view);
43.514 +
43.515 + ui_common = mmyth_uicommon_new (record_view,
43.516 + "Play (!)", "Schedule",
43.517 + "Delete(!)");
43.518 +
43.519 + //ui->
43.520 +
43.521 +
43.522 + /* Button signals */
43.523 + g_signal_connect (G_OBJECT (ui_common->button1), "clicked",
43.524 + G_CALLBACK (cb_not_impl_button), mmyth_ui);
43.525 + g_signal_connect (G_OBJECT (ui_common->button2), "clicked",
43.526 + G_CALLBACK (cb_schedule_button), mmyth_ui);
43.527 + g_signal_connect (G_OBJECT (ui_common->button3), "clicked",
43.528 + G_CALLBACK (cb_close_button), mmyth_ui);
43.529 +
43.530 + return ui_common;
43.531 +}
43.532 +/******************************************************************************
43.533 + * GST VIDEO WIDGET METHODS *
43.534 + *****************************************************************************/
43.535 +
43.536 +static void
43.537 +cb_video_close_button (GtkButton * button, gpointer user_data)
43.538 +{
43.539 + MMythUi *mmyth_ui = (MMythUi *) user_data;
43.540 +
43.541 + /* FIXME
43.542 + mmyth_player_stop (mmyth_ui);
43.543 + */
43.544 +
43.545 + mmyth_ui_set_widget (mmyth_ui, mmyth_ui->main_uicommon);
43.546 +}
43.547 +
43.548 +MMythUiCommon *
43.549 +create_video_view (MMythUi * mmyth_ui)
43.550 +{
43.551 +
43.552 + MMythUiCommon *ui_common;
43.553 +
43.554 + /* FIXME
43.555 + mmyth_player_init (mmyth_ui);
43.556 + */
43.557 +
43.558 + ui_common = mmyth_uicommon_new (mmyth_ui->video_alignment,
43.559 + " Full\nScreen", "Other\nServices",
43.560 + "Close");
43.561 +
43.562 + g_signal_connect (G_OBJECT (ui_common->button1), "clicked",
43.563 + G_CALLBACK (cb_not_impl_button), mmyth_ui);
43.564 + g_signal_connect (G_OBJECT (ui_common->button2), "clicked",
43.565 + G_CALLBACK (cb_not_impl_button), mmyth_ui);
43.566 + g_signal_connect (G_OBJECT (ui_common->button3), "clicked",
43.567 + G_CALLBACK (cb_video_close_button), mmyth_ui);
43.568 +
43.569 + return ui_common;
43.570 +}
44.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
44.2 +++ b/gmyth/src/gui/mmyth_ui.h Wed Sep 20 23:45:35 2006 +0100
44.3 @@ -0,0 +1,75 @@
44.4 +#ifndef MMYTH_UI_H_
44.5 +#define MMYTH_UI_H_
44.6 +
44.7 +#include <gtk/gtk.h>
44.8 +#include <gst/gst.h>
44.9 +
44.10 +#include "config.h"
44.11 +
44.12 +#ifdef MAEMO_PLATFORM
44.13 +#include "hildon-widgets/hildon-program.h"
44.14 +#include "hildon-widgets/hildon-window.h"
44.15 +#endif
44.16 +
44.17 +#include "mmyth_uicommon.h"
44.18 +#include "mmyth_recordui.h"
44.19 +#include "mmyth_schedulerui.h"
44.20 +
44.21 +/* GMyth library includes */
44.22 +#include "gmyth_tvplayer.h"
44.23 +
44.24 +typedef struct _MMythUi
44.25 +{
44.26 +
44.27 + /* The main application window */
44.28 + GtkWidget *main_window;
44.29 + MMythUiCommon *current_uicommon;
44.30 +
44.31 + /* Main widget components */
44.32 + GtkWidget *main_hbox;
44.33 + GtkWidget *video_alignment;
44.34 + GdkPixbuf *logo;
44.35 +
44.36 + /* Main widgets grouping */
44.37 + MMythUiCommon *main_uicommon;
44.38 + MMythUiCommon *video_uicommon;
44.39 + MMythUiCommon *epg_grid_uicommon;
44.40 + MMythUiCommon *record_uicommon;
44.41 + MMythUiCommon *schedule_uicommon;
44.42 +
44.43 + GtkWidget *videow;
44.44 + int idle_id;
44.45 + //GstTagList *tagcache;
44.46 +
44.47 + MMythRecordUI *mmyth_recordui;
44.48 + MMythSchedulerUI *mmyth_schedulerui;
44.49 +
44.50 +#ifdef MAEMO_PLATFORM
44.51 + HildonProgram *program;
44.52 + GtkMenu *main_menu;
44.53 + GtkWidget *menu_setup;
44.54 +#endif
44.55 +
44.56 + GMythTVPlayer *tvplayer;
44.57 +
44.58 +} MMythUi;
44.59 +
44.60 +GdkPixbuf *icon_sports, *icon_news, *icon_movies, *icon_shows;
44.61 +GdkColor main_bg_color;
44.62 +
44.63 +void mmyth_set_main_widget (MMythUi * mmyth_ui, MMythUiCommon * new_ui);
44.64 +//void mmyth_play_selected(GtkButton * button, gpointer user_data);
44.65 +
44.66 +#ifdef MAEMO_PLATFORM
44.67 +MMythUi *mmyth_ui_initialize (HildonProgram *program, GtkWidget * main_window);
44.68 +#else
44.69 +MMythUi *mmyth_ui_initialize (GtkWidget * main_window);
44.70 +#endif
44.71 +
44.72 +void mmyth_ui_finalize (MMythUi * mmyth_ui);
44.73 +
44.74 +void mmyth_ui_set_widget (MMythUi * mmyth_ui, MMythUiCommon * new_uicommon);
44.75 +
44.76 +GtkWidget* mmyth_ui_get_video_widget (MMythUi *mmyth_ui);
44.77 +
44.78 +#endif /* MMYTH_UI_H_ */
45.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
45.2 +++ b/gmyth/src/gui/mmyth_uicommon.c Wed Sep 20 23:45:35 2006 +0100
45.3 @@ -0,0 +1,134 @@
45.4 +
45.5 +#include <gtk/gtk.h>
45.6 +#include <glib.h>
45.7 +#include <glib/gprintf.h>
45.8 +
45.9 +#include "mmyth_uicommon.h"
45.10 +#include "mmyth_ui.h"
45.11 +
45.12 +static void
45.13 +refresh_time_on_screen (GtkWidget *label)
45.14 +{
45.15 + time_t real_time;
45.16 + struct tm sched_time;
45.17 + GString *time_showed;
45.18 +
45.19 + time_showed = g_string_new("");
45.20 + time(&real_time);
45.21 +
45.22 + if (localtime_r((time_t *)&real_time, &sched_time) == NULL) {
45.23 + g_error ("localtime_r error in mmyth_epg_grid_view!\n");
45.24 + return NULL;
45.25 + }
45.26 +
45.27 + g_string_printf(time_showed, "%d:%02d:%02d",
45.28 + sched_time.tm_hour,
45.29 + sched_time.tm_min,
45.30 + sched_time.tm_sec);
45.31 +
45.32 + gtk_label_set_text (GTK_LABEL(label), time_showed->str);
45.33 +}
45.34 +
45.35 +MMythUiCommon *
45.36 +mmyth_uicommon_new (GtkWidget * main_widget, const gchar * label1,
45.37 + const gchar * label2, const gchar * label3)
45.38 +{
45.39 +
45.40 + MMythUiCommon *ui_common = g_new0 (MMythUiCommon, 1);
45.41 +
45.42 + if (!main_widget) {
45.43 + g_warning ("MMythUICommon created with a NULL main widget\n");
45.44 + }
45.45 +
45.46 + ui_common->main_widget = main_widget;
45.47 +
45.48 + ui_common->event_box = gtk_event_box_new();
45.49 +
45.50 + /* Vertical box that divides the control area into two (buttons + clock) */
45.51 + ui_common->vbox = gtk_vbox_new (FALSE, 0); /* spacing */
45.52 + gtk_container_set_border_width(GTK_CONTAINER (ui_common->vbox), 4);
45.53 +
45.54 + gtk_container_add (GTK_CONTAINER (ui_common->event_box),
45.55 + ui_common->vbox);
45.56 + gtk_widget_modify_bg(ui_common->event_box, GTK_STATE_NORMAL, &main_bg_color);
45.57 +
45.58 + /* Vertical box that divides the control area into four */
45.59 + ui_common->button_vbox = gtk_vbox_new (TRUE, 0); /* spacing */
45.60 +
45.61 + gtk_container_set_border_width (GTK_CONTAINER (ui_common->button_vbox), 0);
45.62 +
45.63 + /* The button 1 */
45.64 + ui_common->button1 = gtk_button_new_with_label (label1);
45.65 + gtk_widget_modify_bg(ui_common->button1, GTK_STATE_NORMAL, &main_bg_color);
45.66 + gtk_widget_set_size_request (ui_common->button1, BUTTON_WIDTH,
45.67 + BUTTON_HEIGHT);
45.68 +
45.69 + /* The button 2 */
45.70 + ui_common->button2 = gtk_button_new_with_label (label2);
45.71 + gtk_widget_modify_bg(ui_common->button2, GTK_STATE_NORMAL, &main_bg_color);
45.72 + gtk_widget_set_size_request (ui_common->button2, BUTTON_WIDTH,
45.73 + BUTTON_HEIGHT);
45.74 +
45.75 + /* The button 3 */
45.76 + ui_common->button3 = gtk_button_new_with_label (label3);
45.77 + gtk_widget_modify_bg(ui_common->button3, GTK_STATE_NORMAL, &main_bg_color);
45.78 + gtk_widget_set_size_request (ui_common->button3, BUTTON_WIDTH,
45.79 + BUTTON_HEIGHT);
45.80 +
45.81 + /* The clock label */
45.82 + ui_common->label = gtk_label_new ("Starting...");
45.83 + gtk_widget_show (ui_common->label);
45.84 + ui_common->source_id = g_timeout_add(500, (GSourceFunc) refresh_time_on_screen, ui_common->label);
45.85 +
45.86 + /* Packing components */
45.87 + gtk_box_pack_start (GTK_BOX (ui_common->vbox),
45.88 + ui_common->button_vbox, TRUE, TRUE, 0);
45.89 +
45.90 + gtk_box_pack_start (GTK_BOX (ui_common->vbox),
45.91 + ui_common->label, FALSE, FALSE, 0);
45.92 +
45.93 + gtk_box_pack_start (GTK_BOX (ui_common->button_vbox),
45.94 + ui_common->button1, FALSE, FALSE, 0);
45.95 +
45.96 + gtk_box_pack_start (GTK_BOX (ui_common->button_vbox),
45.97 + ui_common->button2, FALSE, FALSE, 0);
45.98 +
45.99 + gtk_box_pack_start (GTK_BOX (ui_common->button_vbox),
45.100 + ui_common->button3, FALSE, FALSE, 0);
45.101 +
45.102 + gtk_widget_show_all (ui_common->event_box);
45.103 +
45.104 + /* FIXME: mmyth_ui->video_alignment == NULL when mmyth_player_init fails */
45.105 + if(ui_common->main_widget != NULL)
45.106 + g_object_ref (ui_common->main_widget);
45.107 +
45.108 + g_object_ref (ui_common->vbox);
45.109 + g_object_ref (ui_common->button_vbox);
45.110 + g_object_ref (ui_common->label);
45.111 + g_object_ref (ui_common->button1);
45.112 + g_object_ref (ui_common->button2);
45.113 + g_object_ref (ui_common->button3);
45.114 + g_object_ref (ui_common->event_box);
45.115 + return ui_common;
45.116 +}
45.117 +
45.118 +void
45.119 +mmyth_uicommon_free (MMythUiCommon *ui_common)
45.120 +{
45.121 + g_debug ("[%s] Clean uicommon used memory", __FUNCTION__);
45.122 +
45.123 + g_source_remove (ui_common->source_id);
45.124 +
45.125 + g_object_unref (ui_common->main_widget);
45.126 + g_object_unref (ui_common->vbox);
45.127 + g_object_unref (ui_common->button_vbox);
45.128 + g_object_unref (ui_common->label);
45.129 + g_object_unref (ui_common->button1);
45.130 + g_object_unref (ui_common->button2);
45.131 + g_object_unref (ui_common->button3);
45.132 + g_object_unref (ui_common->event_box);
45.133 +
45.134 + g_free (ui_common);
45.135 +}
45.136 +
45.137 +
46.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
46.2 +++ b/gmyth/src/gui/mmyth_uicommon.h Wed Sep 20 23:45:35 2006 +0100
46.3 @@ -0,0 +1,51 @@
46.4 +#ifndef MMYTH_UICOMMON_H_
46.5 +#define MMYTH_UICOMMON_H_
46.6 +
46.7 +#include "config.h"
46.8 +
46.9 +#include <gtk/gtk.h>
46.10 +#include <glib.h>
46.11 +
46.12 +#ifndef MAEMO_PLATFORM
46.13 +#define BUTTON_HEIGHT 50
46.14 +#define BUTTON_WIDTH 100
46.15 +#else
46.16 +#define BUTTON_HEIGHT 80
46.17 +#define BUTTON_WIDTH 150
46.18 +#endif
46.19 +
46.20 +#define MAIN_WINDOW_WIDTH 550
46.21 +#define MAIN_WINDOW_HEIGHT 250
46.22 +
46.23 +#define CHANNELS_DIALOG_WIDTH 300
46.24 +#define CHANNELS_DIALOG_HEIGHT 200
46.25 +
46.26 +#define SETTINGS_DIALOG_WIDTH 300
46.27 +#define SETTINGS_DIALOG_HEIGHT 120
46.28 +
46.29 +extern GdkColor main_bg_color;
46.30 +
46.31 +typedef struct _MMythUiCommon
46.32 +{
46.33 + GtkWidget *main_widget;
46.34 +
46.35 + /* event box to set the background color*/
46.36 + GtkWidget *event_box;
46.37 +
46.38 + GtkWidget *vbox;
46.39 + GtkWidget *button_vbox;
46.40 + GtkWidget *label;
46.41 +
46.42 + GtkWidget *button1;
46.43 + GtkWidget *button2;
46.44 + GtkWidget *button3;
46.45 +
46.46 + gint source_id;
46.47 +} MMythUiCommon;
46.48 +
46.49 +MMythUiCommon *mmyth_uicommon_new (GtkWidget * main_widget,
46.50 + const gchar * label1, const gchar * label2,
46.51 + const gchar * label3);
46.52 +void mmyth_uicommon_free (MMythUiCommon *ui_common);
46.53 +
46.54 +#endif /* MMYTH_UICOMMON_H_ */
47.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
47.2 +++ b/gmyth/src/gui/mmyth_uisettings.c Wed Sep 20 23:45:35 2006 +0100
47.3 @@ -0,0 +1,169 @@
47.4 +#include<gtk/gtk.h>
47.5 +#include<glib.h>
47.6 +#include <sys/types.h>
47.7 +#include <sys/stat.h>
47.8 +#include <unistd.h>
47.9 +#include <string.h>
47.10 +#include <stdio.h>
47.11 +#include <stdlib.h>
47.12 +
47.13 +#include "mmyth_uisettings.h"
47.14 +
47.15 +#include "gmyth_context.h"
47.16 +
47.17 +static GtkWidget *settings_dialog;
47.18 +static GtkWidget *entry_hostname;
47.19 +static GtkWidget *entry_dbname;
47.20 +static GtkWidget *entry_username;
47.21 +static GtkWidget *entry_passwd;
47.22 +static GtkWidget *entry_port;
47.23 +
47.24 +static void settings_dialog_update_data (void);
47.25 +static GtkWidget* add_entry_to_table (GtkWidget *table, GString *init_str,
47.26 + guint pos_left, guint pos_right, guint pos_top, guint pos_bottom);
47.27 +static GtkWidget* add_label_to_table (GtkWidget *table, const gchar *str,
47.28 + guint pos_left, guint pos_right, guint pos_top, guint pos_bottom);
47.29 +
47.30 +
47.31 +gboolean
47.32 +mmyth_uisettings_run (GtkWindow *main_window)
47.33 +{
47.34 +
47.35 + GtkWidget *settings_table;
47.36 + GtkWidget *label_hostname, *label_dbname;
47.37 + GtkWidget *label_username, *label_passwd, *label_port;
47.38 +
47.39 + GMythSettings *msettings = gmyth_context_get_settings();
47.40 +
47.41 + settings_dialog = gtk_dialog_new_with_buttons ("Settings",
47.42 + main_window,
47.43 + GTK_DIALOG_DESTROY_WITH_PARENT,
47.44 + GTK_STOCK_OK,
47.45 + GTK_RESPONSE_ACCEPT,
47.46 + GTK_STOCK_CANCEL,
47.47 + GTK_RESPONSE_REJECT,
47.48 + NULL);
47.49 +
47.50 + gtk_widget_set_size_request (settings_dialog, 400, 244);
47.51 +
47.52 +/* scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL);
47.53 + gtk_widget_show (scrolledwindow1);
47.54 + gtk_container_add (GTK_CONTAINER (window1), scrolledwindow1);
47.55 + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow1), GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER);
47.56 +
47.57 + viewport1 = gtk_viewport_new (NULL, NULL);
47.58 + gtk_widget_show (viewport1);
47.59 + gtk_container_add (GTK_CONTAINER (scrolledwindow1), viewport1);
47.60 + gtk_viewport_set_shadow_type (GTK_VIEWPORT (viewport1), GTK_SHADOW_NONE);
47.61 +*/
47.62 +
47.63 + // Creates the table and attach it to the settings dialog
47.64 + settings_table = gtk_table_new (5, 2, FALSE);
47.65 + gtk_widget_show (settings_table);
47.66 + gtk_box_pack_start (GTK_BOX (GTK_DIALOG(settings_dialog)->vbox), settings_table, FALSE, TRUE, 0);
47.67 + gtk_container_set_border_width (GTK_CONTAINER (settings_table), 3);
47.68 + gtk_table_set_row_spacings (GTK_TABLE (settings_table), 5);
47.69 + gtk_table_set_col_spacings (GTK_TABLE (settings_table), 10);
47.70 +
47.71 + label_hostname = add_label_to_table (settings_table, "Host Name:", 0, 1, 0, 1);
47.72 + label_dbname = add_label_to_table (settings_table, "Database Name:", 0, 1, 1, 2);
47.73 + label_username = add_label_to_table (settings_table, "Username:", 0, 1, 2, 3);
47.74 + label_passwd = add_label_to_table (settings_table, "Password:", 0, 1, 3, 4);
47.75 + label_port = add_label_to_table (settings_table, "Server port:", 0, 1, 4, 5);
47.76 +
47.77 + entry_hostname = add_entry_to_table (settings_table,
47.78 + gmyth_settings_get_backend_hostname (msettings),
47.79 + 1, 2, 0, 1);
47.80 + entry_dbname = add_entry_to_table (settings_table,
47.81 + gmyth_settings_get_dbname (msettings),
47.82 + 1, 2, 1, 2 );
47.83 + entry_username = add_entry_to_table (settings_table,
47.84 + gmyth_settings_get_username (msettings),
47.85 + 1, 2, 2, 3 );
47.86 + entry_passwd = add_entry_to_table (settings_table,
47.87 + gmyth_settings_get_password (msettings),
47.88 + 1, 2, 3, 4 );
47.89 +
47.90 + GString *str_port = g_string_new ("");
47.91 + g_string_printf (str_port, "%d",
47.92 + gmyth_settings_get_backend_port (msettings));
47.93 + entry_port = add_entry_to_table (settings_table, str_port,
47.94 + 1, 2, 4, 5 );
47.95 + g_string_free (str_port, TRUE);
47.96 +
47.97 + if (gtk_dialog_run (GTK_DIALOG (settings_dialog)) == GTK_RESPONSE_ACCEPT) {
47.98 + settings_dialog_update_data ();
47.99 + gtk_widget_destroy (settings_dialog);
47.100 + return TRUE;
47.101 + }
47.102 +
47.103 + gtk_widget_destroy (settings_dialog);
47.104 +
47.105 + return FALSE;
47.106 +
47.107 +}
47.108 +
47.109 +static GtkWidget*
47.110 +add_label_to_table (GtkWidget *table, const gchar *str, guint pos_left, guint pos_right,
47.111 + guint pos_top, guint pos_bottom )
47.112 +{
47.113 + GtkWidget *tmp_label = gtk_label_new (str);
47.114 +
47.115 + gtk_widget_show (tmp_label);
47.116 + gtk_table_attach (GTK_TABLE (table), tmp_label,
47.117 + pos_left, pos_right, pos_top, pos_bottom,
47.118 + (GtkAttachOptions) (GTK_FILL),
47.119 + (GtkAttachOptions) (0), 0, 0);
47.120 + gtk_misc_set_alignment (GTK_MISC (tmp_label), 0, 0.5);
47.121 +
47.122 + return tmp_label;
47.123 +}
47.124 +
47.125 +static GtkWidget*
47.126 +add_entry_to_table (GtkWidget *table, GString *init_str, guint pos_left, guint pos_right,
47.127 + guint pos_top, guint pos_bottom)
47.128 +{
47.129 + GtkWidget *tmp_entry = gtk_entry_new ();
47.130 + gtk_widget_show (tmp_entry);
47.131 + gtk_table_attach (GTK_TABLE (table), tmp_entry,
47.132 + pos_left, pos_right, pos_top, pos_bottom,
47.133 + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
47.134 + (GtkAttachOptions) (0), 0, 0);
47.135 + if (init_str)
47.136 + gtk_entry_set_text (GTK_ENTRY (tmp_entry), (init_str->str));
47.137 +
47.138 + //gtk_entry_set_invisible_char (GTK_ENTRY (entry_port), 9679);
47.139 +
47.140 + return tmp_entry;
47.141 +}
47.142 +
47.143 +static void
47.144 +settings_dialog_update_data (void)
47.145 +{
47.146 + GString *tmp_entry_text;
47.147 + GMythSettings *msettings = gmyth_context_get_settings();
47.148 +
47.149 + if (!msettings) {
47.150 + g_warning ("[%s] Could not get GMythSettings instance from context\n", __FUNCTION__);
47.151 + return;
47.152 + }
47.153 +
47.154 + tmp_entry_text = g_string_new("");
47.155 + g_string_printf(tmp_entry_text, "%s", gtk_entry_get_text( GTK_ENTRY(entry_hostname)));
47.156 + gmyth_settings_set_backend_hostname(msettings, tmp_entry_text);
47.157 +
47.158 + g_string_printf(tmp_entry_text, "%s", gtk_entry_get_text( GTK_ENTRY(entry_dbname)));
47.159 + gmyth_settings_set_dbname(msettings, tmp_entry_text);
47.160 +
47.161 + g_string_printf(tmp_entry_text, "%s", gtk_entry_get_text( GTK_ENTRY(entry_username)));
47.162 + gmyth_settings_set_username(msettings, tmp_entry_text);
47.163 +
47.164 + g_string_printf(tmp_entry_text, "%s", gtk_entry_get_text( GTK_ENTRY(entry_passwd)));
47.165 + gmyth_settings_set_password(msettings, tmp_entry_text);
47.166 +
47.167 + g_string_printf(tmp_entry_text, "%s", gtk_entry_get_text( GTK_ENTRY(entry_port)));
47.168 + gmyth_settings_set_backend_port(msettings, atoi(tmp_entry_text->str));
47.169 +
47.170 + gmyth_settings_save (msettings);
47.171 +
47.172 +}
48.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
48.2 +++ b/gmyth/src/gui/mmyth_uisettings.h Wed Sep 20 23:45:35 2006 +0100
48.3 @@ -0,0 +1,6 @@
48.4 +#ifndef MMYTH_SETTINGS_H_
48.5 +#define MMYTH_SETTINGS_H_
48.6 +
48.7 +gboolean mmyth_uisettings_run (GtkWindow *main_window);
48.8 +
48.9 +#endif /*MMYTH_SETTINGS_H_*/
49.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
49.2 +++ b/gmyth/src/gui/mmyth_videoplayer.c Wed Sep 20 23:45:35 2006 +0100
49.3 @@ -0,0 +1,369 @@
49.4 +
49.5 +#include <gst/gst.h>
49.6 +#include <gtk/gtk.h>
49.7 +#include <gdk/gdkx.h>
49.8 +#include <gst/interfaces/xoverlay.h>
49.9 +#include <unistd.h>
49.10 +
49.11 +#include "mmyth_ui.h"
49.12 +#include "mmyth_videoplayer.h"
49.13 +#include "mmyth_sdpreader.h"
49.14 +
49.15 +#include "esg_database.h"
49.16 +
49.17 +#include "ipd_demux.h"
49.18 +#include "ipd_network.h"
49.19 +
49.20 +#ifdef INDT_IP_DECAPSULATOR
49.21 +#include <sys/types.h>
49.22 +#include <signal.h>
49.23 +#endif
49.24 +
49.25 +/* Global flag/semaphore to control IP decapsulator threads */
49.26 +gboolean state_keep_running = 0;
49.27 +
49.28 +
49.29 +typedef struct _GstPlayerWindowStateChange
49.30 +{
49.31 + GstElement *play;
49.32 + GstState old_state, new_state;
49.33 + MMythUi *mmyth_ui;
49.34 +} GstPlayerWindowStateChange;
49.35 +
49.36 +typedef struct _GstPlayerWindowTagFound
49.37 +{
49.38 + GstElement *play;
49.39 + GstTagList *taglist;
49.40 + MMythUi *mmyth_ui;
49.41 +} GstPlayerWindowTagFound;
49.42 +
49.43 +
49.44 +GstElement *gst_pipeline, *gst_decoder, *gst_videosink;
49.45 +
49.46 +static gboolean idle_state (gpointer data);
49.47 +
49.48 +static gboolean
49.49 +bus_call (GstBus * bus, GstMessage * msg, gpointer data)
49.50 +{
49.51 + MMythUi *mmyth_ui = (MMythUi *) data;
49.52 + GMainLoop *loop = mmyth_ui->loop;
49.53 +
49.54 + switch (GST_MESSAGE_TYPE (msg)) {
49.55 + case GST_MESSAGE_EOS:
49.56 +
49.57 + if (mmyth_ui->idle_id != 0) {
49.58 + g_source_remove (mmyth_ui->idle_id);
49.59 + mmyth_ui->idle_id = 0;
49.60 + }
49.61 +
49.62 + //g_idle_add ((GSourceFunc) idle_eos, data);
49.63 + gst_element_set_state (GST_ELEMENT (GST_MESSAGE_SRC (msg)),
49.64 + GST_STATE_READY);
49.65 + break;
49.66 + case GST_MESSAGE_ERROR:{
49.67 + gchar *debug;
49.68 + GError *err;
49.69 +
49.70 + gst_message_parse_error (msg, &err, &debug);
49.71 + g_free (debug);
49.72 +
49.73 + printf ("Error: %s\n", err->message);
49.74 + g_error_free (err);
49.75 +
49.76 + g_main_loop_quit (loop);
49.77 + }
49.78 + break;
49.79 + case GST_MESSAGE_STATE_CHANGED:{
49.80 + GstState oldstate;
49.81 + GstState newstate;
49.82 + GstState pending;
49.83 + GstPlayerWindowStateChange *st =
49.84 + g_new (GstPlayerWindowStateChange, 1);
49.85 +
49.86 + gst_message_parse_state_changed (msg,
49.87 + &oldstate,
49.88 + &newstate, &pending);
49.89 +
49.90 + st->play = mmyth_ui->play;
49.91 + gst_object_ref (GST_OBJECT (mmyth_ui->play));
49.92 + st->old_state = oldstate;
49.93 + st->new_state = newstate;
49.94 +
49.95 + st->mmyth_ui = mmyth_ui;
49.96 +
49.97 + /* State debug messages */
49.98 + printf ("oldstate = %s, newstate = %s, pendingstate = %s\n",
49.99 + gst_element_state_get_name (oldstate),
49.100 + gst_element_state_get_name (newstate),
49.101 + gst_element_state_get_name (pending));
49.102 +
49.103 + g_idle_add ((GSourceFunc) idle_state, st);
49.104 +
49.105 + }
49.106 + break;
49.107 + default:
49.108 + printf (gst_message_type_get_name (GST_MESSAGE_TYPE (msg)));
49.109 + printf ("\n");
49.110 + break;
49.111 + }
49.112 +
49.113 + return TRUE;
49.114 +}
49.115 +
49.116 +
49.117 +static gboolean
49.118 +cb_iterate (gpointer data)
49.119 +{
49.120 + MMythUi *mmyth_ui = (MMythUi *) data;
49.121 + //gboolean res;
49.122 +
49.123 + g_main_loop_run (mmyth_ui->loop);
49.124 +/*
49.125 + if (!GST_FLAG_IS_SET (mmyth_ui->play, GST_BIN_SELF_SCHEDULABLE)) {
49.126 + res = gst_bin_iterate (GST_BIN (mmyth_ui->play));
49.127 + } else {
49.128 + g_usleep (100);
49.129 + res = (gst_element_get_state (mmyth_ui->play) == GST_STATE_PLAYING);
49.130 + }
49.131 +
49.132 + if (!res)
49.133 + mmyth_ui->idle_id = 0;
49.134 +
49.135 + return res;
49.136 +*/
49.137 + return FALSE;
49.138 +
49.139 +}
49.140 +
49.141 +static gboolean
49.142 +idle_state (gpointer data)
49.143 +{
49.144 + GstPlayerWindowStateChange *st = data;
49.145 +
49.146 + if (st->old_state == GST_STATE_PLAYING) {
49.147 + if (st->mmyth_ui->idle_id != 0) {
49.148 + g_source_remove (st->mmyth_ui->idle_id);
49.149 + st->mmyth_ui->idle_id = 0;
49.150 + }
49.151 + }
49.152 + else if (st->new_state == GST_STATE_PLAYING) {
49.153 + if (st->mmyth_ui->idle_id != 0)
49.154 + g_source_remove (st->mmyth_ui->idle_id);
49.155 +
49.156 + st->mmyth_ui->idle_id = g_idle_add (cb_iterate, st->mmyth_ui);
49.157 + }
49.158 +
49.159 + /* new movie loaded? */
49.160 + if (st->old_state == GST_STATE_READY && st->new_state > GST_STATE_READY) {
49.161 +
49.162 + /* gboolean have_video = FALSE; */
49.163 +
49.164 + gtk_widget_show (st->mmyth_ui->videow);
49.165 +
49.166 + gtk_window_resize (GTK_WINDOW (st->mmyth_ui->main_window), 1, 1);
49.167 +
49.168 + }
49.169 +
49.170 + /* discarded movie? */
49.171 + if (st->old_state > GST_STATE_READY && st->new_state == GST_STATE_READY) {
49.172 +
49.173 + if (st->mmyth_ui->tagcache) {
49.174 + gst_tag_list_free (st->mmyth_ui->tagcache);
49.175 + st->mmyth_ui->tagcache = NULL;
49.176 + }
49.177 + }
49.178 +
49.179 + gst_object_unref (GST_OBJECT (st->play));
49.180 + //g_object_unref (G_OBJECT (st->win));
49.181 + g_free (st);
49.182 +
49.183 + /* once */
49.184 + return FALSE;
49.185 +}
49.186 +
49.187 +
49.188 +
49.189 +static gboolean
49.190 +expose (GtkWidget * widget, GdkEventExpose * event, gpointer user_data)
49.191 +{
49.192 + MMythUi *mmyth_ui = (MMythUi *) user_data;
49.193 +
49.194 + gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (mmyth_ui->videosink),
49.195 + GDK_WINDOW_XWINDOW (mmyth_ui->videow->
49.196 + window));
49.197 + return TRUE;
49.198 +}
49.199 +
49.200 +
49.201 +void
49.202 +mmyth_player_init (MMythUi * mmyth_ui)
49.203 +{
49.204 + GstElement *play;
49.205 + GstElement *source, *parser, *decoder, *videosink;
49.206 +
49.207 + play = gst_pipeline_new ("video-player");
49.208 + source = gst_element_factory_make ("udpsrc", "file-source");
49.209 + parser = gst_element_factory_make ("rtph263pdepay", "rtp-demux");
49.210 + decoder = gst_element_factory_make ("ffdec_h263", "mpeg-decoder");
49.211 + videosink = gst_element_factory_make ("xvimagesink", "image-output");
49.212 + gst_pipeline = play;
49.213 + gst_decoder = decoder;
49.214 + gst_videosink = videosink;
49.215 +
49.216 + if (!(gst_pipeline && source && parser && decoder && videosink)) {
49.217 + /* FIXME: hanlde the error correctly */
49.218 + /* video_alignment is not being created (below)
49.219 + and is causing problems to the ui */
49.220 + g_print ("GstElement creation error!\n");
49.221 + return;
49.222 + }
49.223 +
49.224 + g_object_set (G_OBJECT (videosink), "sync", FALSE, NULL);
49.225 +
49.226 + gst_bus_add_watch (gst_pipeline_get_bus (GST_PIPELINE (gst_pipeline)),
49.227 + bus_call, mmyth_ui);
49.228 +
49.229 + gst_bin_add_many (GST_BIN (gst_pipeline), source, parser, decoder,
49.230 + videosink, NULL);
49.231 +
49.232 + {
49.233 + GstCaps *rtpcaps = gst_caps_new_simple ("application/x-rtp", NULL);
49.234 + gst_element_link_filtered(source, parser, rtpcaps);
49.235 + }
49.236 +
49.237 + gst_element_link_many (/*source,*/ parser, decoder, videosink, NULL);
49.238 +
49.239 + /* actual window */
49.240 + mmyth_ui->play = play;
49.241 + mmyth_ui->videosink = videosink;
49.242 + mmyth_ui->udpsource = source;
49.243 +
49.244 + g_object_ref (mmyth_ui->play);
49.245 + g_object_ref (mmyth_ui->videosink);
49.246 +
49.247 + /* video widget */
49.248 + //mmyth_ui->videow = gst_player_video_new (videosink, play);
49.249 + mmyth_ui->videow = gtk_drawing_area_new ();
49.250 + gtk_widget_set_size_request (mmyth_ui->videow, 300, 240);
49.251 +
49.252 + mmyth_ui->logo = gdk_pixbuf_new_from_file ("logo.png", NULL);
49.253 +
49.254 +
49.255 + mmyth_ui->video_alignment = gtk_alignment_new (0.5, 0.5, 0, 0);
49.256 + gtk_widget_hide (mmyth_ui->video_alignment);
49.257 +
49.258 + gtk_container_add (GTK_CONTAINER (mmyth_ui->video_alignment),
49.259 + mmyth_ui->videow);
49.260 +
49.261 + g_signal_connect (mmyth_ui->videow, "expose-event", G_CALLBACK (expose),
49.262 + mmyth_ui);
49.263 + //g_signal_connect(mmyth_ui->videow, "size_request", G_CALLBACK(cb_preferred_video_size), mmyth_ui);
49.264 +
49.265 +
49.266 + g_object_ref (mmyth_ui->videow);
49.267 + g_object_ref (mmyth_ui->video_alignment);
49.268 +
49.269 + //gnome_app_set_contents (app, videow);
49.270 + //gtk_widget_show (mmyth_ui->videow);
49.271 +
49.272 +//fail:
49.273 +// gst_object_unref (GST_OBJECT (play));
49.274 +// return NULL;
49.275 +
49.276 +}
49.277 +
49.278 +void
49.279 +mmyth_player_stop (MMythUi * mmyth_ui)
49.280 +{
49.281 + gst_element_set_state (mmyth_ui->play, GST_STATE_NULL);
49.282 +
49.283 + if(mmyth_ui->videow != NULL)
49.284 + gtk_widget_hide (mmyth_ui->videow);
49.285 +
49.286 + /* Disable IP Decapsulator playing threads */
49.287 + state_keep_running = FALSE;
49.288 +
49.289 +}
49.290 +
49.291 +static gboolean
49.292 +idle_play (gpointer data)
49.293 +{
49.294 + MMythUi *mmyth_ui = (MMythUi *) data;
49.295 +
49.296 + sleep (2);
49.297 +
49.298 + gst_element_set_state (mmyth_ui->play, GST_STATE_PLAYING);
49.299 +
49.300 + return FALSE;
49.301 +}
49.302 +
49.303 +
49.304 +/* Run IP decapsulator play function in a new thread. The thread is finished setting the
49.305 + * semaphore "state_keep_running" to FALSE*/
49.306 +gpointer
49.307 +run_ipd(gpointer data)
49.308 +{
49.309 + GString *ip_addr = (GString*) data;
49.310 +
49.311 + state_keep_running = TRUE;
49.312 +
49.313 + printf("Inside thread\n");
49.314 +
49.315 + ipd_mpe_play_section (ip_addr->str, &state_keep_running);
49.316 +
49.317 + return 0;
49.318 +}
49.319 +
49.320 +void
49.321 +mmyth_play_channel (MMythUi * mmyth_ui, gint service_number)
49.322 +{
49.323 + ESGDatabase *esg_db;
49.324 + DVBHService *service;
49.325 + SDPData sdp_data;
49.326 + GString *service_ip_addr;
49.327 +
49.328 + /* First verifies if there is a tuned network */
49.329 + if ( !ipd_network_is_tuned() ) {
49.330 + /* FIXME: show alert and handle this error */
49.331 + g_warning ("Play not possible, network not tuned");
49.332 + return;
49.333 + }
49.334 +
49.335 + esg_db = esg_database_get_instance();
49.336 + /* Gets the service structure */
49.337 + service = (DVBHService *) esg_database_get_service_from_number
49.338 + (esg_db, service_number);
49.339 +
49.340 + /* Verifies if sdp fragment exists to this service */
49.341 + if ( service->sdp_file == NULL ) {
49.342 + /* FIXME: Implement error handling */
49.343 + g_warning ("SDP fragment not available to access service");
49.344 + return;
49.345 + }
49.346 +
49.347 + /* Parses the sdp to get ipv6 address and port */
49.348 + mmyth_sdp_parse_file (service->sdp_file->str, &sdp_data);
49.349 +
49.350 + /* Sets the gstreamer properties acording to the service access address */
49.351 + /* FIXME: Develop sdp_bin in gstreamer to give sdp file as pipeline config */
49.352 + g_object_set (G_OBJECT (mmyth_ui->udpsource), "multicast_group",
49.353 + sdp_data.ip_addr->str, NULL);
49.354 + g_object_set (G_OBJECT (mmyth_ui->udpsource), "port", sdp_data.video_port, NULL);
49.355 +
49.356 + /* Shows the video widget on screen */
49.357 + mmyth_ui_set_widget (mmyth_ui, mmyth_ui->video_uicommon);
49.358 +
49.359 + gtk_widget_show (mmyth_ui->videow);
49.360 + gtk_widget_queue_draw (mmyth_ui->videow);
49.361 +
49.362 +#ifdef INDT_IP_DECAPSULATOR
49.363 + /* Will be dealocated in run_ipd */
49.364 + service_ip_addr = g_string_new (sdp_data.ip_addr->str);
49.365 +
49.366 + /* Requests the IP decapsulator to play the channel stream*/
49.367 + g_thread_create (run_ipd, (gpointer) service_ip_addr, FALSE, NULL);
49.368 +#endif
49.369 +
49.370 + //gst_element_set_state (mmyth_ui->play, GST_STATE_PLAYING);
49.371 + g_idle_add (idle_play, mmyth_ui);
49.372 +}
50.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
50.2 +++ b/gmyth/src/gui/mmyth_videoplayer.h Wed Sep 20 23:45:35 2006 +0100
50.3 @@ -0,0 +1,12 @@
50.4 +#ifndef MMYTH_VIDEOPLAYER_H_
50.5 +#define MMYTH_VIDEOPLAYER_H_
50.6 +
50.7 +#include "mmyth_ui.h"
50.8 +
50.9 +void mmyth_player_init (MMythUi * mmyth_ui);
50.10 +void mmyth_player_stop (MMythUi * mmyth_ui);
50.11 +
50.12 +void mmyth_play_channel (MMythUi * mmyth_ui, gint service_id);
50.13 +
50.14 +
50.15 +#endif /* MMYTH_VIDEOPLAYER_H_ */
51.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
51.2 +++ b/gmyth/src/libgmyth/Makefile.am Wed Sep 20 23:45:35 2006 +0100
51.3 @@ -0,0 +1,59 @@
51.4 +SUBDIRS = .
51.5 +
51.6 +lib_LTLIBRARIES = libgmyth.la
51.7 +
51.8 +libgmyth_la_SOURCES = \
51.9 + gmyth_common.c \
51.10 + gmyth_context.c \
51.11 + gmyth_epg.c \
51.12 + gmyth_remote_encoder.c \
51.13 + gmyth_remote_util.c \
51.14 + gmyth_settings.c \
51.15 + gmyth_tvchain.c \
51.16 + gmyth_tvplayer.c \
51.17 + gmyth_scheduler.c \
51.18 + gmyth_util.c \
51.19 + gmyth_query.c \
51.20 + gmyth_socket.c \
51.21 + gmyth_stringlist.c
51.22 +
51.23 +libgmyth_la_CFLAGS = \
51.24 + -DDATADIR=\"$(pkgdatadir)\" \
51.25 + $(GLIB_CFLAGS) \
51.26 + $(GTK_CFLAGS) \
51.27 + $(GOBJECT_CFLAGS) \
51.28 + $(GST_CFLAGS) \
51.29 + $(GSTBASE_CFLAGS) \
51.30 + $(MYSQL_CFLAGS) \
51.31 + -g3 -O0
51.32 +
51.33 +#libgmyth_la_LIBADD = \
51.34 +# $(MYSQL_LIBS)
51.35 +
51.36 +libgmyth_la_LDFLAGS = \
51.37 + -export-dynamic \
51.38 + -lgstinterfaces-0.10 \
51.39 + $(MYSQL_LIBS) \
51.40 + $(GST_LIBS) \
51.41 + $(GSTBASE_LIBS)
51.42 +
51.43 +libgmyth_includedir = \
51.44 + $(pkgincludedir)
51.45 +
51.46 +libgmyth_include_HEADERS = \
51.47 + gmyth_common.h \
51.48 + gmyth_context.h \
51.49 + gmyth_epg.h \
51.50 + gmyth_remote_encoder.h \
51.51 + gmyth_scheduler.h \
51.52 + gmyth_settings.h \
51.53 + gmyth_tvchain.h \
51.54 + gmyth_tvplayer.h \
51.55 + gmyth_util.h \
51.56 + gmyth_query.h \
51.57 + gmyth_socket.h \
51.58 + gmyth_remote_util.h \
51.59 + gmyth_stringlist.h
51.60 +
51.61 +CLEANFILES = $(BUILT_SOURCES)
51.62 +
52.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
52.2 +++ b/gmyth/src/libgmyth/gmyth_common.c Wed Sep 20 23:45:35 2006 +0100
52.3 @@ -0,0 +1,85 @@
52.4 +/**
52.5 + * GMyth Library
52.6 + *
52.7 + * @file gmyth/gmyth_common.c
52.8 + *
52.9 + * @brief <p> This file contains basic common functions for the gmyth library.
52.10 + *
52.11 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
52.12 + * @author Leonardo Sobral Cunha <leonardo.cunha@indt.org.br>
52.13 + *
52.14 + *//*
52.15 + *
52.16 + * This program is free software; you can redistribute it and/or modify
52.17 + * it under the terms of the GNU Lesser General Public License as published by
52.18 + * the Free Software Foundation; either version 2 of the License, or
52.19 + * (at your option) any later version.
52.20 + *
52.21 + * This program is distributed in the hope that it will be useful,
52.22 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
52.23 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
52.24 + * GNU General Public License for more details.
52.25 + *
52.26 + * You should have received a copy of the GNU Lesser General Public License
52.27 + * along with this program; if not, write to the Free Software
52.28 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
52.29 + */
52.30 +
52.31 +#include "gmyth_common.h"
52.32 +
52.33 +static void free_channel_data(gpointer data, gpointer user_data);
52.34 +static void free_program_data(gpointer data, gpointer user_data);
52.35 +
52.36 +/** Frees the memory allocated to the GMythChannelInfo objects inside list.
52.37 + * The list memory is also released by g_list_free(). If LIST is NULL it
52.38 + * simply returns.
52.39 + *
52.40 + * @param list the GList containing a list of GMythChannelInfo to free.
52.41 + */
52.42 +void
52.43 +gmyth_free_channel_list(GList *list)
52.44 +{
52.45 + if (list == NULL) {
52.46 + g_warning ("%s received null GList as parameter", __FUNCTION__);
52.47 + return;
52.48 + }
52.49 +
52.50 + g_list_foreach (list, free_channel_data, NULL);
52.51 +
52.52 + g_list_free (list);
52.53 +}
52.54 +
52.55 +/** Frees the memory allocated to the GMythProgramInfo objects inside list.
52.56 + * The list memory is also released by g_list_free(). If list is NULL it
52.57 + * simply returns.
52.58 + *
52.59 + * @param list the GList containing a list of GMythProgramInfo to free.
52.60 + */
52.61 +void
52.62 +gmyth_free_program_list(GList *list)
52.63 +{
52.64 + if (list == NULL) {
52.65 + g_warning ("%s received null GList as parameter", __FUNCTION__);
52.66 + return;
52.67 + }
52.68 +
52.69 + g_list_foreach (list, free_program_data, NULL);
52.70 +
52.71 + g_list_free (list);
52.72 +}
52.73 +
52.74 +
52.75 +static void
52.76 +free_channel_data(gpointer data, gpointer user_data)
52.77 +{
52.78 + if(data)
52.79 + g_free((GMythChannelInfo*) data);
52.80 +}
52.81 +
52.82 +static void
52.83 +free_program_data(gpointer data, gpointer user_data)
52.84 +{
52.85 + if(data)
52.86 + g_free((GMythProgramInfo*) data);
52.87 +}
52.88 +
53.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
53.2 +++ b/gmyth/src/libgmyth/gmyth_common.h Wed Sep 20 23:45:35 2006 +0100
53.3 @@ -0,0 +1,155 @@
53.4 +/**
53.5 + * GMyth Library
53.6 + *
53.7 + * @file gmyth/gmyth_common.h
53.8 + *
53.9 + * @brief <p> This file contains basic common functions for the gmyth library.
53.10 + *
53.11 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
53.12 + * @author Leonardo Sobral Cunha <leonardo.cunha@indt.org.br>
53.13 + *
53.14 + *//*
53.15 + *
53.16 + * This program is free software; you can redistribute it and/or modify
53.17 + * it under the terms of the GNU Lesser General Public License as published by
53.18 + * the Free Software Foundation; either version 2 of the License, or
53.19 + * (at your option) any later version.
53.20 + *
53.21 + * This program is distributed in the hope that it will be useful,
53.22 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
53.23 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
53.24 + * GNU General Public License for more details.
53.25 + *
53.26 + * You should have received a copy of the GNU Lesser General Public License
53.27 + * along with this program; if not, write to the Free Software
53.28 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
53.29 + */
53.30 +
53.31 +#ifndef GMYTH_COMMON_H_
53.32 +#define GMYTH_COMMON_H_
53.33 +
53.34 +#include <glib.h>
53.35 +#include <time.h>
53.36 +
53.37 +/**
53.38 + * The GMythChannelInfo structure represents the channel information
53.39 + * stored in the backend database.
53.40 + */
53.41 +typedef struct {
53.42 + /** The channel ID in backend database */
53.43 + int channel_ID;
53.44 +
53.45 + /** The channel name in backend database */
53.46 + GString *channel_name;
53.47 +
53.48 +} GMythChannelInfo;
53.49 +
53.50 +
53.51 +/**
53.52 + * The GMythProgramInfo structure represents a program information
53.53 + * stored in the database. It could be a program from the EPG data,
53.54 + * a program scheduled to be recorded, or a program already recorded.
53.55 + */
53.56 +typedef struct {
53.57 +
53.58 + /** The channel unique ID. */
53.59 + GString *chanid;
53.60 +
53.61 + /** The program start time. */
53.62 + time_t startts;
53.63 + /** The program end time. */
53.64 + time_t endts;
53.65 + /** The recording schedule start time. */
53.66 + time_t recstartts;
53.67 + /** The recording schedule end time */
53.68 + time_t recendts;
53.69 +
53.70 + /** The program title. */
53.71 + GString *title;
53.72 + /** The program subtitle. */
53.73 + GString *subtitle;
53.74 + /** The program description. */
53.75 + GString *description;
53.76 + /** The program category. */
53.77 + GString *category;
53.78 +
53.79 + GString *chanstr;
53.80 + GString *chansign;
53.81 + /** The associated channel name. */
53.82 + GString *channame;
53.83 + int chancommfree;
53.84 + GString *chanOutputFilters;
53.85 +
53.86 + GString *seriesid;
53.87 + /** The program unique id. */
53.88 + GString *programid;
53.89 + GString * catType;
53.90 +
53.91 + GString * sortTitle;
53.92 +
53.93 + /** A flag informing if the program has video or not. */
53.94 + gboolean isVideo;
53.95 + int lenMins;
53.96 +
53.97 + GString *year;
53.98 + double stars;
53.99 + int repeat;
53.100 +
53.101 + time_t originalAirDate;
53.102 + time_t lastmodified;
53.103 + time_t lastInUseTime;
53.104 +
53.105 + gboolean hasAirDate;
53.106 +
53.107 + int spread;
53.108 + int startCol;
53.109 +
53.110 +// enum RecStatusType recstatus;
53.111 +// enum RecStatusType oldrecstatus;
53.112 +// enum RecStatusType savedrecstatus;
53.113 + int recpriority2;
53.114 + int reactivate;
53.115 +
53.116 + int recordid;
53.117 + int parentid;
53.118 + //enum RecordingType rectype;
53.119 + //enum RecordingDupInType dupin;
53.120 + //enum RecordingDupMethodType dupmethod;
53.121 +
53.122 + /** The backend video source id associated to this program.*/
53.123 + int sourceid;
53.124 + /** the backend input id associated to this program.*/
53.125 + int inputid;
53.126 + /** The backend card id associated to this program.*/
53.127 + int cardid;
53.128 + gboolean shareable;
53.129 + gboolean duplicate;
53.130 +
53.131 + GString * schedulerid;
53.132 + int findid;
53.133 +
53.134 + int programflags;
53.135 + int transcoder;
53.136 +
53.137 + //proginfo->spread = -1;
53.138 + //proginfo->programflags = proginfo->getProgramFlags();
53.139 +
53.140 + GString *recgroup;
53.141 + GString *playgroup;
53.142 + int recpriority;
53.143 +
53.144 + /** The file size of the recorded program.*/
53.145 + long long filesize;
53.146 + /** The file name of the recorded program.*/
53.147 + GString *pathname;
53.148 + GString *hostname;
53.149 +
53.150 + /* AvailableStatusType availableStatus;*/
53.151 +
53.152 +} GMythProgramInfo;
53.153 +
53.154 +
53.155 +void gmyth_free_channel_list(GList *list);
53.156 +void gmyth_free_program_list(GList *list);
53.157 +
53.158 +#endif /* GMYTH_COMMON_H_ */
54.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
54.2 +++ b/gmyth/src/libgmyth/gmyth_context.c Wed Sep 20 23:45:35 2006 +0100
54.3 @@ -0,0 +1,312 @@
54.4 +/**
54.5 + * GMyth Library
54.6 + *
54.7 + * @file gmyth/gmyth_context.c
54.8 + *
54.9 + * @brief <p> GMythContext class contains general attributes and functions
54.10 + * that express the connection state of each mythtvfrontend.
54.11 + *
54.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
54.13 + * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
54.14 + *
54.15 + *//*
54.16 + *
54.17 + * This program is free software; you can redistribute it and/or modify
54.18 + * it under the terms of the GNU Lesser General Public License as published by
54.19 + * the Free Software Foundation; either version 2 of the License, or
54.20 + * (at your option) any later version.
54.21 + *
54.22 + * This program is distributed in the hope that it will be useful,
54.23 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
54.24 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
54.25 + * GNU General Public License for more details.
54.26 + *
54.27 + * You should have received a copy of the GNU Lesser General Public License
54.28 + * along with this program; if not, write to the Free Software
54.29 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
54.30 + */
54.31 +
54.32 +#include "gmyth_context.h"
54.33 +
54.34 +#include <arpa/inet.h>
54.35 +#include <sys/types.h>
54.36 +#include <sys/socket.h>
54.37 +#include <netdb.h>
54.38 +#include <errno.h>
54.39 +#include <stdlib.h>
54.40 +
54.41 +#include "gmyth_query.h"
54.42 +#include "gmyth_socket.h"
54.43 +
54.44 +static void gmyth_context_class_init (GMythContextClass *klass);
54.45 +static void gmyth_context_init (GMythContext *object);
54.46 +
54.47 +static void gmyth_context_dispose (GObject *object);
54.48 +static void gmyth_context_finalize (GObject *object);
54.49 +
54.50 +
54.51 +G_DEFINE_TYPE(GMythContext, gmyth_context, G_TYPE_OBJECT)
54.52 +
54.53 +static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
54.54 +
54.55 +static GMythContext *gcontext = NULL;
54.56 +
54.57 +static void
54.58 +gmyth_context_class_init (GMythContextClass *klass)
54.59 +{
54.60 + GObjectClass *gobject_class;
54.61 +
54.62 + gobject_class = (GObjectClass *) klass;
54.63 +
54.64 + gobject_class->dispose = gmyth_context_dispose;
54.65 + gobject_class->finalize = gmyth_context_finalize;
54.66 +}
54.67 +
54.68 +static void
54.69 +gmyth_context_init (GMythContext *gmyth_context)
54.70 +{
54.71 +
54.72 +}
54.73 +
54.74 +static void
54.75 +gmyth_context_dispose (GObject *object)
54.76 +{
54.77 + GMythContext *gmyth_context = GMYTH_CONTEXT(object);
54.78 +
54.79 + if ( gmyth_context->gmyth_settings != NULL ) {
54.80 + g_object_unref (gmyth_context->gmyth_settings);
54.81 + gmyth_context->gmyth_settings = NULL;
54.82 + }
54.83 +
54.84 + if ( gmyth_context->localhostname != NULL ) {
54.85 + g_string_free ( gmyth_context->localhostname, TRUE );
54.86 + gmyth_context->localhostname = NULL;
54.87 + }
54.88 +
54.89 + if (gmyth_context->server_socket != NULL) {
54.90 + g_object_unref (gmyth_context->server_socket);
54.91 + gmyth_context->server_socket = NULL;
54.92 + }
54.93 +
54.94 + G_OBJECT_CLASS (gmyth_context_parent_class)->dispose (object);
54.95 +}
54.96 +
54.97 +static void
54.98 +gmyth_context_finalize (GObject *object)
54.99 +{
54.100 + g_signal_handlers_destroy (object);
54.101 +
54.102 + G_OBJECT_CLASS (gmyth_context_parent_class)->finalize (object);
54.103 +}
54.104 +
54.105 +/** Gets the some important address translation info,
54.106 + * from the client socket that will open a connection.
54.107 + *
54.108 + * @return gint error number
54.109 + */
54.110 +static gint
54.111 +myth_context_toaddrinfo( gchar *addr, gint port, struct addrinfo **addrInfo )
54.112 +{
54.113 + struct addrinfo hints;
54.114 + gchar *portStr = g_strnfill( 32, ' ' );
54.115 + gint errorn = EADDRNOTAVAIL;
54.116 +
54.117 + memset( &hints, 0, sizeof(hints) );
54.118 + hints.ai_family = AF_INET;
54.119 + hints.ai_socktype = SOCK_STREAM;
54.120 +
54.121 + /* hints.ai_flags = AI_NUMERICHOST; */
54.122 + if ( port != -1 )
54.123 + sprintf(portStr, "%d", port);
54.124 + else
54.125 + portStr = NULL;
54.126 +
54.127 + g_debug( "[%s] Address: %s, port: %s\n", __FUNCTION__, addr, portStr );
54.128 + if ( ( errorn = getaddrinfo(addr, portStr, &hints, addrInfo) ) != 0 ) {
54.129 + g_printerr( "[%s] Socket ERROR: %s\n", __FUNCTION__, gai_strerror(errorn) );
54.130 + }
54.131 +
54.132 + return errorn;
54.133 +
54.134 +}
54.135 +
54.136 +/** Initializes the GMythContext object. It reads local system information
54.137 + * load gmyth user settings and start connection to the database.
54.138 + *
54.139 + * @return TRUE if initialization was successfull,
54.140 + * FALSE if any error happens.
54.141 + */
54.142 +gboolean
54.143 +gmyth_context_initialize ()
54.144 +{
54.145 + GString *localhost = NULL;
54.146 +
54.147 + if (gcontext == NULL) {
54.148 + gcontext = GMYTH_CONTEXT ( g_object_new (GMYTH_CONTEXT_TYPE, FALSE));
54.149 + }
54.150 +
54.151 + localhost = gmyth_socket_get_local_hostname( );
54.152 +
54.153 + if (localhost==NULL || localhost->len <=0 ) {
54.154 + g_warning ("[%s] Could not determine local hostname. Setting to 127.0.0.1", __FUNCTION__);
54.155 + gcontext->localhostname = g_string_new ("127.0.0.1");
54.156 + } else {
54.157 + gcontext->localhostname = localhost;
54.158 + }
54.159 +
54.160 + if (gcontext->gmyth_settings) {
54.161 + g_object_unref (gcontext->gmyth_settings);
54.162 + gcontext->gmyth_settings = NULL;
54.163 + }
54.164 +
54.165 + gcontext->gmyth_settings = gmyth_settings_new ();
54.166 + if (!gmyth_settings_load (gcontext->gmyth_settings)) {
54.167 + g_warning ("GMythContext: Settings file not opened!\n");
54.168 + } else {
54.169 + g_debug ("GMythContext: Settings file loaded");
54.170 + }
54.171 +
54.172 + if (gcontext->server_socket != NULL) {
54.173 + g_object_unref (gcontext->server_socket);
54.174 + gcontext->server_socket = NULL;
54.175 + }
54.176 +
54.177 + GString *server_hostname =
54.178 + gmyth_settings_get_backend_hostname(gcontext->gmyth_settings);
54.179 + int server_port = gmyth_settings_get_backend_port(gcontext->gmyth_settings);
54.180 +
54.181 + gcontext->server_socket = gmyth_socket_new ();
54.182 + if (!gmyth_socket_connect_to_backend (gcontext->server_socket,
54.183 + server_hostname->str, server_port, FALSE)) {
54.184 + g_warning ("[%s] Socket connection to backend error!", __FUNCTION__);
54.185 + g_object_unref (gcontext->server_socket);
54.186 + gcontext->server_socket = NULL;
54.187 + return FALSE;
54.188 + }
54.189 +
54.190 + return TRUE;
54.191 +}
54.192 +
54.193 +/** Formats a Mythtv protocol command based on strlist and sends it to
54.194 + * the connected backend. The backend response is overwritten into strlist.
54.195 + *
54.196 + * @param strlist the string list to be sent,
54.197 + * and on which the answer will be written.
54.198 + * @return TRUE if command was sent and an answer was received, FALSE if any
54.199 + * error happens.
54.200 + */
54.201 +gboolean
54.202 +gmyth_context_send_receive_stringlist (GMythStringList *strlist)
54.203 +{
54.204 + gint ok = -1;
54.205 +
54.206 + if (!gcontext || !(gcontext->server_socket)) {
54.207 + g_warning ("[%s] GMythContext not initialized", __FUNCTION__);
54.208 + return FALSE;
54.209 + }
54.210 +
54.211 + //g_static_mutex_lock( &mutex );
54.212 +
54.213 + ok = gmyth_socket_sendreceive_stringlist (gcontext->server_socket, strlist);
54.214 +
54.215 + //g_static_mutex_unlock( &mutex );
54.216 +
54.217 + if (!ok) {
54.218 + g_warning ("Connection to backend server lost");
54.219 + }
54.220 +
54.221 + return (ok ? TRUE : FALSE);
54.222 +}
54.223 +
54.224 +/** Gets the GMythSettings object associated to this context.
54.225 + *
54.226 + * @return The GMythSettings object currently valid or NULL if the settings
54.227 + * were not opened.
54.228 + */
54.229 +GMythSettings*
54.230 +gmyth_context_get_settings ()
54.231 +{
54.232 + if (!gcontext) {
54.233 + g_warning ("[%s] GMythContext not initialized\n", __FUNCTION__);
54.234 + return NULL;
54.235 + }
54.236 +
54.237 + return gcontext->gmyth_settings;
54.238 +}
54.239 +
54.240 +/** Gets the machine local hostname.
54.241 + *
54.242 + * @param hostname a valid GString object to be overwritten with the local
54.243 + * hostname.
54.244 + * @return true if the hostname was read, false if any error happened.
54.245 + */
54.246 +gboolean
54.247 +gmyth_context_get_local_hostname (GString *hostname)
54.248 +{
54.249 + if (!hostname) {
54.250 + g_warning ("[%s] Received null argument", __FUNCTION__);
54.251 + return FALSE;
54.252 + }
54.253 +
54.254 + g_string_assign (hostname, gcontext->localhostname->str);
54.255 +
54.256 + return TRUE;
54.257 +}
54.258 +
54.259 +/** Gets a setting information from the backend mysql database.
54.260 + *
54.261 + * @param key The setting key to be retrieved.
54.262 + * @param host the hostname associated to the desired setting.
54.263 + * @param default_value the default setting value if could not query from
54.264 + * backend database.
54.265 + * @return The setting value loaded from database, or the given default value
54.266 + * if the query fails.
54.267 + */
54.268 +GString*
54.269 +gmyth_context_get_setting_onhost (GString *key, GString *host, GString *default_value)
54.270 +{
54.271 + GString *query_str;
54.272 +
54.273 + // TODO: Reuse msql query in gmyth_context
54.274 + GMythQuery *gmyth_query = gmyth_query_new ();
54.275 +
54.276 + if (gmyth_query_connect (gmyth_query)) {
54.277 + MYSQL_RES *msql_res;
54.278 + MYSQL_ROW msql_row;
54.279 +
54.280 + query_str = g_string_new ("");
54.281 + g_string_printf (query_str, "SELECT data FROM settings WHERE value = \"%s\" "
54.282 + "AND hostname = \"%s\" ;", key->str, host->str);
54.283 +
54.284 + msql_res = gmyth_query_process_statement (gmyth_query, query_str->str);
54.285 + if (msql_res) {
54.286 + msql_row = mysql_fetch_row (msql_res);
54.287 + if (msql_row != NULL) {
54.288 + return g_string_new (msql_row[0]);
54.289 + }
54.290 + }
54.291 +
54.292 + g_object_unref (gmyth_query);
54.293 + } else {
54.294 + g_warning ("Database not open while trying to load setting: %s", key->str);
54.295 + }
54.296 +
54.297 +
54.298 + return default_value;
54.299 +}
54.300 +
54.301 +/** Verify if the context is currently connected to a backend.
54.302 + *
54.303 + * @return true if connection was opened, false if not.
54.304 + */
54.305 +gboolean
54.306 +gmyth_context_check_connection ()
54.307 +{
54.308 + // FIXME: Check this based on socket states
54.309 + if (!gcontext) {
54.310 + g_warning ("[%s] GMythContext not initialized", __FUNCTION__);
54.311 + return FALSE;
54.312 + }
54.313 +
54.314 + return (gcontext->server_socket != NULL);
54.315 +}
55.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
55.2 +++ b/gmyth/src/libgmyth/gmyth_context.h Wed Sep 20 23:45:35 2006 +0100
55.3 @@ -0,0 +1,88 @@
55.4 +/**
55.5 + * GMyth Library
55.6 + *
55.7 + * @file gmyth/gmyth_context.h
55.8 + *
55.9 + * @brief <p> GMythContext class contains general attributes and functions
55.10 + * that express the connection state of each mythtvfrontend.
55.11 + *
55.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
55.13 + * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
55.14 + *
55.15 + *//*
55.16 + *
55.17 + * This program is free software; you can redistribute it and/or modify
55.18 + * it under the terms of the GNU Lesser General Public License as published by
55.19 + * the Free Software Foundation; either version 2 of the License, or
55.20 + * (at your option) any later version.
55.21 + *
55.22 + * This program is distributed in the hope that it will be useful,
55.23 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
55.24 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
55.25 + * GNU General Public License for more details.
55.26 + *
55.27 + * You should have received a copy of the GNU Lesser General Public License
55.28 + * along with this program; if not, write to the Free Software
55.29 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
55.30 + */
55.31 +
55.32 +#ifndef __GMYTH_CONTEXT_H__
55.33 +#define __GMYTH_CONTEXT_H__
55.34 +
55.35 +#include <glib-object.h>
55.36 +
55.37 +#include "gmyth_settings.h"
55.38 +#include "gmyth_socket.h"
55.39 +#include "gmyth_stringlist.h"
55.40 +
55.41 +#define G_BEGIN_DECLS
55.42 +
55.43 +#define GMYTH_CONTEXT_TYPE (gmyth_context_get_type ())
55.44 +#define GMYTH_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_CONTEXT_TYPE, GMythContext))
55.45 +#define GMYTH_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_CONTEXT_TYPE, GMythContextClass))
55.46 +#define IS_GMYTH_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_CONTEXT_TYPE))
55.47 +#define IS_GMYTH_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_CONTEXT_TYPE))
55.48 +#define GMYTH_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_CONTEXT_TYPE, GMythContextClass))
55.49 +
55.50 +#define MYTHTV_VERSION_DEFAULT 30
55.51 +
55.52 +typedef struct _GMythContext GMythContext;
55.53 +typedef struct _GMythContextClass GMythContextClass;
55.54 +
55.55 +struct _GMythContextClass
55.56 +{
55.57 + GObjectClass parent_class;
55.58 +
55.59 + /* callbacks */
55.60 + /* no one for now */
55.61 +};
55.62 +
55.63 +struct _GMythContext
55.64 +{
55.65 + GObject parent;
55.66 +
55.67 + GMythSettings *gmyth_settings;
55.68 + GMythSocket *server_socket;
55.69 +
55.70 + GString *localhostname;
55.71 +};
55.72 +
55.73 +
55.74 +GType gmyth_context_get_type (void);
55.75 +void gmyth_context_create();
55.76 +
55.77 +gboolean gmyth_context_initialize ();
55.78 +gboolean gmyth_context_check_connection ();
55.79 +GMythSettings* gmyth_context_get_settings ();
55.80 +
55.81 +gboolean gmyth_context_send_receive_stringlist (GMythStringList *strlist);
55.82 +
55.83 +GString* gmyth_context_get_setting_onhost (GString *key, GString *host, GString *default_value);
55.84 +gboolean gmyth_context_get_local_hostname (GString *hostname);
55.85 +
55.86 +GString* gmyth_context_get_setting_onhost (GString *key, GString *host, GString *default_value);
55.87 +
55.88 +
55.89 +#define G_END_DECLS
55.90 +
55.91 +#endif /* __GMYTH_CONTEXT_H__ */
56.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
56.2 +++ b/gmyth/src/libgmyth/gmyth_epg.c Wed Sep 20 23:45:35 2006 +0100
56.3 @@ -0,0 +1,278 @@
56.4 +/**
56.5 + * GMyth Library
56.6 + *
56.7 + * @file gmyth/gmyth_epg.c
56.8 + *
56.9 + * @brief <p> GMythEPG class provides access to the program and channel data
56.10 + * from the Electronic Program Guide (EPG) of the Mythtv backend.
56.11 + *
56.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
56.13 + * @author Leonardo Sobral Cunha <leonardo.cunha@indt.org.br>
56.14 + *
56.15 + *//*
56.16 + *
56.17 + * This program is free software; you can redistribute it and/or modify
56.18 + * it under the terms of the GNU Lesser General Public License as published by
56.19 + * the Free Software Foundation; either version 2 of the License, or
56.20 + * (at your option) any later version.
56.21 + *
56.22 + * This program is distributed in the hope that it will be useful,
56.23 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
56.24 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
56.25 + * GNU General Public License for more details.
56.26 + *
56.27 + * You should have received a copy of the GNU Lesser General Public License
56.28 + * along with this program; if not, write to the Free Software
56.29 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
56.30 + */
56.31 +
56.32 +#include <mysql.h>
56.33 +#include <stdlib.h>
56.34 +#include <string.h>
56.35 +#include <assert.h>
56.36 +
56.37 +#include "gmyth_epg.h"
56.38 +#include "gmyth_util.h"
56.39 +
56.40 +static void gmyth_epg_class_init (GMythEPGClass *klass);
56.41 +static void gmyth_epg_init (GMythEPG *object);
56.42 +
56.43 +static void gmyth_epg_dispose (GObject *object);
56.44 +static void gmyth_epg_finalize (GObject *object);
56.45 +
56.46 +G_DEFINE_TYPE(GMythEPG, gmyth_epg, G_TYPE_OBJECT)
56.47 +
56.48 +static void
56.49 +gmyth_epg_class_init (GMythEPGClass *klass)
56.50 +{
56.51 + GObjectClass *gobject_class;
56.52 +
56.53 + gobject_class = (GObjectClass *) klass;
56.54 +
56.55 + gobject_class->dispose = gmyth_epg_dispose;
56.56 + gobject_class->finalize = gmyth_epg_finalize;
56.57 +}
56.58 +
56.59 +static void
56.60 +gmyth_epg_init (GMythEPG *gmyth_epg)
56.61 +{
56.62 + gmyth_epg->sqlquery = gmyth_query_new ();
56.63 +}
56.64 +
56.65 +static void
56.66 +gmyth_epg_dispose (GObject *object)
56.67 +{
56.68 + //GMythEPG *gmyth_epg = GMYTH_EPG(object);
56.69 +
56.70 + G_OBJECT_CLASS (gmyth_epg_parent_class)->dispose (object);
56.71 +}
56.72 +
56.73 +static void
56.74 +gmyth_epg_finalize (GObject *object)
56.75 +{
56.76 + g_signal_handlers_destroy (object);
56.77 +
56.78 + G_OBJECT_CLASS (gmyth_epg_parent_class)->finalize (object);
56.79 +}
56.80 +
56.81 +/**
56.82 + * Creates a new instance of GMythEPG.
56.83 + *
56.84 + * @return a new instance of GMythEPG.
56.85 + */
56.86 +GMythEPG*
56.87 +gmyth_epg_new ()
56.88 +{
56.89 + GMythEPG *epg = GMYTH_EPG (g_object_new(GMYTH_EPG_TYPE, NULL));
56.90 +
56.91 + return epg;
56.92 +}
56.93 +
56.94 +/** Connects to the Mysql database in the backend. The backend address
56.95 + * is loaded from the GMythSettings instance.
56.96 + *
56.97 + * @param gmyth_epg the GMythEPG instance to be connected.
56.98 + * @return true if connection was success, false if failed.
56.99 + */
56.100 +gboolean
56.101 +gmyth_epg_connect (GMythEPG *gmyth_epg)
56.102 +{
56.103 + assert(gmyth_epg);
56.104 +
56.105 + if (gmyth_epg->sqlquery == NULL) {
56.106 + g_warning ("[%s] GMythEPG not initialized", __FUNCTION__);
56.107 + return FALSE;
56.108 + }
56.109 +
56.110 + if (!gmyth_query_connect(gmyth_epg->sqlquery)) {
56.111 + g_warning ("[%s] Error while connecting to db", __FUNCTION__);
56.112 + return FALSE;
56.113 + }
56.114 +
56.115 + return TRUE;
56.116 +}
56.117 +
56.118 +/** Disconnects from the Mysql database in the backend.
56.119 + *
56.120 + * @param gmyth_epg the GMythEPG instance to be disconnected
56.121 + * @return true if disconnection was success, false if failed.
56.122 + */
56.123 +gboolean
56.124 +gmyth_epg_disconnect (GMythEPG *gmyth_epg)
56.125 +{
56.126 + assert(gmyth_epg);
56.127 +
56.128 + if (gmyth_epg->sqlquery != NULL) {
56.129 + g_object_unref (gmyth_epg->sqlquery);
56.130 + }
56.131 +
56.132 + return TRUE;
56.133 +}
56.134 +
56.135 +/** Retrieves the available list of channels from the backend Mysql database.
56.136 + *
56.137 + * @param gmyth_epg the GMythEPG instance.
56.138 + * @param glist_ptr the GList pointer to be filled with the loaded list address.
56.139 + * @return The amount of channels retrieved from database, or -1 if error.
56.140 + */
56.141 +gint
56.142 +gmyth_epg_get_channel_list (GMythEPG *gmyth_epg, GList **glist_ptr)
56.143 +{
56.144 + MYSQL_RES *msql_res;
56.145 +
56.146 + assert(gmyth_epg);
56.147 +
56.148 + msql_res = gmyth_query_process_statement (gmyth_epg->sqlquery,
56.149 + "SELECT chanid,name FROM channel;");
56.150 +
56.151 + (*glist_ptr) = NULL;
56.152 +
56.153 + if (msql_res == NULL) {
56.154 + g_warning ("[%s] msql query returned NULL MYSQL_RES", __FUNCTION__);
56.155 + return -1;
56.156 + } else {
56.157 + MYSQL_ROW row;
56.158 + GMythChannelInfo *channel_info;
56.159 +
56.160 + while ((row = mysql_fetch_row (msql_res)) != NULL){
56.161 +
56.162 + channel_info = g_new0(GMythChannelInfo, 1);
56.163 + channel_info->channel_ID = atoi (row[0]);
56.164 + channel_info->channel_name = g_string_new (row[1]);
56.165 +
56.166 + (*glist_ptr) = g_list_append ((*glist_ptr), channel_info);
56.167 + }
56.168 + }
56.169 + mysql_free_result (msql_res);
56.170 + return (!(*glist_ptr)) ? 0 : g_list_length (*glist_ptr);
56.171 +}
56.172 +
56.173 +/**
56.174 + * Retrieves the available list of channels from the backend Mysql database.
56.175 + *
56.176 + * @param gmyth_epg the GMythEPG instance.
56.177 + * @param proglist the GList pointer to be filled with the loaded list.
56.178 + * @param chan_num the channel num on which to search for program.
56.179 + * @param starttime the start time to search for programs.
56.180 + * @param endtime the end time to search for programs.
56.181 + * @return The amount of channels retrieved from database, or -1 if error.
56.182 + */
56.183 +gint
56.184 +gmyth_epg_get_program_list (GMythEPG *gmyth_epg, GList **proglist,
56.185 + const gint chan_num, time_t starttime, time_t endtime)
56.186 +{
56.187 + GString *startts = gmyth_util_time_to_string(starttime);
56.188 + GString *endts = gmyth_util_time_to_string(endtime);
56.189 + MYSQL_ROW row;
56.190 + GString *querystr;
56.191 +
56.192 + assert(gmyth_epg);
56.193 +
56.194 + querystr = g_string_new(
56.195 + "SELECT DISTINCT program.chanid, program.starttime, program.endtime, "
56.196 + " program.title, program.subtitle, program.description, "
56.197 + " program.category, channel.channum, channel.callsign, "
56.198 + " channel.name, program.previouslyshown, channel.commfree, "
56.199 + " channel.outputfilters, program.seriesid, program.programid, "
56.200 + " program.airdate, program.stars, program.originalairdate, "
56.201 + " program.category_type, oldrecstatus.recordid, "
56.202 + " oldrecstatus.rectype, oldrecstatus.recstatus, "
56.203 + " oldrecstatus.findid "
56.204 + "FROM program "
56.205 + "LEFT JOIN channel ON program.chanid = channel.chanid "
56.206 + "LEFT JOIN oldrecorded AS oldrecstatus ON "
56.207 + " program.title = oldrecstatus.title AND "
56.208 + " channel.callsign = oldrecstatus.station AND "
56.209 + " program.starttime = oldrecstatus.starttime "
56.210 + );
56.211 +
56.212 + g_string_append_printf (querystr,
56.213 + "WHERE program.chanid = %d "
56.214 + " AND program.endtime >= '%s' "
56.215 + " AND program.starttime <= '%s' "
56.216 + " AND program.manualid = 0 ",
56.217 + chan_num, startts->str, endts->str);
56.218 +
56.219 + if (!g_strrstr(querystr->str, " GROUP BY "))
56.220 + querystr = g_string_append(querystr,
56.221 + " GROUP BY program.starttime, channel.channum, "
56.222 + " channel.callsign, program.title ");
56.223 +
56.224 + if (!g_strrstr(querystr->str, " LIMIT "))
56.225 + querystr = g_string_append(querystr, " LIMIT 1000 ");
56.226 +
56.227 + MYSQL_RES *res_set =
56.228 + gmyth_query_process_statement(gmyth_epg->sqlquery, querystr->str);
56.229 +
56.230 + if (res_set == NULL) {
56.231 + g_warning ("[%s] msql query returned NULL MYSQL_RES", __FUNCTION__);
56.232 + return -1;
56.233 + }
56.234 +
56.235 + (*proglist) = NULL;
56.236 + while ((row = mysql_fetch_row (res_set)) != NULL) {
56.237 +
56.238 + GMythProgramInfo *p = g_new0 (GMythProgramInfo, 1);
56.239 + p->chanid = g_string_new (row[0]);
56.240 +
56.241 + p->startts = gmyth_util_string_to_time (g_string_new (row[1]));
56.242 + p->endts = gmyth_util_string_to_time (g_string_new (row[2]));
56.243 +
56.244 + p->recstartts = p->startts;
56.245 + p->recendts = p->endts;
56.246 + p->lastmodified = p->startts;
56.247 +
56.248 + p->title = g_string_new (row[3]);
56.249 + p->subtitle = g_string_new (row[4]);
56.250 + p->description = g_string_new (row[5]);
56.251 + p->category = g_string_new (row[6]);
56.252 + p->chanstr = g_string_new (row[7]);
56.253 + p->chansign = g_string_new (row[8]);
56.254 + p->channame = g_string_new (row[9]);
56.255 + p->repeat = atoi(row[10]);
56.256 + p->chancommfree = atoi(row[11]);
56.257 + p->chanOutputFilters = g_string_new (row[12]);
56.258 + p->seriesid = g_string_new (row[13]);
56.259 + p->programid = g_string_new (row[14]);
56.260 + p->year = g_string_new (row[15]);
56.261 + p->stars = atof(row[16]);
56.262 +
56.263 + if (!row[17] || !strcmp(row[17], "")) {
56.264 + p->originalAirDate = 0;
56.265 + p->hasAirDate = FALSE;
56.266 + } else {
56.267 + p->originalAirDate = gmyth_util_string_to_time (g_string_new (row[17]));
56.268 + p->hasAirDate = TRUE;
56.269 + }
56.270 +
56.271 + p->catType = g_string_new (row[18]);
56.272 +
56.273 + *proglist = g_list_append((*proglist), p);
56.274 + }
56.275 +
56.276 + /* deallocate */
56.277 + mysql_free_result (res_set);
56.278 + g_string_free(querystr, TRUE);
56.279 +
56.280 + return TRUE;
56.281 +}
57.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
57.2 +++ b/gmyth/src/libgmyth/gmyth_epg.h Wed Sep 20 23:45:35 2006 +0100
57.3 @@ -0,0 +1,75 @@
57.4 +/**
57.5 + * GMyth Library
57.6 + *
57.7 + * @file gmyth/gmyth_epg.h
57.8 + *
57.9 + * @brief <p> GMythEPG class provides access to the program and channel data
57.10 + * from the Electronic Program Guide (EPG) of the Mythtv backend.
57.11 + *
57.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
57.13 + * @author Leonardo Sobral Cunha <leonardo.cunha@indt.org.br>
57.14 + *
57.15 + *//*
57.16 + *
57.17 + * This program is free software; you can redistribute it and/or modify
57.18 + * it under the terms of the GNU Lesser General Public License as published by
57.19 + * the Free Software Foundation; either version 2 of the License, or
57.20 + * (at your option) any later version.
57.21 + *
57.22 + * This program is distributed in the hope that it will be useful,
57.23 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
57.24 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
57.25 + * GNU General Public License for more details.
57.26 + *
57.27 + * You should have received a copy of the GNU Lesser General Public License
57.28 + * along with this program; if not, write to the Free Software
57.29 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
57.30 + */
57.31 +
57.32 +#ifndef GMYTH_EPG_H_
57.33 +#define GMYTH_EPG_H_
57.34 +
57.35 +#include <glib-object.h>
57.36 +
57.37 +#include "gmyth_query.h"
57.38 +#include "gmyth_common.h"
57.39 +
57.40 +#define G_BEGIN_DECLS
57.41 +
57.42 +#define GMYTH_EPG_TYPE (gmyth_epg_get_type ())
57.43 +#define GMYTH_EPG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_EPG_TYPE, GMythEPG))
57.44 +#define GMYTH_EPG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_EPG_TYPE, GMythEPGClass))
57.45 +#define IS_GMYTH_EPG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_EPG_TYPE))
57.46 +#define IS_GMYTH_EPG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_EPG_TYPE))
57.47 +#define GMYTH_EPG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_EPG_TYPE, GMythEPGClass))
57.48 +
57.49 +typedef struct _GMythEPG GMythEPG;
57.50 +typedef struct _GMythEPGClass GMythEPGClass;
57.51 +
57.52 +struct _GMythEPGClass
57.53 +{
57.54 + GObjectClass parent_class;
57.55 +
57.56 + /* callbacks */
57.57 + /* no one for now */
57.58 +};
57.59 +
57.60 +struct _GMythEPG
57.61 +{
57.62 + GObject parent;
57.63 +
57.64 + GMythQuery *sqlquery;
57.65 +};
57.66 +
57.67 +GType gmyth_epg_get_type (void);
57.68 +
57.69 +GMythEPG* gmyth_epg_new ();
57.70 +
57.71 +gboolean gmyth_epg_connect (GMythEPG *gmyth_epg);
57.72 +gboolean gmyth_epg_disconnect (GMythEPG *gmyth_epg);
57.73 +
57.74 +gint gmyth_epg_get_channel_list (GMythEPG *gmyth_epg, GList **glist_ptr);
57.75 +gint gmyth_epg_get_program_list (GMythEPG *gmyth_epg, GList **proglist,
57.76 + const gint chanNum, time_t starttime, time_t endtime);
57.77 +
57.78 +#endif /*GMYTH_EPG_H_*/
58.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
58.2 +++ b/gmyth/src/libgmyth/gmyth_query.c Wed Sep 20 23:45:35 2006 +0100
58.3 @@ -0,0 +1,221 @@
58.4 +/**
58.5 + * GMyth Library
58.6 + *
58.7 + * @file gmyth/gmyth_query.c
58.8 + *
58.9 + * @brief <p> GMythQuery class provides a wrapper for accessing
58.10 + * the libmysqlclient funtions.
58.11 + *
58.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
58.13 + * @author Leonardo Sobral Cunha <leonardo.cunha@indt.org.br>
58.14 + *
58.15 + *//*
58.16 + *
58.17 + * This program is free software; you can redistribute it and/or modify
58.18 + * it under the terms of the GNU Lesser General Public License as published by
58.19 + * the Free Software Foundation; either version 2 of the License, or
58.20 + * (at your option) any later version.
58.21 + *
58.22 + * This program is distributed in the hope that it will be useful,
58.23 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
58.24 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
58.25 + * GNU General Public License for more details.
58.26 + *
58.27 + * You should have received a copy of the GNU Lesser General Public License
58.28 + * along with this program; if not, write to the Free Software
58.29 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
58.30 + */
58.31 +
58.32 +#include <stdlib.h>
58.33 +#include <stdio.h>
58.34 +#include <assert.h>
58.35 +
58.36 +#include "gmyth_query.h"
58.37 +#include "gmyth_settings.h"
58.38 +#include "gmyth_context.h"
58.39 +
58.40 +static void gmyth_query_class_init (GMythQueryClass *klass);
58.41 +static void gmyth_query_init (GMythQuery *object);
58.42 +
58.43 +static void gmyth_query_dispose (GObject *object);
58.44 +static void gmyth_query_finalize (GObject *object);
58.45 +
58.46 +static void gmyth_query_print_error (MYSQL *conn, char *message);
58.47 +
58.48 +G_DEFINE_TYPE(GMythQuery, gmyth_query, G_TYPE_OBJECT)
58.49 +
58.50 +static void
58.51 +gmyth_query_class_init (GMythQueryClass *klass)
58.52 +{
58.53 + GObjectClass *gobject_class;
58.54 +
58.55 + gobject_class = (GObjectClass *) klass;
58.56 +
58.57 + gobject_class->dispose = gmyth_query_dispose;
58.58 + gobject_class->finalize = gmyth_query_finalize;
58.59 +}
58.60 +
58.61 +static void
58.62 +gmyth_query_init (GMythQuery *gmyth_query)
58.63 +{
58.64 + GMythSettings *gmyth_settings = gmyth_context_get_settings ();
58.65 +
58.66 + gmyth_query->opt_host_name = gmyth_settings_get_backend_hostname(gmyth_settings);
58.67 + gmyth_query->opt_user_name = gmyth_settings_get_username(gmyth_settings);
58.68 + gmyth_query->opt_password = gmyth_settings_get_password(gmyth_settings);
58.69 + gmyth_query->opt_db_name = gmyth_settings_get_dbname(gmyth_settings);
58.70 +
58.71 + /* initialize connection handler */
58.72 + gmyth_query->conn = mysql_init (NULL);
58.73 +
58.74 + if (!(gmyth_query->conn))
58.75 + g_warning ("[%s] MSQL structure not initialized", __FUNCTION__);
58.76 +
58.77 +}
58.78 +
58.79 +static void
58.80 +gmyth_query_dispose (GObject *object)
58.81 +{
58.82 + GMythQuery *gmyth_query = GMYTH_QUERY (object);
58.83 +
58.84 + /* disconnect from server */
58.85 + gmyth_query_disconnect (gmyth_query);
58.86 +
58.87 + G_OBJECT_CLASS (gmyth_query_parent_class)->dispose (object);
58.88 +}
58.89 +
58.90 +static void
58.91 +gmyth_query_finalize (GObject *object)
58.92 +{
58.93 + g_signal_handlers_destroy (object);
58.94 +
58.95 + G_OBJECT_CLASS (gmyth_query_parent_class)->finalize (object);
58.96 +}
58.97 +
58.98 +/** Creates a new instance of GMythQuery.
58.99 + *
58.100 + * @return a new instance of GMythQuery.
58.101 + */
58.102 +GMythQuery*
58.103 +gmyth_query_new ()
58.104 +{
58.105 + GMythQuery *sql_query = GMYTH_QUERY (g_object_new(GMYTH_QUERY_TYPE, NULL));
58.106 +
58.107 + return sql_query;
58.108 +}
58.109 +
58.110 +/** Connects to the Mysql database in the backend. The backend address
58.111 + * is loaded from the GMythSettings instance.
58.112 + *
58.113 + * @param gmyth_query the GMythEPG instance to be connected.
58.114 + * @return true if connection was success, false if failed.
58.115 + */
58.116 +gboolean
58.117 +gmyth_query_connect (GMythQuery *gmyth_query)
58.118 +{
58.119 + char *opt_host_name;
58.120 + char *opt_user_name;
58.121 + char *opt_password;
58.122 + char *opt_db_name;
58.123 +
58.124 + assert(gmyth_query);
58.125 +
58.126 + opt_host_name = (gmyth_query->opt_host_name ? gmyth_query->opt_host_name->str : NULL);
58.127 + opt_db_name = (gmyth_query->opt_db_name ? gmyth_query->opt_db_name->str : NULL);
58.128 + opt_user_name = (gmyth_query->opt_user_name ? gmyth_query->opt_user_name->str : NULL);
58.129 + opt_password = (gmyth_query->opt_password ? gmyth_query->opt_password->str : NULL);
58.130 +
58.131 +
58.132 + if (gmyth_query->conn == NULL) {
58.133 + gmyth_query_print_error (NULL, "mysql_init() failed (probably out of memory)");
58.134 + return FALSE;
58.135 + }
58.136 +
58.137 + /* connect to server */
58.138 + if (mysql_real_connect (gmyth_query->conn, opt_host_name,
58.139 + opt_user_name, opt_password, opt_db_name,
58.140 + 0, NULL, 0) == NULL) {
58.141 +
58.142 + gmyth_query_print_error (gmyth_query->conn, "mysql_real_connect() failed");
58.143 + return FALSE;
58.144 + }
58.145 +
58.146 + g_debug ("[%s] Connection to Mysql server succeeded!", __FUNCTION__);
58.147 +
58.148 + return TRUE;
58.149 +}
58.150 +
58.151 +/** Disconnects from the Mysql database in the backend.
58.152 + *
58.153 + * @param gmyth_query the GMythQuery instance to be disconnected
58.154 + * @return true if disconnection was success, false if failed.
58.155 + */
58.156 +gboolean
58.157 +gmyth_query_disconnect (GMythQuery *gmyth_query)
58.158 +{
58.159 + assert(gmyth_query);
58.160 +
58.161 + /* TODO: Check how to return error */
58.162 + g_debug ("[%s] Closing gmyth_query->conn", __FUNCTION__);
58.163 + mysql_close (gmyth_query->conn);
58.164 +
58.165 + return TRUE;
58.166 +}
58.167 +
58.168 +static void
58.169 +gmyth_query_print_error (MYSQL *conn, char *message)
58.170 +{
58.171 + fprintf (stderr, "%s\n", message);
58.172 +
58.173 + if (conn != NULL) {
58.174 +#if MYSQL_VERSION_ID >= 40101
58.175 + fprintf (stderr, "Error %u (%s): %s\n",
58.176 + mysql_errno (conn), mysql_sqlstate(conn), mysql_error (conn));
58.177 +#else
58.178 + fprintf (stderr, "Error %u: %s\n",
58.179 + mysql_errno (conn), mysql_error (conn));
58.180 +#endif
58.181 + }
58.182 +}
58.183 +
58.184 +/** Sends the given query to the backend returning the query result as
58.185 + * MYSQL_RES pointer.
58.186 + *
58.187 + * FIXME: this function is returning NULL whether any error happens
58.188 + * or no rows are returned (e.g. UPDATE or REPLACE).
58.189 + *
58.190 + * @param gmyth_query the GMythQuery instance.
58.191 + * @param stmt_str the query text.
58.192 + * @return the MYSQL_RES result pointer or NULL if any error happens.
58.193 + */
58.194 +MYSQL_RES*
58.195 +gmyth_query_process_statement (GMythQuery *gmyth_query, char *stmt_str)
58.196 +{
58.197 + MYSQL_RES *res_set;
58.198 +
58.199 + assert(gmyth_query);
58.200 +
58.201 + g_debug ("[%s] Running mysql query %s", __FUNCTION__, stmt_str);
58.202 +
58.203 + if (gmyth_query == NULL)
58.204 + return NULL;
58.205 +
58.206 + /* the statement failed */
58.207 + if (mysql_query (gmyth_query->conn, stmt_str) != 0) {
58.208 + gmyth_query_print_error (gmyth_query->conn, "Could not execute statement");
58.209 + return NULL;
58.210 + }
58.211 +
58.212 + /* the statement succeeded; determine whether it returned data */
58.213 + res_set = mysql_store_result (gmyth_query->conn);
58.214 + if (res_set) {
58.215 + return res_set;
58.216 + } else if (mysql_field_count (gmyth_query->conn) == 0) {
58.217 + g_debug ("%lu rows affected\n",
58.218 + (unsigned long) mysql_affected_rows (gmyth_query->conn));
58.219 + } else {
58.220 + gmyth_query_print_error (gmyth_query->conn, "Could not retrieve result set");
58.221 + }
58.222 +
58.223 + return NULL;
58.224 +}
59.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
59.2 +++ b/gmyth/src/libgmyth/gmyth_query.h Wed Sep 20 23:45:35 2006 +0100
59.3 @@ -0,0 +1,84 @@
59.4 +/**
59.5 + * GMyth Library
59.6 + *
59.7 + * @file gmyth/gmyth_query.h
59.8 + *
59.9 + * @brief <p> GMythQuery class provides a wrapper for accessing
59.10 + * the libmysqlclient funtions.
59.11 + *
59.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
59.13 + * @author Leonardo Sobral Cunha <leonardo.cunha@indt.org.br>
59.14 + *
59.15 + *//*
59.16 + *
59.17 + * This program is free software; you can redistribute it and/or modify
59.18 + * it under the terms of the GNU Lesser General Public License as published by
59.19 + * the Free Software Foundation; either version 2 of the License, or
59.20 + * (at your option) any later version.
59.21 + *
59.22 + * This program is distributed in the hope that it will be useful,
59.23 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
59.24 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
59.25 + * GNU General Public License for more details.
59.26 + *
59.27 + * You should have received a copy of the GNU Lesser General Public License
59.28 + * along with this program; if not, write to the Free Software
59.29 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
59.30 + */
59.31 +
59.32 +#ifndef __GMYTH_QUERY_H__
59.33 +#define __GMYTH_QUERY_H__
59.34 +
59.35 +#include <glib-object.h>
59.36 +
59.37 +/* MYSQL includes */
59.38 +#include <mysql.h>
59.39 +
59.40 +#define G_BEGIN_DECLS
59.41 +
59.42 +#define GMYTH_QUERY_TYPE (gmyth_query_get_type ())
59.43 +#define GMYTH_QUERY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_QUERY_TYPE, GMythQuery))
59.44 +#define GMYTH_QUERY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_QUERY_TYPE, GMythQueryClass))
59.45 +#define IS_GMYTH_QUERY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_QUERY_TYPE))
59.46 +#define IS_GMYTH_QUERY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_QUERY_TYPE))
59.47 +#define GMYTH_QUERY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_QUERY_TYPE, GMythQueryClass))
59.48 +
59.49 +
59.50 +typedef struct _GMythQuery GMythQuery;
59.51 +typedef struct _GMythQueryClass GMythQueryClass;
59.52 +
59.53 +struct _GMythQueryClass
59.54 +{
59.55 + GObjectClass parent_class;
59.56 +
59.57 + /* callbacks */
59.58 + /* no one for now */
59.59 +};
59.60 +
59.61 +struct _GMythQuery
59.62 +{
59.63 + GObject parent;
59.64 +
59.65 + GString *opt_host_name; /* server host (default=localhost) */
59.66 + GString *opt_user_name; /* username (default=login name) */
59.67 + GString *opt_password; /* password (default=none) */
59.68 + unsigned int opt_port_num; /* port number (use built-in value) */
59.69 + GString *opt_socket_name; /* socket name (use built-in value) */
59.70 + GString *opt_db_name; /* database name (default=none) */
59.71 + unsigned int opt_flags; /* connection flags (none) */
59.72 + MYSQL *conn; /* pointer to connection handler */
59.73 +};
59.74 +
59.75 +
59.76 +GType gmyth_query_get_type (void);
59.77 +
59.78 +GMythQuery* gmyth_query_new ();
59.79 +MYSQL_RES * gmyth_query_process_statement
59.80 + (GMythQuery *gmyth_query, char *stmt_str);
59.81 +
59.82 +gboolean gmyth_query_connect (GMythQuery *gmyth_query);
59.83 +gboolean gmyth_query_disconnect (GMythQuery *gmyth_query);
59.84 +
59.85 +#define G_END_DECLS
59.86 +
59.87 +#endif /* __GMYTH_QUERY_H__ */
60.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
60.2 +++ b/gmyth/src/libgmyth/gmyth_remote_encoder.c Wed Sep 20 23:45:35 2006 +0100
60.3 @@ -0,0 +1,207 @@
60.4 +/**
60.5 + * GMyth Library
60.6 + *
60.7 + * @file gmyth/gmyth_remote_encoder.c
60.8 + *
60.9 + * @brief <p> GMythRemoteEncoder class defines functions for playing live tv.
60.10 + *
60.11 + * The remote encoder is used by gmyth_tvplayer to setup livetv.
60.12 + *
60.13 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
60.14 + * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
60.15 + *
60.16 + *//*
60.17 + *
60.18 + * This program is free software; you can redistribute it and/or modify
60.19 + * it under the terms of the GNU Lesser General Public License as published by
60.20 + * the Free Software Foundation; either version 2 of the License, or
60.21 + * (at your option) any later version.
60.22 + *
60.23 + * This program is distributed in the hope that it will be useful,
60.24 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
60.25 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
60.26 + * GNU General Public License for more details.
60.27 + *
60.28 + * You should have received a copy of the GNU Lesser General Public License
60.29 + * along with this program; if not, write to the Free Software
60.30 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
60.31 + */
60.32 +
60.33 +#include "gmyth_remote_encoder.h"
60.34 +
60.35 +#include <assert.h>
60.36 +
60.37 +#include "gmyth_stringlist.h"
60.38 +
60.39 +static void gmyth_remote_encoder_class_init (GMythRemoteEncoderClass *klass);
60.40 +static void gmyth_remote_encoder_init (GMythRemoteEncoder *object);
60.41 +
60.42 +static void gmyth_remote_encoder_dispose (GObject *object);
60.43 +static void gmyth_remote_encoder_finalize (GObject *object);
60.44 +
60.45 +G_DEFINE_TYPE(GMythRemoteEncoder, gmyth_remote_encoder, G_TYPE_OBJECT)
60.46 +
60.47 +static void
60.48 +gmyth_remote_encoder_class_init (GMythRemoteEncoderClass *klass)
60.49 +{
60.50 + GObjectClass *gobject_class;
60.51 +
60.52 + gobject_class = (GObjectClass *) klass;
60.53 +
60.54 + gobject_class->dispose = gmyth_remote_encoder_dispose;
60.55 + gobject_class->finalize = gmyth_remote_encoder_finalize;
60.56 +}
60.57 +
60.58 +static void
60.59 +gmyth_remote_encoder_init (GMythRemoteEncoder *gmyth_remote_encoder)
60.60 +{
60.61 +}
60.62 +
60.63 +static void
60.64 +gmyth_remote_encoder_dispose (GObject *object)
60.65 +{
60.66 + // GMythRemoteEncoder *gmyth_remote_encoder = GMYTH_REMOTE_ENCODER(object);
60.67 +
60.68 + G_OBJECT_CLASS (gmyth_remote_encoder_parent_class)->dispose (object);
60.69 +}
60.70 +
60.71 +
60.72 +static void
60.73 +gmyth_remote_encoder_finalize (GObject *object)
60.74 +{
60.75 + g_signal_handlers_destroy (object);
60.76 +
60.77 + GMythRemoteEncoder *remote_encoder = GMYTH_REMOTE_ENCODER(object);
60.78 +
60.79 + g_debug ("[%s] Closing control socket", __FUNCTION__);
60.80 + gmyth_socket_close_connection(remote_encoder->myth_socket);
60.81 + g_object_unref (remote_encoder->myth_socket);
60.82 +
60.83 + G_OBJECT_CLASS (gmyth_remote_encoder_parent_class)->finalize (object);
60.84 +}
60.85 +
60.86 +/** Creates a new instance of GMythRemoteEncoder.
60.87 + *
60.88 + * @return a new instance of GMythRemoteEncoder.
60.89 + */
60.90 +GMythRemoteEncoder*
60.91 +gmyth_remote_encoder_new (int num, GString *hostname, gshort port)
60.92 +{
60.93 + GMythRemoteEncoder *encoder = GMYTH_REMOTE_ENCODER ( g_object_new (
60.94 + GMYTH_REMOTE_ENCODER_TYPE, FALSE ));
60.95 +
60.96 + encoder->recorder_num = num;
60.97 + encoder->hostname = g_string_new (hostname->str);
60.98 + encoder->port = port;
60.99 +
60.100 + return encoder;
60.101 +}
60.102 +
60.103 +/** Configures the remote encoder instance connecting it to Mythtv backend.
60.104 + *
60.105 + * @param remote_encoder the GMythRemoteEncoder instance.
60.106 + * @return TRUE if successfull, FALSE if any error happens.
60.107 + */
60.108 +gboolean
60.109 +gmyth_remote_encoder_setup (GMythRemoteEncoder *remote_encoder)
60.110 +{
60.111 + assert (remote_encoder);
60.112 + g_debug ("[%s] Creating socket and connecting to backend", __FUNCTION__);
60.113 +
60.114 + if (remote_encoder->myth_socket == NULL) {
60.115 +
60.116 + remote_encoder->myth_socket = gmyth_socket_new ();
60.117 +
60.118 + if (!gmyth_socket_connect_to_backend (remote_encoder->myth_socket, remote_encoder->hostname->str,
60.119 + remote_encoder->port, TRUE) ) {
60.120 + g_warning ("GMythRemoteEncoder: Connection to backend failed");
60.121 + return FALSE;
60.122 + }
60.123 +
60.124 + } else {
60.125 + g_warning("Remote encoder socket already created\n");
60.126 + }
60.127 +
60.128 + return TRUE;
60.129 +}
60.130 +
60.131 +/** Sends the SPAWN_LIVETV command through Mythtv protocol. This command
60.132 + * requests the backend to start capturing TV content.
60.133 + *
60.134 + * @param remote_encoder The GMythRemoteEncoder instance.
60.135 + * @param tvchain_id The tvchain unique id.
60.136 + * @return true if success, false if any error happens.
60.137 + */
60.138 +gboolean
60.139 +gmyth_remote_encoder_spawntv (GMythRemoteEncoder *remote_encoder, GString *tvchain_id)
60.140 +{
60.141 + GMythStringList *str_list;
60.142 + GString *tmp_str;
60.143 +
60.144 + g_debug ("[%s] Spawntv with tvchain_id = %s", __FUNCTION__, tvchain_id->str);
60.145 +
60.146 + str_list = gmyth_string_list_new ();
60.147 +
60.148 + tmp_str = g_string_new ("QUERY_RECORDER ");
60.149 + g_string_append_printf (tmp_str, "%d", remote_encoder->recorder_num);
60.150 +
60.151 + gmyth_string_list_append_string (str_list, tmp_str);
60.152 + gmyth_string_list_append_string (str_list, g_string_new ("SPAWN_LIVETV"));
60.153 + gmyth_string_list_append_string (str_list, tvchain_id);
60.154 + gmyth_string_list_append_int (str_list, 0); // PIP = FALSE (0)
60.155 +
60.156 + gmyth_socket_sendreceive_stringlist (remote_encoder->myth_socket, str_list);
60.157 +
60.158 + g_string_free (tmp_str, TRUE);
60.159 +
60.160 + tmp_str = gmyth_string_list_get_string (str_list, 0);
60.161 + if (tmp_str == NULL) {
60.162 + g_warning ("[%s] Spawntv request returned %s", __FUNCTION__, tmp_str->str);
60.163 + return FALSE;
60.164 + }
60.165 +
60.166 + if (g_ascii_strncasecmp (tmp_str->str, "ok", 2)) {
60.167 + g_warning ("[%s] Spawntv request returned %s", __FUNCTION__, tmp_str->str);
60.168 + g_object_unref (str_list);
60.169 + return FALSE;
60.170 + }
60.171 +
60.172 + g_object_unref (str_list);
60.173 + return TRUE;
60.174 +
60.175 +}
60.176 +
60.177 +/** Sends the command STOP_LIVETV to Mythtv backend.
60.178 + *
60.179 + * @param remote_encoder the GMythRemoteEncoder instance.
60.180 + * @return true if success, false if any error happens.
60.181 + */
60.182 +gboolean
60.183 +gmyth_remote_encoder_stop_livetv (GMythRemoteEncoder *remote_encoder)
60.184 +{
60.185 + GMythStringList *str_list;
60.186 + GString *tmp_str;
60.187 +
60.188 + g_debug ("[%s]", __FUNCTION__);
60.189 +
60.190 + str_list = gmyth_string_list_new ();
60.191 +
60.192 + tmp_str = g_string_new ("QUERY_RECORDER ");
60.193 + g_string_append_printf (tmp_str, "%d", remote_encoder->recorder_num);
60.194 + gmyth_string_list_append_string (str_list, g_string_new ("STOP_LIVETV"));
60.195 +
60.196 + gmyth_socket_sendreceive_stringlist (remote_encoder->myth_socket, str_list);
60.197 +
60.198 + g_string_free (tmp_str, TRUE);
60.199 +
60.200 + tmp_str = gmyth_string_list_get_string (str_list, 0);
60.201 + if (g_ascii_strncasecmp (tmp_str->str, "ok", 2)) {
60.202 + g_warning ("[%s] Stop livetv request returned %s", __FUNCTION__, tmp_str->str);
60.203 + g_object_unref (str_list);
60.204 + return FALSE;
60.205 + }
60.206 +
60.207 + g_object_unref (str_list);
60.208 + return TRUE;
60.209 +
60.210 +}
61.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
61.2 +++ b/gmyth/src/libgmyth/gmyth_remote_encoder.h Wed Sep 20 23:45:35 2006 +0100
61.3 @@ -0,0 +1,89 @@
61.4 +/**
61.5 + * GMyth Library
61.6 + *
61.7 + * @file gmyth/gmyth_remote_encoder.h
61.8 + *
61.9 + * @brief <p> GMythRemoteEncoder class defines functions for playing live tv.
61.10 + *
61.11 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
61.12 + * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
61.13 + *
61.14 + *//*
61.15 + *
61.16 + * This program is free software; you can redistribute it and/or modify
61.17 + * it under the terms of the GNU Lesser General Public License as published by
61.18 + * the Free Software Foundation; either version 2 of the License, or
61.19 + * (at your option) any later version.
61.20 + *
61.21 + * This program is distributed in the hope that it will be useful,
61.22 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
61.23 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
61.24 + * GNU General Public License for more details.
61.25 + *
61.26 + * You should have received a copy of the GNU Lesser General Public License
61.27 + * along with this program; if not, write to the Free Software
61.28 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
61.29 + */
61.30 +
61.31 +#ifndef __GMYTH_REMOTE_ENCODER_H__
61.32 +#define __GMYTH_REMOTE_ENCODER_H__
61.33 +
61.34 +#include <glib-object.h>
61.35 +
61.36 +#include "gmyth_socket.h"
61.37 +
61.38 +#include <stdio.h>
61.39 +#include <stdlib.h>
61.40 +#include <string.h>
61.41 +#include <netdb.h>
61.42 +#include <sys/socket.h>
61.43 +#include <unistd.h>
61.44 +
61.45 +#define G_BEGIN_DECLS
61.46 +
61.47 +#define GMYTH_REMOTE_ENCODER_TYPE (gmyth_remote_encoder_get_type ())
61.48 +#define GMYTH_REMOTE_ENCODER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_REMOTE_ENCODER_TYPE, GMythRemoteEncoder))
61.49 +#define GMYTH_REMOTE_ENCODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_REMOTE_ENCODER_TYPE, GMythRemoteEncoderClass))
61.50 +#define IS_GMYTH_REMOTE_ENCODER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_REMOTE_ENCODER_TYPE))
61.51 +#define IS_GMYTH_REMOTE_ENCODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_REMOTE_ENCODER_TYPE))
61.52 +#define GMYTH_REMOTE_ENCODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_REMOTE_ENCODER_TYPE, GMythRemoteEncoderClass))
61.53 +
61.54 +
61.55 +typedef struct _GMythRemoteEncoder GMythRemoteEncoder;
61.56 +typedef struct _GMythRemoteEncoderClass GMythRemoteEncoderClass;
61.57 +
61.58 +struct _GMythRemoteEncoderClass
61.59 +{
61.60 + GObjectClass parent_class;
61.61 +
61.62 + /* callbacks */
61.63 + /* no one for now */
61.64 +};
61.65 +
61.66 +struct _GMythRemoteEncoder
61.67 +{
61.68 + GObject parent;
61.69 +
61.70 + /* socket descriptor */
61.71 + GMythSocket *myth_socket;
61.72 +
61.73 + int recorder_num;
61.74 + GString *hostname;
61.75 + int port;
61.76 +};
61.77 +
61.78 +
61.79 +GType gmyth_remote_encoder_get_type (void);
61.80 +
61.81 +GMythRemoteEncoder* gmyth_remote_encoder_new (int num,
61.82 + GString *hostname,
61.83 + gshort port);
61.84 +
61.85 +gboolean gmyth_remote_encoder_setup (GMythRemoteEncoder *encoder);
61.86 +gboolean gmyth_remote_encoder_spawntv (GMythRemoteEncoder *remote_encoder,
61.87 + GString *tvchain_id);
61.88 +gboolean gmyth_remote_encoder_stop_livetv (GMythRemoteEncoder *remote_encoder);
61.89 +
61.90 +#define G_END_DECLS
61.91 +
61.92 +#endif /* __GMYTH_REMOTE_ENCODER_H__ */
62.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
62.2 +++ b/gmyth/src/libgmyth/gmyth_remote_util.c Wed Sep 20 23:45:35 2006 +0100
62.3 @@ -0,0 +1,70 @@
62.4 +/**
62.5 + * GMyth Library
62.6 + *
62.7 + * @file gmyth/gmyth_remote_util.c
62.8 + *
62.9 + * @brief <p> This component provides utility functions for accessing remote data.
62.10 + *
62.11 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
62.12 + * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
62.13 + *
62.14 + *//*
62.15 + *
62.16 + * This program is free software; you can redistribute it and/or modify
62.17 + * it under the terms of the GNU Lesser General Public License as published by
62.18 + * the Free Software Foundation; either version 2 of the License, or
62.19 + * (at your option) any later version.
62.20 + *
62.21 + * This program is distributed in the hope that it will be useful,
62.22 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
62.23 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
62.24 + * GNU General Public License for more details.
62.25 + *
62.26 + * You should have received a copy of the GNU Lesser General Public License
62.27 + * along with this program; if not, write to the Free Software
62.28 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
62.29 + */
62.30 +
62.31 +#include "gmyth_remote_util.h"
62.32 +
62.33 +#include "gmyth_context.h"
62.34 +#include "gmyth_remote_encoder.h"
62.35 +#include "gmyth_stringlist.h"
62.36 +
62.37 +/** Requests the Mythtv backend for a free remote recorder.
62.38 + *
62.39 + * @param curr The recorder index, or -1 to consider the first one.
62.40 + * @return the remote encoder instance available, or NULL if any error happens.
62.41 + */
62.42 +GMythRemoteEncoder*
62.43 +remote_request_next_free_recorder (int curr)
62.44 +{
62.45 + GMythRemoteEncoder *encoder;
62.46 + GString *hostname;
62.47 + int num, port;
62.48 +
62.49 + GMythStringList *strlist = gmyth_string_list_new();
62.50 +
62.51 + g_debug ("[%s] Request next free recorder in the backend", __FUNCTION__);
62.52 +
62.53 + gmyth_string_list_append_char_array (strlist, "GET_NEXT_FREE_RECORDER");
62.54 + gmyth_string_list_append_int (strlist, curr);
62.55 +
62.56 + if (!gmyth_context_send_receive_stringlist(strlist)) {
62.57 + g_warning ("GET_NEXT_FREE_RECORDER request error!\n");
62.58 + return NULL;
62.59 + }
62.60 +
62.61 + num = gmyth_string_list_get_int (strlist, 0);
62.62 + hostname = gmyth_string_list_get_string (strlist, 1);
62.63 + port = gmyth_string_list_get_int (strlist, 2);
62.64 +
62.65 + g_debug ("[%s] Free recorder info received: num: %d, hostname: %s, port: %d",
62.66 + __FUNCTION__, num, hostname->str, port);
62.67 +
62.68 + encoder = gmyth_remote_encoder_new (num, hostname, port);
62.69 +
62.70 + g_object_unref (strlist);
62.71 +
62.72 + return encoder;
62.73 +}
63.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
63.2 +++ b/gmyth/src/libgmyth/gmyth_remote_util.h Wed Sep 20 23:45:35 2006 +0100
63.3 @@ -0,0 +1,35 @@
63.4 +/**
63.5 + * GMyth Library
63.6 + *
63.7 + * @file gmyth/gmyth_remote_util.h
63.8 + *
63.9 + * @brief <p> This component provides utility functions for accessing remote data.
63.10 + *
63.11 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
63.12 + * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
63.13 + *
63.14 + *//*
63.15 + *
63.16 + * This program is free software; you can redistribute it and/or modify
63.17 + * it under the terms of the GNU Lesser General Public License as published by
63.18 + * the Free Software Foundation; either version 2 of the License, or
63.19 + * (at your option) any later version.
63.20 + *
63.21 + * This program is distributed in the hope that it will be useful,
63.22 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
63.23 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
63.24 + * GNU General Public License for more details.
63.25 + *
63.26 + * You should have received a copy of the GNU Lesser General Public License
63.27 + * along with this program; if not, write to the Free Software
63.28 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
63.29 + */
63.30 +
63.31 +#ifndef __REMOTE_UTIL_H__
63.32 +#define __REMOTE_UTIL_H__
63.33 +
63.34 +#include "gmyth_remote_encoder.h"
63.35 +
63.36 +GMythRemoteEncoder* remote_request_next_free_recorder (int curr);
63.37 +
63.38 +#endif
64.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
64.2 +++ b/gmyth/src/libgmyth/gmyth_scheduler.c Wed Sep 20 23:45:35 2006 +0100
64.3 @@ -0,0 +1,610 @@
64.4 +/**
64.5 + * GMyth Library
64.6 + *
64.7 + * @file gmyth/gmyth_scheduler.c
64.8 + *
64.9 + * @brief <p> The scheduler encapsulates all functions for browsing, scheduling
64.10 + * and modifying the recorded content.
64.11 + *
64.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
64.13 + * @author Alexsandro Jose Virginio dos Santos <alexsandro.santos@indt.org.br>
64.14 + *
64.15 + *//*
64.16 + *
64.17 + * This program is free software; you can redistribute it and/or modify
64.18 + * it under the terms of the GNU Lesser General Public License as published by
64.19 + * the Free Software Foundation; either version 2 of the License, or
64.20 + * (at your option) any later version.
64.21 + *
64.22 + * This program is distributed in the hope that it will be useful,
64.23 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
64.24 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
64.25 + * GNU General Public License for more details.
64.26 + *
64.27 + * You should have received a copy of the GNU Lesser General Public License
64.28 + * along with this program; if not, write to the Free Software
64.29 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
64.30 + */
64.31 +
64.32 +#include <assert.h>
64.33 +
64.34 +#include "gmyth_scheduler.h"
64.35 +
64.36 +#include "gmyth_context.h"
64.37 +#include "gmyth_util.h"
64.38 +#include "gmyth_query.h"
64.39 +
64.40 +static void gmyth_scheduler_class_init (GMythSchedulerClass *klass);
64.41 +static void gmyth_scheduler_init (GMythScheduler *object);
64.42 +
64.43 +static void gmyth_scheduler_dispose (GObject *object);
64.44 +static void gmyth_scheduler_finalize (GObject *object);
64.45 +
64.46 +static gint get_record_id_from_database (GMythScheduler *scheduler);
64.47 +static void update_backend (gint record_id);
64.48 +
64.49 +G_DEFINE_TYPE(GMythScheduler, gmyth_scheduler, G_TYPE_OBJECT)
64.50 +
64.51 +static void
64.52 +gmyth_scheduler_class_init (GMythSchedulerClass *klass)
64.53 +{
64.54 + GObjectClass *gobject_class;
64.55 +
64.56 + gobject_class = (GObjectClass *) klass;
64.57 +
64.58 + gobject_class->dispose = gmyth_scheduler_dispose;
64.59 + gobject_class->finalize = gmyth_scheduler_finalize;
64.60 +}
64.61 +
64.62 +static void
64.63 +gmyth_scheduler_init (GMythScheduler *sched)
64.64 +{
64.65 + sched->recordid =0;
64.66 + sched->type = 0;
64.67 + sched->search = 0;
64.68 + sched->profile = g_string_new("");
64.69 +
64.70 + sched->dupin = 0;
64.71 + sched->dupmethod = 0;
64.72 + sched->autoexpire = 0;
64.73 + sched->autotranscode = 0;
64.74 + sched->transcoder = 0;
64.75 +
64.76 + sched->autocommflag = 0;
64.77 + sched->autouserjob1 = 0;
64.78 + sched->autouserjob2 = 0;
64.79 + sched->autouserjob3 = 0;
64.80 + sched->autouserjob4 = 0;
64.81 +
64.82 + sched->startoffset = 0;
64.83 + sched->endoffset = 0;
64.84 + sched->maxepisodes = 0;
64.85 + sched->maxnewest = 0;
64.86 +
64.87 + sched->recpriority = 0;
64.88 + sched->recgroup = 0;
64.89 + sched->playgroup = 0;
64.90 +
64.91 + sched->prefinput = 0;
64.92 + sched->inactive = 0;
64.93 +
64.94 + sched->searchType = g_string_new("");
64.95 + sched->searchForWhat = g_string_new("");
64.96 +
64.97 + sched->msqlquery = gmyth_query_new ();
64.98 +}
64.99 +
64.100 +static void
64.101 +gmyth_scheduler_dispose (GObject *object)
64.102 +{
64.103 + G_OBJECT_CLASS (gmyth_scheduler_parent_class)->dispose (object);
64.104 +}
64.105 +
64.106 +static void
64.107 +gmyth_scheduler_finalize (GObject *object)
64.108 +{
64.109 + g_signal_handlers_destroy (object);
64.110 +
64.111 + G_OBJECT_CLASS (gmyth_scheduler_parent_class)->finalize (object);
64.112 +}
64.113 +
64.114 +/** Creates a new instance of GMythScheduler.
64.115 + *
64.116 + * @return a new instance of GMythScheduler.
64.117 + */
64.118 +GMythScheduler*
64.119 +gmyth_scheduler_new ()
64.120 +{
64.121 + GMythScheduler *scheduler =
64.122 + GMYTH_SCHEDULER (g_object_new(GMYTH_SCHEDULER_TYPE, NULL));
64.123 +
64.124 + return scheduler;
64.125 +}
64.126 +
64.127 +/** Connects to the Mysql database in the backend. The backend address
64.128 + * is loaded from the GMythSettings instance.
64.129 + *
64.130 + * @param scheduler the GMythScheduler instance to be connected.
64.131 + * @return true if connection was success, false if failed.
64.132 + */
64.133 +gboolean
64.134 +gmyth_scheduler_connect (GMythScheduler *scheduler)
64.135 +{
64.136 + assert(scheduler);
64.137 +
64.138 + if (scheduler->msqlquery == NULL) {
64.139 + g_warning ("[%s] MMythScheduler not initialized", __FUNCTION__);
64.140 + return FALSE;
64.141 + }
64.142 +
64.143 + if (!gmyth_query_connect(scheduler->msqlquery)) {
64.144 + g_warning ("[%s] Error while connecting to db", __FUNCTION__);
64.145 + return FALSE;
64.146 + }
64.147 +
64.148 + return TRUE;
64.149 +}
64.150 +
64.151 +/** Disconnects from the Mysql database in the backend.
64.152 + *
64.153 + * @param scheduler the GMythScheduler instance to be disconnected
64.154 + * @return true if disconnection was success, false if failed.
64.155 + */
64.156 +gboolean
64.157 +gmyth_scheduler_disconnect (GMythScheduler *scheduler)
64.158 +{
64.159 + assert(scheduler);
64.160 +
64.161 + if (scheduler->msqlquery != NULL) {
64.162 + g_object_unref (scheduler->msqlquery);
64.163 + }
64.164 +
64.165 + return TRUE;
64.166 +}
64.167 +
64.168 +/** Retrieves from the backend Mysql database the list of recording schedules.
64.169 + *
64.170 + * @param scheduler The GMythScheduler instance.
64.171 + * @param schedule_list the GList pointer to be filled with the loaded list of ScheduleInfo items.
64.172 + * @return The amount of schedules retrieved from database, or -1 if error.
64.173 + */
64.174 +gint
64.175 +gmyth_scheduler_get_schedule_list ( GMythScheduler *scheduler, GList **schedule_list)
64.176 +{
64.177 + ScheduleInfo *schedule;
64.178 + MYSQL_RES *msql_res;
64.179 + GString *query_str = g_string_new ("");
64.180 + GString *date_time = g_string_new ("");
64.181 +
64.182 + assert(scheduler);
64.183 +
64.184 + g_string_printf (query_str,
64.185 + "SELECT recordid,programid,chanid,starttime,startdate,"
64.186 + "endtime,enddate,title,subtitle,description,category FROM record;");
64.187 +
64.188 + if (scheduler->msqlquery == NULL) {
64.189 + g_warning ("[%s] Scheduler db connection not initialized", __FUNCTION__);
64.190 + return -1;
64.191 + }
64.192 + msql_res = gmyth_query_process_statement (scheduler->msqlquery, query_str->str);
64.193 +
64.194 + if (msql_res == NULL) {
64.195 + g_warning ("DB retrieval of schedule list failed");
64.196 + return -1;
64.197 + } else {
64.198 + MYSQL_ROW row;
64.199 + *schedule_list = NULL;
64.200 +
64.201 + while((row = mysql_fetch_row (msql_res)) != NULL) {
64.202 + schedule = g_new0(ScheduleInfo, 1);
64.203 +
64.204 + schedule->record_id = atoi (row[0]);
64.205 + schedule->program_id = atoi (row[1]);
64.206 + schedule->channel_id = atoi (row[2]);
64.207 +
64.208 + /* generate a time_t from a time and a date db field */
64.209 + g_string_printf (date_time, "%s %s", row[4], row[3]);
64.210 +
64.211 + schedule->start_time = gmyth_util_string_to_time (date_time);
64.212 +
64.213 + /* generate a time_t from a time and a date db field */
64.214 + g_string_printf (date_time, "%s %s", row[6], row[5]);
64.215 +
64.216 + schedule->end_time = gmyth_util_string_to_time (date_time);
64.217 +
64.218 + schedule->title = g_string_new (row[7]);
64.219 + schedule->subtitle = g_string_new (row[8]);
64.220 + schedule->description = g_string_new (row[9]);
64.221 + schedule->category = g_string_new (row[10]);
64.222 +
64.223 + (*schedule_list) = g_list_append (*(schedule_list), schedule);
64.224 + }
64.225 + }
64.226 +
64.227 + mysql_free_result (msql_res);
64.228 + g_string_free(query_str, TRUE);
64.229 + g_string_free(date_time, TRUE);
64.230 +
64.231 + return (*schedule_list == NULL) ? 0 : g_list_length (*schedule_list);
64.232 +}
64.233 +
64.234 +/** Retrieves from the backend Mysql database the list of recorded programs.
64.235 + *
64.236 + * @param scheduler The GMythScheduler instance.
64.237 + * @param recorded_list the GList pointer to be filled with the loaded RecordInfo items.
64.238 + * @return The amount of recorded retrieved from database, or -1 if error.
64.239 + */
64.240 +gint
64.241 +gmyth_scheduler_get_recorded_list (GMythScheduler *scheduler, GList **recorded_list)
64.242 +{
64.243 + RecordedInfo *record;
64.244 + MYSQL_RES *msql_res;
64.245 + GString *query_str = g_string_new ("");
64.246 + GString *date_time = g_string_new ("");
64.247 +
64.248 + assert(scheduler);
64.249 +
64.250 + g_string_printf (query_str,
64.251 + "SELECT recordid,programid,chanid,starttime,progstart,"
64.252 + "endtime,progend,title,subtitle,description,category,basename FROM recorded;");
64.253 +
64.254 + if (scheduler->msqlquery == NULL) {
64.255 + g_warning ("[%s] Scheduler db connection not initialized", __FUNCTION__);
64.256 + return -1;
64.257 + }
64.258 +
64.259 + msql_res = gmyth_query_process_statement (scheduler->msqlquery, query_str->str);
64.260 +
64.261 + if (msql_res == NULL) {
64.262 + g_warning ("DB retrieval of recording list failed");
64.263 + return -1;
64.264 + } else {
64.265 + MYSQL_ROW row;
64.266 + *recorded_list = NULL;
64.267 +
64.268 + while((row = mysql_fetch_row (msql_res))!=NULL){
64.269 + record = g_new0(RecordedInfo, 1);
64.270 +
64.271 + record->record_id = atoi (row[0]);
64.272 + record->program_id = atoi (row[1]);
64.273 + record->channel_id = atoi (row[2]);
64.274 +
64.275 + /* the db field time already contains the date. therefore
64.276 + * we are not using the date field */
64.277 + /* generate a time_t from a time and a date db field */
64.278 + /* g_string_printf (date_time, "%s %s", row[4], row[3]); */
64.279 + g_string_printf (date_time, "%s", row[3]);
64.280 +
64.281 + record->start_time = gmyth_util_string_to_time (date_time);
64.282 +
64.283 + /* the db field time already contains the date. therefore
64.284 + * we are not using the date field */
64.285 + /* generate a time_t from a time and a date db field */
64.286 + /* g_string_printf (date_time, "%s %s", row[6], row[5]); */
64.287 + g_string_printf (date_time, "%s", row[5]);
64.288 +
64.289 + record->end_time = gmyth_util_string_to_time (date_time);
64.290 +
64.291 + record->title = g_string_new (row[7]);
64.292 + record->subtitle = g_string_new (row[8]);
64.293 + record->description = g_string_new (row[9]);
64.294 + record->category = g_string_new (row[10]);
64.295 + record->basename = g_string_new (row[11]);
64.296 +
64.297 + *recorded_list = g_list_append (*recorded_list, record);
64.298 + }
64.299 + }
64.300 +
64.301 + mysql_free_result (msql_res);
64.302 + g_string_free(query_str, TRUE);
64.303 + g_string_free(date_time, TRUE);
64.304 +
64.305 + return (*recorded_list == NULL) ? 0 : g_list_length (*recorded_list);
64.306 +}
64.307 +
64.308 +/** Requests the Mysql database in the backend to add a new schedule.
64.309 + *
64.310 + * @param scheduler the GMythScheduler instance.
64.311 + * @param schedule_info the ScheduleInfo with recording schedule information
64.312 + * to be added. record_id = -1 to add a new schedule, otherwise this
64.313 + * function will update the schedule in the db
64.314 + * @return gboolean returns FALSE if some error occurs, TRUE otherwise
64.315 + */
64.316 +gboolean
64.317 +gmyth_scheduler_add_schedule (GMythScheduler *scheduler,
64.318 + ScheduleInfo *schedule_info)
64.319 +{
64.320 + struct tm start_tm;
64.321 + struct tm end_tm;
64.322 +
64.323 + MYSQL_RES *msql_res;
64.324 + GString *query_str = g_string_new ("");
64.325 +
64.326 + assert(scheduler);
64.327 +
64.328 + if (scheduler->msqlquery == NULL) {
64.329 + g_warning ("[%s] Scheduler db connection not initialized", __FUNCTION__);
64.330 + return 0;
64.331 + }
64.332 +
64.333 + /* manipulating time */
64.334 + if(localtime_r(&schedule_info->start_time, &start_tm) == NULL) {
64.335 + g_warning ("localtime_r error in libgmyth scheduler!\n");
64.336 + return FALSE;
64.337 + }
64.338 +
64.339 + if(localtime_r(&schedule_info->end_time, &end_tm) == NULL) {
64.340 + g_warning ("localtime_r error in libgmyth scheduler!\n");
64.341 + return FALSE;
64.342 + }
64.343 +
64.344 + //TODO: verify if this funtion realy does what it should do!
64.345 + g_string_printf (query_str, "REPLACE INTO record "
64.346 + "(recordid, type, chanid, starttime, "
64.347 + "startdate, endtime, enddate, title,"
64.348 + "profile, recpriority, maxnewest, inactive, "
64.349 + "maxepisodes, autoexpire, startoffset, endoffset, "
64.350 + "recgroup, dupmethod, dupin, station, "
64.351 + "autocommflag, findday, findtime, findid, "
64.352 + "search, autotranscode, transcoder, tsdefault, "
64.353 + "autouserjob1, autouserjob2, autouserjob3, autouserjob4) "
64.354 + " values ( %d, 1, %d, \"%02d:%02d:00\"," //recordid, type, chanid, starttime
64.355 + " \"%d-%02d-%02d\", \"%02d:%02d:00\", \"%04d-%02d-%02d\", \"%s\","
64.356 + //startdate, endtime, enddate, title
64.357 + "DEFAULT, 0, 0, 0, " //profile, recpriority, maxnewest, inactive
64.358 + "0, 1, 0, 0, " //maxepisodes, autoexpire, startoffset, endoffset
64.359 + "DEFAULT, 6, 15, %d, " //recgroup, dupmethod, dupin, station
64.360 + "1, %d, \"%02d:%02d:00\", %d, " //autocommflag, findday, findtime, findid
64.361 + "5, 0, 29, 1, " //search, autotranscode, transcoder, tsdefault
64.362 + "0, 0, 0, 0 );", //autouserjob1, autouserjob2, autouserjob3, autouserjob4
64.363 + schedule_info->record_id, schedule_info->channel_id,
64.364 + start_tm.tm_hour, start_tm.tm_min,
64.365 + start_tm.tm_year+1900, start_tm.tm_mon+1,
64.366 + start_tm.tm_mday,
64.367 + end_tm.tm_hour, end_tm.tm_min,
64.368 + end_tm.tm_year+1900, end_tm.tm_mon+1,
64.369 + end_tm.tm_mday, schedule_info->title->str, //title
64.370 + schedule_info->channel_id,//station
64.371 + start_tm.tm_wday+1, //findday
64.372 + start_tm.tm_hour, start_tm.tm_min, //findtime
64.373 + (gint)(schedule_info->start_time/60/60/24 + 719528)//findid
64.374 + );
64.375 +
64.376 + msql_res = gmyth_query_process_statement (scheduler->msqlquery, query_str->str);
64.377 +
64.378 + /* FIXME: currently no way to detect db error in UPDATE, REPLACES!
64.379 + if (msql_res == NULL) {
64.380 + g_warning ("DB retrieval of recording list failed");
64.381 + return -1;
64.382 + }*/
64.383 +
64.384 + /* TODO: verify record_id = -1 semantics */
64.385 + if (schedule_info->record_id <= 0)
64.386 + schedule_info->record_id = get_record_id_from_database(scheduler);
64.387 +
64.388 + /* Notify the backend of changes */
64.389 + update_backend(schedule_info->record_id);
64.390 +
64.391 + /* free allocated memory */
64.392 + mysql_free_result (msql_res);
64.393 + g_string_free(query_str, TRUE);
64.394 +
64.395 + return 1;
64.396 +}
64.397 +
64.398 +/** Requests the Mysql database in the backend to remove an existing schedule.
64.399 + *
64.400 + * @param scheduler the GMythScheduler instance.
64.401 + * @param record_id The schedule's record id to be removed
64.402 + * @return gboolean TRUE if success, FALSE if error
64.403 + */
64.404 +gboolean
64.405 +gmyth_scheduler_delete_schedule (GMythScheduler *scheduler, gint record_id)
64.406 +{
64.407 +
64.408 + MYSQL_RES *msql_res;
64.409 + GString *query_str = g_string_new ("");
64.410 +
64.411 + assert(scheduler);
64.412 +
64.413 + if (scheduler->msqlquery == NULL) {
64.414 + g_warning ("[%s] Scheduler db connection not initialized", __FUNCTION__);
64.415 + return FALSE;
64.416 + }
64.417 +
64.418 + //========================================
64.419 + g_string_printf (query_str,
64.420 + "DELETE FROM record WHERE recordid=%d", record_id);
64.421 +
64.422 + msql_res = gmyth_query_process_statement (scheduler->msqlquery, query_str->str);
64.423 +
64.424 + if (msql_res == NULL) {
64.425 + g_warning ("[%s] Error while trying to delete a schedule in the database", __FUNCTION__);
64.426 + return FALSE;
64.427 + }
64.428 +
64.429 + update_backend(record_id);// Notify the backend of the changes
64.430 +
64.431 + mysql_free_result (msql_res);
64.432 + g_string_free(query_str, TRUE);
64.433 +
64.434 + return TRUE;
64.435 +}
64.436 +
64.437 +/** Requests the Mysql database in the backend to remove an existing recorded item.
64.438 + *
64.439 + * @param scheduler the GMythScheduler instance.
64.440 + * @param record_id The recorded item id to be removed
64.441 + * @return gboolean TRUE if success, FALSE if error
64.442 + */
64.443 +gboolean
64.444 +gmyth_scheduler_delete_recorded (GMythScheduler *scheduler, gint record_id)
64.445 +{
64.446 +
64.447 + MYSQL_RES *msql_res;
64.448 + GString *query_str = g_string_new ("");
64.449 +
64.450 + assert(scheduler);
64.451 +
64.452 + if (scheduler->msqlquery == NULL) {
64.453 + g_warning ("[%s] Scheduler db connection not initialized", __FUNCTION__);
64.454 + return FALSE;
64.455 + }
64.456 +
64.457 + //========================================
64.458 + g_string_printf (query_str,
64.459 + "DELETE FROM recorded WHERE recordid=%d", record_id);
64.460 +
64.461 + msql_res = gmyth_query_process_statement (scheduler->msqlquery, query_str->str);
64.462 +
64.463 + update_backend(record_id);// Notify the backend of the changes
64.464 +
64.465 + mysql_free_result (msql_res);
64.466 + g_string_free(query_str, TRUE);
64.467 +
64.468 + return TRUE;
64.469 +}
64.470 +
64.471 +/** Retrieves an existing recorded item information from database. The information
64.472 + * is used to fill the returned GMythProgramInfo.
64.473 + *
64.474 + * @param scheduler The GMythScheduler instance.
64.475 + * @param channel The channel associated to the record
64.476 + * @param starttime The record start time
64.477 + * @return A GMythProgramInfo struct with the requested record item
64.478 + * information, or NULL if error.
64.479 + */
64.480 +GMythProgramInfo*
64.481 +gmyth_scheduler_get_recorded (GMythScheduler *scheduler,
64.482 + GString *channel, time_t starttime)
64.483 +{
64.484 + MYSQL_RES *msql_res;
64.485 + GMythProgramInfo *proginfo = NULL;
64.486 + GString *query_str = g_string_new("");
64.487 + GString *time_str = gmyth_util_time_to_string (starttime);
64.488 +
64.489 + assert(scheduler);
64.490 +
64.491 + if (scheduler->msqlquery == NULL) {
64.492 + g_warning ("[%s] Scheduler db connection not initialized", __FUNCTION__);
64.493 + return NULL;
64.494 + }
64.495 +
64.496 + g_string_printf (query_str, "SELECT recorded.chanid,starttime,endtime,title, "
64.497 + "subtitle,description,channel.channum, "
64.498 + "channel.callsign,channel.name,channel.commfree, "
64.499 + "channel.outputfilters,seriesid,programid,filesize, "
64.500 + "lastmodified,stars,previouslyshown,originalairdate, "
64.501 + "hostname,recordid,transcoder,playgroup, "
64.502 + "recorded.recpriority,progstart,progend,basename,recgroup "
64.503 + "FROM recorded "
64.504 + "LEFT JOIN channel "
64.505 + "ON recorded.chanid = channel.chanid "
64.506 + "WHERE recorded.chanid = \"%s\" "
64.507 + "AND starttime = \"%s\" ;",
64.508 + channel->str, time_str->str);
64.509 +
64.510 + msql_res = gmyth_query_process_statement (scheduler->msqlquery, query_str->str);
64.511 +
64.512 + if (msql_res /*&& query.size() > 0*/) {
64.513 +
64.514 + MYSQL_ROW msql_row = mysql_fetch_row (msql_res);
64.515 + if (msql_row) {
64.516 +
64.517 + proginfo = g_new0 (GMythProgramInfo, 1);
64.518 +
64.519 + proginfo->chanid = g_string_new (msql_row[0]);
64.520 + proginfo->startts = gmyth_util_string_to_time (g_string_new (msql_row[23]));
64.521 + proginfo->endts = gmyth_util_string_to_time (g_string_new (msql_row[24]));
64.522 + proginfo->recstartts = gmyth_util_string_to_time (g_string_new (msql_row[1]));
64.523 + proginfo->recendts = gmyth_util_string_to_time (g_string_new (msql_row[2]));
64.524 + proginfo->title = g_string_new (msql_row[3]);
64.525 + proginfo->subtitle = g_string_new (msql_row[4]);
64.526 + proginfo->description = g_string_new (msql_row[5]);
64.527 +
64.528 + proginfo->chanstr = g_string_new (msql_row[6]);
64.529 + proginfo->chansign = g_string_new (msql_row[7]);
64.530 + proginfo->channame = g_string_new (msql_row[0]);
64.531 + proginfo->chancommfree = atoi (msql_row[9]);
64.532 + proginfo->chanOutputFilters = g_string_new (msql_row[10]);
64.533 + proginfo->seriesid = g_string_new (msql_row[11]);
64.534 + proginfo->programid = g_string_new (msql_row[12]);
64.535 + proginfo->filesize = atoll (msql_row[13]);
64.536 +
64.537 + proginfo->lastmodified = gmyth_util_string_to_time (g_string_new (msql_row[14]));
64.538 +
64.539 + proginfo->stars = atof (msql_row[15]);
64.540 + proginfo->repeat = atoi (msql_row[16]);
64.541 +
64.542 + if (msql_row[17] == NULL) {
64.543 + proginfo->originalAirDate = 0;
64.544 + proginfo->hasAirDate = FALSE;
64.545 + } else {
64.546 + proginfo->originalAirDate = gmyth_util_string_to_time (g_string_new (msql_row[17]));
64.547 + proginfo->hasAirDate = TRUE;
64.548 + }
64.549 +
64.550 + proginfo->hostname = g_string_new (msql_row[18]);
64.551 + proginfo->recordid = atoi (msql_row[19]);
64.552 + proginfo->transcoder = atoi (msql_row[20]);
64.553 +
64.554 + //proginfo->spread = -1;
64.555 + //proginfo->programflags = proginfo->getProgramFlags();
64.556 +
64.557 + proginfo->recgroup = g_string_new (msql_row[26]);
64.558 + proginfo->playgroup = g_string_new (msql_row[21]);
64.559 + proginfo->recpriority = atoi (msql_row[22]);
64.560 +
64.561 + proginfo->pathname = g_string_new (msql_row[25]);
64.562 +
64.563 + g_debug ("One program info loaded from mysql database\n");
64.564 + }
64.565 + }
64.566 +
64.567 + mysql_free_result (msql_res);
64.568 + g_string_free(query_str, TRUE);
64.569 + g_string_free(time_str, TRUE);
64.570 +
64.571 + return proginfo;
64.572 +}
64.573 +
64.574 +/** Retrieves the next record id.
64.575 + *
64.576 + * @param scheduler The GMythScheduler instance.
64.577 + * @return gint record_id if success, -1 otherwise
64.578 + */
64.579 +static gint
64.580 +get_record_id_from_database (GMythScheduler *scheduler)
64.581 +{
64.582 + gint record_id;
64.583 +
64.584 + assert(scheduler);
64.585 +
64.586 + if (scheduler->msqlquery == NULL) {
64.587 + g_warning ("[%s] Scheduler db connection not initialized", __FUNCTION__);
64.588 + return 0;
64.589 + }
64.590 +
64.591 + record_id = mysql_insert_id (scheduler->msqlquery->conn);
64.592 +
64.593 + return record_id;
64.594 +}
64.595 +
64.596 +/** Notifies the backend of an update in the db.
64.597 + *
64.598 + * @param record_id the id of the modified recording.
64.599 + */
64.600 +static void
64.601 +update_backend(gint record_id)//fixme: put void and discovery record_id inside
64.602 +{
64.603 + GMythStringList *strlist = gmyth_string_list_new ();
64.604 + GString *datastr = g_string_new ("RESCHEDULE_RECORDINGS ");
64.605 +
64.606 + g_string_append_printf (datastr, "%d", record_id);
64.607 + gmyth_string_list_append_string (strlist, datastr);
64.608 +
64.609 + gmyth_context_send_receive_stringlist (strlist);
64.610 +
64.611 + g_string_free(datastr, TRUE);
64.612 + g_object_unref(strlist);
64.613 +}
65.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
65.2 +++ b/gmyth/src/libgmyth/gmyth_scheduler.h Wed Sep 20 23:45:35 2006 +0100
65.3 @@ -0,0 +1,156 @@
65.4 +/**
65.5 + * GMyth Library
65.6 + *
65.7 + * @file gmyth/gmyth_scheduler.h
65.8 + *
65.9 + * @brief <p> The scheduler encapsulates all functions for browsing, scheduling
65.10 + * and modifying the recorded content.
65.11 + *
65.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
65.13 + * @author Alexsandro Jose Virginio dos Santos <alexsandro.santos@indt.org.br>
65.14 + *
65.15 + *//*
65.16 + *
65.17 + * This program is free software; you can redistribute it and/or modify
65.18 + * it under the terms of the GNU Lesser General Public License as published by
65.19 + * the Free Software Foundation; either version 2 of the License, or
65.20 + * (at your option) any later version.
65.21 + *
65.22 + * This program is distributed in the hope that it will be useful,
65.23 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
65.24 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
65.25 + * GNU General Public License for more details.
65.26 + *
65.27 + * You should have received a copy of the GNU Lesser General Public License
65.28 + * along with this program; if not, write to the Free Software
65.29 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
65.30 + */
65.31 +
65.32 +#ifndef __GMYTH_SCHEDULER_H__
65.33 +#define __GMYTH_SCHEDULER_H__
65.34 +
65.35 +#include <glib-object.h>
65.36 +#include <time.h>
65.37 +
65.38 +#include "gmyth_common.h"
65.39 +#include "gmyth_query.h"
65.40 +
65.41 +#define G_BEGIN_DECLS
65.42 +
65.43 +#define GMYTH_SCHEDULER_TYPE (gmyth_scheduler_get_type ())
65.44 +#define GMYTH_SCHEDULER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_SCHEDULER_TYPE, GMythScheduler))
65.45 +#define GMYTH_SCHEDULER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_SCHEDULER_TYPE, GMythSchedulerClass))
65.46 +#define IS_GMYTH_SCHEDULER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_SCHEDULER_TYPE))
65.47 +#define IS_GMYTH_SCHEDULER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_SCHEDULER_TYPE))
65.48 +#define GMYTH_SCHEDULER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_SCHEDULER_TYPE, GMythSchedulerClass))
65.49 +
65.50 +
65.51 +typedef struct _GMythScheduler GMythScheduler;
65.52 +typedef struct _GMythSchedulerClass GMythSchedulerClass;
65.53 +
65.54 +struct _GMythSchedulerClass
65.55 +{
65.56 + GObjectClass parent_class;
65.57 +
65.58 + /* callbacks */
65.59 + /* no one for now */
65.60 +};
65.61 +
65.62 +struct _GMythScheduler
65.63 +{
65.64 + GObject parent;
65.65 +
65.66 + unsigned long recordid;
65.67 + unsigned long type;
65.68 + unsigned long search;
65.69 + GString *profile;
65.70 +
65.71 + long dupin;
65.72 + long dupmethod;
65.73 + long autoexpire;
65.74 + short int autotranscode;
65.75 + long transcoder;
65.76 +
65.77 + short int autocommflag;
65.78 + short int autouserjob1;
65.79 + short int autouserjob2;
65.80 + short int autouserjob3;
65.81 + short int autouserjob4;
65.82 +
65.83 + long startoffset;
65.84 + long endoffset;
65.85 + long maxepisodes;
65.86 + long maxnewest;
65.87 +
65.88 + long recpriority;
65.89 + GString *recgroup;
65.90 + GString *playgroup;
65.91 +
65.92 + long prefinput;
65.93 + short int inactive;
65.94 +
65.95 + GString *searchType;
65.96 + GString *searchForWhat;
65.97 +
65.98 + GMythQuery *msqlquery;
65.99 +};
65.100 +
65.101 +typedef struct {
65.102 + gint record_id;
65.103 + gint program_id;
65.104 + gint channel_id;
65.105 +
65.106 + time_t start_time;
65.107 + time_t end_time;
65.108 +
65.109 + GString *title;
65.110 + GString *subtitle;
65.111 + GString *description;
65.112 + GString *category;
65.113 +
65.114 +} ScheduleInfo;
65.115 +
65.116 +typedef struct {
65.117 + gint record_id;
65.118 + gint program_id;
65.119 + gint channel_id;
65.120 +
65.121 + time_t start_time;
65.122 + time_t end_time;
65.123 +
65.124 + GString *title;
65.125 + GString *subtitle;
65.126 + GString *description;
65.127 + GString *category;
65.128 +
65.129 + GString *basename;
65.130 +
65.131 +} RecordedInfo;
65.132 +
65.133 +
65.134 +GType gmyth_scheduler_get_type (void);
65.135 +
65.136 +GMythScheduler* gmyth_scheduler_new ();
65.137 +gboolean gmyth_scheduler_connect (GMythScheduler *scheduler);
65.138 +gboolean gmyth_scheduler_disconnect (GMythScheduler *scheduler);
65.139 +
65.140 +gint gmyth_scheduler_get_schedule_list (GMythScheduler *scheduler,
65.141 + GList **sched_list);
65.142 +gint gmyth_scheduler_get_recorded_list (GMythScheduler *scheduler,
65.143 + GList **rec_list);
65.144 +
65.145 +GMythProgramInfo* gmyth_scheduler_get_recorded (GMythScheduler *scheduler,
65.146 + GString *channel, time_t starttime);
65.147 +
65.148 +gint gmyth_scheduler_add_schedule(GMythScheduler *scheduler,
65.149 + ScheduleInfo *schedule_info);
65.150 +
65.151 +gint gmyth_scheduler_delete_schedule (GMythScheduler *scheduler,
65.152 + gint record_id);
65.153 +gint gmyth_scheduler_delete_recorded (GMythScheduler *scheduler,
65.154 + gint record_id);
65.155 +
65.156 +#define G_END_DECLS
65.157 +
65.158 +#endif /* __GMYTH_SCHEDULER_H__ */
65.159 +
66.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
66.2 +++ b/gmyth/src/libgmyth/gmyth_settings.c Wed Sep 20 23:45:35 2006 +0100
66.3 @@ -0,0 +1,417 @@
66.4 +/**
66.5 + * GMyth Library
66.6 + *
66.7 + * @file gmyth/gmyth_settings.c
66.8 + *
66.9 + * @brief <p> This component contains functions acessing and modifying
66.10 + * user and program settings.
66.11 + *
66.12 + * The standard settings file is created in the user home folder, in the
66.13 + * file ~/.mmyth/settings.dat.
66.14 + *
66.15 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
66.16 + * @author Alexsandro Jose Virginio dos Santos <alexsandro.santos@indt.org.br>
66.17 + *
66.18 + *//*
66.19 + *
66.20 + * This program is free software; you can redistribute it and/or modify
66.21 + * it under the terms of the GNU Lesser General Public License as published by
66.22 + * the Free Software Foundation; either version 2 of the License, or
66.23 + * (at your option) any later version.
66.24 + *
66.25 + * This program is distributed in the hope that it will be useful,
66.26 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
66.27 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
66.28 + * GNU General Public License for more details.
66.29 + *
66.30 + * You should have received a copy of the GNU Lesser General Public License
66.31 + * along with this program; if not, write to the Free Software
66.32 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
66.33 + */
66.34 +
66.35 +#include "gmyth_settings.h"
66.36 +
66.37 +#include <string.h>
66.38 +#include <stdlib.h>
66.39 +#include <unistd.h>
66.40 +#include <fcntl.h>
66.41 +
66.42 +#include <glib.h>
66.43 +#include <glib/gprintf.h>
66.44 +#include <glib/gstdio.h>
66.45 +
66.46 +#define GMYTH_SETTINGS_FILE_NAME "settings.dat"
66.47 +#define GMYTH_SETTINGS_DIR ".mmyth"
66.48 +
66.49 +static void gmyth_settings_class_init (GMythSettingsClass *klass);
66.50 +static void gmyth_settings_init (GMythSettings *object);
66.51 +
66.52 +static void gmyth_settings_dispose (GObject *object);
66.53 +static void gmyth_settings_finalize (GObject *object);
66.54 +
66.55 +static void fill_settings_data(GMythSettings *gmyth_settings, char* line);
66.56 +
66.57 +G_DEFINE_TYPE(GMythSettings, gmyth_settings, G_TYPE_OBJECT)
66.58 +
66.59 +static void
66.60 +gmyth_settings_class_init (GMythSettingsClass *klass)
66.61 +{
66.62 + GObjectClass *gobject_class;
66.63 +
66.64 + gobject_class = (GObjectClass *) klass;
66.65 +
66.66 + gobject_class->dispose = gmyth_settings_dispose;
66.67 + gobject_class->finalize = gmyth_settings_finalize;
66.68 +}
66.69 +
66.70 +static void
66.71 +gmyth_settings_init (GMythSettings *gmyth_settings)
66.72 +{
66.73 +
66.74 + gmyth_settings->settings_file = NULL;
66.75 +
66.76 + gmyth_settings->backend_hostname = g_string_new("127.0.0.1");
66.77 + gmyth_settings->backend_port = 6543;
66.78 + gmyth_settings->mysql_dbname = g_string_new("mythconverg");
66.79 + gmyth_settings->mysql_username = g_string_new("mythtv");
66.80 + gmyth_settings->mysql_password = g_string_new("mythtv");
66.81 + gmyth_settings->database_type = g_string_new("mysql");
66.82 +
66.83 +}
66.84 +
66.85 +
66.86 +static void
66.87 +gmyth_settings_dispose (GObject *object)
66.88 +{
66.89 + GMythSettings *gmyth_settings = GMYTH_SETTINGS(object);
66.90 +
66.91 + if ( gmyth_settings->backend_hostname != NULL )
66.92 + g_string_free( gmyth_settings->backend_hostname, TRUE );
66.93 + if ( gmyth_settings->mysql_dbname != NULL )
66.94 + g_string_free( gmyth_settings->mysql_dbname, TRUE );
66.95 + if ( gmyth_settings->mysql_username != NULL )
66.96 + g_string_free( gmyth_settings->mysql_username, TRUE );
66.97 + if ( gmyth_settings->mysql_password != NULL )
66.98 + g_string_free( gmyth_settings->mysql_password, TRUE );
66.99 + if ( gmyth_settings->database_type != NULL )
66.100 + g_string_free( gmyth_settings->database_type, TRUE );
66.101 +
66.102 + G_OBJECT_CLASS (gmyth_settings_parent_class)->dispose (object);
66.103 +}
66.104 +
66.105 +static void
66.106 +gmyth_settings_finalize (GObject *object)
66.107 +{
66.108 + g_signal_handlers_destroy (object);
66.109 +
66.110 + G_OBJECT_CLASS (gmyth_settings_parent_class)->finalize (object);
66.111 +}
66.112 +
66.113 +/** Creates a new instance of GMythSettings.
66.114 + *
66.115 + * @return a new instance of GMythSettings.
66.116 + */
66.117 +GMythSettings*
66.118 +gmyth_settings_new ()
66.119 +{
66.120 + GMythSettings *gmyth_settings = GMYTH_SETTINGS (g_object_new(GMYTH_SETTINGS_TYPE, NULL));
66.121 +
66.122 + return gmyth_settings;
66.123 +}
66.124 +
66.125 +static gboolean
66.126 +gmyth_settings_ensure_dir_exists (const gchar *dir)
66.127 +{
66.128 +
66.129 + g_debug ("[%s] \tdir = %s\n", __FUNCTION__, dir);
66.130 +
66.131 + if (g_file_test (dir, G_FILE_TEST_IS_DIR) == FALSE) {
66.132 + if (g_file_test (dir, G_FILE_TEST_EXISTS) == TRUE) {
66.133 + g_warning ("%s exists, please move it out of the way.", dir);
66.134 + return FALSE;
66.135 + }
66.136 +
66.137 + if (mkdir (dir, 488) != 0) {
66.138 + g_warning ("Failed to create directory %s.", dir);
66.139 + return FALSE;
66.140 + }
66.141 + }
66.142 +
66.143 + return TRUE;
66.144 +}
66.145 +
66.146 +static gboolean
66.147 +gmyth_settings_ensure_file_exists (const gchar *file_name) {
66.148 +
66.149 + int file = 0;
66.150 +
66.151 + if ( g_file_test( file_name, G_FILE_TEST_EXISTS ) == FALSE ) {
66.152 + g_debug ( "\n\tCreating %s file...\n", file_name );
66.153 + file = creat( file_name, S_IRWXU | S_IRWXO | S_IRWXG );
66.154 +
66.155 + if ( close( file ) == -1 )
66.156 + return FALSE;
66.157 + }
66.158 +
66.159 + return TRUE;
66.160 +}
66.161 +
66.162 +/** Loads the GMyth settings from the given file.
66.163 + *
66.164 + * @param gmyth_settings the GMythSettings instance.
66.165 + * @param filename The desired file to be opened.
66.166 + * @return TRUE if success, FALSE if error.
66.167 + */
66.168 +gboolean
66.169 +gmyth_settings_load_from_file (GMythSettings *gmyth_settings, GString *filename)
66.170 +{
66.171 + FILE *file_desc;
66.172 + char line[100];
66.173 +
66.174 + g_debug ("[%s] Loading GMyth settings file: %s", __FUNCTION__, filename->str);
66.175 +
66.176 + file_desc = fopen(filename->str, "r");
66.177 + if( file_desc == NULL) {
66.178 + g_warning ("[%s] Settings file %s could not be opened", __FUNCTION__, filename->str);
66.179 + return FALSE;
66.180 + }
66.181 +
66.182 + gmyth_settings->settings_file = g_string_new (filename->str);
66.183 +
66.184 + while(fgets(line, 100, file_desc)) {
66.185 + int i;
66.186 +
66.187 + /* Removes the new line characters from the end of line */
66.188 + for ( i = strlen(line)-1; i >= 0; i--) {
66.189 + if ( !g_ascii_iscntrl (line[i]) ) {
66.190 + line[i+1] = '\0';
66.191 + break;
66.192 + }
66.193 + }
66.194 +
66.195 + fill_settings_data(gmyth_settings, line);
66.196 + }
66.197 +
66.198 + fclose (file_desc);
66.199 +
66.200 + return TRUE;
66.201 +}
66.202 +
66.203 +/** Loads the GMyth settings from the standard settings file
66.204 + * (~/.mmyth/settings.dat).
66.205 + *
66.206 + * @param gmyth_settings the GMythSettings instance.
66.207 + * @return TRUE if success, FALSE if error.
66.208 + */
66.209 +gboolean
66.210 +gmyth_settings_load (GMythSettings *gmyth_settings)
66.211 +{
66.212 + GString* file_full_path = g_string_new( g_build_filename( g_get_home_dir(),
66.213 + GMYTH_SETTINGS_DIR, GMYTH_SETTINGS_FILE_NAME, NULL ) );
66.214 +
66.215 + gmyth_settings->settings_file = file_full_path;
66.216 +
66.217 + gmyth_settings_ensure_dir_exists( g_build_filename( g_get_home_dir(), GMYTH_SETTINGS_DIR, NULL ) );
66.218 +
66.219 + // Verifies if the file already exist
66.220 + if ( g_file_test( file_full_path->str, G_FILE_TEST_EXISTS ) == FALSE ) {
66.221 + g_debug ("[%s] Settings file does not exist. A new one will be created.\n", __FUNCTION__);
66.222 +
66.223 + if ( gmyth_settings_ensure_file_exists( file_full_path->str ) == FALSE )
66.224 + return FALSE;
66.225 +
66.226 + // Creates the file with default values (see _init function)
66.227 + return gmyth_settings_save (gmyth_settings);
66.228 +
66.229 + } else {
66.230 + g_debug ("[%s] Opening settings from file %s", __FUNCTION__, file_full_path->str);
66.231 +
66.232 + return gmyth_settings_load_from_file (gmyth_settings, file_full_path);
66.233 + }
66.234 +}
66.235 +
66.236 +/** Saves the current gmyth_settings to the settings file related to the
66.237 + * given instance.
66.238 + *
66.239 + * @param gmyth_settings the GMythSettings instance.
66.240 + * @return TRUE if success, FALSE if error.
66.241 + */
66.242 +gboolean
66.243 +gmyth_settings_save (GMythSettings *gmyth_settings)
66.244 +{
66.245 + FILE *file_desc;
66.246 +
66.247 + if (gmyth_settings->settings_file == NULL) {
66.248 + g_warning ("[%s] Settings were not loaded from file, could not save!", __FUNCTION__);
66.249 + }
66.250 +
66.251 + file_desc = fopen(gmyth_settings->settings_file->str, "w");
66.252 + if( file_desc == NULL) {
66.253 + g_warning ("GMYTH_SETTINGS: settings file %s not found", gmyth_settings->settings_file->str);
66.254 + return FALSE;
66.255 + }
66.256 +
66.257 + g_fprintf(file_desc, "#Maemo-Myth Settings\n");
66.258 +
66.259 + g_fprintf(file_desc, "#General settings related with mythtv database\n");
66.260 + g_fprintf(file_desc, "dbname=%s\n", gmyth_settings->mysql_dbname->str);
66.261 + g_fprintf(file_desc, "username=%s\n", gmyth_settings->mysql_username->str);
66.262 + g_fprintf(file_desc, "password=%s\n", gmyth_settings->mysql_password->str);
66.263 +
66.264 + g_fprintf(file_desc, "\n#General settings related with mythtv backend\n");
66.265 + g_fprintf(file_desc, "hostname=%s\n", gmyth_settings->backend_hostname->str);
66.266 + g_fprintf(file_desc, "backend_port=%d\n", gmyth_settings->backend_port);
66.267 +
66.268 + fclose (file_desc);
66.269 +
66.270 + g_debug ("[%s] Settings file saved", __FUNCTION__);
66.271 + return TRUE;
66.272 +}
66.273 +
66.274 +/** Gets the backend hostname from the settings.
66.275 + *
66.276 + * @param gmyth_settings the GMythSettings instance.
66.277 + * @return The loaded backend hostname, or the default value "127.0.0.1" if settings
66.278 + * file was not opened.
66.279 + */
66.280 +GString*
66.281 +gmyth_settings_get_backend_hostname (GMythSettings *gmyth_settings)
66.282 +{
66.283 + return g_string_new (gmyth_settings->backend_hostname->str);
66.284 +}
66.285 +
66.286 +/** Sets the backend hostname to the settings.
66.287 + *
66.288 + * @param gmyth_settings the GMythSettings instance.
66.289 + * @param new_hostname The new hostname.
66.290 + */
66.291 +void
66.292 +gmyth_settings_set_backend_hostname (GMythSettings *gmyth_settings, GString *new_hostname)
66.293 +{
66.294 + g_string_assign (gmyth_settings->backend_hostname, new_hostname->str);
66.295 +}
66.296 +
66.297 +/** Gets the user name to connect to backend database.
66.298 + *
66.299 + * @param gmyth_settings the GMythSettings instance.
66.300 + * @return The loaded user name, or the default value "mythtv" if settings
66.301 + * file was not opened.
66.302 + */
66.303 +GString*
66.304 +gmyth_settings_get_username (GMythSettings *gmyth_settings)
66.305 +{
66.306 + return g_string_new (gmyth_settings->mysql_username->str);
66.307 +}
66.308 +
66.309 +/** Sets the username to connect to backend database.
66.310 + *
66.311 + * @param gmyth_settings the GMythSettings instance.
66.312 + * @param new_username The new username.
66.313 + */
66.314 +void
66.315 +gmyth_settings_set_username (GMythSettings *gmyth_settings, GString *new_username)
66.316 +{
66.317 + g_string_assign (gmyth_settings->mysql_username, new_username->str);
66.318 +}
66.319 +
66.320 +/** Gets the database password from the settings file.
66.321 + *
66.322 + * @param gmyth_settings the GMythSettings instance.
66.323 + * @return The loaded password, or the default value "mythtv" if settings
66.324 + * file was not opened.
66.325 + */
66.326 +GString*
66.327 +gmyth_settings_get_password (GMythSettings *gmyth_settings)
66.328 +{
66.329 + return g_string_new (gmyth_settings->mysql_password->str);
66.330 +}
66.331 +
66.332 +/** Sets the database password.
66.333 + *
66.334 + * @param gmyth_settings the GMythSettings instance.
66.335 + * @param new_password The new password.
66.336 + */
66.337 +
66.338 +void
66.339 +gmyth_settings_set_password (GMythSettings *gmyth_settings, GString *new_password)
66.340 +{
66.341 + g_string_assign (gmyth_settings->mysql_password, new_password->str);
66.342 +}
66.343 +
66.344 +/** Gets the backend database name from the settings file.
66.345 + *
66.346 + * @param gmyth_settings the GMythSettings instance.
66.347 + * @return The loaded database name, or the default value "mythconverg" if settings
66.348 + * file was not opened.
66.349 + */
66.350 +GString*
66.351 +gmyth_settings_get_dbname (GMythSettings *gmyth_settings)
66.352 +{
66.353 + return g_string_new (gmyth_settings->mysql_dbname->str);
66.354 +}
66.355 +
66.356 +/** Sets the Mythtv database name to the settings.
66.357 + *
66.358 + * @param gmyth_settings the GMythSettings instance.
66.359 + * @param new_dbname The new database name.
66.360 + */
66.361 +
66.362 +void
66.363 +gmyth_settings_set_dbname (GMythSettings *gmyth_settings, GString *new_dbname)
66.364 +{
66.365 + g_string_assign (gmyth_settings->mysql_dbname, new_dbname->str);
66.366 +}
66.367 +
66.368 +/** Gets the backend port from the settings.
66.369 + *
66.370 + * @param gmyth_settings the GMythSettings instance.
66.371 + * @return The loaded backend port, or the default value "6543" if settings
66.372 + * file was not opened.
66.373 + */
66.374 +int
66.375 +gmyth_settings_get_backend_port (GMythSettings *gmyth_settings)
66.376 +{
66.377 + return gmyth_settings->backend_port;
66.378 +}
66.379 +
66.380 +/** Sets the backend port.
66.381 + *
66.382 + * @param gmyth_settings the GMythSettings instance.
66.383 + * @param new_port The new port.
66.384 + */
66.385 +void
66.386 +gmyth_settings_set_backend_port (GMythSettings *gmyth_settings, gint new_port)
66.387 +{
66.388 + gmyth_settings->backend_port = new_port;
66.389 +}
66.390 +
66.391 +
66.392 +static void
66.393 +fill_settings_data(GMythSettings *gmyth_settings, char* line)
66.394 +{
66.395 + gchar** str_splited;
66.396 +
66.397 + GString *gstr_splited;
66.398 + gstr_splited = g_string_new("");
66.399 + str_splited = g_strsplit (line, "=", -1);
66.400 +
66.401 + if(!(strcmp(str_splited[0], "hostname"))){
66.402 + g_string_assign(gstr_splited, str_splited[1]);
66.403 + gmyth_settings_set_backend_hostname(gmyth_settings, gstr_splited);
66.404 + }
66.405 + else if (!(strcmp(str_splited[0], "dbname"))){
66.406 + g_string_assign(gstr_splited, str_splited[1]);
66.407 + gmyth_settings_set_dbname(gmyth_settings, gstr_splited);
66.408 + }
66.409 + else if (!(strcmp(str_splited[0], "username"))){
66.410 + g_string_assign(gstr_splited, str_splited[1]);
66.411 + gmyth_settings_set_username(gmyth_settings, gstr_splited);
66.412 + }
66.413 + else if (!(strcmp(str_splited[0], "password"))){
66.414 + g_string_assign(gstr_splited, str_splited[1]);
66.415 + gmyth_settings_set_password(gmyth_settings, gstr_splited);
66.416 + }
66.417 + else if (!(strcmp(str_splited[0], "backend_port"))){
66.418 + gmyth_settings_set_backend_port(gmyth_settings, atoi(str_splited[1]));
66.419 + }
66.420 +}
67.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
67.2 +++ b/gmyth/src/libgmyth/gmyth_settings.h Wed Sep 20 23:45:35 2006 +0100
67.3 @@ -0,0 +1,103 @@
67.4 +/**
67.5 + * GMyth Library
67.6 + *
67.7 + * @file gmyth/gmyth_settings.h
67.8 + *
67.9 + * @brief <p> This component contains functions acessing and modifying
67.10 + * user and program settings.
67.11 + *
67.12 + * The standard settings file is created in the user home folder, in the
67.13 + * file ~/.mmyth/settings.dat.
67.14 + *
67.15 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
67.16 + * @author Alexsandro Jose Virginio dos Santos <alexsandro.santos@indt.org.br>
67.17 + *
67.18 + *//*
67.19 + *
67.20 + * This program is free software; you can redistribute it and/or modify
67.21 + * it under the terms of the GNU Lesser General Public License as published by
67.22 + * the Free Software Foundation; either version 2 of the License, or
67.23 + * (at your option) any later version.
67.24 + *
67.25 + * This program is distributed in the hope that it will be useful,
67.26 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
67.27 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
67.28 + * GNU General Public License for more details.
67.29 + *
67.30 + * You should have received a copy of the GNU Lesser General Public License
67.31 + * along with this program; if not, write to the Free Software
67.32 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
67.33 + */
67.34 +
67.35 +#ifndef __GMYTH_SETTINGS_H__
67.36 +#define __GMYTH_SETTINGS_H__
67.37 +
67.38 +#include <glib-object.h>
67.39 +
67.40 +//#include <stdio.h>
67.41 +//#include <stdlib.h>
67.42 +//#include <string.h>
67.43 +//#include <netdb.h>
67.44 +//#include <sys/socket.h>
67.45 +//#include <unistd.h>
67.46 +
67.47 +#define G_BEGIN_DECLS
67.48 +
67.49 +#define GMYTH_SETTINGS_TYPE (gmyth_settings_get_type ())
67.50 +#define GMYTH_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_SETTINGS_TYPE, GMythSettings))
67.51 +#define GMYTH_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_SETTINGS_TYPE, GMythSettingsClass))
67.52 +#define IS_GMYTH_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_SETTINGS_TYPE))
67.53 +#define IS_GMYTH_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_SETTINGS_TYPE))
67.54 +#define GMYTH_SETTINGS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_SETTINGS_TYPE, GMythSettingsClass))
67.55 +
67.56 +
67.57 +typedef struct _GMythSettings GMythSettings;
67.58 +typedef struct _GMythSettingsClass GMythSettingsClass;
67.59 +
67.60 +struct _GMythSettingsClass
67.61 +{
67.62 + GObjectClass parent_class;
67.63 +
67.64 + /* callbacks */
67.65 + /* no one for now */
67.66 +};
67.67 +
67.68 +struct _GMythSettings
67.69 +{
67.70 + GObject parent;
67.71 +
67.72 + GString *settings_file;
67.73 +
67.74 + GString *backend_hostname;
67.75 + int backend_port;
67.76 +
67.77 + GString *mysql_dbname;
67.78 + GString *mysql_username;
67.79 + GString *mysql_password;
67.80 + // FIXME: Why do we need database_type? Do we intend to support other dbs?
67.81 + GString *database_type;
67.82 +};
67.83 +
67.84 +
67.85 +GType gmyth_settings_get_type (void);
67.86 +
67.87 +GMythSettings* gmyth_settings_new ();
67.88 +gboolean gmyth_settings_load_from_file (GMythSettings *gmyth_settings, GString *filename);
67.89 +gboolean gmyth_settings_load (GMythSettings *msettings);
67.90 +gboolean gmyth_settings_save (GMythSettings *gmyth_settings);
67.91 +
67.92 +GString* gmyth_settings_get_backend_hostname (GMythSettings *gmyth_settings);
67.93 +void gmyth_settings_set_backend_hostname (GMythSettings *gmyth_settings, GString *new_hostname);
67.94 +GString* gmyth_settings_get_username (GMythSettings *gmyth_settings);
67.95 +void gmyth_settings_set_username (GMythSettings *gmyth_settings, GString *new_username);
67.96 +GString* gmyth_settings_get_password (GMythSettings *gmyth_settings);
67.97 +void gmyth_settings_set_password (GMythSettings *gmyth_settings, GString *new_password);
67.98 +GString* gmyth_settings_get_dbname (GMythSettings *gmyth_settings);
67.99 +void gmyth_settings_set_dbname (GMythSettings *gmyth_settings, GString *new_dbname);
67.100 +int gmyth_settings_get_backend_port (GMythSettings *gmyth_settings);
67.101 +void gmyth_settings_set_backend_port (GMythSettings *gmyth_settings, gint new_port);
67.102 +
67.103 +
67.104 +#define G_END_DECLS
67.105 +
67.106 +#endif /* __GMYTH_SETTINGS_H__ */
68.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
68.2 +++ b/gmyth/src/libgmyth/gmyth_socket.c Wed Sep 20 23:45:35 2006 +0100
68.3 @@ -0,0 +1,708 @@
68.4 +/**
68.5 + * GMyth Library
68.6 + *
68.7 + * @file gmyth/gmyth_socket.c
68.8 + *
68.9 + * @brief <p> MythTV socket implementation, according to the MythTV Project
68.10 + * (www.mythtv.org).
68.11 + *
68.12 + * This component provides basic socket functionalities to interact with
68.13 + * the Mythtv backend.
68.14 + * <p>
68.15 + *
68.16 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
68.17 + * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
68.18 + *
68.19 + *//*
68.20 + *
68.21 + * This program is free software; you can redistribute it and/or modify
68.22 + * it under the terms of the GNU Lesser General Public License as published by
68.23 + * the Free Software Foundation; either version 2 of the License, or
68.24 + * (at your option) any later version.
68.25 + *
68.26 + * This program is distributed in the hope that it will be useful,
68.27 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
68.28 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
68.29 + * GNU General Public License for more details.
68.30 + *
68.31 + * You should have received a copy of the GNU Lesser General Public License
68.32 + * along with this program; if not, write to the Free Software
68.33 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
68.34 + */
68.35 +
68.36 +#include <glib.h>
68.37 +#include <glib/gprintf.h>
68.38 +
68.39 +#include <arpa/inet.h>
68.40 +#include <sys/types.h>
68.41 +#include <sys/socket.h>
68.42 +#include <netdb.h>
68.43 +#include <errno.h>
68.44 +#include <stdlib.h>
68.45 +
68.46 +#include "gmyth_socket.h"
68.47 +#include "gmyth_stringlist.h"
68.48 +#include "gmyth_context.h"
68.49 +
68.50 +#define BUFLEN 512
68.51 +#define MYTH_SEPARATOR "[]:[]"
68.52 +#define MYTH_PROTOCOL_FIELD_SIZE 8
68.53 +
68.54 +static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
68.55 +
68.56 +static void gmyth_socket_class_init (GMythSocketClass *klass);
68.57 +static void gmyth_socket_init (GMythSocket *object);
68.58 +
68.59 +static void gmyth_socket_dispose (GObject *object);
68.60 +static void gmyth_socket_finalize (GObject *object);
68.61 +
68.62 +G_DEFINE_TYPE(GMythSocket, gmyth_socket, G_TYPE_OBJECT)
68.63 +
68.64 +static void
68.65 +gmyth_socket_class_init (GMythSocketClass *klass)
68.66 +{
68.67 + GObjectClass *gobject_class;
68.68 +
68.69 + gobject_class = (GObjectClass *) klass;
68.70 +
68.71 + gobject_class->dispose = gmyth_socket_dispose;
68.72 + gobject_class->finalize = gmyth_socket_finalize;
68.73 +}
68.74 +
68.75 +static void
68.76 +gmyth_socket_init (GMythSocket *gmyth_socket)
68.77 +{
68.78 +}
68.79 +
68.80 +/** Gets the some important address translation info, from the client socket
68.81 + * that will open a connection.
68.82 + *
68.83 + * @return gint that represents the error number from getaddrinfo().
68.84 + */
68.85 +static gint
68.86 +gmyth_socket_toaddrinfo( gchar *addr, gint port, struct addrinfo **addrInfo )
68.87 +{
68.88 + struct addrinfo hints;
68.89 + gchar *portStr = g_strnfill( 32, ' ' );
68.90 + gint errorn = EADDRNOTAVAIL;
68.91 +
68.92 + memset( &hints, 0, sizeof(hints) );
68.93 + hints.ai_family = AF_INET;
68.94 + hints.ai_socktype = SOCK_STREAM;
68.95 + /* hints.ai_flags = AI_NUMERICHOST; */
68.96 + if ( port != -1 )
68.97 + sprintf(portStr, "%d", port);
68.98 + else
68.99 + portStr = NULL;
68.100 +
68.101 + g_debug( "[%s] Address: %s, port: %s\n", __FUNCTION__, addr, portStr );
68.102 + if ( ( errorn = getaddrinfo(addr, portStr, &hints, addrInfo) ) != 0 ) {
68.103 + g_printerr( "[%s] Socket ERROR: %s\n", __FUNCTION__, gai_strerror(errorn) );
68.104 + }
68.105 +
68.106 + return errorn;
68.107 +}
68.108 +
68.109 +/** This function retrieves the local hostname of the
68.110 + * client machine.
68.111 + *
68.112 + * @return GString* get local hostname.
68.113 + */
68.114 +GString *
68.115 +gmyth_socket_get_local_hostname( )
68.116 +{
68.117 + GString *str = g_string_new("");
68.118 +
68.119 + gchar *localhostname = g_strnfill( 1024, ' ' );
68.120 + gchar *localaddr = g_strdup( "127.0.0.1" );
68.121 +
68.122 + gboolean found_addr = FALSE;
68.123 +
68.124 + struct addrinfo* addr_info_data = NULL, *addr_info0 = NULL;
68.125 +
68.126 + struct sockaddr_in* sa = NULL;
68.127 +
68.128 + g_static_mutex_lock( &mutex );
68.129 +
68.130 + gethostname(localhostname, 1024);
68.131 +
68.132 + gint err = gmyth_socket_toaddrinfo( localhostname, -1, &addr_info_data );
68.133 +
68.134 + addr_info0 = addr_info_data;
68.135 +
68.136 + while( addr_info0 != NULL && addr_info0->ai_addr != NULL &&
68.137 + ( sa = (struct sockaddr_in*)addr_info0->ai_addr ) != NULL && !found_addr ) {
68.138 + localaddr = inet_ntoa( sa->sin_addr );
68.139 + if ( localaddr != NULL )
68.140 + g_print( "[%s] localaddr = %s\n", __FUNCTION__, localaddr );
68.141 +
68.142 + if ( localaddr != NULL && ( g_strrstr( localaddr, "127" ) == NULL ) ) {
68.143 + g_print( "[%s] Trying the address %s (err = %d).\n",
68.144 + __FUNCTION__, localaddr, err );
68.145 + g_print( "[%s] Found local address %s!\n", __FUNCTION__, localaddr );
68.146 + str = g_string_assign( str, g_strdup( localaddr ) );
68.147 + found_addr = TRUE;
68.148 + break;
68.149 + }
68.150 + addr_info0 = addr_info0->ai_next;
68.151 + };
68.152 +
68.153 + if ( found_addr == FALSE ) {
68.154 + g_warning("[%s] Could not determine the local hostname address. Setting to %s\n",
68.155 + __FUNCTION__, localaddr );
68.156 + if ( localaddr != NULL )
68.157 + str = g_string_assign( str, localaddr );
68.158 + else
68.159 + str = g_string_assign( str, "127.0.0.1" );
68.160 + }
68.161 +
68.162 + g_static_mutex_unlock( &mutex );
68.163 +
68.164 + if (localhostname!=NULL)
68.165 + g_free( localhostname );
68.166 +
68.167 + return str;
68.168 +}
68.169 +
68.170 +static void
68.171 +gmyth_socket_dispose (GObject *object)
68.172 +{
68.173 + GMythSocket *gmyth_socket = GMYTH_SOCKET(object);
68.174 +
68.175 + gmyth_socket_close_connection (gmyth_socket);
68.176 + /* disconnect socket */
68.177 + G_OBJECT_CLASS (gmyth_socket_parent_class)->dispose (object);
68.178 +}
68.179 +
68.180 +static void
68.181 +gmyth_socket_finalize (GObject *object)
68.182 +{
68.183 + g_signal_handlers_destroy (object);
68.184 +
68.185 + G_OBJECT_CLASS (gmyth_socket_parent_class)->finalize (object);
68.186 +}
68.187 +
68.188 +/** Creates a new instance of GMythSocket.
68.189 + *
68.190 + * @return a new instance of GMythSocket.
68.191 + */
68.192 +GMythSocket*
68.193 +gmyth_socket_new ()
68.194 +{
68.195 + GMythSocket *gmyth_socket = GMYTH_SOCKET (g_object_new(GMYTH_SOCKET_TYPE, NULL));
68.196 +
68.197 + gmyth_socket->sd_io_ch = NULL;
68.198 +
68.199 + gmyth_socket->hostname = g_strdup("");
68.200 +
68.201 + gmyth_socket->port = 6543;
68.202 +
68.203 + return gmyth_socket;
68.204 +}
68.205 +
68.206 +/** Connects to the backend.
68.207 + *
68.208 + * @param gmyth_socket The GMythSocket instance.
68.209 + * @param hostname The backend hostname or IP address.
68.210 + * @param port The backend port.
68.211 + * @return TRUE if success, FALSE if error.
68.212 + */
68.213 +gboolean
68.214 +gmyth_socket_connect (GMythSocket **gmyth_socket,
68.215 + gchar *hostname, gint port)
68.216 +{
68.217 + struct addrinfo *addr_info_data = NULL, *addr_info0 = NULL;
68.218 + gint ret_code = -1;
68.219 + gint errno;
68.220 + gboolean ret = TRUE;
68.221 +
68.222 + if ( hostname == NULL )
68.223 + g_printerr ( "[%s] Invalid hostname parameter!\n", __FUNCTION__ );
68.224 +
68.225 + errno = gmyth_socket_toaddrinfo( hostname, port, &addr_info_data );
68.226 +
68.227 + g_return_val_if_fail( addr_info_data != NULL, FALSE );
68.228 +
68.229 + /* store hostname and port number */
68.230 + (*gmyth_socket)->hostname = g_strdup( hostname );
68.231 + (*gmyth_socket)->port = port;
68.232 +
68.233 + for ( addr_info0 = addr_info_data; addr_info0; addr_info0 = addr_info_data->ai_next ) {
68.234 +
68.235 + struct sockaddr_in *sa = (struct sockaddr_in*)addr_info0->ai_addr;
68.236 + /* init socket descriptor */
68.237 + (*gmyth_socket)->sd = socket( addr_info0->ai_family, addr_info0->ai_socktype,
68.238 + addr_info0->ai_protocol );
68.239 +
68.240 + if ( (*gmyth_socket)->sd < 0 )
68.241 + continue;
68.242 +
68.243 + g_debug( "[%s] hostname = %s, sock_fd = %d, addr = %s, addr_len = %d, \
68.244 + ai_family = %d, ai_protocol = %d\n",
68.245 + __FUNCTION__, hostname, (*gmyth_socket)->sd, inet_ntoa( sa->sin_addr ),
68.246 + addr_info0->ai_addrlen, addr_info0->ai_family, addr_info0->ai_protocol );
68.247 +
68.248 + if ( ( ret_code = connect( (*gmyth_socket)->sd, (struct sockaddr *)addr_info0->ai_addr,
68.249 + addr_info0->ai_addrlen ) ) < 0 )
68.250 + {
68.251 + g_printerr( "[%s] Error connecting to backend!\n", __FUNCTION__ );
68.252 + if ( ret_code == ETIMEDOUT )
68.253 + g_printerr( "[%s]\tBackend host unreachable!\n", __FUNCTION__ );
68.254 +
68.255 + g_printerr( "ERROR: %s\n", gai_strerror(ret_code) );
68.256 + continue;
68.257 + }
68.258 +
68.259 + /* only will be reached if none of the error above occurred */
68.260 + break;
68.261 +
68.262 + }
68.263 +
68.264 + (*gmyth_socket)->sd_io_ch = g_io_channel_unix_new( (*gmyth_socket)->sd );
68.265 +
68.266 + //if (addr_info_data != NULL )
68.267 + //freeaddrinfo( addr_info_data );
68.268 +
68.269 + ret = ( ret_code == 0 ) ? TRUE : FALSE ;
68.270 +
68.271 + return ret;
68.272 +
68.273 +}
68.274 +
68.275 +/** Gets the GIOChannel associated to the given GMythSocket.
68.276 + *
68.277 + * @param gmyth_socket The GMythSocket instance.
68.278 + */
68.279 +GIOChannel *
68.280 +gmyth_socket_get_io_channel( GMythSocket *gmyth_socket )
68.281 +{
68.282 + g_return_val_if_fail( gmyth_socket != NULL, NULL );
68.283 +
68.284 + return gmyth_socket->sd_io_ch;
68.285 +}
68.286 +
68.287 +/** Verifies if the socket is able to read.
68.288 + *
68.289 + * @param gmyth_socket The GMythSocket instance.
68.290 + * @return TRUE if the socket is able to read, FALSE if not.
68.291 + */
68.292 +gboolean
68.293 +gmyth_socket_is_able_to_read( GMythSocket *gmyth_socket )
68.294 +{
68.295 + gboolean ret = TRUE;
68.296 +
68.297 + /* verify if the input (read) buffer is ready to receive data */
68.298 + GIOCondition io_cond = g_io_channel_get_buffer_condition( gmyth_socket->sd_io_ch );
68.299 +
68.300 + if ( ( io_cond & G_IO_IN ) == 0 ) {
68.301 + g_warning ("[%s] IO channel is not able to send data!\n", __FUNCTION__);
68.302 + ret = FALSE;
68.303 + }
68.304 +
68.305 + return ret;
68.306 +
68.307 +}
68.308 +
68.309 +/** Verifies if the socket is able to write.
68.310 + *
68.311 + * @param gmyth_socket The GMythSocket instance.
68.312 + * @return TRUE if the socket is able to write, FALSE if not.
68.313 + */
68.314 +gboolean
68.315 +gmyth_socket_is_able_to_write( GMythSocket *gmyth_socket )
68.316 +{
68.317 + gboolean ret = TRUE;
68.318 +
68.319 + /* verify if the input (read) buffer is ready to receive data */
68.320 + GIOCondition io_cond = g_io_channel_get_buffer_condition( gmyth_socket->sd_io_ch );
68.321 +
68.322 + if ( ( ( io_cond & G_IO_OUT ) == 0 ) || ( ( io_cond & G_IO_HUP ) == 0 ) ) {
68.323 + g_warning ("[%s] IO channel is not able to send data!\n", __FUNCTION__);
68.324 + ret = FALSE;
68.325 + }
68.326 +
68.327 + return ret;
68.328 +
68.329 +}
68.330 +
68.331 +/** Sends a command to the backend.
68.332 + *
68.333 + * @param gmyth_socket the GMythSocket instance.
68.334 + * @param command The string command to be sent.
68.335 + */
68.336 +gboolean
68.337 +gmyth_socket_send_command(GMythSocket *gmyth_socket, GString *command)
68.338 +{
68.339 + gboolean ret = TRUE;
68.340 +
68.341 + GIOStatus io_status = G_IO_STATUS_NORMAL;
68.342 + //GIOCondition io_cond;
68.343 + GError* error = NULL;
68.344 + gchar *buffer = NULL;
68.345 +
68.346 + gsize bytes_written = 0;
68.347 +
68.348 + if( command == NULL || ( command->len <= 0 ) ) {
68.349 + g_warning ("[%s] Invalid NULL command parameter!\n", __FUNCTION__);
68.350 + ret = FALSE;
68.351 + goto done;
68.352 + }
68.353 +
68.354 + g_static_mutex_lock( &mutex );
68.355 + g_debug ("[%s] Sending command to backend: %s\n", __FUNCTION__, command->str);
68.356 +
68.357 + /*
68.358 + io_cond = g_io_channel_get_buffer_condition( gmyth_socket->sd_io_ch );
68.359 +
68.360 + if ( ( io_cond & G_IO_IN ) == 0 ) {
68.361 + g_warning ("[%s] IO channel is not able to send data!\n", __FUNCTION__);
68.362 + ret = FALSE;
68.363 + goto done;
68.364 + }
68.365 + */
68.366 +
68.367 + buffer = g_strnfill( BUFLEN, ' ' );
68.368 + snprintf( buffer, MYTH_PROTOCOL_FIELD_SIZE+1, "%-8d", command->len);
68.369 + g_print( "[%s] buffer = [%s]\n", __FUNCTION__, buffer );
68.370 +
68.371 + command = g_string_prepend(command, buffer);
68.372 +
68.373 + g_print( "[%s] command = [%s]\n", __FUNCTION__, command->str );
68.374 +
68.375 + /* write bytes to socket */
68.376 + io_status = g_io_channel_write_chars( gmyth_socket->sd_io_ch, command->str,
68.377 + command->len, &bytes_written, &error );
68.378 +
68.379 +
68.380 + if( (io_status == G_IO_STATUS_ERROR) || ( bytes_written <= 0 ) ) {
68.381 + g_warning ("[%s] Error while writing to socket", __FUNCTION__);
68.382 + ret = FALSE;
68.383 + } else if ( bytes_written < command->len ) {
68.384 + g_warning ("[%s] Not all data was written socket", __FUNCTION__);
68.385 + ret = FALSE;
68.386 + }
68.387 +
68.388 + io_status = g_io_channel_flush( gmyth_socket->sd_io_ch, &error );
68.389 +
68.390 + if ( ( bytes_written != command->len ) || ( io_status == G_IO_STATUS_ERROR ) )
68.391 + {
68.392 + g_warning ("[%s] Some problem occurred when sending data to the socket\n", __FUNCTION__);
68.393 +
68.394 + ret = TRUE;
68.395 + }
68.396 +
68.397 + g_static_mutex_unlock( &mutex );
68.398 +done:
68.399 + if ( error != NULL ) {
68.400 + g_printerr( "[%s] Error found reading data from IO channel: (%d, %s)\n", __FUNCTION__, error->code, error->message );
68.401 + ret = FALSE;
68.402 + g_error_free( error );
68.403 + }
68.404 +
68.405 + if ( buffer!= NULL )
68.406 + g_free( buffer );
68.407 +
68.408 + return ret;
68.409 +}
68.410 +
68.411 +/** Starts Mythtv protocol level connection. Checks Mythtv protocol version
68.412 + * supported by the backend and send the "ANN" command.
68.413 + *
68.414 + * @param gmyth_socket the GMythSocket instance.
68.415 + * @param hostname_backend The backend hostname or IP address.
68.416 + * @param port The backend port to connect.
68.417 + * @param blocking_client A flag to choose between blocking and non-blocking
68.418 + * backend connection.
68.419 + */
68.420 +gboolean
68.421 +gmyth_socket_connect_to_backend (GMythSocket *gmyth_socket,
68.422 + gchar *hostname_backend, int port, gboolean blocking_client)
68.423 +{
68.424 + if (!gmyth_socket_connect (&gmyth_socket, hostname_backend, port)) {
68.425 + g_warning ("[%s] Could not open socket to backend machine", __FUNCTION__);
68.426 + return FALSE;
68.427 + }
68.428 +
68.429 + if (gmyth_socket_check_protocol_version (gmyth_socket)) {
68.430 +
68.431 + GString *result;
68.432 + GString *base_str = g_string_new("");
68.433 + GString *hostname = NULL;
68.434 +
68.435 + hostname = gmyth_socket_get_local_hostname();
68.436 +
68.437 + g_string_printf(base_str, "ANN %s %s 0",
68.438 + (blocking_client ? "Playback" : "Monitor"),
68.439 + hostname->str);
68.440 +
68.441 + g_debug ("[%s] Connection command sent to backend: %s", __FUNCTION__, base_str->str);
68.442 +
68.443 + gmyth_socket_send_command (gmyth_socket, base_str);
68.444 + result = gmyth_socket_receive_response(gmyth_socket);
68.445 +
68.446 + if (result != NULL) {
68.447 + g_debug ("[%s] Response received from backend: %s", __FUNCTION__, result->str);
68.448 + g_string_free (result, TRUE);
68.449 + }
68.450 +
68.451 + g_string_free (hostname, TRUE);
68.452 + g_string_free (base_str, TRUE);
68.453 +
68.454 + return TRUE;
68.455 + } else {
68.456 + g_warning ("[%s] GMythSocket could not connect to the backend", __FUNCTION__);
68.457 + return FALSE;
68.458 + }
68.459 +
68.460 +}
68.461 +
68.462 +/** Closes the socket connection to the backend.
68.463 + *
68.464 + * @param gmyth_socket The GMythSocket instance.
68.465 + */
68.466 +void
68.467 +gmyth_socket_close_connection (GMythSocket *gmyth_socket)
68.468 +{
68.469 + close (gmyth_socket->sd);
68.470 +}
68.471 +
68.472 +
68.473 +/** Try the MythTV version numbers, and get the version returned by
68.474 + * the possible REJECT message, in order to contruct a new
68.475 + * MythTV version request.
68.476 + *
68.477 + * @param gmyth_socket The GMythSocket instance.
68.478 + * @param mythtv_version The Mythtv protocol version to be tested
68.479 + */
68.480 +gboolean
68.481 +gmyth_socket_check_protocol_version_number (GMythSocket *gmyth_socket, gint mythtv_version)
68.482 +{
68.483 + GString *response;
68.484 + GString *payload;
68.485 + gchar *new_version = g_strdup("");
68.486 + gboolean res = TRUE;
68.487 +
68.488 +try_new_version:
68.489 + payload = g_string_new ("MYTH_PROTO_VERSION");
68.490 + g_string_append_printf( payload, " %d", mythtv_version );
68.491 +
68.492 + gmyth_socket_send_command(gmyth_socket, payload);
68.493 + response = gmyth_socket_receive_response(gmyth_socket);
68.494 +
68.495 + if (response == NULL) {
68.496 + g_warning ("[%s] Check protocol version error! Not answered!", __FUNCTION__);
68.497 + res = FALSE;
68.498 + goto done;
68.499 + }
68.500 +
68.501 + res = g_str_has_prefix (response->str, "ACCEPT");
68.502 + if (!res) {
68.503 + g_warning ("[%s] Protocol version request error: %s", __FUNCTION__, response->str);
68.504 + /* get the version number returned by the REJECT message */
68.505 + if ( ( res = g_str_has_prefix (response->str, "REJECT") ) == TRUE ) {
68.506 + new_version = g_strrstr( response->str, "]" );
68.507 + if (new_version!=NULL) {
68.508 + ++new_version; /* skip ']' character */
68.509 + if ( new_version != NULL ) {
68.510 + g_print( "[%s] got MythTV version = %s\n", __FUNCTION__, new_version );
68.511 + mythtv_version = g_ascii_strtoull( g_strdup( new_version ), NULL, 10 );
68.512 + /* do reconnection to the socket (socket is closed if the MythTV version was wrong) */
68.513 + gmyth_socket_connect( &gmyth_socket, gmyth_socket->hostname, gmyth_socket->port );
68.514 + /* g_free( new_version ); */
68.515 + goto try_new_version;
68.516 + }
68.517 + }
68.518 + }
68.519 + }
68.520 +
68.521 +done:
68.522 + if ( payload != NULL )
68.523 + g_string_free (payload, TRUE);
68.524 + if ( response != NULL )
68.525 + g_string_free (response, TRUE);
68.526 +// if (new_version!=NULL)
68.527 +// g_free( new_version );
68.528 +
68.529 + return res;
68.530 +}
68.531 +
68.532 +/** Verifies if the Mythtv backend supported the GMyth supported version.
68.533 + *
68.534 + * @param gmyth_socket The GMythSocket instance.
68.535 + * @return TRUE if supports, FALSE if not.
68.536 + */
68.537 +gboolean
68.538 +gmyth_socket_check_protocol_version (GMythSocket *gmyth_socket)
68.539 +{
68.540 + return gmyth_socket_check_protocol_version_number( gmyth_socket, MYTHTV_VERSION_DEFAULT );
68.541 +}
68.542 +
68.543 +/** Receives a backend answer after a gmyth_socket_send_command_call ().
68.544 + *
68.545 + * @param gmyth_socket The GMythSocket instance.
68.546 + * @return The response received, or NULL if error or nothing was received.
68.547 + */
68.548 +GString*
68.549 +gmyth_socket_receive_response(GMythSocket *gmyth_socket)
68.550 +{
68.551 + GIOStatus io_status = G_IO_STATUS_NORMAL;
68.552 + GError* error = NULL;
68.553 + gchar *buffer = NULL;
68.554 +
68.555 + GString *str = NULL;
68.556 +
68.557 + gsize bytes_read = 0;
68.558 + gint len = 0;
68.559 + GIOCondition io_cond;
68.560 +
68.561 + g_return_val_if_fail( gmyth_socket != NULL, NULL );
68.562 +
68.563 + /* verify if the input (read) buffer is ready to receive data */
68.564 +
68.565 + buffer = g_strnfill( BUFLEN, ' ' );
68.566 +
68.567 + g_static_mutex_lock( &mutex );
68.568 +
68.569 + io_status = g_io_channel_read_chars( gmyth_socket->sd_io_ch, buffer, MYTH_PROTOCOL_FIELD_SIZE, &bytes_read, &error );
68.570 +
68.571 +
68.572 + /* verify if the input (read) buffer is ready to receive data */
68.573 + io_cond = g_io_channel_get_buffer_condition( gmyth_socket->sd_io_ch );
68.574 +
68.575 + g_print ( "[%s] Bytes read = %d\n", __FUNCTION__, bytes_read );
68.576 +
68.577 + if( (io_status == G_IO_STATUS_ERROR) || (bytes_read <= 0) ) {
68.578 + g_warning ("[%s] Error in mythprotocol response from backend\n", __FUNCTION__);
68.579 + str = NULL;
68.580 + //return NULL;
68.581 + } else {
68.582 +
68.583 + io_status = g_io_channel_flush( gmyth_socket->sd_io_ch, &error );
68.584 + /* verify if the input (read) buffer is ready to receive data */
68.585 + io_cond = g_io_channel_get_buffer_condition( gmyth_socket->sd_io_ch );
68.586 +
68.587 + if ( ( io_cond & G_IO_IN ) != 0 ) {
68.588 +
68.589 + snprintf( buffer, MYTH_PROTOCOL_FIELD_SIZE+1, "%-8s", g_strdup(buffer));
68.590 + g_print( "[%s] buffer = [%s]\n", __FUNCTION__, buffer );
68.591 +
68.592 + /* removes trailing whitespace */
68.593 + buffer = g_strstrip( buffer );
68.594 +
68.595 + len = (gint)strtoull ( buffer, NULL, 10 );
68.596 +
68.597 + bytes_read = 0;
68.598 + io_status = g_io_channel_read_chars( gmyth_socket->sd_io_ch, buffer, len, &bytes_read, &error );
68.599 + buffer[bytes_read] = '\0';
68.600 + }
68.601 + }
68.602 +
68.603 + g_static_mutex_unlock( &mutex );
68.604 +
68.605 + g_debug ("[%s] Response received from backend: {%s}\n", __FUNCTION__, buffer);
68.606 +
68.607 + if ( ( bytes_read != len ) || ( io_status == G_IO_STATUS_ERROR ) )
68.608 + str = NULL;
68.609 + else
68.610 + str = g_string_new( buffer );
68.611 +
68.612 + if ( buffer != NULL )
68.613 + g_free( buffer );
68.614 +
68.615 + if ( error != NULL ) {
68.616 + g_printerr( "[%s] Error found receiving response from the IO channel: (%d, %s)\n", __FUNCTION__, error->code, error->message );
68.617 + str = NULL;
68.618 + g_error_free( error );
68.619 + }
68.620 +
68.621 + return str;
68.622 +}
68.623 +
68.624 +/** Format a Mythtv command from the str_list entries and send it to backend.
68.625 + *
68.626 + * @param gmyth_socket The GMythSocket instance.
68.627 + * @param str_list The string list to form the command
68.628 + * @return TRUE if command was sent, FALSE if any error happens.
68.629 + */
68.630 +gboolean
68.631 +gmyth_socket_write_stringlist(GMythSocket *gmyth_socket, GMythStringList* str_list)
68.632 +{
68.633 +
68.634 + GList *tmp_list;
68.635 + GPtrArray *ptr_array;
68.636 + gchar *str_array;
68.637 +
68.638 + g_static_mutex_lock( &mutex );
68.639 +
68.640 + ptr_array = g_ptr_array_sized_new(g_list_length(str_list->glist));
68.641 +
68.642 + g_print( "[%s] Number of parameters = %d\n", __FUNCTION__, g_list_length(str_list->glist) );
68.643 +
68.644 + // FIXME: change this implementation!
68.645 + tmp_list = str_list->glist;
68.646 + for(; tmp_list; tmp_list = tmp_list->next) {
68.647 + if ( tmp_list->data != NULL )
68.648 + g_ptr_array_add(ptr_array, ((GString*)tmp_list->data)->str);
68.649 + }
68.650 + g_ptr_array_add(ptr_array, NULL); // g_str_joinv() needs a NULL terminated string
68.651 +
68.652 + str_array = g_strjoinv (MYTH_SEPARATOR, (gchar **) (ptr_array->pdata));
68.653 +
68.654 + g_static_mutex_unlock( &mutex );
68.655 +
68.656 + // Sends message to backend
68.657 + // TODO: implement looping to send remaining data, and add timeout testing!
68.658 + gmyth_socket_send_command(gmyth_socket, g_string_new(str_array));
68.659 +
68.660 + g_free (str_array);
68.661 + g_ptr_array_free (ptr_array, TRUE);
68.662 +
68.663 + return TRUE;
68.664 +}
68.665 +
68.666 +/* Receives a backend command response and split it into the given string list.
68.667 + *
68.668 + * @param gmyth_socket The GMythSocket instance.
68.669 + * @param str_list the string list to be filled.
68.670 + * @return The number of received strings.
68.671 + */
68.672 +gint
68.673 +gmyth_socket_read_stringlist (GMythSocket *gmyth_socket, GMythStringList* str_list)
68.674 +{
68.675 + GString *response;
68.676 + gchar **str_array;
68.677 + gint i;
68.678 +
68.679 + response = gmyth_socket_receive_response(gmyth_socket);
68.680 + g_static_mutex_lock( &mutex );
68.681 +
68.682 + gmyth_string_list_clear_all (str_list);
68.683 + str_array = g_strsplit (response->str, MYTH_SEPARATOR, -1);
68.684 +
68.685 + for (i=0; i< g_strv_length (str_array); i++) {
68.686 + gmyth_string_list_append_string (str_list, g_string_new (str_array[i]));
68.687 + }
68.688 + g_static_mutex_unlock( &mutex );
68.689 +
68.690 + g_string_free (response, TRUE);
68.691 + g_strfreev (str_array);
68.692 +
68.693 + return gmyth_string_list_length (str_list);
68.694 +}
68.695 +
68.696 +/** Formats a Mythtv protocol command based on str_list and sends it to
68.697 + * the connected backend. The backend response is overwritten into str_list.
68.698 + *
68.699 + * @param gmyth_socket The GMythSocket instance.
68.700 + * @param str_list The string list to be sent, and on which the answer
68.701 + * will be written.
68.702 + * @return TRUE if command was sent and an answer was received, FALSE if any
68.703 + * error happens.
68.704 + */
68.705 +gint
68.706 +gmyth_socket_sendreceive_stringlist (GMythSocket *gmyth_socket, GMythStringList *str_list)
68.707 +{
68.708 + gmyth_socket_write_stringlist (gmyth_socket, str_list);
68.709 +
68.710 + return gmyth_socket_read_stringlist (gmyth_socket, str_list);
68.711 +}
69.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
69.2 +++ b/gmyth/src/libgmyth/gmyth_socket.h Wed Sep 20 23:45:35 2006 +0100
69.3 @@ -0,0 +1,116 @@
69.4 +/**
69.5 + * GMyth Library
69.6 + *
69.7 + * @file gmyth/gmyth_socket.h
69.8 + *
69.9 + * @brief <p> MythTV socket implementation, according to the MythTV Project
69.10 + * (www.mythtv.org).
69.11 + *
69.12 + * This component provides basic socket functionalities to interact with
69.13 + * the Mythtv backend.
69.14 + * <p>
69.15 + *
69.16 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
69.17 + * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
69.18 + *
69.19 + *//*
69.20 + *
69.21 + * This program is free software; you can redistribute it and/or modify
69.22 + * it under the terms of the GNU Lesser General Public License as published by
69.23 + * the Free Software Foundation; either version 2 of the License, or
69.24 + * (at your option) any later version.
69.25 + *
69.26 + * This program is distributed in the hope that it will be useful,
69.27 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
69.28 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
69.29 + * GNU General Public License for more details.
69.30 + *
69.31 + * You should have received a copy of the GNU Lesser General Public License
69.32 + * along with this program; if not, write to the Free Software
69.33 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
69.34 + */
69.35 +
69.36 +#ifndef __GMYTH_SOCKET_H__
69.37 +#define __GMYTH_SOCKET_H__
69.38 +
69.39 +#include <glib-object.h>
69.40 +
69.41 +#include <string.h>
69.42 +#include <netdb.h>
69.43 +#include <sys/socket.h>
69.44 +#include <unistd.h>
69.45 +#include <glib.h>
69.46 +
69.47 +#include "gmyth_stringlist.h"
69.48 +
69.49 +#define G_BEGIN_DECLS
69.50 +
69.51 +#define GMYTH_SOCKET_TYPE (gmyth_socket_get_type ())
69.52 +#define GMYTH_SOCKET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_SOCKET_TYPE, GMythSocket))
69.53 +#define GMYTH_SOCKET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_SOCKET_TYPE, GMythSocketClass))
69.54 +#define IS_GMYTH_SOCKET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_SOCKET_TYPE))
69.55 +#define IS_GMYTH_SOCKET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_SOCKET_TYPE))
69.56 +#define GMYTH_SOCKET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_SOCKET_TYPE, GMythSocketClass))
69.57 +
69.58 +
69.59 +typedef struct _GMythSocket GMythSocket;
69.60 +typedef struct _GMythSocketClass GMythSocketClass;
69.61 +
69.62 +struct _GMythSocketClass
69.63 +{
69.64 + GObjectClass parent_class;
69.65 +
69.66 + /* callbacks */
69.67 + /* no one for now */
69.68 +};
69.69 +
69.70 +struct _GMythSocket
69.71 +{
69.72 + GObject parent;
69.73 +
69.74 + /* socket descriptor */
69.75 + int sd;
69.76 + GIOChannel *sd_io_ch;
69.77 +
69.78 + gchar *hostname;
69.79 + gint port;
69.80 +};
69.81 +
69.82 +
69.83 +GType gmyth_socket_get_type (void);
69.84 +
69.85 +GMythSocket * gmyth_socket_new ();
69.86 +
69.87 +GIOChannel * gmyth_socket_get_io_channel (GMythSocket *gmyth_socket );
69.88 +
69.89 +gboolean gmyth_socket_is_able_to_read (GMythSocket *gmyth_socket );
69.90 +gboolean gmyth_socket_is_able_to_write (GMythSocket *gmyth_socket );
69.91 +
69.92 +gboolean gmyth_socket_send_command (GMythSocket *gmyth_socket,
69.93 + GString *command);
69.94 +GString * gmyth_socket_receive_response (GMythSocket *gmyth_socket);
69.95 +int gmyth_socket_sendreceive_stringlist (GMythSocket * gmyth_socket,
69.96 + GMythStringList *str_list);
69.97 +
69.98 +gboolean gmyth_socket_connect (GMythSocket **gmyth_socket,
69.99 + gchar *hostname, gint port);
69.100 +gboolean gmyth_socket_connect_to_backend (GMythSocket *gmyth_socket,
69.101 + gchar *hostname_backend, int port,
69.102 + gboolean blocking_client);
69.103 +
69.104 +GString * gmyth_socket_get_local_hostname ();
69.105 +
69.106 +void gmyth_socket_close_connection (GMythSocket *gmyth_socket);
69.107 +
69.108 +gboolean gmyth_socket_check_protocol_version (GMythSocket *gmyth_socket);
69.109 +gboolean gmyth_socket_check_protocol_version_number (GMythSocket *gmyth_socket,
69.110 + gint mythtv_version);
69.111 +
69.112 +gboolean gmyth_socket_write_stringlist(GMythSocket *gmyth_socket,
69.113 + GMythStringList* str_list);
69.114 +int gmyth_socket_read_stringlist(GMythSocket *gmyth_socket,
69.115 + GMythStringList* str_list);
69.116 +
69.117 +#define G_END_DECLS
69.118 +
69.119 +#endif /* __GMYTH_SOCKET_H__ */
70.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
70.2 +++ b/gmyth/src/libgmyth/gmyth_stringlist.c Wed Sep 20 23:45:35 2006 +0100
70.3 @@ -0,0 +1,272 @@
70.4 +/**
70.5 + * GMyth Library
70.6 + *
70.7 + * @file gmyth/gmyth_stringlist.c
70.8 + *
70.9 + * @brief <p> This component contains functions for dealing with the stringlist
70.10 + * format of the mythprotocol.
70.11 + *
70.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
70.13 + * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
70.14 + *
70.15 + *//*
70.16 + *
70.17 + * This program is free software; you can redistribute it and/or modify
70.18 + * it under the terms of the GNU Lesser General Public License as published by
70.19 + * the Free Software Foundation; either version 2 of the License, or
70.20 + * (at your option) any later version.
70.21 + *
70.22 + * This program is distributed in the hope that it will be useful,
70.23 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
70.24 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
70.25 + * GNU General Public License for more details.
70.26 + *
70.27 + * You should have received a copy of the GNU Lesser General Public License
70.28 + * along with this program; if not, write to the Free Software
70.29 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
70.30 + */
70.31 +
70.32 +#include "gmyth_stringlist.h"
70.33 +
70.34 +static void gmyth_string_list_class_init (GMythStringListClass *klass);
70.35 +static void gmyth_string_list_init (GMythStringList *object);
70.36 +
70.37 +static void gmyth_string_list_dispose (GObject *object);
70.38 +static void gmyth_string_list_finalize (GObject *object);
70.39 +
70.40 +G_DEFINE_TYPE(GMythStringList, gmyth_string_list, G_TYPE_OBJECT)
70.41 +
70.42 +static void
70.43 +gmyth_string_list_class_init (GMythStringListClass *klass)
70.44 +{
70.45 + GObjectClass *gobject_class;
70.46 +
70.47 + gobject_class = (GObjectClass *) klass;
70.48 +
70.49 + gobject_class->dispose = gmyth_string_list_dispose;
70.50 + gobject_class->finalize = gmyth_string_list_finalize;
70.51 +}
70.52 +
70.53 +static void
70.54 +gmyth_string_list_init (GMythStringList *gmyth_string_list)
70.55 +{
70.56 + gmyth_string_list->glist = NULL;
70.57 +}
70.58 +
70.59 +static void
70.60 +gmyth_string_list_dispose (GObject *object)
70.61 +{
70.62 + GMythStringList *gmyth_string_list = GMYTH_STRING_LIST(object);
70.63 +
70.64 + if (gmyth_string_list->glist)
70.65 + gmyth_string_list_clear_all(gmyth_string_list);
70.66 +
70.67 + G_OBJECT_CLASS (gmyth_string_list_parent_class)->dispose (object);
70.68 +}
70.69 +
70.70 +static void
70.71 +gmyth_string_list_finalize (GObject *object)
70.72 +{
70.73 + //GMythStringList *gmyth_string_list = GMYTH_STRING_LIST(object);
70.74 +
70.75 + g_signal_handlers_destroy (object);
70.76 +
70.77 + G_OBJECT_CLASS (gmyth_string_list_parent_class)->finalize (object);
70.78 +}
70.79 +
70.80 +/** Creates a new instance of GStringList.
70.81 + *
70.82 + * @return a new instance of GStringList.
70.83 + */
70.84 +GMythStringList *
70.85 +gmyth_string_list_new ()
70.86 +{
70.87 + GMythStringList *gmyth_string_list = GMYTH_STRING_LIST (g_object_new(GMYTH_STRING_LIST_TYPE, NULL));
70.88 +
70.89 + return gmyth_string_list;
70.90 +}
70.91 +
70.92 +/** Appends a guint64 to the string list.
70.93 + *
70.94 + * @param strlist The GMythStringList instance.
70.95 + * @param value The guint64 to be appended.
70.96 + *
70.97 + * @return The appended guint64 converted to a GString object.
70.98 + */
70.99 +GString*
70.100 +gmyth_string_list_append_int ( GMythStringList *strlist, const gint value )
70.101 +{
70.102 + GString *tmp_str = g_string_new ("");
70.103 +
70.104 + g_string_printf (tmp_str, "%d", value);
70.105 +
70.106 + gmyth_string_list_append_string (strlist, tmp_str);
70.107 +
70.108 + return tmp_str;
70.109 +}
70.110 +
70.111 +/** Appends a guint64 to the string list.
70.112 + *
70.113 + * @param strlist The GMythStringList instance.
70.114 + * @param value The guint64 to be appended.
70.115 + *
70.116 + * @return The appended guint64 converted to a GString object.
70.117 + */
70.118 +GString*
70.119 +gmyth_string_list_append_uint64 ( GMythStringList *strlist, const guint64 value)
70.120 +{
70.121 + GString *tmp_str = g_string_new ("");
70.122 +
70.123 + glong l2 = ( (guint64)(value) & 0xffffffffLL );
70.124 + glong l1 = ( ((guint64)(value) >> 32 ) & 0xffffffffLL );
70.125 +
70.126 + /* high order part of guint64 value */
70.127 + g_string_printf (tmp_str, "%ld", l1);
70.128 +
70.129 + g_debug( "[%s] uint64 (high) = %s\n", __FUNCTION__, tmp_str->str );
70.130 +
70.131 + gmyth_string_list_append_string (strlist, tmp_str);
70.132 +
70.133 + /* low order part of guint64 value */
70.134 + g_string_printf (tmp_str, "%ld", l2);
70.135 +
70.136 + g_debug( "[%s] uint64 (low) = %s\n", __FUNCTION__, tmp_str->str );
70.137 +
70.138 + gmyth_string_list_append_string (strlist, tmp_str);
70.139 +
70.140 + return tmp_str;
70.141 +}
70.142 +
70.143 +/** Appends a char array to the string list.
70.144 + *
70.145 + * @param strlist The GMythStringList instance.
70.146 + * @param value The char array to be appended.
70.147 + *
70.148 + * @return The appended char array converted to a GString object.
70.149 + */
70.150 +GString*
70.151 +gmyth_string_list_append_char_array ( GMythStringList *strlist, const gchar* value )
70.152 +{
70.153 + GString *tmp_str = NULL;
70.154 +
70.155 + g_return_val_if_fail( strlist != NULL, NULL );
70.156 +
70.157 + tmp_str = g_string_new (value);
70.158 +
70.159 + g_return_val_if_fail( tmp_str != NULL, NULL );
70.160 +
70.161 + gmyth_string_list_append_string (strlist, tmp_str);
70.162 +
70.163 + return tmp_str;
70.164 +}
70.165 +
70.166 +/** Appends a string to the string list.
70.167 + *
70.168 + * @param strlist The GMythStringList instance.
70.169 + * @param value The string to be appended.
70.170 + *
70.171 + * @return The appended string itself.
70.172 + */
70.173 +GString*
70.174 +gmyth_string_list_append_string ( GMythStringList *strlist, GString *value )
70.175 +{
70.176 + g_return_val_if_fail( strlist != NULL, NULL );
70.177 +
70.178 + strlist->glist = g_list_append (strlist->glist, value);
70.179 +
70.180 + return value;
70.181 +}
70.182 +
70.183 +/** Gets an integer value from the string list at the given position.
70.184 + *
70.185 + * @param strlist The GMythStringList instance.
70.186 + * @param index the integer position in the list, starting with zero.
70.187 + * @return The integer value.
70.188 + */
70.189 +gint
70.190 +gmyth_string_list_get_int ( GMythStringList *strlist, const gint index )
70.191 +{
70.192 + //TODO: Create static method check_index()
70.193 + GString *tmp_str = NULL;
70.194 +
70.195 + g_return_val_if_fail( strlist != NULL, 0 );
70.196 +
70.197 + tmp_str = (GString *) g_list_nth_data (strlist->glist, index);
70.198 +
70.199 + g_return_val_if_fail( tmp_str != NULL && tmp_str->str != NULL, 0 );
70.200 +
70.201 + return (int) ( 0x00000000ffffffffL & g_ascii_strtoull ( tmp_str->str, NULL, 0 ) );
70.202 +}
70.203 +
70.204 +/** Gets a guint64 value from the string list at the given position.
70.205 + * According to the Mythtv protocol, the 64 bits value is formed by
70.206 + * two strings.
70.207 + *
70.208 + * @param strlist The GMythStringList instance.
70.209 + * @param index the index of the first string forming the 64 bits value.
70.210 + * Index starts with zero.
70.211 + * @return The guint64 value.
70.212 + */
70.213 +guint64
70.214 +gmyth_string_list_get_uint64 ( GMythStringList *strlist, const gint index )
70.215 +{
70.216 + //TODO: Create static method check_index()
70.217 + guint64 ret_value = 0;
70.218 +
70.219 + g_return_val_if_fail( strlist != NULL, 0 );
70.220 +
70.221 + const GString *tmp_str1 = (GString *) g_list_nth_data (strlist->glist, index);
70.222 + const GString *tmp_str2 = (GString *) g_list_nth_data (strlist->glist, index+1);
70.223 +
70.224 + glong l1 = (glong)g_ascii_strtoull (tmp_str1->str, NULL, 10);
70.225 + glong l2 = (glong)g_ascii_strtoull (tmp_str2->str, NULL, 10);
70.226 +
70.227 + ret_value = ((guint64)(l2) & 0xffffffffLL) | ((guint64)(l1) << 32);
70.228 +
70.229 + g_debug( "[%s] returning uint64 value = %llu\n", __FUNCTION__, ret_value );
70.230 +
70.231 + return ret_value;
70.232 +}
70.233 +
70.234 +/** Gets a string from the string list at the given position.
70.235 + *
70.236 + * @param strlist The GMythStringList instance.
70.237 + * @param index the string position in the list, starting with zero.
70.238 + * @return A pointer to the string data.
70.239 + */
70.240 +GString*
70.241 +gmyth_string_list_get_string ( GMythStringList *strlist, const gint index )
70.242 +{
70.243 + if (!strlist || !(strlist->glist)) {
70.244 + g_warning ("%s received Null arguments", __FUNCTION__);
70.245 + return NULL;
70.246 + }
70.247 +
70.248 + return (GString *) g_list_nth_data (strlist->glist, index);
70.249 +}
70.250 +
70.251 +/** Removes all strings from the string list.
70.252 + *
70.253 + * @param strlist The GMythStringList instance.
70.254 + */
70.255 +void
70.256 +gmyth_string_list_clear_all ( GMythStringList *strlist )
70.257 +{
70.258 + if ( strlist != NULL && strlist->glist ) {
70.259 + g_list_free (strlist->glist);
70.260 + strlist->glist = NULL;
70.261 + }
70.262 +}
70.263 +
70.264 +/** Retrieves the number of elements in the string list.
70.265 + *
70.266 + * @param strlist The GMythStringList instance.
70.267 + * @return the string list length.
70.268 + */
70.269 +gint
70.270 +gmyth_string_list_length ( GMythStringList *strlist )
70.271 +{
70.272 + g_return_val_if_fail( strlist != NULL && strlist->glist != NULL, 0 );
70.273 +
70.274 + return g_list_length (strlist->glist);
70.275 +}
71.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
71.2 +++ b/gmyth/src/libgmyth/gmyth_stringlist.h Wed Sep 20 23:45:35 2006 +0100
71.3 @@ -0,0 +1,97 @@
71.4 +/**
71.5 + * GMyth Library
71.6 + *
71.7 + * @file gmyth/gmyth_stringlist.h
71.8 + *
71.9 + * @brief <p> This component contains functions for dealing with the stringlist
71.10 + * format of the mythprotocol.
71.11 + *
71.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
71.13 + * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
71.14 + *
71.15 + *//*
71.16 + *
71.17 + * This program is free software; you can redistribute it and/or modify
71.18 + * it under the terms of the GNU Lesser General Public License as published by
71.19 + * the Free Software Foundation; either version 2 of the License, or
71.20 + * (at your option) any later version.
71.21 + *
71.22 + * This program is distributed in the hope that it will be useful,
71.23 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
71.24 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
71.25 + * GNU General Public License for more details.
71.26 + *
71.27 + * You should have received a copy of the GNU Lesser General Public License
71.28 + * along with this program; if not, write to the Free Software
71.29 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
71.30 + */
71.31 +
71.32 +#ifndef GMYTH_STRING_LIST_H_
71.33 +#define GMYTH_STRING_LIST_H_
71.34 +
71.35 +#include <glib-object.h>
71.36 +
71.37 +#include <stdio.h>
71.38 +#include <stdlib.h>
71.39 +#include <string.h>
71.40 +#include <netdb.h>
71.41 +#include <sys/socket.h>
71.42 +#include <unistd.h>
71.43 +
71.44 +#define G_BEGIN_DECLS
71.45 +
71.46 +#define GMYTH_STRING_LIST_TYPE (gmyth_string_list_get_type ())
71.47 +#define GMYTH_STRING_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_STRING_LIST_TYPE, GMythStringList))
71.48 +#define GMYTH_STRING_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_STRING_LIST_TYPE, GMythStringListClass))
71.49 +#define IS_GMYTH_STRING_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_STRING_LIST_TYPE))
71.50 +#define IS_GMYTH_STRING_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_STRING_LIST_TYPE))
71.51 +#define GMYTH_STRING_LIST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_STRING_LIST_TYPE, GMythStringListClass))
71.52 +
71.53 +
71.54 +typedef struct _GMythStringList GMythStringList;
71.55 +typedef struct _GMythStringListClass GMythStringListClass;
71.56 +
71.57 +struct _GMythStringListClass
71.58 +{
71.59 + GObjectClass parent_class;
71.60 +
71.61 + /* callbacks */
71.62 + /* no one for now */
71.63 +};
71.64 +
71.65 +struct _GMythStringList
71.66 +{
71.67 + GObject parent;
71.68 +
71.69 + /* string list */
71.70 + GList *glist;
71.71 +};
71.72 +
71.73 +
71.74 +GType gmyth_string_list_get_type (void);
71.75 +
71.76 +GMythStringList * gmyth_string_list_new ();
71.77 +
71.78 +void gmyth_string_list_clear_all (GMythStringList *strlist);
71.79 +int gmyth_string_list_length (GMythStringList *strlist);
71.80 +
71.81 +GString * gmyth_string_list_append_int (GMythStringList *strlist,
71.82 + const gint value);
71.83 +GString * gmyth_string_list_append_uint64 (GMythStringList *strlist,
71.84 + const guint64 value);
71.85 +
71.86 +GString * gmyth_string_list_append_char_array (GMythStringList *strlist,
71.87 + const char* value);
71.88 +GString * gmyth_string_list_append_string (GMythStringList *strlist,
71.89 + GString *value);
71.90 +
71.91 +int gmyth_string_list_get_int (GMythStringList *strlist, const gint index);
71.92 +guint64 gmyth_string_list_get_uint64 (GMythStringList *strlist, const gint index);
71.93 +GString * gmyth_string_list_get_string (GMythStringList *strlist, const gint index);
71.94 +
71.95 +#define gmyth_string_list_get_char_array(strlist, index) \
71.96 + (gmyth_string_list_get_string(strlist, index))->str
71.97 +
71.98 +#define G_END_DECLS
71.99 +
71.100 +#endif /*GMYTH_STRING_LIST_H_*/
72.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
72.2 +++ b/gmyth/src/libgmyth/gmyth_tvchain.c Wed Sep 20 23:45:35 2006 +0100
72.3 @@ -0,0 +1,324 @@
72.4 +/**
72.5 + * GMyth Library
72.6 + *
72.7 + * @file gmyth/gmyth_tvchain.c
72.8 + *
72.9 + * @brief <p> This component contains functions for creating and accessing
72.10 + * the tvchain functions for live tv playback.
72.11 + *
72.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
72.13 + * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
72.14 + *
72.15 + *//*
72.16 + *
72.17 + * This program is free software; you can redistribute it and/or modify
72.18 + * it under the terms of the GNU Lesser General Public License as published by
72.19 + * the Free Software Foundation; either version 2 of the License, or
72.20 + * (at your option) any later version.
72.21 + *
72.22 + * This program is distributed in the hope that it will be useful,
72.23 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
72.24 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
72.25 + * GNU General Public License for more details.
72.26 + *
72.27 + * You should have received a copy of the GNU Lesser General Public License
72.28 + * along with this program; if not, write to the Free Software
72.29 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
72.30 + */
72.31 +
72.32 +#include <glib.h>
72.33 +#include <time.h>
72.34 +#include <stdio.h>
72.35 +#include <stdlib.h>
72.36 +
72.37 +#include "gmyth_epg.h"
72.38 +#include "gmyth_tvchain.h"
72.39 +#include "gmyth_util.h"
72.40 +#include "gmyth_query.h"
72.41 +#include "gmyth_scheduler.h"
72.42 +
72.43 +static void gmyth_tvchain_class_init (GMythTVChainClass *klass);
72.44 +static void gmyth_tvchain_init (GMythTVChain *object);
72.45 +
72.46 +static void gmyth_tvchain_dispose (GObject *object);
72.47 +static void gmyth_tvchain_finalize (GObject *object);
72.48 +
72.49 +G_DEFINE_TYPE(GMythTVChain, gmyth_tvchain, G_TYPE_OBJECT)
72.50 +
72.51 +static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
72.52 +
72.53 +static void
72.54 +gmyth_tvchain_class_init (GMythTVChainClass *klass)
72.55 +{
72.56 + GObjectClass *gobject_class;
72.57 +
72.58 + gobject_class = (GObjectClass *) klass;
72.59 +
72.60 + gobject_class->dispose = gmyth_tvchain_dispose;
72.61 + gobject_class->finalize = gmyth_tvchain_finalize;
72.62 +}
72.63 +
72.64 +static void
72.65 +gmyth_tvchain_init (GMythTVChain *tvchain)
72.66 +{
72.67 + tvchain->tvchain_id = NULL;
72.68 +
72.69 + tvchain->cur_chanid = g_string_new ("");
72.70 + tvchain->cur_startts = 0;
72.71 +}
72.72 +
72.73 +static void
72.74 +gmyth_tvchain_dispose (GObject *object)
72.75 +{
72.76 + //GMythTVChain *tvchain = GMYTH_TVCHAIN(object);
72.77 +
72.78 + G_OBJECT_CLASS (gmyth_tvchain_parent_class)->dispose (object);
72.79 +}
72.80 +
72.81 +static void
72.82 +gmyth_tvchain_finalize (GObject *object)
72.83 +{
72.84 + g_signal_handlers_destroy (object);
72.85 +
72.86 + G_OBJECT_CLASS (gmyth_tvchain_parent_class)->finalize (object);
72.87 +}
72.88 +
72.89 +/** Initializes the tvchain and generates the tvchain id.
72.90 + *
72.91 + * @param tvchain The GMythTVChain instance.
72.92 + * @param hostname The local hostname used to generate the tvchain id.
72.93 + */
72.94 +void
72.95 +gmyth_tvchain_initialize (GMythTVChain *tvchain, GString *hostname)
72.96 +{
72.97 + if (tvchain->tvchain_id == NULL) {
72.98 + GString *isodate;
72.99 + time_t cur_time;
72.100 +
72.101 + time(&cur_time);
72.102 + isodate = gmyth_util_time_to_isoformat (cur_time);
72.103 +
72.104 + tvchain->tvchain_id = g_string_sized_new(7 + hostname->len + isodate->len);
72.105 + g_string_printf(tvchain->tvchain_id,
72.106 + "live-%s-%s", hostname->str, isodate->str);
72.107 +
72.108 + g_print("tv_chain_id: %s\n", tvchain->tvchain_id->str);
72.109 +
72.110 + g_string_free(isodate, TRUE);
72.111 +
72.112 + } else {
72.113 + g_warning ("[%s] TVchain already initialized", __FUNCTION__);
72.114 + }
72.115 +}
72.116 +
72.117 +/** Gets the tvchain id.
72.118 + *
72.119 + * @param tvchain The GMythTVChain instance.
72.120 + * @return The tvchain id.
72.121 + */
72.122 +GString*
72.123 +gmyth_tvchain_get_id (GMythTVChain *tvchain)
72.124 +{
72.125 + return g_string_new (tvchain->tvchain_id->str);
72.126 +}
72.127 +
72.128 +/** Reloads all tvchain entries in the database.
72.129 + *
72.130 + * @param tvchain The GMythTVChain instance.
72.131 + * @return TRUE if success, or FALSE if error.
72.132 + */
72.133 +gboolean
72.134 +gmyth_tvchain_reload_all (GMythTVChain *tvchain)
72.135 +{
72.136 + MYSQL_ROW msql_row;
72.137 + MYSQL_RES *msql_res;
72.138 + GMythQuery *gmyth_query;
72.139 +
72.140 + GString *stmt_str;
72.141 +
72.142 + g_static_mutex_lock( &mutex );
72.143 +
72.144 + guint prev_size = g_list_length (tvchain->tvchain_list);
72.145 +
72.146 + g_debug ("[%s] chainid: %s", __FUNCTION__, tvchain->tvchain_id->str);
72.147 +
72.148 + g_list_free (tvchain->tvchain_list);
72.149 + tvchain->tvchain_list = NULL;
72.150 +
72.151 + // TODO: Reuse gmyth_query already connected from context
72.152 + gmyth_query = gmyth_query_new ();
72.153 + if (!gmyth_query_connect (gmyth_query)) {
72.154 + g_warning ("[%s] Could not connect to db", __FUNCTION__);
72.155 + g_static_mutex_unlock( &mutex );
72.156 +
72.157 + return FALSE;
72.158 + }
72.159 +
72.160 + stmt_str = g_string_new ("");
72.161 + g_string_printf (stmt_str,
72.162 + "SELECT chanid, starttime, endtime, discontinuity, "
72.163 + "chainpos, hostprefix, cardtype, channame, input "
72.164 + "FROM tvchain "
72.165 + "WHERE chainid = \"%s\" ORDER BY chainpos;",
72.166 + tvchain->tvchain_id->str);
72.167 +
72.168 + msql_res = gmyth_query_process_statement(gmyth_query, stmt_str->str);
72.169 + if (msql_res != NULL) {
72.170 +
72.171 + while ((msql_row = mysql_fetch_row (msql_res)) != NULL) {
72.172 + struct LiveTVChainEntry *entry = g_new0 (struct LiveTVChainEntry, 1);
72.173 + entry->chanid = g_string_new (msql_row[0]);
72.174 + entry->starttime = gmyth_util_string_to_time (g_string_new ((gchar*)msql_row[1]));
72.175 + entry->endtime = gmyth_util_string_to_time (g_string_new (msql_row[2]));
72.176 + entry->discontinuity = atoi (msql_row[3]) != 0;
72.177 + entry->hostprefix = g_string_new (msql_row[5]);
72.178 + entry->cardtype = g_string_new (msql_row[6]);
72.179 + entry->channum = g_string_new (msql_row[7]);
72.180 + entry->inputname = g_string_new (msql_row[8]);
72.181 +
72.182 + //m_maxpos = query.value(4).toInt() + 1;
72.183 +
72.184 + tvchain->tvchain_list = g_list_append (tvchain->tvchain_list, entry);
72.185 + }
72.186 + } else {
72.187 + g_warning ("gmyth_tvchain_reload_all query error!\n");
72.188 + g_static_mutex_unlock( &mutex );
72.189 +
72.190 + return FALSE;
72.191 + }
72.192 +
72.193 + g_static_mutex_unlock( &mutex );
72.194 +
72.195 + tvchain->cur_pos = gmyth_tvchain_program_is_at (tvchain, tvchain->cur_chanid, tvchain->cur_startts);
72.196 +
72.197 + if (tvchain->cur_pos < 0)
72.198 + tvchain->cur_pos = 0;
72.199 +
72.200 + // if (m_switchid >= 0)
72.201 + // m_switchid = ProgramIsAt(m_switchentry.chanid,m_switchentry.starttime);
72.202 +
72.203 + if (prev_size != g_list_length (tvchain->tvchain_list)) {
72.204 + g_debug ("[%s] Added new recording", __FUNCTION__);
72.205 + }
72.206 +
72.207 + g_string_free (stmt_str, TRUE);
72.208 +
72.209 + mysql_free_result (msql_res);
72.210 +
72.211 + g_object_unref (gmyth_query);
72.212 +
72.213 + return TRUE;
72.214 +}
72.215 +
72.216 +/** Returns the internal index for the TV chain related to the given
72.217 + * channel and start time.
72.218 + *
72.219 + * @param tvchain The GMythTVChain instance.
72.220 + * @param chanid The channel id.
72.221 + * @param startts The program start time.
72.222 + */
72.223 +int
72.224 +gmyth_tvchain_program_is_at (GMythTVChain *tvchain, GString *chanid, time_t startts)
72.225 +{
72.226 + int count = 0;
72.227 + struct LiveTVChainEntry *entry;
72.228 + GList *tmp_list = tvchain->tvchain_list;
72.229 +
72.230 + g_static_mutex_lock( &mutex );
72.231 +
72.232 + for (; tmp_list; tmp_list = tvchain->tvchain_list->next, ++count)
72.233 + {
72.234 + entry = (struct LiveTVChainEntry*) tmp_list->data;
72.235 + if (!g_strncasecmp (entry->chanid->str, chanid->str, chanid->len)
72.236 + && entry->starttime == startts)
72.237 + {
72.238 + g_static_mutex_unlock( &mutex );
72.239 + return count;
72.240 + }
72.241 + }
72.242 + g_static_mutex_unlock( &mutex );
72.243 +
72.244 + return -1;
72.245 +}
72.246 +
72.247 +/** Get the program info associated to the tvchain.
72.248 + *
72.249 + * @param tvchain The GMythTVChain instance.
72.250 + * @param index The tvchain index.
72.251 + * @return The program info structure.
72.252 + */
72.253 +GMythProgramInfo*
72.254 +gmyth_tvchain_get_program_at (GMythTVChain *tvchain, int index)
72.255 +{
72.256 + struct LiveTVChainEntry *entry;
72.257 +
72.258 + entry = gmyth_tvchain_get_entry_at (tvchain, index);
72.259 +
72.260 + if (entry)
72.261 + return gmyth_tvchain_entry_to_program (tvchain, entry);
72.262 +
72.263 + return NULL;
72.264 +}
72.265 +
72.266 +/** Gets a LiveTVChainEntry associated to the tvchain by its index.
72.267 + *
72.268 + * @param tvchain The GMythTVChain instance.
72.269 + * @param index The tvchain entry index
72.270 + * @return The LiveTVchainEntry structure.
72.271 + */
72.272 +struct LiveTVChainEntry*
72.273 +gmyth_tvchain_get_entry_at (GMythTVChain *tvchain, int index)
72.274 +{
72.275 + struct LiveTVChainEntry* chain_entry = NULL;
72.276 +
72.277 + g_static_mutex_lock( &mutex );
72.278 +
72.279 + int size = g_list_length (tvchain->tvchain_list);
72.280 + int new_index = (index < 0 || index >= size) ? size - 1 : index;
72.281 +
72.282 + if (new_index >= 0)
72.283 + chain_entry = (struct LiveTVChainEntry*) g_list_nth_data (tvchain->tvchain_list, new_index);
72.284 +
72.285 + g_static_mutex_unlock( &mutex );
72.286 +
72.287 + if ( chain_entry != NULL ) {
72.288 + g_debug ("[%s] Got TV Chain entry at %d.\n", __FUNCTION__, new_index );
72.289 +
72.290 + } else {
72.291 + g_warning ("[%s] failed to get entry at index %d", __FUNCTION__, index);
72.292 + }
72.293 +
72.294 + return chain_entry;
72.295 +}
72.296 +
72.297 +/** Gets the program info from backend database associated to the tv chain entry.
72.298 + *
72.299 + * @param tvchain The GMythTVChain instance.
72.300 + * @param entry the LiveTVChainEntry to be converted.
72.301 + * @return The progrma info.
72.302 + */
72.303 +GMythProgramInfo*
72.304 +gmyth_tvchain_entry_to_program (GMythTVChain *tvchain, struct LiveTVChainEntry *entry)
72.305 +{
72.306 + GMythProgramInfo *proginfo = NULL;
72.307 +
72.308 + if (!entry || !tvchain) {
72.309 + g_warning ("gmyth_tvchain_entry_to_program() received NULL argument");
72.310 + return NULL;
72.311 + }
72.312 +
72.313 + GMythScheduler *scheduler = gmyth_scheduler_new ();
72.314 +
72.315 + gmyth_scheduler_connect( scheduler );
72.316 + proginfo = gmyth_scheduler_get_recorded (scheduler,
72.317 + entry->chanid, entry->starttime);
72.318 + gmyth_scheduler_disconnect( scheduler );
72.319 +
72.320 + if (proginfo) {
72.321 + proginfo->pathname = g_string_prepend (proginfo->pathname, entry->hostprefix->str);
72.322 + } else {
72.323 + g_warning ("tvchain_entry_to_program(%s, %ld) failed!", entry->chanid->str, entry->starttime);
72.324 + }
72.325 +
72.326 + return proginfo;
72.327 +}
73.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
73.2 +++ b/gmyth/src/libgmyth/gmyth_tvchain.h Wed Sep 20 23:45:35 2006 +0100
73.3 @@ -0,0 +1,105 @@
73.4 +/**
73.5 + * GMyth Library
73.6 + *
73.7 + * @file gmyth/gmyth_tvchain.h
73.8 + *
73.9 + * @brief <p> This component contains functions for creating and accessing
73.10 + * the tvchain functions for live tv playback.
73.11 + *
73.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
73.13 + * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
73.14 + *
73.15 + *//*
73.16 + *
73.17 + * This program is free software; you can redistribute it and/or modify
73.18 + * it under the terms of the GNU Lesser General Public License as published by
73.19 + * the Free Software Foundation; either version 2 of the License, or
73.20 + * (at your option) any later version.
73.21 + *
73.22 + * This program is distributed in the hope that it will be useful,
73.23 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
73.24 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
73.25 + * GNU General Public License for more details.
73.26 + *
73.27 + * You should have received a copy of the GNU Lesser General Public License
73.28 + * along with this program; if not, write to the Free Software
73.29 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
73.30 + */
73.31 +
73.32 +#ifndef LIVETVCHAIN_H_
73.33 +#define LIVETVCHAIN_H_
73.34 +
73.35 +#include <glib-object.h>
73.36 +#include <time.h>
73.37 +
73.38 +#include "gmyth_common.h"
73.39 +
73.40 +#define G_BEGIN_DECLS
73.41 +
73.42 +#define GMYTH_TVCHAIN_TYPE (gmyth_tvchain_get_type ())
73.43 +#define GMYTH_TVCHAIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_TVCHAIN_TYPE, GMythTVChain))
73.44 +#define GMYTH_TVCHAIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_TVCHAIN_TYPE, GMythTVChainClass))
73.45 +#define IS_GMYTH_TVCHAIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_TVCHAIN_TYPE))
73.46 +#define IS_GMYTH_TVCHAIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_TVCHAIN_TYPE))
73.47 +#define GMYTH_TVCHAIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_TVCHAIN_TYPE, GMythTVChainClass))
73.48 +
73.49 +
73.50 +typedef struct _GMythTVChain GMythTVChain;
73.51 +typedef struct _GMythTVChainClass GMythTVChainClass;
73.52 +
73.53 +
73.54 +struct LiveTVChainEntry
73.55 +{
73.56 + GString *chanid;
73.57 +
73.58 + time_t starttime;
73.59 + time_t endtime;
73.60 +
73.61 + gboolean discontinuity; // if true, can't play smooth from last entry
73.62 + GString *hostprefix;
73.63 + GString *cardtype;
73.64 + GString *channum;
73.65 + GString *inputname;
73.66 +};
73.67 +
73.68 +
73.69 +struct _GMythTVChainClass
73.70 +{
73.71 + GObjectClass parent_class;
73.72 +
73.73 + /* callbacks */
73.74 + /* no one for now */
73.75 +};
73.76 +
73.77 +struct _GMythTVChain
73.78 +{
73.79 + GObject parent;
73.80 +
73.81 + GString *tvchain_id;
73.82 + GList *tvchain_list;
73.83 +
73.84 + time_t cur_startts;
73.85 + GString *cur_chanid;
73.86 + int cur_pos;
73.87 +};
73.88 +
73.89 +
73.90 +GType gmyth_tvchain_get_type (void);
73.91 +
73.92 +void gmyth_tvchain_initialize (GMythTVChain *tvchain,
73.93 + GString *hostname);
73.94 +gboolean gmyth_tvchain_reload_all (GMythTVChain *tvchain);
73.95 +GString* gmyth_tvchain_get_id (GMythTVChain *tvchain);
73.96 +int gmyth_tvchain_program_is_at (GMythTVChain *tvchain,
73.97 + GString *chanid, time_t startts);
73.98 +
73.99 +struct LiveTVChainEntry* gmyth_tvchain_get_entry_at (GMythTVChain *tvchain,
73.100 + gint index);
73.101 +
73.102 +GMythProgramInfo* gmyth_tvchain_entry_to_program (GMythTVChain *tvchain,
73.103 + struct LiveTVChainEntry *entry);
73.104 +GMythProgramInfo* gmyth_tvchain_get_program_at (GMythTVChain *tvchain, gint index);
73.105 +
73.106 +#define G_END_DECLS
73.107 +
73.108 +#endif /*LIVETVCHAIN_H_*/
74.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
74.2 +++ b/gmyth/src/libgmyth/gmyth_tvplayer.c Wed Sep 20 23:45:35 2006 +0100
74.3 @@ -0,0 +1,719 @@
74.4 +/**
74.5 + * GMyth Library
74.6 + *
74.7 + * @file gmyth/gmyth_tvplayer.c
74.8 + *
74.9 + * @brief <p> This component provides playback of the remote A/V using
74.10 + * GStreamer.
74.11 + *
74.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
74.13 + * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
74.14 + *
74.15 + *//*
74.16 + *
74.17 + * This program is free software; you can redistribute it and/or modify
74.18 + * it under the terms of the GNU Lesser General Public License as published by
74.19 + * the Free Software Foundation; either version 2 of the License, or
74.20 + * (at your option) any later version.
74.21 + *
74.22 + * This program is distributed in the hope that it will be useful,
74.23 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
74.24 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
74.25 + * GNU General Public License for more details.
74.26 + *
74.27 + * You should have received a copy of the GNU Lesser General Public License
74.28 + * along with this program; if not, write to the Free Software
74.29 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
74.30 + */
74.31 +
74.32 +#include "gmyth_tvplayer.h"
74.33 +
74.34 +#include <gdk/gdkx.h>
74.35 +
74.36 +#include "gmyth_context.h"
74.37 +#include "gmyth_remote_util.h"
74.38 +
74.39 +typedef struct _GstPlayerWindowStateChange
74.40 +{
74.41 + GstElement *play;
74.42 + GstState old_state, new_state;
74.43 + GMythTVPlayer *tvplayer;
74.44 +} GstPlayerWindowStateChange;
74.45 +
74.46 +typedef struct _GstPlayerWindowTagFound
74.47 +{
74.48 + GstElement *play;
74.49 + GstTagList *taglist;
74.50 + GMythTVPlayer *tvplayer;
74.51 +} GstPlayerWindowTagFound;
74.52 +
74.53 +/*
74.54 +static gboolean idle_state (gpointer data);
74.55 +static gboolean bus_call (GstBus * bus, GstMessage * msg, gpointer data);
74.56 +*/
74.57 +
74.58 +static void gmyth_tvplayer_class_init (GMythTVPlayerClass *klass);
74.59 +static void gmyth_tvplayer_init (GMythTVPlayer *object);
74.60 +
74.61 +static void gmyth_tvplayer_dispose (GObject *object);
74.62 +static void gmyth_tvplayer_finalize (GObject *object);
74.63 +
74.64 +G_DEFINE_TYPE(GMythTVPlayer, gmyth_tvplayer, G_TYPE_OBJECT)
74.65 +
74.66 +static gboolean gmyth_tvplayer_create_pipeline (GMythTVPlayer* tvplayer);
74.67 +static void new_pad_cb (GstElement *element,
74.68 + GstPad *pad, gpointer data);
74.69 +
74.70 +static gboolean expose_cb (GtkWidget * widget,
74.71 + GdkEventExpose * event,
74.72 + gpointer user_data);
74.73 +
74.74 +static void
74.75 +gmyth_tvplayer_class_init (GMythTVPlayerClass *klass)
74.76 +{
74.77 + GObjectClass *gobject_class;
74.78 +
74.79 + gobject_class = (GObjectClass *) klass;
74.80 +
74.81 + gobject_class->dispose = gmyth_tvplayer_dispose;
74.82 + gobject_class->finalize = gmyth_tvplayer_finalize;
74.83 +}
74.84 +
74.85 +static void
74.86 +new_pad_cb (GstElement *element, GstPad *pad, gpointer data)
74.87 +{
74.88 + GMythTVPlayer *tvplayer = GMYTH_TVPLAYER (data);
74.89 + GstPadLinkReturn ret;
74.90 + char *s;
74.91 +
74.92 + s = gst_caps_to_string (pad->caps);
74.93 +
74.94 + if ( s[0] == 'a') {
74.95 + ret = gst_pad_link (pad, gst_element_get_pad (tvplayer->audioqueue, "sink"));
74.96 + } else {
74.97 + ret = gst_pad_link (pad, gst_element_get_pad (tvplayer->videoqueue, "sink"));
74.98 + }
74.99 +
74.100 + g_free(s);
74.101 +}
74.102 +
74.103 +static gboolean
74.104 +expose_cb (GtkWidget * widget, GdkEventExpose * event, gpointer user_data)
74.105 +{
74.106 + GMythTVPlayer *tvplayer = GMYTH_TVPLAYER (user_data);
74.107 +
74.108 + if (tvplayer && tvplayer->videow) {
74.109 + gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (tvplayer->gst_videosink),
74.110 + GDK_WINDOW_XWINDOW (widget->window));
74.111 + return TRUE;
74.112 + }
74.113 +
74.114 + g_warning ("GMythTVPlayer expose called before setting video window\n");
74.115 +
74.116 + return FALSE;
74.117 +}
74.118 +
74.119 +static void
74.120 +gmyth_tvplayer_init (GMythTVPlayer *tvplayer)
74.121 +{
74.122 + tvplayer->gst_pipeline = NULL;
74.123 + tvplayer->gst_source = NULL;
74.124 + tvplayer->gst_videodec = NULL;
74.125 + tvplayer->gst_videosink = NULL;
74.126 + tvplayer->videoqueue = NULL;
74.127 + tvplayer->audioqueue = NULL;
74.128 +
74.129 + /* GTKWidget for rendering the video */
74.130 + tvplayer->videow = NULL;
74.131 + tvplayer->expose_handler = 0;
74.132 +
74.133 + tvplayer->backend_hostname = NULL;
74.134 + tvplayer->backend_port = 0;
74.135 + tvplayer->local_hostname = NULL;
74.136 +
74.137 + tvplayer->remote_encoder = NULL;
74.138 + tvplayer->tvchain = NULL;
74.139 + tvplayer->proginfo = NULL;
74.140 +}
74.141 +
74.142 +static void
74.143 +gmyth_tvplayer_dispose (GObject *object)
74.144 +{
74.145 +
74.146 + G_OBJECT_CLASS (gmyth_tvplayer_parent_class)->dispose (object);
74.147 +}
74.148 +
74.149 +static void
74.150 +gmyth_tvplayer_finalize (GObject *object)
74.151 +{
74.152 + g_signal_handlers_destroy (object);
74.153 +
74.154 + GMythTVPlayer *tvplayer = GMYTH_TVPLAYER (object);
74.155 +
74.156 + g_debug ("[%s] Finalizing tvplayer", __FUNCTION__);
74.157 +
74.158 + if (tvplayer->videow != NULL) {
74.159 + if (g_signal_handler_is_connected (tvplayer->videow,
74.160 + tvplayer->expose_handler)) {
74.161 + g_signal_handler_disconnect (tvplayer->videow,
74.162 + tvplayer->expose_handler);
74.163 + }
74.164 + g_object_unref (tvplayer->videow);
74.165 + }
74.166 +
74.167 + if ( tvplayer->remote_encoder != NULL )
74.168 + g_object_unref (tvplayer->remote_encoder);
74.169 + if ( tvplayer->tvchain != NULL )
74.170 + g_object_unref (tvplayer->tvchain);
74.171 + if ( tvplayer->proginfo != NULL )
74.172 + g_object_unref (tvplayer->proginfo);
74.173 +
74.174 + // Release Gstreamer elements
74.175 + if ( tvplayer->gst_pipeline != NULL )
74.176 + g_object_unref (tvplayer->gst_pipeline);
74.177 + if ( tvplayer->gst_source != NULL )
74.178 + g_object_unref (tvplayer->gst_source);
74.179 + if ( tvplayer->gst_videodec != NULL )
74.180 + g_object_unref (tvplayer->gst_videodec);
74.181 + if ( tvplayer->gst_videosink != NULL )
74.182 + g_object_unref (tvplayer->gst_videosink);
74.183 + if ( tvplayer->videoqueue != NULL )
74.184 + g_object_unref (tvplayer->videoqueue);
74.185 + if ( tvplayer->audioqueue != NULL )
74.186 + g_object_unref (tvplayer->audioqueue);
74.187 +
74.188 + G_OBJECT_CLASS (gmyth_tvplayer_parent_class)->finalize (object);
74.189 +}
74.190 +
74.191 +/** Creates a new instance of GMythTVPlayer.
74.192 + *
74.193 + * @return a new instance of GMythTVPlayer.
74.194 + */
74.195 +GMythTVPlayer *
74.196 +gmyth_tvplayer_new ()
74.197 +{
74.198 + GMythTVPlayer *tvplayer =
74.199 + GMYTH_TVPLAYER (g_object_new(GMYTH_TVPLAYER_TYPE, NULL));
74.200 +
74.201 + return tvplayer;
74.202 +}
74.203 +
74.204 +/** Initializes the tv player.
74.205 + *
74.206 + * @param tvplayer the object instance.
74.207 + * @return gboolean TRUE if the pipeline was created
74.208 + * successfully, FALSE otherwise.
74.209 + */
74.210 +gboolean
74.211 +gmyth_tvplayer_initialize (GMythTVPlayer *tvplayer)
74.212 +{
74.213 +
74.214 + if (!gmyth_tvplayer_create_pipeline (tvplayer)) {
74.215 + g_warning ("[%s] Error while creating pipeline. TV Player not initialized", __FUNCTION__);
74.216 + return FALSE;
74.217 + } else {
74.218 + g_debug ("[%s] GStreamer pipeline created", __FUNCTION__);
74.219 + }
74.220 +
74.221 + return TRUE;
74.222 +}
74.223 +
74.224 +/** Creates the GStreamer pipeline used by the player.
74.225 + *
74.226 + * @param tvplayer the object instance.
74.227 + * @return gboolean TRUE if the pipeline was created
74.228 + * successfully, FALSE otherwise.
74.229 + */
74.230 +static gboolean
74.231 +gmyth_tvplayer_create_pipeline (GMythTVPlayer* tvplayer)
74.232 +{
74.233 + GstElement *pipeline;
74.234 + GstElement *source, *parser;
74.235 + GstElement *videodec, *videosink;
74.236 +#ifndef MAEMO_PLATFORM
74.237 + GstElement *audiodec, *audioconv;
74.238 +#endif
74.239 + GstElement *audiosink;
74.240 + GstElement *videoqueue, *audioqueue;
74.241 +
74.242 + g_debug ("GMythTVPlayer: Setting the Gstreamer pipeline\n");
74.243 +
74.244 + pipeline = gst_pipeline_new ("video-player");
74.245 + source = gst_element_factory_make ("mythtvsrc", "myth-source");
74.246 + parser = gst_element_factory_make ("ffdemux_nuv", "nuv-demux");
74.247 +
74.248 + /* Gstreamer Video elements */
74.249 + videoqueue = gst_element_factory_make ("queue", "video-queue");
74.250 + videodec = gst_element_factory_make ("ffdec_mpeg4", "video-decoder");
74.251 +#ifdef MAEMO_PLATFORM
74.252 + videosink = gst_element_factory_make ("sdlvideosink", "image-output");
74.253 +#else
74.254 + videosink = gst_element_factory_make ("xvimagesink", "image-output");
74.255 +#endif
74.256 +
74.257 + /* Gstreamer Audio elements */
74.258 + audioqueue = gst_element_factory_make ("queue", "audio-queue");
74.259 +#ifdef MAEMO_PLATFORM
74.260 + audiosink = gst_element_factory_make ("dspmp3sink", "audio-output");
74.261 +#else
74.262 + audiodec = gst_element_factory_make ("ffdec_mp3", "audio-decoder");
74.263 + audioconv = gst_element_factory_make ("audioconvert", "audio-converter");
74.264 + audiosink = gst_element_factory_make ("alsasink", "audio-output");
74.265 +#endif
74.266 +
74.267 + if (!(pipeline && source && parser && videodec && videosink) ||
74.268 + !(videoqueue && audioqueue && audiosink)) {
74.269 + /* FIXME: hanlde the error correctly */
74.270 + /* video_alignment is not being created (below)
74.271 + and is causing problems to the ui */
74.272 +
74.273 + tvplayer->gst_pipeline = NULL;
74.274 + tvplayer->gst_videodec = NULL;
74.275 + tvplayer->gst_videosink = NULL;
74.276 +
74.277 + g_warning ("GstElement creation error!\n");
74.278 + return FALSE;
74.279 + }
74.280 +
74.281 +#ifndef MAEMO_PLATFORM
74.282 + if (!(audiodec && audioconv)) {
74.283 + g_warning ("GstElement for audio stream creation error!");
74.284 + return FALSE;
74.285 + }
74.286 +#endif
74.287 +
74.288 +
74.289 + tvplayer->gst_pipeline = pipeline;
74.290 + tvplayer->gst_source = source;
74.291 + tvplayer->gst_videodec = videodec;
74.292 + tvplayer->gst_videosink = videosink;
74.293 + g_object_ref (tvplayer->gst_pipeline);
74.294 + g_object_ref (tvplayer->gst_source);
74.295 + g_object_ref (tvplayer->gst_videodec);
74.296 + g_object_ref (tvplayer->gst_videosink);
74.297 +
74.298 + tvplayer->videoqueue = videoqueue;
74.299 + tvplayer->audioqueue = audioqueue;
74.300 + g_object_ref (tvplayer->videoqueue);
74.301 + g_object_ref (tvplayer->audioqueue);
74.302 +
74.303 + g_object_set (G_OBJECT (videosink), "sync", TRUE, NULL);
74.304 + g_object_set (G_OBJECT (audiosink), "sync", FALSE, NULL);
74.305 +
74.306 +// gst_bus_add_watch (gst_pipeline_get_bus (GST_PIPELINE (tvplayer->gst_pipeline)),
74.307 +// bus_call, tvplayer);
74.308 +
74.309 + gst_bin_add_many (GST_BIN (pipeline), source, parser, videoqueue,
74.310 + videodec, videosink, audioqueue, audiodec, audioconv, audiosink, NULL);
74.311 +
74.312 + {
74.313 +// GstCaps *rtpcaps = gst_caps_new_simple ("application/x-rtp", NULL);
74.314 +// gst_element_link_filtered(source, parser, rtpcaps);
74.315 + }
74.316 +
74.317 + gst_element_link (source, parser);
74.318 + gst_element_link_many (videoqueue, videodec, videosink, NULL);
74.319 + gst_element_link_many (audioqueue, audiodec, audioconv, audiosink, NULL);
74.320 +
74.321 + g_signal_connect (parser, "pad-added", G_CALLBACK (new_pad_cb), tvplayer);
74.322 +
74.323 + return TRUE;
74.324 +}
74.325 +
74.326 +/** Configures the backend and the tv player
74.327 + * for playing the recorded content A/V.
74.328 + *
74.329 + * FIXME: Change filename to program info or other structure about the recorded
74.330 + *
74.331 + * @param tvplayer the object instance.
74.332 + * @param filename the file uri of the recorded content to be played.
74.333 + * @return TRUE if successfull, FALSE if any error happens.
74.334 + */
74.335 +gboolean
74.336 +gmyth_tvplayer_record_setup (GMythTVPlayer *tvplayer, gchar *filename)
74.337 +{
74.338 + GMythSettings *msettings = gmyth_context_get_settings();
74.339 +
74.340 + // FIXME: we should receive the uri instead of filename
74.341 + GString *hostname = gmyth_settings_get_backend_hostname (msettings);
74.342 + int port = gmyth_settings_get_backend_port(msettings);
74.343 +
74.344 + GString *fullpath = g_string_new ("myth://");
74.345 + g_string_append_printf (fullpath, "%s:%d/%s", hostname->str, port, filename);
74.346 +
74.347 + tvplayer->is_livetv = FALSE;
74.348 +
74.349 + g_debug ("[%s] Setting record uri to gstreamer pipeline to %s", __FUNCTION__, fullpath->str);
74.350 +
74.351 + g_object_set (G_OBJECT (tvplayer->gst_source), "location",
74.352 + fullpath->str, NULL);
74.353 +
74.354 + return TRUE;
74.355 +}
74.356 +
74.357 +/** Configures the backend and the tv player
74.358 + * for playing the live tv.
74.359 + *
74.360 + * @param tvplayer the object instance.
74.361 + * @return TRUE if successfull, FALSE if any error happens.
74.362 + */
74.363 +gboolean
74.364 +gmyth_tvplayer_livetv_setup (GMythTVPlayer *tvplayer)
74.365 +{
74.366 + GMythSettings *msettings = gmyth_context_get_settings ();
74.367 + gboolean res = TRUE;
74.368 +
74.369 + res = gmyth_context_check_connection();
74.370 + if (!res) {
74.371 + g_warning ("[%s] LiveTV can not connect to backend", __FUNCTION__);
74.372 + res = FALSE;
74.373 + goto error;
74.374 + }
74.375 +
74.376 + tvplayer->backend_hostname = gmyth_settings_get_backend_hostname(msettings);
74.377 + tvplayer->backend_port = gmyth_settings_get_backend_port (msettings);
74.378 +
74.379 + tvplayer->local_hostname = g_string_new("");
74.380 + gmyth_context_get_local_hostname (tvplayer->local_hostname);
74.381 +
74.382 + if ( tvplayer->local_hostname == NULL ) {
74.383 + res = FALSE;
74.384 + goto error;
74.385 + }
74.386 +
74.387 + // Gets the remote encoder num
74.388 + tvplayer->remote_encoder = remote_request_next_free_recorder (-1);
74.389 +
74.390 + if ( tvplayer->remote_encoder == NULL ) {
74.391 + g_warning ("[%s] None remote encoder available", __FUNCTION__);
74.392 + res = FALSE;
74.393 + goto error;
74.394 + }
74.395 +
74.396 + // Creates livetv chain handler
74.397 + tvplayer->tvchain = GMYTH_TVCHAIN ( g_object_new(GMYTH_TVCHAIN_TYPE, NULL) );
74.398 + gmyth_tvchain_initialize ( tvplayer->tvchain, tvplayer->local_hostname );
74.399 +
74.400 + if ( tvplayer->tvchain == NULL || tvplayer->tvchain->tvchain_id == NULL ) {
74.401 + res = FALSE;
74.402 + goto error;
74.403 + }
74.404 +
74.405 + // Init remote encoder. Opens its control socket.
74.406 + res = gmyth_remote_encoder_setup(tvplayer->remote_encoder);
74.407 + if ( !res ) {
74.408 + g_warning ("[%s] Fail while setting remote encoder\n", __FUNCTION__);
74.409 + res = FALSE;
74.410 + goto error;
74.411 + }
74.412 + // Spawn live tv. Uses the socket to send mythprotocol data to start livetv in the backend (remotelly)
74.413 + res = gmyth_remote_encoder_spawntv ( tvplayer->remote_encoder,
74.414 + gmyth_tvchain_get_id(tvplayer->tvchain) );
74.415 + if (!res) {
74.416 + g_warning ("[%s] Fail while spawn tv\n", __FUNCTION__);
74.417 + res = FALSE;
74.418 + goto error;
74.419 + }
74.420 +
74.421 + // Reload all TV chain from Mysql database.
74.422 + gmyth_tvchain_reload_all (tvplayer->tvchain);
74.423 +
74.424 + if ( tvplayer->tvchain == NULL ) {
74.425 + res = FALSE;
74.426 + goto error;
74.427 + }
74.428 +
74.429 + // Get program info from database using chanid and starttime
74.430 + tvplayer->proginfo = gmyth_tvchain_get_program_at (tvplayer->tvchain, -1);
74.431 + if ( tvplayer->proginfo == NULL ) {
74.432 + g_warning ("[%s] LiveTV not successfully started.\n", __FUNCTION__ );
74.433 + res = FALSE;
74.434 + goto error;
74.435 + } else {
74.436 + g_debug ("[%s] MythLiveTV: All requests to backend to start TV were OK.\n", __FUNCTION__ );
74.437 + }
74.438 +
74.439 + return res;
74.440 +
74.441 +error:
74.442 + if ( tvplayer->backend_hostname != NULL ) {
74.443 + g_string_free( tvplayer->backend_hostname, TRUE );
74.444 + res = FALSE;
74.445 + }
74.446 +
74.447 + if ( tvplayer->local_hostname != NULL ) {
74.448 + g_string_free( tvplayer->local_hostname, TRUE );
74.449 + res = FALSE;
74.450 + }
74.451 +
74.452 + if ( tvplayer->remote_encoder != NULL ) {
74.453 + g_object_unref (tvplayer->remote_encoder);
74.454 + tvplayer->remote_encoder = NULL;
74.455 + }
74.456 +
74.457 + if ( tvplayer->tvchain != NULL ) {
74.458 + g_object_unref (tvplayer->tvchain);
74.459 + tvplayer->tvchain = NULL;
74.460 + }
74.461 +
74.462 + if ( tvplayer->proginfo != NULL ) {
74.463 + g_object_unref (tvplayer->proginfo);
74.464 + tvplayer->proginfo = NULL;
74.465 + }
74.466 +
74.467 + return res;
74.468 +
74.469 +}
74.470 +
74.471 +/** Sets the GTK video widget for the tv player.
74.472 + *
74.473 + * @param tvplayer the object instance.
74.474 + * @param videow the GTK video window.
74.475 + * @return TRUE if successfull, FALSE if any error happens.
74.476 + */
74.477 +gboolean
74.478 +gmyth_tvplayer_set_widget (GMythTVPlayer *tvplayer, GtkWidget *videow)
74.479 +{
74.480 + tvplayer->videow = videow;
74.481 + g_object_ref (videow);
74.482 +
74.483 + g_debug ("[%s] Setting widget for tv player render", __FUNCTION__);
74.484 +
74.485 + tvplayer->expose_handler = g_signal_connect (tvplayer->videow, "expose-event",
74.486 + G_CALLBACK (expose_cb), tvplayer);
74.487 +
74.488 + //g_signal_connect(miptv_ui->videow, "size_request", G_CALLBACK(cb_preferred_video_size), miptv_ui);
74.489 +
74.490 + return TRUE;
74.491 +}
74.492 +
74.493 +#if 0
74.494 +static gboolean
74.495 +bus_call (GstBus * bus, GstMessage * msg, gpointer data)
74.496 +{
74.497 + GMythTVPlayer *tvplayer = GMYTH_TVPLAYER ( data );
74.498 + GMainLoop *loop = tvplayer->loop;
74.499 +
74.500 + switch (GST_MESSAGE_TYPE (msg)) {
74.501 + case GST_MESSAGE_EOS:
74.502 + printf ("End of stream\n");
74.503 +/* if (miptv_ui->idle_id != 0) {
74.504 + g_source_remove (miptv_ui->idle_id);
74.505 + miptv_ui->idle_id = 0;
74.506 + }*/
74.507 +
74.508 + //g_idle_add ((GSourceFunc) idle_eos, data);
74.509 + gst_element_set_state (GST_ELEMENT (GST_MESSAGE_SRC (msg)),
74.510 + GST_STATE_READY);
74.511 + break;
74.512 + case GST_MESSAGE_ERROR:
74.513 + {
74.514 + gchar *debug;
74.515 + GError *err;
74.516 +
74.517 + gst_message_parse_error (msg, &err, &debug);
74.518 + g_free (debug);
74.519 +
74.520 + printf ("Error: %s\n", err->message);
74.521 + g_error_free (err);
74.522 +
74.523 + g_main_loop_quit (loop);
74.524 + }
74.525 + break;
74.526 + case GST_MESSAGE_STATE_CHANGED:{
74.527 + GstState oldstate;
74.528 + GstState newstate;
74.529 + GstState pending;
74.530 + GstPlayerWindowStateChange *st =
74.531 + g_new (GstPlayerWindowStateChange, 1);
74.532 +
74.533 + gst_message_parse_state_changed (msg,
74.534 + &oldstate,
74.535 + &newstate, &pending);
74.536 +
74.537 + st->play = tvplayer->gst_pipeline;
74.538 + gst_object_ref (GST_OBJECT (tvplayer->gst_pipeline));
74.539 + st->old_state = oldstate;
74.540 + st->new_state = newstate;
74.541 +
74.542 + st->tvplayer = tvplayer;
74.543 +
74.544 + /* State debug messages */
74.545 + printf ("oldstate = %s, newstate = %s, pendingstate = %s\n",
74.546 + gst_element_state_get_name (oldstate),
74.547 + gst_element_state_get_name (newstate),
74.548 + gst_element_state_get_name (pending));
74.549 +
74.550 + //g_idle_add ((GSourceFunc) idle_state, st);
74.551 +
74.552 + }
74.553 + break;
74.554 + default:
74.555 + printf (gst_message_type_get_name (GST_MESSAGE_TYPE (msg)));
74.556 + printf ("\n");
74.557 + break;
74.558 + }
74.559 +
74.560 + return TRUE;
74.561 +}
74.562 +#endif
74.563 +
74.564 +
74.565 +#if 0
74.566 +static gboolean
74.567 +idle_state (gpointer data)
74.568 +{
74.569 + GstPlayerWindowStateChange *st = data;
74.570 +
74.571 + if (st->old_state == GST_STATE_PLAYING) {
74.572 + if (st->miptv_ui->idle_id != 0) {
74.573 + g_source_remove (st->miptv_ui->idle_id);
74.574 + st->miptv_ui->idle_id = 0;
74.575 + }
74.576 + }
74.577 + else if (st->new_state == GST_STATE_PLAYING) {
74.578 + if (st->miptv_ui->idle_id != 0)
74.579 + g_source_remove (st->miptv_ui->idle_id);
74.580 +
74.581 + st->miptv_ui->idle_id = g_idle_add (cb_iterate, st->miptv_ui);
74.582 + }
74.583 +
74.584 + /* new movie loaded? */
74.585 + if (st->old_state == GST_STATE_READY && st->new_state > GST_STATE_READY) {
74.586 +
74.587 + /* gboolean have_video = FALSE; */
74.588 +
74.589 + gtk_widget_show (st->miptv_ui->videow);
74.590 +
74.591 + gtk_window_resize (GTK_WINDOW (st->miptv_ui->main_window), 1, 1);
74.592 +
74.593 + }
74.594 +
74.595 + /* discarded movie? */
74.596 + if (st->old_state > GST_STATE_READY && st->new_state == GST_STATE_READY) {
74.597 +
74.598 + if (st->miptv_ui->tagcache) {
74.599 + gst_tag_list_free (st->miptv_ui->tagcache);
74.600 + st->miptv_ui->tagcache = NULL;
74.601 + }
74.602 + }
74.603 +
74.604 + gst_object_unref (GST_OBJECT (st->play));
74.605 + //g_object_unref (G_OBJECT (st->win));
74.606 + g_free (st);
74.607 +
74.608 + /* once */
74.609 + return FALSE;
74.610 +}
74.611 +
74.612 +#endif
74.613 +
74.614 +/** Stops playing the current A/V.
74.615 + *
74.616 + * FIXME: How to proceed differently between livetv
74.617 + * and recorded content?
74.618 + *
74.619 + * @param tvplayer the object instance.
74.620 + * @return void
74.621 + */
74.622 +void
74.623 +gmyth_tvplayer_stop_playing (GMythTVPlayer *tvplayer)
74.624 +{
74.625 + g_debug ("[%s] Setting gstreamer pipeline state to NULL", __FUNCTION__);
74.626 +
74.627 + gst_element_set_state (tvplayer->gst_pipeline, GST_STATE_NULL);
74.628 +
74.629 + if (tvplayer->is_livetv) {
74.630 + if (!gmyth_remote_encoder_stop_livetv (tvplayer->remote_encoder)) {
74.631 + g_warning ("[%s] Error while stoping remote encoder", __FUNCTION__);
74.632 + }
74.633 + }
74.634 +}
74.635 +
74.636 +/** Queries if the tvplayer is active playing A/V content.
74.637 + *
74.638 + * @param tvplayer the object instance.
74.639 + * @return TRUE if the tvplayer is active, FALSE otherwise.
74.640 + */
74.641 +gboolean
74.642 +gmyth_tvplayer_is_playing (GMythTVPlayer *tvplayer)
74.643 +{
74.644 + return (GST_STATE (tvplayer->gst_pipeline) == GST_STATE_PLAYING);
74.645 +}
74.646 +
74.647 +/** Static function that sets the tvplayer state to PLAYING.
74.648 + *
74.649 + * @param tvplayer the object instance.
74.650 + * @return TRUE if the tvplayer is active, FALSE otherwise.
74.651 + */
74.652 +static gboolean
74.653 +idle_play (gpointer data)
74.654 +{
74.655 + GMythTVPlayer *tvplayer = GMYTH_TVPLAYER (data);
74.656 +
74.657 + g_debug ("GMythTVPlayer: Setting pipeline state to PLAYING\n");
74.658 +
74.659 + gst_element_set_state (tvplayer->gst_pipeline, GST_STATE_PLAYING);
74.660 +
74.661 + return FALSE;
74.662 +}
74.663 +
74.664 +/** Start playing A/V with the tvplayer attributes.
74.665 + *
74.666 + * @param tvplayer the object instance.
74.667 + */
74.668 +void
74.669 +gmyth_tvplayer_start_playing (GMythTVPlayer *tvplayer)
74.670 +{
74.671 +
74.672 + // FIXME: Move this to livetv_setup??
74.673 + if (tvplayer->is_livetv) {
74.674 +
74.675 + #if 0
74.676 + if (!tvplayer || !(tvplayer->proginfo) || !(tvplayer->local_hostname)
74.677 + || !(tvplayer->gst_source)) {
74.678 + g_warning ("GMythtvPlayer not ready to start playing\n");
74.679 + }
74.680 +
74.681 + if (!(tvplayer->proginfo->pathname)) {
74.682 + g_warning ("[%s] Playback url is null, could not play the myth content", __FUNCTION__);
74.683 + return;
74.684 + }
74.685 +
74.686 + g_debug ("GMythTVPlayer: Start playing %s", tvplayer->proginfo->pathname->str);
74.687 +#endif
74.688 + g_object_set (G_OBJECT (tvplayer->gst_source), "mythtv-live",
74.689 + TRUE, NULL);
74.690 +#if 0
74.691 + if ( tvplayer->tvchain != NULL ) {
74.692 + GString *str_chainid = gmyth_tvchain_get_id(tvplayer->tvchain);
74.693 + g_print( "[%s]\tCHAIN ID: %s\n", __FUNCTION__, str_chainid->str );
74.694 +
74.695 + g_object_set (G_OBJECT (tvplayer->gst_source), "mythtv-live-chainid",
74.696 + g_strdup( str_chainid->str ), NULL);
74.697 + if ( str_chainid!=NULL)
74.698 + g_string_free( str_chainid, FALSE );
74.699 + }
74.700 +
74.701 + if ( tvplayer->remote_encoder != NULL )
74.702 + g_object_set (G_OBJECT (tvplayer->gst_source), "mythtv-live-id",
74.703 + tvplayer->remote_encoder->recorder_num, NULL );
74.704 + g_debug ("[%s] Setting location to %s", __FUNCTION__,
74.705 + tvplayer->proginfo->pathname->str);
74.706 +
74.707 + /* Sets the gstreamer properties acording to the service access address */
74.708 + g_object_set (G_OBJECT (tvplayer->gst_source), "location",
74.709 + tvplayer->proginfo->pathname->str, NULL);
74.710 +#endif
74.711 + }
74.712 +
74.713 + g_object_set (G_OBJECT (tvplayer->gst_source), "mythtv-version",
74.714 + MYTHTV_VERSION_DEFAULT, NULL);
74.715 +
74.716 + g_object_set (G_OBJECT (tvplayer->gst_source), "mythtv-debug",
74.717 + TRUE, NULL);
74.718 +
74.719 + g_idle_add (idle_play, tvplayer);
74.720 +
74.721 +}
74.722 +
75.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
75.2 +++ b/gmyth/src/libgmyth/gmyth_tvplayer.h Wed Sep 20 23:45:35 2006 +0100
75.3 @@ -0,0 +1,112 @@
75.4 +/**
75.5 + * GMyth Library
75.6 + *
75.7 + * @file gmyth/gmyth_tvplayer.h
75.8 + *
75.9 + * @brief <p> This component provides playback of the remote A/V using
75.10 + * GStreamer.
75.11 + *
75.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
75.13 + * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
75.14 + *
75.15 + *//*
75.16 + *
75.17 + * This program is free software; you can redistribute it and/or modify
75.18 + * it under the terms of the GNU Lesser General Public License as published by
75.19 + * the Free Software Foundation; either version 2 of the License, or
75.20 + * (at your option) any later version.
75.21 + *
75.22 + * This program is distributed in the hope that it will be useful,
75.23 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
75.24 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
75.25 + * GNU General Public License for more details.
75.26 + *
75.27 + * You should have received a copy of the GNU Lesser General Public License
75.28 + * along with this program; if not, write to the Free Software
75.29 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
75.30 + */
75.31 +
75.32 +#ifndef GMYTH_TVPLAYER_H_
75.33 +#define GMYTH_TVPLAYER_H_
75.34 +
75.35 +#include <glib-object.h>
75.36 +#include <gtk/gtk.h>
75.37 +
75.38 +/* GStreamer includes */
75.39 +#include <gst/gst.h>
75.40 +#include <gst/interfaces/xoverlay.h>
75.41 +
75.42 +#include "gmyth_remote_encoder.h"
75.43 +#include "gmyth_tvchain.h"
75.44 +#include "gmyth_common.h"
75.45 +
75.46 +#define G_BEGIN_DECLS
75.47 +
75.48 +#define GMYTH_TVPLAYER_TYPE (gmyth_tvplayer_get_type ())
75.49 +#define GMYTH_TVPLAYER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_TVPLAYER_TYPE, GMythTVPlayer))
75.50 +#define GMYTH_TVPLAYER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_TVPLAYER_TYPE, GMythTVPlayerClass))
75.51 +#define IS_GMYTH_TVPLAYER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_TVPLAYER_TYPE))
75.52 +#define IS_GMYTH_TVPLAYER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_TVPLAYER_TYPE))
75.53 +#define GMYTH_TVPLAYER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_TVPLAYER_TYPE, GMythTVPlayerClass))
75.54 +
75.55 +
75.56 +typedef struct _GMythTVPlayer GMythTVPlayer;
75.57 +typedef struct _GMythTVPlayerClass GMythTVPlayerClass;
75.58 +
75.59 +struct _GMythTVPlayerClass
75.60 +{
75.61 + GObjectClass parent_class;
75.62 +
75.63 + /* callbacks */
75.64 + /* no one for now */
75.65 +};
75.66 +
75.67 +struct _GMythTVPlayer
75.68 +{
75.69 + GObject parent;
75.70 +
75.71 + GstElement *gst_pipeline;
75.72 + GstElement *gst_source;
75.73 + GstElement *gst_videodec;
75.74 + GstElement *gst_videosink;
75.75 + GstElement *videoqueue;
75.76 + GstElement *audioqueue;
75.77 +
75.78 + gulong expose_handler;
75.79 +// GMainLoop *loop;
75.80 +
75.81 + GtkWidget *videow;
75.82 +
75.83 + /* Backend connection related variables */
75.84 + GString *backend_hostname;
75.85 + gint backend_port;
75.86 + GString *local_hostname;
75.87 +
75.88 + GMythRemoteEncoder *remote_encoder;
75.89 + GMythTVChain *tvchain;
75.90 + GMythProgramInfo *proginfo;
75.91 +
75.92 + gboolean is_livetv;
75.93 +};
75.94 +
75.95 +
75.96 +GType gmyth_tvplayer_get_type (void);
75.97 +
75.98 +GMythTVPlayer* gmyth_tvplayer_new ();
75.99 +gboolean gmyth_tvplayer_initialize (GMythTVPlayer *tvplayer);
75.100 +
75.101 +void gmyth_tvplayer_start_playing (GMythTVPlayer *tvplayer);
75.102 +void gmyth_tvplayer_stop_playing (GMythTVPlayer *tvplayer);
75.103 +
75.104 +gboolean gmyth_tvplayer_set_widget (GMythTVPlayer *tvplayer,
75.105 + GtkWidget *videow);
75.106 +
75.107 +gboolean gmyth_tvplayer_is_playing (GMythTVPlayer *tvplayer);
75.108 +
75.109 +gboolean gmyth_tvplayer_record_setup (GMythTVPlayer *tvplayer,
75.110 + gchar *filename);
75.111 +gboolean gmyth_tvplayer_livetv_setup (GMythTVPlayer *tvplayer);
75.112 +
75.113 +#define G_END_DECLS
75.114 +
75.115 +#endif /*GMYTH_TVPLAYER_H_*/
76.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
76.2 +++ b/gmyth/src/libgmyth/gmyth_util.c Wed Sep 20 23:45:35 2006 +0100
76.3 @@ -0,0 +1,138 @@
76.4 +/**
76.5 +* GMyth Library
76.6 +*
76.7 +* @file gmyth/gmyth_util.c
76.8 +*
76.9 +* @brief <p> This component provides utility functions.
76.10 +*
76.11 +* Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
76.12 +* @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
76.13 +*
76.14 +*//*
76.15 +*
76.16 +* This program is free software; you can redistribute it and/or modify
76.17 +* it under the terms of the GNU Lesser General Public License as published by
76.18 +* the Free Software Foundation; either version 2 of the License, or
76.19 +* (at your option) any later version.
76.20 +*
76.21 +* This program is distributed in the hope that it will be useful,
76.22 +* but WITHOUT ANY WARRANTY; without even the implied warranty of
76.23 +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
76.24 +* GNU General Public License for more details.
76.25 +*
76.26 +* You should have received a copy of the GNU Lesser General Public License
76.27 +* along with this program; if not, write to the Free Software
76.28 +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
76.29 +*/
76.30 +
76.31 +#include "gmyth_util.h"
76.32 +
76.33 +#include <glib.h>
76.34 +#include <glib/gprintf.h>
76.35 +
76.36 +/** Converts a time_t struct in a GString at ISO standard format
76.37 + * (e.g. 2006-07-20T09:56:41).
76.38 + *
76.39 + * The returned GString memory should be deallocated from
76.40 + * the calling function.
76.41 + *
76.42 + * @param time_value the time value to be converted
76.43 + * @return GString* the converted isoformat string
76.44 + */
76.45 +GString*
76.46 +gmyth_util_time_to_isoformat (time_t time_value)
76.47 +{
76.48 + struct tm tm_time;
76.49 + GString *result;
76.50 +
76.51 + if (localtime_r(&time_value, &tm_time) == NULL) {
76.52 + g_warning ("gmyth_util_time_to_isoformat convertion error!\n");
76.53 + return NULL;
76.54 + }
76.55 +
76.56 + result = g_string_sized_new(20);
76.57 + g_string_printf(result, "%04d-%02d-%02dT%02d:%02d:%02d",
76.58 + tm_time.tm_year + 1900, tm_time.tm_mon + 1, tm_time.tm_mday,
76.59 + tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec);
76.60 +
76.61 + return result;
76.62 +}
76.63 +
76.64 +/** Converts a time_t struct in a GString to the following
76.65 + * format (e.g. 2006-07-20 09:56:41).
76.66 + *
76.67 + * The returned GString memory should be deallocated from
76.68 + * the calling function.
76.69 + *
76.70 + * @param time_value the time value to be converted
76.71 + * @return GString* the converted string
76.72 + */
76.73 +GString*
76.74 +gmyth_util_time_to_string (time_t time_value)
76.75 +{
76.76 + GString *result = gmyth_util_time_to_isoformat (time_value);
76.77 + result->str[10] = ' ';
76.78 +
76.79 + return result;
76.80 +}
76.81 +
76.82 +/** Converts a GString in the following format
76.83 + * (e.g. 2006-07-20 09:56:41) to a time_t struct.
76.84 + *
76.85 + * @param time_str the string to be converted
76.86 + * @return time_t the time converted value
76.87 + */
76.88 +time_t
76.89 +gmyth_util_string_to_time (GString* time_str)
76.90 +{
76.91 + int year, month, day, hour, min, sec;
76.92 +
76.93 + g_debug( "[%s] time_str = %s.\n", __FUNCTION__, time_str != NULL ? time_str->str : "[time string is NULL!]" );
76.94 +
76.95 + if (sscanf (time_str->str, "%04d-%02d-%02d %02d:%02d:%02d",
76.96 + &year, &month, &day, &hour, &min, &sec) < 3) { /* At least date */
76.97 + g_warning ("GMythUtil: isoformat_to_time converter error!\n");
76.98 + return 0;
76.99 + } else {
76.100 + struct tm tm_time;
76.101 + tm_time.tm_year = year - 1900;
76.102 + tm_time.tm_mon = month - 1;
76.103 + tm_time.tm_mday = day;
76.104 + tm_time.tm_hour = hour;
76.105 + tm_time.tm_min = min;
76.106 + tm_time.tm_sec = sec;
76.107 +
76.108 + return mktime (&tm_time);
76.109 + }
76.110 +}
76.111 +
76.112 +/** Decodes a long long variable from the string list
76.113 + * format of the myhtprotocol.
76.114 + *
76.115 + * @param strlist the string list of mythprotocol values
76.116 + * @param offset the list node offset of the long long variable
76.117 + * @return guint64 the long long converted value
76.118 + */
76.119 +guint64
76.120 +gmyth_util_decode_long_long(GMythStringList *strlist, guint offset)
76.121 +{
76.122 +
76.123 + guint64 ret_value = 0LL;
76.124 +
76.125 + g_return_val_if_fail( strlist != NULL, ret_value );
76.126 +
76.127 + if ( offset < gmyth_string_list_length( strlist ))
76.128 + g_printerr( "[%s] Offset is lower than the Stringlist (offset = %d)!\n",
76.129 + __FUNCTION__, offset );
76.130 +
76.131 + g_return_val_if_fail( offset < gmyth_string_list_length( strlist ), ret_value );
76.132 +
76.133 + gint l1 = gmyth_string_list_get_int( strlist, offset );
76.134 + gint l2 = gmyth_string_list_get_int( strlist, offset + 1 );
76.135 +
76.136 + ret_value = ((guint64)(l2) & 0xffffffffLL) | ((guint64)(l1) << 32);
76.137 +
76.138 + return ret_value;
76.139 +
76.140 +}
76.141 +
77.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
77.2 +++ b/gmyth/src/libgmyth/gmyth_util.h Wed Sep 20 23:45:35 2006 +0100
77.3 @@ -0,0 +1,42 @@
77.4 +/**
77.5 +* GMyth Library
77.6 +*
77.7 +* @file gmyth/gmyth_util.h
77.8 +*
77.9 +* @brief <p> This component provides utility functions.
77.10 +*
77.11 +* Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
77.12 +* @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
77.13 +*
77.14 +*//*
77.15 +*
77.16 +* This program is free software; you can redistribute it and/or modify
77.17 +* it under the terms of the GNU Lesser General Public License as published by
77.18 +* the Free Software Foundation; either version 2 of the License, or
77.19 +* (at your option) any later version.
77.20 +*
77.21 +* This program is distributed in the hope that it will be useful,
77.22 +* but WITHOUT ANY WARRANTY; without even the implied warranty of
77.23 +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
77.24 +* GNU General Public License for more details.
77.25 +*
77.26 +* You should have received a copy of the GNU Lesser General Public License
77.27 +* along with this program; if not, write to the Free Software
77.28 +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
77.29 +*/
77.30 +
77.31 +#ifndef GMYTH_UTIL_H_
77.32 +#define GMYTH_UTIL_H_
77.33 +
77.34 +#include <time.h>
77.35 +#include <glib.h>
77.36 +
77.37 +#include "gmyth_stringlist.h"
77.38 +
77.39 +GString * gmyth_util_time_to_isoformat(time_t time_value);
77.40 +GString * gmyth_util_time_to_string (time_t time_value);
77.41 +time_t gmyth_util_string_to_time (GString* time_str);
77.42 +guint64 gmyth_util_decode_long_long (GMythStringList *strlist,
77.43 + guint offset);
77.44 +
77.45 +#endif /*GMYTH_UTIL_H_*/
78.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
78.2 +++ b/gmyth/src/mmyth_main.c Wed Sep 20 23:45:35 2006 +0100
78.3 @@ -0,0 +1,103 @@
78.4 +
78.5 +#include <gtk/gtk.h>
78.6 +
78.7 +#include "config.h"
78.8 +
78.9 +#ifdef MAEMO_PLATFORM
78.10 +#include "hildon-widgets/hildon-program.h"
78.11 +#include "hildon-widgets/hildon-window.h"
78.12 +#endif
78.13 +
78.14 +#include "gmyth_remote_encoder.h"
78.15 +#include "gmyth_settings.h"
78.16 +#include "gmyth_context.h"
78.17 +#include "gmyth_tvchain.h"
78.18 +#include "gmyth_tvplayer.h"
78.19 +#include "gmyth_remote_util.h"
78.20 +
78.21 +#include "mmyth_ui.h"
78.22 +
78.23 +static void
78.24 +cb_destroy (GtkWidget * widget, gpointer data)
78.25 +{
78.26 + MMythUi *mmyth_ui = (MMythUi *) data;
78.27 +
78.28 + if (mmyth_ui->tvplayer != NULL) {
78.29 + if (gmyth_tvplayer_is_playing (mmyth_ui->tvplayer) )
78.30 + gmyth_tvplayer_stop_playing (mmyth_ui->tvplayer);
78.31 + }
78.32 +
78.33 + mmyth_ui_finalize (mmyth_ui);
78.34 +
78.35 + gtk_main_quit ();
78.36 +}
78.37 +
78.38 +#ifdef NDEBUG
78.39 +static void
78.40 +debug_error_func( const gchar*log_domain, GLogLevelFlags log_level, const gchar *message,
78.41 + gpointer user_data )
78.42 +
78.43 +{
78.44 + /* leave this with NO print out messages, once you need to disable debug messages! */
78.45 + //g_print ( "[%s] DEBUG messages disabled!\n", __FUNCTION__ );
78.46 +}
78.47 +#endif
78.48 +
78.49 +gint
78.50 +main (gint argc, gchar * argv[])
78.51 +{
78.52 + GtkWidget *window;
78.53 + MMythUi *mmyth_ui;
78.54 +#ifdef MAEMO_PLATFORM
78.55 + HildonProgram *program = NULL;
78.56 +#endif
78.57 +
78.58 + /* init threads */
78.59 + g_thread_init (NULL);
78.60 +
78.61 + /* Initializes GTK */
78.62 + gtk_init (&argc, &argv);
78.63 + gst_init (&argc, &argv);
78.64 +#ifdef NDEBUG
78.65 + g_log_set_default_handler( debug_error_func, NULL );
78.66 +#endif
78.67 +
78.68 + /* Init libmmyth context */
78.69 + gmyth_context_initialize ();
78.70 +
78.71 +#ifndef MAEMO_PLATFORM
78.72 + /* create the main window */
78.73 + window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
78.74 + gtk_widget_set_size_request (window, MAIN_WINDOW_WIDTH, MAIN_WINDOW_HEIGHT);
78.75 + gtk_window_set_title (GTK_WINDOW (window), "Mythtv Frontend");
78.76 +#else
78.77 + /* Creating Hildonized main view */
78.78 + program = HILDON_PROGRAM(hildon_program_get_instance());
78.79 + window = hildon_window_new();
78.80 +
78.81 + //g_signal_connect(G_OBJECT(window), "delete_event", gtk_main_quit, NULL);
78.82 +
78.83 + hildon_program_add_window(program, HILDON_WINDOW (window));
78.84 + g_set_application_name("Maemo Mythtv");
78.85 +#endif
78.86 +
78.87 + /* Initializes MMyth Widgets */
78.88 +#ifdef MAEMO_PLATFORM
78.89 + mmyth_ui = mmyth_ui_initialize (program, window);
78.90 +#else
78.91 + mmyth_ui = mmyth_ui_initialize (window);
78.92 +#endif
78.93 +
78.94 + //mmyth_ui->loop = g_main_loop_new (NULL, FALSE);
78.95 +
78.96 + /* Connect destroy signal handling */
78.97 + g_signal_connect (window, "destroy", G_CALLBACK (cb_destroy), mmyth_ui);
78.98 +
78.99 + /* Shows main window and start gtk loop */
78.100 + gtk_widget_show (window);
78.101 +
78.102 + gtk_main ();
78.103 +
78.104 + return 0;
78.105 +}
78.106 +