mirror of
				https://github.com/rofafor/vdr-plugin-satip.git
				synced 2023-10-10 11:37:42 +00:00 
			
		
		
		
	Initial revision.
This commit is contained in:
		
							
								
								
									
										6
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					.dependencies
 | 
				
			||||||
 | 
					*.o
 | 
				
			||||||
 | 
					*.so
 | 
				
			||||||
 | 
					*~
 | 
				
			||||||
 | 
					po/*.pot
 | 
				
			||||||
 | 
					po/*.mo
 | 
				
			||||||
							
								
								
									
										340
									
								
								COPYING
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										340
									
								
								COPYING
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,340 @@
 | 
				
			|||||||
 | 
							    GNU GENERAL PUBLIC LICENSE
 | 
				
			||||||
 | 
							       Version 2, June 1991
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
 | 
				
			||||||
 | 
					 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 | 
				
			||||||
 | 
					 Everyone is permitted to copy and distribute verbatim copies
 | 
				
			||||||
 | 
					 of this license document, but changing it is not allowed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								    Preamble
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The licenses for most software are designed to take away your
 | 
				
			||||||
 | 
					freedom to share and change it.  By contrast, the GNU General Public
 | 
				
			||||||
 | 
					License is intended to guarantee your freedom to share and change free
 | 
				
			||||||
 | 
					software--to make sure the software is free for all its users.  This
 | 
				
			||||||
 | 
					General Public License applies to most of the Free Software
 | 
				
			||||||
 | 
					Foundation's software and to any other program whose authors commit to
 | 
				
			||||||
 | 
					using it.  (Some other Free Software Foundation software is covered by
 | 
				
			||||||
 | 
					the GNU Lesser General Public License instead.)  You can apply it to
 | 
				
			||||||
 | 
					your programs, too.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  When we speak of free software, we are referring to freedom, not
 | 
				
			||||||
 | 
					price.  Our General Public Licenses are designed to make sure that you
 | 
				
			||||||
 | 
					have the freedom to distribute copies of free software (and charge for
 | 
				
			||||||
 | 
					this service if you wish), that you receive source code or can get it
 | 
				
			||||||
 | 
					if you want it, that you can change the software or use pieces of it
 | 
				
			||||||
 | 
					in new free programs; and that you know you can do these things.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  To protect your rights, we need to make restrictions that forbid
 | 
				
			||||||
 | 
					anyone to deny you these rights or to ask you to surrender the rights.
 | 
				
			||||||
 | 
					These restrictions translate to certain responsibilities for you if you
 | 
				
			||||||
 | 
					distribute copies of the software, or if you modify it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  For example, if you distribute copies of such a program, whether
 | 
				
			||||||
 | 
					gratis or for a fee, you must give the recipients all the rights that
 | 
				
			||||||
 | 
					you have.  You must make sure that they, too, receive or can get the
 | 
				
			||||||
 | 
					source code.  And you must show them these terms so they know their
 | 
				
			||||||
 | 
					rights.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  We protect your rights with two steps: (1) copyright the software, and
 | 
				
			||||||
 | 
					(2) offer you this license which gives you legal permission to copy,
 | 
				
			||||||
 | 
					distribute and/or modify the software.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Also, for each author's protection and ours, we want to make certain
 | 
				
			||||||
 | 
					that everyone understands that there is no warranty for this free
 | 
				
			||||||
 | 
					software.  If the software is modified by someone else and passed on, we
 | 
				
			||||||
 | 
					want its recipients to know that what they have is not the original, so
 | 
				
			||||||
 | 
					that any problems introduced by others will not reflect on the original
 | 
				
			||||||
 | 
					authors' reputations.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Finally, any free program is threatened constantly by software
 | 
				
			||||||
 | 
					patents.  We wish to avoid the danger that redistributors of a free
 | 
				
			||||||
 | 
					program will individually obtain patent licenses, in effect making the
 | 
				
			||||||
 | 
					program proprietary.  To prevent this, we have made it clear that any
 | 
				
			||||||
 | 
					patent must be licensed for everyone's free use or not licensed at all.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The precise terms and conditions for copying, distribution and
 | 
				
			||||||
 | 
					modification follow.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							    GNU GENERAL PUBLIC LICENSE
 | 
				
			||||||
 | 
					   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  0. This License applies to any program or other work which contains
 | 
				
			||||||
 | 
					a notice placed by the copyright holder saying it may be distributed
 | 
				
			||||||
 | 
					under the terms of this General Public License.  The "Program", below,
 | 
				
			||||||
 | 
					refers to any such program or work, and a "work based on the Program"
 | 
				
			||||||
 | 
					means either the Program or any derivative work under copyright law:
 | 
				
			||||||
 | 
					that is to say, a work containing the Program or a portion of it,
 | 
				
			||||||
 | 
					either verbatim or with modifications and/or translated into another
 | 
				
			||||||
 | 
					language.  (Hereinafter, translation is included without limitation in
 | 
				
			||||||
 | 
					the term "modification".)  Each licensee is addressed as "you".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Activities other than copying, distribution and modification are not
 | 
				
			||||||
 | 
					covered by this License; they are outside its scope.  The act of
 | 
				
			||||||
 | 
					running the Program is not restricted, and the output from the Program
 | 
				
			||||||
 | 
					is covered only if its contents constitute a work based on the
 | 
				
			||||||
 | 
					Program (independent of having been made by running the Program).
 | 
				
			||||||
 | 
					Whether that is true depends on what the Program does.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  1. You may copy and distribute verbatim copies of the Program's
 | 
				
			||||||
 | 
					source code as you receive it, in any medium, provided that you
 | 
				
			||||||
 | 
					conspicuously and appropriately publish on each copy an appropriate
 | 
				
			||||||
 | 
					copyright notice and disclaimer of warranty; keep intact all the
 | 
				
			||||||
 | 
					notices that refer to this License and to the absence of any warranty;
 | 
				
			||||||
 | 
					and give any other recipients of the Program a copy of this License
 | 
				
			||||||
 | 
					along with the Program.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You may charge a fee for the physical act of transferring a copy, and
 | 
				
			||||||
 | 
					you may at your option offer warranty protection in exchange for a fee.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  2. You may modify your copy or copies of the Program or any portion
 | 
				
			||||||
 | 
					of it, thus forming a work based on the Program, and copy and
 | 
				
			||||||
 | 
					distribute such modifications or work under the terms of Section 1
 | 
				
			||||||
 | 
					above, provided that you also meet all of these conditions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    a) You must cause the modified files to carry prominent notices
 | 
				
			||||||
 | 
					    stating that you changed the files and the date of any change.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    b) You must cause any work that you distribute or publish, that in
 | 
				
			||||||
 | 
					    whole or in part contains or is derived from the Program or any
 | 
				
			||||||
 | 
					    part thereof, to be licensed as a whole at no charge to all third
 | 
				
			||||||
 | 
					    parties under the terms of this License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    c) If the modified program normally reads commands interactively
 | 
				
			||||||
 | 
					    when run, you must cause it, when started running for such
 | 
				
			||||||
 | 
					    interactive use in the most ordinary way, to print or display an
 | 
				
			||||||
 | 
					    announcement including an appropriate copyright notice and a
 | 
				
			||||||
 | 
					    notice that there is no warranty (or else, saying that you provide
 | 
				
			||||||
 | 
					    a warranty) and that users may redistribute the program under
 | 
				
			||||||
 | 
					    these conditions, and telling the user how to view a copy of this
 | 
				
			||||||
 | 
					    License.  (Exception: if the Program itself is interactive but
 | 
				
			||||||
 | 
					    does not normally print such an announcement, your work based on
 | 
				
			||||||
 | 
					    the Program is not required to print an announcement.)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					These requirements apply to the modified work as a whole.  If
 | 
				
			||||||
 | 
					identifiable sections of that work are not derived from the Program,
 | 
				
			||||||
 | 
					and can be reasonably considered independent and separate works in
 | 
				
			||||||
 | 
					themselves, then this License, and its terms, do not apply to those
 | 
				
			||||||
 | 
					sections when you distribute them as separate works.  But when you
 | 
				
			||||||
 | 
					distribute the same sections as part of a whole which is a work based
 | 
				
			||||||
 | 
					on the Program, the distribution of the whole must be on the terms of
 | 
				
			||||||
 | 
					this License, whose permissions for other licensees extend to the
 | 
				
			||||||
 | 
					entire whole, and thus to each and every part regardless of who wrote it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Thus, it is not the intent of this section to claim rights or contest
 | 
				
			||||||
 | 
					your rights to work written entirely by you; rather, the intent is to
 | 
				
			||||||
 | 
					exercise the right to control the distribution of derivative or
 | 
				
			||||||
 | 
					collective works based on the Program.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In addition, mere aggregation of another work not based on the Program
 | 
				
			||||||
 | 
					with the Program (or with a work based on the Program) on a volume of
 | 
				
			||||||
 | 
					a storage or distribution medium does not bring the other work under
 | 
				
			||||||
 | 
					the scope of this License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  3. You may copy and distribute the Program (or a work based on it,
 | 
				
			||||||
 | 
					under Section 2) in object code or executable form under the terms of
 | 
				
			||||||
 | 
					Sections 1 and 2 above provided that you also do one of the following:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    a) Accompany it with the complete corresponding machine-readable
 | 
				
			||||||
 | 
					    source code, which must be distributed under the terms of Sections
 | 
				
			||||||
 | 
					    1 and 2 above on a medium customarily used for software interchange; or,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    b) Accompany it with a written offer, valid for at least three
 | 
				
			||||||
 | 
					    years, to give any third party, for a charge no more than your
 | 
				
			||||||
 | 
					    cost of physically performing source distribution, a complete
 | 
				
			||||||
 | 
					    machine-readable copy of the corresponding source code, to be
 | 
				
			||||||
 | 
					    distributed under the terms of Sections 1 and 2 above on a medium
 | 
				
			||||||
 | 
					    customarily used for software interchange; or,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    c) Accompany it with the information you received as to the offer
 | 
				
			||||||
 | 
					    to distribute corresponding source code.  (This alternative is
 | 
				
			||||||
 | 
					    allowed only for noncommercial distribution and only if you
 | 
				
			||||||
 | 
					    received the program in object code or executable form with such
 | 
				
			||||||
 | 
					    an offer, in accord with Subsection b above.)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The source code for a work means the preferred form of the work for
 | 
				
			||||||
 | 
					making modifications to it.  For an executable work, complete source
 | 
				
			||||||
 | 
					code means all the source code for all modules it contains, plus any
 | 
				
			||||||
 | 
					associated interface definition files, plus the scripts used to
 | 
				
			||||||
 | 
					control compilation and installation of the executable.  However, as a
 | 
				
			||||||
 | 
					special exception, the source code distributed need not include
 | 
				
			||||||
 | 
					anything that is normally distributed (in either source or binary
 | 
				
			||||||
 | 
					form) with the major components (compiler, kernel, and so on) of the
 | 
				
			||||||
 | 
					operating system on which the executable runs, unless that component
 | 
				
			||||||
 | 
					itself accompanies the executable.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If distribution of executable or object code is made by offering
 | 
				
			||||||
 | 
					access to copy from a designated place, then offering equivalent
 | 
				
			||||||
 | 
					access to copy the source code from the same place counts as
 | 
				
			||||||
 | 
					distribution of the source code, even though third parties are not
 | 
				
			||||||
 | 
					compelled to copy the source along with the object code.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  4. You may not copy, modify, sublicense, or distribute the Program
 | 
				
			||||||
 | 
					except as expressly provided under this License.  Any attempt
 | 
				
			||||||
 | 
					otherwise to copy, modify, sublicense or distribute the Program is
 | 
				
			||||||
 | 
					void, and will automatically terminate your rights under this License.
 | 
				
			||||||
 | 
					However, parties who have received copies, or rights, from you under
 | 
				
			||||||
 | 
					this License will not have their licenses terminated so long as such
 | 
				
			||||||
 | 
					parties remain in full compliance.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  5. You are not required to accept this License, since you have not
 | 
				
			||||||
 | 
					signed it.  However, nothing else grants you permission to modify or
 | 
				
			||||||
 | 
					distribute the Program or its derivative works.  These actions are
 | 
				
			||||||
 | 
					prohibited by law if you do not accept this License.  Therefore, by
 | 
				
			||||||
 | 
					modifying or distributing the Program (or any work based on the
 | 
				
			||||||
 | 
					Program), you indicate your acceptance of this License to do so, and
 | 
				
			||||||
 | 
					all its terms and conditions for copying, distributing or modifying
 | 
				
			||||||
 | 
					the Program or works based on it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  6. Each time you redistribute the Program (or any work based on the
 | 
				
			||||||
 | 
					Program), the recipient automatically receives a license from the
 | 
				
			||||||
 | 
					original licensor to copy, distribute or modify the Program subject to
 | 
				
			||||||
 | 
					these terms and conditions.  You may not impose any further
 | 
				
			||||||
 | 
					restrictions on the recipients' exercise of the rights granted herein.
 | 
				
			||||||
 | 
					You are not responsible for enforcing compliance by third parties to
 | 
				
			||||||
 | 
					this License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  7. If, as a consequence of a court judgment or allegation of patent
 | 
				
			||||||
 | 
					infringement or for any other reason (not limited to patent issues),
 | 
				
			||||||
 | 
					conditions are imposed on you (whether by court order, agreement or
 | 
				
			||||||
 | 
					otherwise) that contradict the conditions of this License, they do not
 | 
				
			||||||
 | 
					excuse you from the conditions of this License.  If you cannot
 | 
				
			||||||
 | 
					distribute so as to satisfy simultaneously your obligations under this
 | 
				
			||||||
 | 
					License and any other pertinent obligations, then as a consequence you
 | 
				
			||||||
 | 
					may not distribute the Program at all.  For example, if a patent
 | 
				
			||||||
 | 
					license would not permit royalty-free redistribution of the Program by
 | 
				
			||||||
 | 
					all those who receive copies directly or indirectly through you, then
 | 
				
			||||||
 | 
					the only way you could satisfy both it and this License would be to
 | 
				
			||||||
 | 
					refrain entirely from distribution of the Program.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If any portion of this section is held invalid or unenforceable under
 | 
				
			||||||
 | 
					any particular circumstance, the balance of the section is intended to
 | 
				
			||||||
 | 
					apply and the section as a whole is intended to apply in other
 | 
				
			||||||
 | 
					circumstances.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It is not the purpose of this section to induce you to infringe any
 | 
				
			||||||
 | 
					patents or other property right claims or to contest validity of any
 | 
				
			||||||
 | 
					such claims; this section has the sole purpose of protecting the
 | 
				
			||||||
 | 
					integrity of the free software distribution system, which is
 | 
				
			||||||
 | 
					implemented by public license practices.  Many people have made
 | 
				
			||||||
 | 
					generous contributions to the wide range of software distributed
 | 
				
			||||||
 | 
					through that system in reliance on consistent application of that
 | 
				
			||||||
 | 
					system; it is up to the author/donor to decide if he or she is willing
 | 
				
			||||||
 | 
					to distribute software through any other system and a licensee cannot
 | 
				
			||||||
 | 
					impose that choice.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This section is intended to make thoroughly clear what is believed to
 | 
				
			||||||
 | 
					be a consequence of the rest of this License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  8. If the distribution and/or use of the Program is restricted in
 | 
				
			||||||
 | 
					certain countries either by patents or by copyrighted interfaces, the
 | 
				
			||||||
 | 
					original copyright holder who places the Program under this License
 | 
				
			||||||
 | 
					may add an explicit geographical distribution limitation excluding
 | 
				
			||||||
 | 
					those countries, so that distribution is permitted only in or among
 | 
				
			||||||
 | 
					countries not thus excluded.  In such case, this License incorporates
 | 
				
			||||||
 | 
					the limitation as if written in the body of this License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  9. The Free Software Foundation may publish revised and/or new versions
 | 
				
			||||||
 | 
					of the General Public License from time to time.  Such new versions will
 | 
				
			||||||
 | 
					be similar in spirit to the present version, but may differ in detail to
 | 
				
			||||||
 | 
					address new problems or concerns.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Each version is given a distinguishing version number.  If the Program
 | 
				
			||||||
 | 
					specifies a version number of this License which applies to it and "any
 | 
				
			||||||
 | 
					later version", you have the option of following the terms and conditions
 | 
				
			||||||
 | 
					either of that version or of any later version published by the Free
 | 
				
			||||||
 | 
					Software Foundation.  If the Program does not specify a version number of
 | 
				
			||||||
 | 
					this License, you may choose any version ever published by the Free Software
 | 
				
			||||||
 | 
					Foundation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  10. If you wish to incorporate parts of the Program into other free
 | 
				
			||||||
 | 
					programs whose distribution conditions are different, write to the author
 | 
				
			||||||
 | 
					to ask for permission.  For software which is copyrighted by the Free
 | 
				
			||||||
 | 
					Software Foundation, write to the Free Software Foundation; we sometimes
 | 
				
			||||||
 | 
					make exceptions for this.  Our decision will be guided by the two goals
 | 
				
			||||||
 | 
					of preserving the free status of all derivatives of our free software and
 | 
				
			||||||
 | 
					of promoting the sharing and reuse of software generally.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								    NO WARRANTY
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
 | 
				
			||||||
 | 
					FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
 | 
				
			||||||
 | 
					OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
 | 
				
			||||||
 | 
					PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
 | 
				
			||||||
 | 
					OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | 
				
			||||||
 | 
					MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
 | 
				
			||||||
 | 
					TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
 | 
				
			||||||
 | 
					PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
 | 
				
			||||||
 | 
					REPAIR OR CORRECTION.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
 | 
				
			||||||
 | 
					WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
 | 
				
			||||||
 | 
					REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
 | 
				
			||||||
 | 
					INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
 | 
				
			||||||
 | 
					OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
 | 
				
			||||||
 | 
					TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
 | 
				
			||||||
 | 
					YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
 | 
				
			||||||
 | 
					PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
 | 
				
			||||||
 | 
					POSSIBILITY OF SUCH DAMAGES.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							     END OF TERMS AND CONDITIONS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						    How to Apply These Terms to Your New Programs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  If you develop a new program, and you want it to be of the greatest
 | 
				
			||||||
 | 
					possible use to the public, the best way to achieve this is to make it
 | 
				
			||||||
 | 
					free software which everyone can redistribute and change under these terms.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  To do so, attach the following notices to the program.  It is safest
 | 
				
			||||||
 | 
					to attach them to the start of each source file to most effectively
 | 
				
			||||||
 | 
					convey the exclusion of warranty; and each file should have at least
 | 
				
			||||||
 | 
					the "copyright" line and a pointer to where the full notice is found.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <one line to give the program's name and a brief idea of what it does.>
 | 
				
			||||||
 | 
					    Copyright (C) <year>  <name of author>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					    it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					    the Free Software Foundation; either version 2 of the License, or
 | 
				
			||||||
 | 
					    (at your option) any later version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					    GNU General Public License for more details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					    along with this program; if not, write to the Free Software
 | 
				
			||||||
 | 
					    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Also add information on how to contact you by electronic and paper mail.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If the program is interactive, make it output a short notice like this
 | 
				
			||||||
 | 
					when it starts in an interactive mode:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Gnomovision version 69, Copyright (C) year name of author
 | 
				
			||||||
 | 
					    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
 | 
				
			||||||
 | 
					    This is free software, and you are welcome to redistribute it
 | 
				
			||||||
 | 
					    under certain conditions; type `show c' for details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The hypothetical commands `show w' and `show c' should show the appropriate
 | 
				
			||||||
 | 
					parts of the General Public License.  Of course, the commands you use may
 | 
				
			||||||
 | 
					be called something other than `show w' and `show c'; they could even be
 | 
				
			||||||
 | 
					mouse-clicks or menu items--whatever suits your program.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You should also get your employer (if you work as a programmer) or your
 | 
				
			||||||
 | 
					school, if any, to sign a "copyright disclaimer" for the program, if
 | 
				
			||||||
 | 
					necessary.  Here is a sample; alter the names:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
 | 
				
			||||||
 | 
					  `Gnomovision' (which makes passes at compilers) written by James Hacker.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <signature of Ty Coon>, 1 April 1989
 | 
				
			||||||
 | 
					  Ty Coon, President of Vice
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This General Public License does not permit incorporating your program into
 | 
				
			||||||
 | 
					proprietary programs.  If your program is a subroutine library, you may
 | 
				
			||||||
 | 
					consider it more useful to permit linking proprietary applications with the
 | 
				
			||||||
 | 
					library.  If this is what you want to do, use the GNU Lesser General
 | 
				
			||||||
 | 
					Public License instead of this License.
 | 
				
			||||||
							
								
								
									
										8
									
								
								HISTORY
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								HISTORY
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					===================================
 | 
				
			||||||
 | 
					VDR Plugin 'satip' Revision History
 | 
				
			||||||
 | 
					===================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2014-03-08: Version 0.0.1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Initial revision.
 | 
				
			||||||
 | 
					- Added German translation (Thanks to Frank Neumann).
 | 
				
			||||||
							
								
								
									
										157
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,157 @@
 | 
				
			|||||||
 | 
					#
 | 
				
			||||||
 | 
					# Makefile for SAT>IP plugin
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Debugging on/off
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#SATIP_DEBUG = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Strip debug symbols?  Set eg. to /bin/true if not
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					STRIP = strip
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# The official name of this plugin.
 | 
				
			||||||
 | 
					# This name will be used in the '-P...' option of VDR to load the plugin.
 | 
				
			||||||
 | 
					# By default the main source file also carries this name.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PLUGIN = satip
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### The version number of this plugin (taken from the main source file):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VERSION = $(shell grep 'const char VERSION\[\] *=' $(PLUGIN).c | awk '{ print $$5 }' | sed -e 's/[";]//g')
 | 
				
			||||||
 | 
					GITTAG  = $(shell git describe --always 2>/dev/null)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### The directory environment:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Use package data if installed...otherwise assume we're under the VDR source directory:
 | 
				
			||||||
 | 
					PKGCFG = $(if $(VDRDIR),$(shell pkg-config --variable=$(1) $(VDRDIR)/vdr.pc),$(shell PKG_CONFIG_PATH="$$PKG_CONFIG_PATH:../../.." pkg-config --variable=$(1) vdr))
 | 
				
			||||||
 | 
					LIBDIR = $(call PKGCFG,libdir)
 | 
				
			||||||
 | 
					LOCDIR = $(call PKGCFG,locdir)
 | 
				
			||||||
 | 
					PLGCFG = $(call PKGCFG,plgcfg)
 | 
				
			||||||
 | 
					CFGDIR = $(call PKGCFG,configdir)
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					TMPDIR ?= /tmp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### The compiler options:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export CFLAGS   = $(call PKGCFG,cflags)
 | 
				
			||||||
 | 
					export CXXFLAGS = $(call PKGCFG,cxxflags)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### The version number of VDR's plugin API:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					APIVERSION = $(call PKGCFG,apiversion)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Allow user defined options to overwrite defaults:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-include $(PLGCFG)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### The name of the distribution archive:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ARCHIVE = $(PLUGIN)-$(VERSION)
 | 
				
			||||||
 | 
					PACKAGE = vdr-$(ARCHIVE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### The name of the shared object file:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SOFILE = libvdr-$(PLUGIN).so
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Libraries
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LIBS = $(shell curl-config --libs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Includes and Defines (add further entries here):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					INCLUDES +=
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DEFINES += -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ifdef SATIP_DEBUG
 | 
				
			||||||
 | 
					DEFINES += -DDEBUG
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ifneq ($(strip $(GITTAG)),)
 | 
				
			||||||
 | 
					DEFINES += -DGITVERSION='"-GIT-$(GITTAG)"'
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PHONY: all all-redirect
 | 
				
			||||||
 | 
					all-redirect: all
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### The object files (add further files here):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OBJS = $(PLUGIN).o common.o config.o device.o discover.o \
 | 
				
			||||||
 | 
						sectionfilter.o setup.o socket.o source.o statistics.o tuner.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### The main target:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					all: $(SOFILE) i18n
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Implicit rules:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%.o: %.c
 | 
				
			||||||
 | 
						$(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Dependencies:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MAKEDEP = $(CXX) -MM -MG
 | 
				
			||||||
 | 
					DEPFILE = .dependencies
 | 
				
			||||||
 | 
					$(DEPFILE): Makefile
 | 
				
			||||||
 | 
						@$(MAKEDEP) $(CXXFLAGS) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-include $(DEPFILE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Internationalization (I18N):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PODIR     = po
 | 
				
			||||||
 | 
					I18Npo    = $(wildcard $(PODIR)/*.po)
 | 
				
			||||||
 | 
					I18Nmo    = $(addsuffix .mo, $(foreach file, $(I18Npo), $(basename $(file))))
 | 
				
			||||||
 | 
					I18Nmsgs  = $(addprefix $(DESTDIR)$(LOCDIR)/, $(addsuffix /LC_MESSAGES/vdr-$(PLUGIN).mo, $(notdir $(foreach file, $(I18Npo), $(basename $(file))))))
 | 
				
			||||||
 | 
					I18Npot   = $(PODIR)/$(PLUGIN).pot
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%.mo: %.po
 | 
				
			||||||
 | 
						msgfmt -c -o $@ $<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(I18Npot): $(wildcard *.c)
 | 
				
			||||||
 | 
						xgettext -C -cTRANSLATORS --no-wrap --no-location -k -ktr -ktrNOOP --package-name=vdr-$(PLUGIN) --package-version=$(VERSION) --msgid-bugs-address='<see README>' -o $@ `ls $^`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%.po: $(I18Npot)
 | 
				
			||||||
 | 
						msgmerge -U --no-wrap --no-location --backup=none -q -N $@ $<
 | 
				
			||||||
 | 
						@touch $@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(I18Nmsgs): $(DESTDIR)$(LOCDIR)/%/LC_MESSAGES/vdr-$(PLUGIN).mo: $(PODIR)/%.mo
 | 
				
			||||||
 | 
						install -D -m644 $< $@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PHONY: i18n
 | 
				
			||||||
 | 
					i18n: $(I18Nmo) $(I18Npot)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					install-i18n: $(I18Nmsgs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Targets:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(SOFILE): $(OBJS)
 | 
				
			||||||
 | 
						$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) $(LIBS) -o $@
 | 
				
			||||||
 | 
					ifndef SATIP_DEBUG
 | 
				
			||||||
 | 
						@$(STRIP) $@
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					install-lib: $(SOFILE)
 | 
				
			||||||
 | 
						install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					install-conf:
 | 
				
			||||||
 | 
						@mkdir -p $(DESTDIR)$(CFGDIR)/plugins/$(PLUGIN)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					install: install-lib install-i18n install-conf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dist: $(I18Npo) clean
 | 
				
			||||||
 | 
						@-rm -rf $(TMPDIR)/$(ARCHIVE)
 | 
				
			||||||
 | 
						@mkdir $(TMPDIR)/$(ARCHIVE)
 | 
				
			||||||
 | 
						@cp -a * $(TMPDIR)/$(ARCHIVE)
 | 
				
			||||||
 | 
						@tar czf $(PACKAGE).tgz -C $(TMPDIR) $(ARCHIVE)
 | 
				
			||||||
 | 
						@-rm -rf $(TMPDIR)/$(ARCHIVE)
 | 
				
			||||||
 | 
						@echo Distribution package created as $(PACKAGE).tgz
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					clean:
 | 
				
			||||||
 | 
						@-rm -f $(PODIR)/*.mo $(PODIR)/*.pot
 | 
				
			||||||
 | 
						@-rm -f $(OBJS) $(DEPFILE) *.so *.tgz core* *~
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PHONY: cppcheck
 | 
				
			||||||
 | 
					cppcheck:
 | 
				
			||||||
 | 
						@cppcheck --language=c++ --enable=all -v -f $(OBJS:%.o=%.c)
 | 
				
			||||||
							
								
								
									
										175
									
								
								README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								README
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,175 @@
 | 
				
			|||||||
 | 
					This is an SAT>IP plugin for the Video Disk Recorder (VDR).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Written by:                  Rolf Ahrenberg
 | 
				
			||||||
 | 
					                             < R o l f . A h r e n b e r g @ s c i . f i >
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Project's homepage:          http://www.saunalahti.fi/~rahrenbe/vdr/satip/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Latest version available at: http://www.saunalahti.fi/~rahrenbe/vdr/satip/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					it under the terms of the GNU General Public License version 2 as
 | 
				
			||||||
 | 
					published by the Free Software Foundation.
 | 
				
			||||||
 | 
					See the file COPYING for more information.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Requirements:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Libcurl - the multiprotocol file transfer library with RTSP support
 | 
				
			||||||
 | 
					  http://curl.haxx.se/libcurl/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- VDR-2.1.4+ for scrambled channels
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Description:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This plugin integrates SAT>IP network devices seamlessly into VDR.
 | 
				
			||||||
 | 
					You can use any SAT>IP channel like any other normal DVB channel for
 | 
				
			||||||
 | 
					live viewing, recording, etc. The plugin also features full section
 | 
				
			||||||
 | 
					filtering capabilities which allow for example EIT information to be
 | 
				
			||||||
 | 
					extracted from the incoming stream.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Installation:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					tar -xzf /put/your/path/here/vdr-satip-X.Y.Z.tgz
 | 
				
			||||||
 | 
					make -C satip-X.Y.Z install
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Setup menu:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Enable EPG scanning = yes  If you want exclude all SAT>IP devices 
 | 
				
			||||||
 | 
					                             from VDR's EIT background scanning, set
 | 
				
			||||||
 | 
					                             this option to "no".
 | 
				
			||||||
 | 
					- Disabled filters = none    Certain section filters might cause some
 | 
				
			||||||
 | 
					                             unwanted behaviour to VDR such as time
 | 
				
			||||||
 | 
					                             being falsely synchronized etc. This option
 | 
				
			||||||
 | 
					                             allows creation of  blacklists of ill-behaving
 | 
				
			||||||
 | 
					                             filters. If this option is set to a non-zero
 | 
				
			||||||
 | 
					                             value, the menu page will contain that many
 | 
				
			||||||
 | 
					                             "Disable filter" options which allow you
 | 
				
			||||||
 | 
					                             to disable the individual section filters.
 | 
				
			||||||
 | 
					                             Valid range: "none" = 0 ... 7
 | 
				
			||||||
 | 
					- [Blue:Info]                Opens SAT>IP information/statistics menu.
 | 
				
			||||||
 | 
					- [Ok]                       Opens information menu of selected SAT>IP
 | 
				
			||||||
 | 
					                             device.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Information menu:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- [Red:General]              Opens the general information page.
 | 
				
			||||||
 | 
					- [Green:Pids]               Opens the pid statistics page.
 | 
				
			||||||
 | 
					- [Yellow:Filters]           Opens the section filter statistics page.
 | 
				
			||||||
 | 
					- [Blue:Bits/bytes]          Toggles between bits and bytes mode.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SAT>IP device menu:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- [Red:Scan]                 Starts the channel scanning sometime in
 | 
				
			||||||
 | 
					                             the future.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Configuration:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Parameters
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Various parameters, depending on whether this is a DVB-S, DVB-S2, DVB-T,
 | 
				
			||||||
 | 
					  or DVB-T2 channel. Each parameter consist of a key character, followed by
 | 
				
			||||||
 | 
					  an integer number that represents the actual setting of that parameter.
 | 
				
			||||||
 | 
					  The valid key characters, their meaning, and allowed values are:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  B  Bandwidth (1712, 5, 6, 7, 8, 10)
 | 
				
			||||||
 | 
					  C  Code rate high priority (12, 23, 34, 35, 45, 56, 67, 78, 89, 910)
 | 
				
			||||||
 | 
					  G  Guard interval (4, 8, 16, 32, 128, 19128, 19256)
 | 
				
			||||||
 | 
					  H  Horizontal polarization
 | 
				
			||||||
 | 
					  L  Left circular polarization
 | 
				
			||||||
 | 
					  M  Modulation (2, 5, 16, 64, 256)
 | 
				
			||||||
 | 
					  N  pilot toNes (0, 1)
 | 
				
			||||||
 | 
					  O  rollOff (20, 25, 35)
 | 
				
			||||||
 | 
					  P  stream id (0-255)
 | 
				
			||||||
 | 
					  Q  t2 system id (0-65535)
 | 
				
			||||||
 | 
					  R  Right circular polarization
 | 
				
			||||||
 | 
					  S  delivery System (0, 1)
 | 
				
			||||||
 | 
					  T  Transmission mode (1, 2, 4, 8, 16, 32)
 | 
				
			||||||
 | 
					  V  Vertical polarization
 | 
				
			||||||
 | 
					  X  siso/miso mode (0, 1)
 | 
				
			||||||
 | 
					  Z  signal source position (1-255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Bandwidth: The bandwidth of the channel in MHz (1712 in kHz)
 | 
				
			||||||
 | 
					    (DVB-T/DVB-T2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Code rate high priority: Forward Error Correction (FEC) of the high
 | 
				
			||||||
 | 
					    priority stream (DVB-T/DVB-T2) or the the inner FEC scheme (DVB-S/DVB-S2)
 | 
				
			||||||
 | 
					    12 = 1/2, 23 = 2/3, 34 = 3/4, 35 = 3/5, 45 = 4/5, 56 = 5/6,
 | 
				
			||||||
 | 
					    67 = 6/7, 78 = 7/8, 89 = 8/9, 910 = 9/10
 | 
				
			||||||
 | 
					    (DVB-T/DVB-T2/DVB-S/DVB-S2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Guard interval: The guard interval value
 | 
				
			||||||
 | 
					    4 = 1/4, 8 = 1/8, 16 = 1/16, 32 = 1/32, 128 = 1/128,
 | 
				
			||||||
 | 
					    19128 = 19/128, 19256 = 19/256
 | 
				
			||||||
 | 
					    (DVB-T/DVB-T2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Modulation: Specifies the modulation/constellation of the channel
 | 
				
			||||||
 | 
					    2   = QPSK (DVB-S, DVB-S2, DVB-T, DVB-T2)
 | 
				
			||||||
 | 
					    5   = 8PSK (DVB-S, DVB-S2)
 | 
				
			||||||
 | 
					    16  = QAM16 (DVB-T, DVB-T2)
 | 
				
			||||||
 | 
					    64  = QAM64 (DVB-T, DVB-T2)
 | 
				
			||||||
 | 
					    256 = QAM256 (DVB-T2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Pilot tones: Specifies pilot tones usage
 | 
				
			||||||
 | 
					    0 = off, 1 = on
 | 
				
			||||||
 | 
					    (DVB-S2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Rolloff: The Nyquist filter rolloff factor
 | 
				
			||||||
 | 
					    35 = 0.35, 25 = 0.25, 20 = 0.20
 | 
				
			||||||
 | 
					    (DVB-S/DVB-S2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Stream id: Physical Layer Pipe (PLP) id (0-255) for DVB-T2 multiplex
 | 
				
			||||||
 | 
					    (DVB-T2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  T2 system id: Unique identifier (0-65535) of the T2 system
 | 
				
			||||||
 | 
					    (DVB-T2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Transmission mode: Number of DVB-T OFDM carriers
 | 
				
			||||||
 | 
					    32 = 32k, 16 = 16k, 8 = 8k, 4 = 4k, 2 = 2k, 1 = 1k
 | 
				
			||||||
 | 
					    (DVB-T/DVB-T2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Delivery System: The delivery system
 | 
				
			||||||
 | 
					    0 = "first generation" (DVB-S/DVB-T)
 | 
				
			||||||
 | 
					    1 = "second generation" (DVB-S2/DVB-T2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Polarization: Satellite antenna polarization
 | 
				
			||||||
 | 
					    H = horizontal, V = vertical
 | 
				
			||||||
 | 
					    R = circular right, L = circular left
 | 
				
			||||||
 | 
					    (DVB-S/DVB-S2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Signal source: Specifies the signal source (satellite) position
 | 
				
			||||||
 | 
					    (DVB-S/DVB-S2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  SISO/MISO: Specifies the Single-Input/Multiple-Input Single-Output mode
 | 
				
			||||||
 | 
					    0 = SISO, 1 = MISO
 | 
				
			||||||
 | 
					    (DVB-T2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Source
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  There are two separate signal sources for SAT>IP channels:
 | 
				
			||||||
 | 
					    Z = SAT>IP Satellite (DVB-S/DVB-S2)
 | 
				
			||||||
 | 
					    Y = SAT>IP Terrestrial (DVB-T/DVB-T2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Examples
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  MTV3;DVB-T:658000000:B8C23D23G8M64S0T8Y0:T:0:305=2:561=fin@4,562=dut@4:5010;1073=fin,1074=dut:0:49:8438:8193:0
 | 
				
			||||||
 | 
					  =>
 | 
				
			||||||
 | 
					  MTV3;SAT>IP:658000000:B8C23G8M64S0T8:Y:0:305=2:561=fin@4,562=dut@4:5010;1073=fin,1074=dut:0:49:8438:8193:0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Das Erste HD;DVB-S2:11494:HC23M5O35S1:S19.2E:22000:5101=27:5102=deu@3,5103=mis@3;5106=deu@106:5104;5105=deu:0:10301:1:1019:0
 | 
				
			||||||
 | 
					  =>
 | 
				
			||||||
 | 
					  Das Erste HD;SAT>IP:11494:HC23M5O35S1:Z:22000:5101=27:5102=deu@3,5103=mis@3;5106=deu@106:5104;5105=deu:0:10301:1:1019:0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Notes:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- The stream id "-1" states about unsuccessful tuning. This might be a
 | 
				
			||||||
 | 
					  result of invalid channel parameters or lack of free SAT>IP tuners.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- SAT>IP specification 1.2 doesn't support DVB-C/DVB-C2 receivers yet.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- If the plugin doesn't detect your SAT>IP network device, make sure
 | 
				
			||||||
 | 
					  your setup doesn't have firewalled the UDP port 1900.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Acknowledgements:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Big thanks to Digital Devices GmbH for providing the Octopus Net
 | 
				
			||||||
 | 
					  hardware for development!
 | 
				
			||||||
							
								
								
									
										81
									
								
								common.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								common.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,81 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * common.c: SAT>IP plugin for the Video Disk Recorder
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * See the README file for copyright information and how to reach the author.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <ctype.h>
 | 
				
			||||||
 | 
					#include <vdr/tools.h>
 | 
				
			||||||
 | 
					#include "common.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint16_t ts_pid(const uint8_t *bufP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  return (uint16_t)(((bufP[1] & 0x1f) << 8) + bufP[2]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t payload(const uint8_t *bufP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (!(bufP[3] & 0x10)) // no payload?
 | 
				
			||||||
 | 
					     return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (bufP[3] & 0x20) {  // adaptation field?
 | 
				
			||||||
 | 
					     if (bufP[4] > 183)  // corrupted data?
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					     else
 | 
				
			||||||
 | 
					        return (uint8_t)((184 - 1) - bufP[4]);
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return 184;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char *id_pid(const u_short pidP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  for (int i = 0; i < SECTION_FILTER_TABLE_SIZE; ++i) {
 | 
				
			||||||
 | 
					      if (pidP == section_filter_table[i].pid)
 | 
				
			||||||
 | 
					         return section_filter_table[i].tag;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					  return "---";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					char *StripTags(char *strP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (strP) {
 | 
				
			||||||
 | 
					     char *c = strP, *r = strP, t = 0;
 | 
				
			||||||
 | 
					     while (*strP) {
 | 
				
			||||||
 | 
					           if (*strP == '<')
 | 
				
			||||||
 | 
					              ++t;
 | 
				
			||||||
 | 
					           else if (*strP == '>')
 | 
				
			||||||
 | 
					              --t;
 | 
				
			||||||
 | 
					           else if (t < 1)
 | 
				
			||||||
 | 
					              *(c++) = *strP;
 | 
				
			||||||
 | 
					           ++strP;
 | 
				
			||||||
 | 
					           }
 | 
				
			||||||
 | 
					     *c = 0;
 | 
				
			||||||
 | 
					     return r;
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					  return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cString ChangeCase(const cString &strP, bool upperP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  cString res(strP);
 | 
				
			||||||
 | 
					  char *p = (char *)*res;
 | 
				
			||||||
 | 
					  while (p && *p) {
 | 
				
			||||||
 | 
					        *p = upperP ? toupper(*p) : tolower(*p);
 | 
				
			||||||
 | 
					        ++p;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					  return res;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const section_filter_table_type section_filter_table[SECTION_FILTER_TABLE_SIZE] =
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  /* description              tag    pid   tid   mask */
 | 
				
			||||||
 | 
					  {trNOOP("PAT (0x00)"),      "PAT", 0x00, 0x00, 0xFF},
 | 
				
			||||||
 | 
					  {trNOOP("NIT (0x40)"),      "NIT", 0x10, 0x40, 0xFF},
 | 
				
			||||||
 | 
					  {trNOOP("SDT (0x42)"),      "SDT", 0x11, 0x42, 0xFF},
 | 
				
			||||||
 | 
					  {trNOOP("EIT (0x4E/0x4F)"), "EIT", 0x12, 0x4E, 0xFE},
 | 
				
			||||||
 | 
					  {trNOOP("EIT (0x5X)"),      "EIT", 0x12, 0x50, 0xF0},
 | 
				
			||||||
 | 
					  {trNOOP("EIT (0x6X)"),      "EIT", 0x12, 0x60, 0xF0},
 | 
				
			||||||
 | 
					  {trNOOP("TDT (0x70)"),      "TDT", 0x14, 0x70, 0xFF},
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										102
									
								
								common.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								common.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,102 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * common.h: SAT>IP plugin for the Video Disk Recorder
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * See the README file for copyright information and how to reach the author.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __SATIP_COMMON_H
 | 
				
			||||||
 | 
					#define __SATIP_COMMON_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <vdr/tools.h>
 | 
				
			||||||
 | 
					#include <vdr/config.h>
 | 
				
			||||||
 | 
					#include <vdr/i18n.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef DEBUG
 | 
				
			||||||
 | 
					#define debug(x...) dsyslog("SATIP: " x);
 | 
				
			||||||
 | 
					#define info(x...)  isyslog("SATIP: " x);
 | 
				
			||||||
 | 
					#define error(x...) esyslog("ERROR: " x);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#define debug(x...) ;
 | 
				
			||||||
 | 
					#define info(x...)  isyslog("SATIP: " x);
 | 
				
			||||||
 | 
					#define error(x...) esyslog("ERROR: " x);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ELEMENTS(x)                      (sizeof(x) / sizeof(x[0]))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SATIP_BUFFER_SIZE                MEGABYTE(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SATIP_DEVICE_INFO_ALL            0
 | 
				
			||||||
 | 
					#define SATIP_DEVICE_INFO_GENERAL        1
 | 
				
			||||||
 | 
					#define SATIP_DEVICE_INFO_PIDS           2
 | 
				
			||||||
 | 
					#define SATIP_DEVICE_INFO_FILTERS        3
 | 
				
			||||||
 | 
					#define SATIP_DEVICE_INFO_PROTOCOL       4
 | 
				
			||||||
 | 
					#define SATIP_DEVICE_INFO_BITRATE        5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SATIP_STATS_ACTIVE_PIDS_COUNT    10
 | 
				
			||||||
 | 
					#define SATIP_STATS_ACTIVE_FILTERS_COUNT 10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SECTION_FILTER_TABLE_SIZE        7
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SATIP_CURL_EASY_GETINFO(X, Y, Z) \
 | 
				
			||||||
 | 
					  if ((res = curl_easy_getinfo((X), (Y), (Z))) != CURLE_OK) { \
 | 
				
			||||||
 | 
					     error("curl_easy_getinfo(%s) [%s,%d] failed: %s (%d)", #Y,  __FILE__, __LINE__, curl_easy_strerror(res), res); \
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SATIP_CURL_EASY_SETOPT(X, Y, Z) \
 | 
				
			||||||
 | 
					  if ((res = curl_easy_setopt((X), (Y), (Z))) != CURLE_OK) { \
 | 
				
			||||||
 | 
					     error("curl_easy_setopt(%s, %s) [%s,%d] failed: %s (%d)", #Y, #Z, __FILE__, __LINE__, curl_easy_strerror(res), res); \
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SATIP_CURL_EASY_PERFORM(X) \
 | 
				
			||||||
 | 
					  if ((res = curl_easy_perform((X))) != CURLE_OK) { \
 | 
				
			||||||
 | 
					     error("curl_easy_perform() [%s,%d] failed: %s (%d)",  __FILE__, __LINE__, curl_easy_strerror(res), res); \
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ERROR_IF_FUNC(exp, errstr, func, ret)              \
 | 
				
			||||||
 | 
					  do {                                                     \
 | 
				
			||||||
 | 
					     if (exp) {                                            \
 | 
				
			||||||
 | 
					        char tmp[64];                                      \
 | 
				
			||||||
 | 
					        error("[%s,%d]: "errstr": %s", __FILE__, __LINE__, \
 | 
				
			||||||
 | 
					              strerror_r(errno, tmp, sizeof(tmp)));        \
 | 
				
			||||||
 | 
					        func;                                              \
 | 
				
			||||||
 | 
					        ret;                                               \
 | 
				
			||||||
 | 
					        }                                                  \
 | 
				
			||||||
 | 
					  } while (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ERROR_IF_RET(exp, errstr, ret) ERROR_IF_FUNC(exp, errstr, ,ret);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ERROR_IF(exp, errstr) ERROR_IF_FUNC(exp, errstr, , );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DELETE_POINTER(ptr)      \
 | 
				
			||||||
 | 
					  do {                           \
 | 
				
			||||||
 | 
					     if (ptr) {                  \
 | 
				
			||||||
 | 
					        typeof(*ptr) *tmp = ptr; \
 | 
				
			||||||
 | 
					        ptr = NULL;              \
 | 
				
			||||||
 | 
					        delete(tmp);             \
 | 
				
			||||||
 | 
					        }                        \
 | 
				
			||||||
 | 
					  } while (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint16_t ts_pid(const uint8_t *bufP);
 | 
				
			||||||
 | 
					uint8_t payload(const uint8_t *bufP);
 | 
				
			||||||
 | 
					const char *id_pid(const u_short pidP);
 | 
				
			||||||
 | 
					char *StripTags(char *strP);
 | 
				
			||||||
 | 
					cString ChangeCase(const cString &strP, bool upperP);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct section_filter_table_type {
 | 
				
			||||||
 | 
					  const char *description;
 | 
				
			||||||
 | 
					  const char *tag;
 | 
				
			||||||
 | 
					  u_short pid;
 | 
				
			||||||
 | 
					  u_char tid;
 | 
				
			||||||
 | 
					  u_char mask;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern const section_filter_table_type section_filter_table[SECTION_FILTER_TABLE_SIZE];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern const char VERSION[];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // __SATIP_COMMON_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										45
									
								
								config.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								config.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * config.c: SAT>IP plugin for the Video Disk Recorder
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * See the README file for copyright information and how to reach the author.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "discover.h"
 | 
				
			||||||
 | 
					#include "config.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cSatipConfig SatipConfig;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cSatipConfig::cSatipConfig(void)
 | 
				
			||||||
 | 
					: eitScanM(1),
 | 
				
			||||||
 | 
					  useBytesM(1)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  for (unsigned int i = 0; i < ARRAY_SIZE(disabledFiltersM); ++i)
 | 
				
			||||||
 | 
					      disabledFiltersM[i] = -1;
 | 
				
			||||||
 | 
					  memset(configDirectoryM, 0, sizeof(configDirectoryM));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unsigned int cSatipConfig::GetDisabledFiltersCount(void) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  unsigned int n = 0;
 | 
				
			||||||
 | 
					  while ((n < ARRAY_SIZE(disabledFiltersM) && (disabledFiltersM[n] != -1)))
 | 
				
			||||||
 | 
					        n++;
 | 
				
			||||||
 | 
					  return n;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int cSatipConfig::GetDisabledFilters(unsigned int indexP) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  return (indexP < ARRAY_SIZE(disabledFiltersM)) ? disabledFiltersM[indexP] : -1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipConfig::SetDisabledFilters(unsigned int indexP, int numberP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (indexP < ARRAY_SIZE(disabledFiltersM))
 | 
				
			||||||
 | 
					     disabledFiltersM[indexP] = numberP;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipConfig::SetConfigDirectory(const char *directoryP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipConfig::%s(%s)", __FUNCTION__, directoryP);
 | 
				
			||||||
 | 
					  ERROR_IF(!realpath(directoryP, configDirectoryM), "Cannot canonicalize configuration directory");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										38
									
								
								config.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								config.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * config.h: SAT>IP plugin for the Video Disk Recorder
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * See the README file for copyright information and how to reach the author.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __SATIP_CONFIG_H
 | 
				
			||||||
 | 
					#define __SATIP_CONFIG_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <vdr/menuitems.h>
 | 
				
			||||||
 | 
					#include "common.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class cSatipConfig
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  unsigned int eitScanM;
 | 
				
			||||||
 | 
					  unsigned int useBytesM;
 | 
				
			||||||
 | 
					  int disabledFiltersM[SECTION_FILTER_TABLE_SIZE];
 | 
				
			||||||
 | 
					  char configDirectoryM[PATH_MAX];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  cSatipConfig();
 | 
				
			||||||
 | 
					  unsigned int GetEITScan(void) const { return eitScanM; }
 | 
				
			||||||
 | 
					  unsigned int GetUseBytes(void) const { return useBytesM; }
 | 
				
			||||||
 | 
					  const char *GetConfigDirectory(void) const { return configDirectoryM; }
 | 
				
			||||||
 | 
					  unsigned int GetDisabledFiltersCount(void) const;
 | 
				
			||||||
 | 
					  int GetDisabledFilters(unsigned int indexP) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void SetEITScan(unsigned int onOffP) { eitScanM = onOffP; }
 | 
				
			||||||
 | 
					  void SetUseBytes(unsigned int onOffP) { useBytesM = onOffP; }
 | 
				
			||||||
 | 
					  void SetConfigDirectory(const char *directoryP);
 | 
				
			||||||
 | 
					  void SetDisabledFilters(unsigned int indexP, int numberP);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern cSatipConfig SatipConfig;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // __SATIP_CONFIG_H
 | 
				
			||||||
							
								
								
									
										442
									
								
								device.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										442
									
								
								device.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,442 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * device.c: SAT>IP plugin for the Video Disk Recorder
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * See the README file for copyright information and how to reach the author.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "config.h"
 | 
				
			||||||
 | 
					#include "discover.h"
 | 
				
			||||||
 | 
					#include "source.h"
 | 
				
			||||||
 | 
					#include "device.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SATIP_MAX_DEVICES MAXDEVICES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static cSatipDevice * SatipDevicesS[SATIP_MAX_DEVICES] = { NULL };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cSatipDevice::cSatipDevice(unsigned int indexP)
 | 
				
			||||||
 | 
					: deviceIndexM(indexP),
 | 
				
			||||||
 | 
					  isPacketDeliveredM(false),
 | 
				
			||||||
 | 
					  isOpenDvrM(false),
 | 
				
			||||||
 | 
					  deviceNameM(*cString::sprintf("%s %d", *DeviceType(), deviceIndexM)),
 | 
				
			||||||
 | 
					  channelM()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  unsigned int bufsize = (unsigned int)SATIP_BUFFER_SIZE;
 | 
				
			||||||
 | 
					  bufsize -= (bufsize % TS_SIZE);
 | 
				
			||||||
 | 
					  isyslog("creating SAT>IP device %d (CardIndex=%d)", deviceIndexM, CardIndex());
 | 
				
			||||||
 | 
					  tsBufferM = new cRingBufferLinear(bufsize + 1, TS_SIZE, false,
 | 
				
			||||||
 | 
					                                   *cString::sprintf("SAT>IP TS %d", deviceIndexM));
 | 
				
			||||||
 | 
					  if (tsBufferM) {
 | 
				
			||||||
 | 
					     tsBufferM->SetTimeouts(100, 100);
 | 
				
			||||||
 | 
					     tsBufferM->SetIoThrottle();
 | 
				
			||||||
 | 
					     pTunerM = new cSatipTuner(*this, tsBufferM->Free());
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					  // Start section handler
 | 
				
			||||||
 | 
					  pSectionFilterHandlerM = new cSatipSectionFilterHandler(deviceIndexM, bufsize + 1);
 | 
				
			||||||
 | 
					  StartSectionHandler();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cSatipDevice::~cSatipDevice()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
 | 
				
			||||||
 | 
					  // Stop section handler
 | 
				
			||||||
 | 
					  StopSectionHandler();
 | 
				
			||||||
 | 
					  DELETE_POINTER(pSectionFilterHandlerM);
 | 
				
			||||||
 | 
					  DELETE_POINTER(pTunerM);
 | 
				
			||||||
 | 
					  DELETE_POINTER(tsBufferM);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cSatipDevice::Initialize(unsigned int deviceCountP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceCountP);
 | 
				
			||||||
 | 
					  new cSatipSourceParam('Y', "DVB-T (SAT>IP)");
 | 
				
			||||||
 | 
					  new cSatipSourceParam('Z', "DVB-S (SAT>IP)");
 | 
				
			||||||
 | 
					  if (deviceCountP > SATIP_MAX_DEVICES)
 | 
				
			||||||
 | 
					     deviceCountP = SATIP_MAX_DEVICES;
 | 
				
			||||||
 | 
					  for (unsigned int i = 0; i < deviceCountP; ++i)
 | 
				
			||||||
 | 
					      SatipDevicesS[i] = new cSatipDevice(i);
 | 
				
			||||||
 | 
					  for (unsigned int i = deviceCountP; i < SATIP_MAX_DEVICES; ++i)
 | 
				
			||||||
 | 
					      SatipDevicesS[i] = NULL;
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipDevice::Shutdown(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipDevice::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  for (int i = 0; i < SATIP_MAX_DEVICES; ++i) {
 | 
				
			||||||
 | 
					      if (SatipDevicesS[i])
 | 
				
			||||||
 | 
					         SatipDevicesS[i]->CloseDvr();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unsigned int cSatipDevice::Count(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  unsigned int count = 0;
 | 
				
			||||||
 | 
					  debug("cSatipDevice::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  for (unsigned int i = 0; i < SATIP_MAX_DEVICES; ++i) {
 | 
				
			||||||
 | 
					      if (SatipDevicesS[i] != NULL)
 | 
				
			||||||
 | 
					         count++;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					  return count;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cSatipDevice *cSatipDevice::GetSatipDevice(int cardIndexP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipDevice::%s(%d)", __FUNCTION__, cardIndexP);
 | 
				
			||||||
 | 
					  for (unsigned int i = 0; i < SATIP_MAX_DEVICES; ++i) {
 | 
				
			||||||
 | 
					      if (SatipDevicesS[i] && (SatipDevicesS[i]->CardIndex() == cardIndexP)) {
 | 
				
			||||||
 | 
					         //debug("cSatipDevice::%s(%d): found!", __FUNCTION__, cardIndexP);
 | 
				
			||||||
 | 
					         return SatipDevicesS[i];
 | 
				
			||||||
 | 
					         }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					  return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cString cSatipDevice::GetGeneralInformation(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
 | 
				
			||||||
 | 
					  return cString::sprintf("SAT>IP device: %d\nCardIndex: %d\nStream: %s\nSignal: %s\nStream bitrate: %s\n%sChannel: %s",
 | 
				
			||||||
 | 
					                          deviceIndexM, CardIndex(),
 | 
				
			||||||
 | 
					                          pTunerM ? *pTunerM->GetInformation() : "",
 | 
				
			||||||
 | 
					                          pTunerM ? *pTunerM->GetSignalStatus() : "",
 | 
				
			||||||
 | 
					                          pTunerM ? *pTunerM->GetTunerStatistic() : "",
 | 
				
			||||||
 | 
					                          *GetBufferStatistic(),
 | 
				
			||||||
 | 
					                          *Channels.GetByNumber(cDevice::CurrentChannel())->ToText());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cString cSatipDevice::GetPidsInformation(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
 | 
				
			||||||
 | 
					  return GetPidStatistic();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cString cSatipDevice::GetFiltersInformation(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
 | 
				
			||||||
 | 
					  return cString::sprintf("Active section filters:\n%s", pSectionFilterHandlerM ? *pSectionFilterHandlerM->GetInformation() : "");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cString cSatipDevice::GetInformation(unsigned int pageP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  // generate information string
 | 
				
			||||||
 | 
					  cString s;
 | 
				
			||||||
 | 
					  switch (pageP) {
 | 
				
			||||||
 | 
					    case SATIP_DEVICE_INFO_GENERAL:
 | 
				
			||||||
 | 
					         s = GetGeneralInformation();
 | 
				
			||||||
 | 
					         break;
 | 
				
			||||||
 | 
					    case SATIP_DEVICE_INFO_PIDS:
 | 
				
			||||||
 | 
					         s = GetPidsInformation();
 | 
				
			||||||
 | 
					         break;
 | 
				
			||||||
 | 
					    case SATIP_DEVICE_INFO_FILTERS:
 | 
				
			||||||
 | 
					         s = GetFiltersInformation();
 | 
				
			||||||
 | 
					         break;
 | 
				
			||||||
 | 
					    case SATIP_DEVICE_INFO_PROTOCOL:
 | 
				
			||||||
 | 
					         s = pTunerM ? *pTunerM->GetInformation() : "";
 | 
				
			||||||
 | 
					         break;
 | 
				
			||||||
 | 
					    case SATIP_DEVICE_INFO_BITRATE:
 | 
				
			||||||
 | 
					         s = pTunerM ? *pTunerM->GetTunerStatistic() : "";
 | 
				
			||||||
 | 
					         break;
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
					         s = cString::sprintf("%s%s%s",
 | 
				
			||||||
 | 
					                              *GetGeneralInformation(),
 | 
				
			||||||
 | 
					                              *GetPidsInformation(),
 | 
				
			||||||
 | 
					                              *GetFiltersInformation());
 | 
				
			||||||
 | 
					         break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  return s;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cString cSatipDevice::DeviceType(void) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
 | 
				
			||||||
 | 
					  return "SAT>IP";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cString cSatipDevice::DeviceName(void) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
 | 
				
			||||||
 | 
					  return deviceNameM;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int cSatipDevice::SignalStrength(void) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
 | 
				
			||||||
 | 
					  return (pTunerM ? pTunerM->SignalStrength() : -1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int cSatipDevice::SignalQuality(void) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
 | 
				
			||||||
 | 
					  return (pTunerM ? pTunerM->SignalQuality() : -1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cSatipDevice::ProvidesSource(int sourceP) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
 | 
				
			||||||
 | 
					  int model = 0;
 | 
				
			||||||
 | 
					  if (cSource::IsType(sourceP, 'Z'))
 | 
				
			||||||
 | 
					     model |= cSatipServer::eSatipModelTypeDVBS2;
 | 
				
			||||||
 | 
					  if (cSource::IsType(sourceP, 'Y'))
 | 
				
			||||||
 | 
					     model |= cSatipServer::eSatipModelTypeDVBT2 | cSatipServer::eSatipModelTypeDVBT;
 | 
				
			||||||
 | 
					  return !!cSatipDiscover::GetInstance()->GetServer(model);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cSatipDevice::ProvidesTransponder(const cChannel *channelP) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
 | 
				
			||||||
 | 
					  return (ProvidesSource(channelP->Source()));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cSatipDevice::ProvidesChannel(const cChannel *channelP, int priorityP, bool *needsDetachReceiversP) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  bool result = false;
 | 
				
			||||||
 | 
					  bool hasPriority = (priorityP == IDLEPRIORITY) || (priorityP > this->Priority());
 | 
				
			||||||
 | 
					  bool needsDetachReceivers = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (channelP && ProvidesTransponder(channelP)) {
 | 
				
			||||||
 | 
					     result = hasPriority;
 | 
				
			||||||
 | 
					     if (priorityP > IDLEPRIORITY) {
 | 
				
			||||||
 | 
					        if (Receiving()) {
 | 
				
			||||||
 | 
					           if (IsTunedToTransponder(channelP)) {
 | 
				
			||||||
 | 
					              if (channelP->Vpid() && !HasPid(channelP->Vpid()) || channelP->Apid(0) && !HasPid(channelP->Apid(0)) || channelP->Dpid(0) && !HasPid(channelP->Dpid(0))) {
 | 
				
			||||||
 | 
					                 if (CamSlot() && channelP->Ca() >= CA_ENCRYPTED_MIN) {
 | 
				
			||||||
 | 
					                    if (CamSlot()->CanDecrypt(channelP))
 | 
				
			||||||
 | 
					                       result = true;
 | 
				
			||||||
 | 
					                    else
 | 
				
			||||||
 | 
					                       needsDetachReceivers = true;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                 else
 | 
				
			||||||
 | 
					                    result = true;
 | 
				
			||||||
 | 
					                 }
 | 
				
			||||||
 | 
					              else
 | 
				
			||||||
 | 
					                 result = true;
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					           else
 | 
				
			||||||
 | 
					              needsDetachReceivers = Receiving();
 | 
				
			||||||
 | 
					           }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					  if (needsDetachReceiversP)
 | 
				
			||||||
 | 
					     *needsDetachReceiversP = needsDetachReceivers;
 | 
				
			||||||
 | 
					  return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cSatipDevice::ProvidesEIT(void) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  return (SatipConfig.GetEITScan() && pTunerM && pTunerM->IsTuned());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int cSatipDevice::NumProvidedSystems(void) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  return cSatipDiscover::GetInstance()->NumProvidedSystems();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const cChannel *cSatipDevice::GetCurrentlyTunedTransponder(void) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  return &channelM;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cSatipDevice::IsTunedToTransponder(const cChannel *channelP) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (pTunerM && !pTunerM->IsTuned())
 | 
				
			||||||
 | 
					     return false;
 | 
				
			||||||
 | 
					  if ((channelM.Source() != channelP->Source()) || (channelM.Transponder() != channelP->Transponder()))
 | 
				
			||||||
 | 
					     return false;
 | 
				
			||||||
 | 
					  return (strcmp(channelM.Parameters(), channelP->Parameters()) == 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cSatipDevice::MaySwitchTransponder(const cChannel *channelP) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  return cDevice::MaySwitchTransponder(channelP);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cSatipDevice::SetChannelDevice(const cChannel *channelP, bool liveViewP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (channelP) {
 | 
				
			||||||
 | 
					     cSatipTransponderParameters stp(channelP->Parameters());
 | 
				
			||||||
 | 
					     cString params = stp.UrlParameters(cSource::ToChar(channelP->Source()));
 | 
				
			||||||
 | 
					     cString address;
 | 
				
			||||||
 | 
					     int mode = 0;
 | 
				
			||||||
 | 
					     if (cSource::IsType(channelP->Source(), 'Z'))
 | 
				
			||||||
 | 
					        mode |= cSatipServer::eSatipModelTypeDVBS2;
 | 
				
			||||||
 | 
					     if (cSource::IsType(channelP->Source(), 'Y'))
 | 
				
			||||||
 | 
					        mode |= stp.System() ? cSatipServer::eSatipModelTypeDVBT2 : cSatipServer::eSatipModelTypeDVBT;
 | 
				
			||||||
 | 
					     cSatipServer *server = cSatipDiscover::GetInstance()->GetServer(mode);
 | 
				
			||||||
 | 
					     if (!server) {
 | 
				
			||||||
 | 
					        debug("cSatipDevice::%s(%u): no suitable server found", __FUNCTION__, deviceIndexM);
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					     address = server->Address();
 | 
				
			||||||
 | 
					     float freq = channelP->Frequency();
 | 
				
			||||||
 | 
					     if (isempty(params)) {
 | 
				
			||||||
 | 
					        error("Unrecognized SAT>IP channel parameters: %s", channelP->Parameters());
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					     // Scale down frequencies to MHz
 | 
				
			||||||
 | 
					     while (freq > 20000L)
 | 
				
			||||||
 | 
					           freq /= 1000L;
 | 
				
			||||||
 | 
					     params = cString::sprintf("freq=%s%s", *dtoa(freq, "%.3f"), *params);
 | 
				
			||||||
 | 
					     if (cSource::IsType(channelP->Source(), 'Z'))
 | 
				
			||||||
 | 
					        params = cString::sprintf("%s&sr=%d", *params, channelP->Srate());
 | 
				
			||||||
 | 
					     if (pTunerM && pTunerM->SetSource(*address, *params, deviceIndexM)) {
 | 
				
			||||||
 | 
					        deviceNameM = cString::sprintf("%s %d %s:%s:%s", *DeviceType(), deviceIndexM, server->Address(), server->Model(), server->Description());
 | 
				
			||||||
 | 
					        channelM = *channelP;
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					  return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cSatipDevice::SetPid(cPidHandle *handleP, int typeP, bool onP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipDevice::%s(%u): pid=%d type=%d on=%d", __FUNCTION__, deviceIndexM, handleP->pid, typeP, onP);
 | 
				
			||||||
 | 
					  if (pTunerM && handleP && handleP->pid >= 0) {
 | 
				
			||||||
 | 
					     if (onP)
 | 
				
			||||||
 | 
					        return pTunerM->SetPid(handleP->pid, typeP, true);
 | 
				
			||||||
 | 
					     else if (!handleP->used)
 | 
				
			||||||
 | 
					        return pTunerM->SetPid(handleP->pid, typeP, false);
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int cSatipDevice::OpenFilter(u_short pidP, u_char tidP, u_char maskP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipDevice::%s(%u): pid=%d tid=%d mask=%d", __FUNCTION__, deviceIndexM, pidP, tidP,  maskP);
 | 
				
			||||||
 | 
					  if (pSectionFilterHandlerM) {
 | 
				
			||||||
 | 
					     if (pTunerM)
 | 
				
			||||||
 | 
					        pTunerM->SetPid(pidP, ptOther, true);
 | 
				
			||||||
 | 
					     return pSectionFilterHandlerM->Open(pidP, tidP, maskP);
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					  return -1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipDevice::CloseFilter(int handleP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipDevice::%s(%u): handle=%d", __FUNCTION__, deviceIndexM, handleP);
 | 
				
			||||||
 | 
					  if (pSectionFilterHandlerM) {
 | 
				
			||||||
 | 
					     if (pTunerM)
 | 
				
			||||||
 | 
					        pTunerM->SetPid(pSectionFilterHandlerM->GetPid(handleP), ptOther, false);
 | 
				
			||||||
 | 
					     pSectionFilterHandlerM->Close(handleP);
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cSatipDevice::OpenDvr(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
 | 
				
			||||||
 | 
					  isPacketDeliveredM = false;
 | 
				
			||||||
 | 
					  tsBufferM->Clear();
 | 
				
			||||||
 | 
					  if (pTunerM)
 | 
				
			||||||
 | 
					     pTunerM->Open();
 | 
				
			||||||
 | 
					  isOpenDvrM = true;
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipDevice::CloseDvr(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
 | 
				
			||||||
 | 
					  if (pTunerM)
 | 
				
			||||||
 | 
					     pTunerM->Close();
 | 
				
			||||||
 | 
					  isOpenDvrM = false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cSatipDevice::HasLock(int timeoutMsP) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipDevice::%s(%u): timeoutMs=%d", __FUNCTION__, deviceIndexM, timeoutMsP);
 | 
				
			||||||
 | 
					  return (pTunerM && pTunerM->HasLock());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cSatipDevice::HasInternalCam(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
 | 
				
			||||||
 | 
					  return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipDevice::WriteData(uchar *bufferP, int lengthP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
 | 
				
			||||||
 | 
					  // Fill up TS buffer
 | 
				
			||||||
 | 
					  if (tsBufferM) {
 | 
				
			||||||
 | 
					     int len = tsBufferM->Put(bufferP, lengthP);
 | 
				
			||||||
 | 
					     if (len != lengthP)
 | 
				
			||||||
 | 
					        tsBufferM->ReportOverflow(lengthP - len);
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					  // Filter the sections
 | 
				
			||||||
 | 
					  if (pSectionFilterHandlerM)
 | 
				
			||||||
 | 
					     pSectionFilterHandlerM->Write(bufferP, lengthP);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unsigned int cSatipDevice::CheckData(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
 | 
				
			||||||
 | 
					  if (tsBufferM)
 | 
				
			||||||
 | 
					     return (unsigned int)tsBufferM->Free();
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uchar *cSatipDevice::GetData(int *availableP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
 | 
				
			||||||
 | 
					  if (isOpenDvrM && tsBufferM) {
 | 
				
			||||||
 | 
					     int count = 0;
 | 
				
			||||||
 | 
					     if (isPacketDeliveredM)
 | 
				
			||||||
 | 
					        SkipData(TS_SIZE);
 | 
				
			||||||
 | 
					     uchar *p = tsBufferM->Get(count);
 | 
				
			||||||
 | 
					     if (p && count >= TS_SIZE) {
 | 
				
			||||||
 | 
					        if (*p != TS_SYNC_BYTE) {
 | 
				
			||||||
 | 
					           for (int i = 1; i < count; i++) {
 | 
				
			||||||
 | 
					               if (p[i] == TS_SYNC_BYTE) {
 | 
				
			||||||
 | 
					                  count = i;
 | 
				
			||||||
 | 
					                  break;
 | 
				
			||||||
 | 
					                  }
 | 
				
			||||||
 | 
					               }
 | 
				
			||||||
 | 
					           tsBufferM->Del(count);
 | 
				
			||||||
 | 
					           info("Skipped %d bytes to sync on TS packet", count);
 | 
				
			||||||
 | 
					           return NULL;
 | 
				
			||||||
 | 
					           }
 | 
				
			||||||
 | 
					        isPacketDeliveredM = true;
 | 
				
			||||||
 | 
					        if (availableP)
 | 
				
			||||||
 | 
					           *availableP = count;
 | 
				
			||||||
 | 
					        // Update pid statistics
 | 
				
			||||||
 | 
					        AddPidStatistic(ts_pid(p), payload(p));
 | 
				
			||||||
 | 
					        return p;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					  return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipDevice::SkipData(int countP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
 | 
				
			||||||
 | 
					  tsBufferM->Del(countP);
 | 
				
			||||||
 | 
					  isPacketDeliveredM = false;
 | 
				
			||||||
 | 
					  // Update buffer statistics
 | 
				
			||||||
 | 
					  AddBufferStatistic(countP, tsBufferM->Available());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cSatipDevice::GetTSPacket(uchar *&dataP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
 | 
				
			||||||
 | 
					  if (tsBufferM) {
 | 
				
			||||||
 | 
					#if defined(APIVERSNUM) && APIVERSNUM >= 20104
 | 
				
			||||||
 | 
					     if (cCamSlot *cs = CamSlot()) {
 | 
				
			||||||
 | 
					        if (cs->WantsTsData()) {
 | 
				
			||||||
 | 
					           int available;
 | 
				
			||||||
 | 
					           dataP = GetData(&available);
 | 
				
			||||||
 | 
					           if (dataP) {
 | 
				
			||||||
 | 
					              dataP = cs->Decrypt(dataP, available);
 | 
				
			||||||
 | 
					              SkipData(available);
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					           return true;
 | 
				
			||||||
 | 
					           }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					     dataP = GetData();
 | 
				
			||||||
 | 
					     return true;
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					  // Reduce cpu load by preventing busylooping
 | 
				
			||||||
 | 
					  cCondWait::SleepMs(10);
 | 
				
			||||||
 | 
					  dataP = NULL;
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										106
									
								
								device.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								device.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,106 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * device.h: SAT>IP plugin for the Video Disk Recorder
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * See the README file for copyright information and how to reach the author.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __SATIP_DEVICE_H
 | 
				
			||||||
 | 
					#define __SATIP_DEVICE_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <vdr/device.h>
 | 
				
			||||||
 | 
					#include "common.h"
 | 
				
			||||||
 | 
					#include "deviceif.h"
 | 
				
			||||||
 | 
					#include "tuner.h"
 | 
				
			||||||
 | 
					#include "sectionfilter.h"
 | 
				
			||||||
 | 
					#include "statistics.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class cSatipDevice : public cDevice, public cSatipPidStatistics, public cSatipBufferStatistics, public cSatipDeviceIf {
 | 
				
			||||||
 | 
					  // static ones
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  static unsigned int deviceCount;
 | 
				
			||||||
 | 
					  static bool Initialize(unsigned int DeviceCount);
 | 
				
			||||||
 | 
					  static void Shutdown(void);
 | 
				
			||||||
 | 
					  static unsigned int Count(void);
 | 
				
			||||||
 | 
					  static cSatipDevice *GetSatipDevice(int CardIndex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // private parts
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  unsigned int deviceIndexM;
 | 
				
			||||||
 | 
					  bool isPacketDeliveredM;
 | 
				
			||||||
 | 
					  bool isOpenDvrM;
 | 
				
			||||||
 | 
					  cString deviceNameM;
 | 
				
			||||||
 | 
					  cChannel channelM;
 | 
				
			||||||
 | 
					  cRingBufferLinear *tsBufferM;
 | 
				
			||||||
 | 
					  cSatipTuner *pTunerM;
 | 
				
			||||||
 | 
					  cSatipSectionFilterHandler *pSectionFilterHandlerM;
 | 
				
			||||||
 | 
					  cMutex mutexM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // constructor & destructor
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  cSatipDevice(unsigned int deviceIndexP);
 | 
				
			||||||
 | 
					  virtual ~cSatipDevice();
 | 
				
			||||||
 | 
					  cString GetInformation(unsigned int pageP = SATIP_DEVICE_INFO_ALL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // copy and assignment constructors
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  cSatipDevice(const cSatipDevice&);
 | 
				
			||||||
 | 
					  cSatipDevice& operator=(const cSatipDevice&);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // for statistics and general information
 | 
				
			||||||
 | 
					  cString GetGeneralInformation(void);
 | 
				
			||||||
 | 
					  cString GetPidsInformation(void);
 | 
				
			||||||
 | 
					  cString GetFiltersInformation(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // for channel info
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  virtual cString DeviceType(void) const;
 | 
				
			||||||
 | 
					  virtual cString DeviceName(void) const;
 | 
				
			||||||
 | 
					  virtual int SignalStrength(void) const;
 | 
				
			||||||
 | 
					  virtual int SignalQuality(void) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // for channel selection
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  virtual bool ProvidesSource(int sourceP) const;
 | 
				
			||||||
 | 
					  virtual bool ProvidesTransponder(const cChannel *channelP) const;
 | 
				
			||||||
 | 
					  virtual bool ProvidesChannel(const cChannel *channelP, int priorityP = -1, bool *needsDetachReceiversP = NULL) const;
 | 
				
			||||||
 | 
					  virtual bool ProvidesEIT(void) const;
 | 
				
			||||||
 | 
					  virtual int NumProvidedSystems(void) const;
 | 
				
			||||||
 | 
					  virtual const cChannel *GetCurrentlyTunedTransponder(void) const;
 | 
				
			||||||
 | 
					  virtual bool IsTunedToTransponder(const cChannel *channelP) const;
 | 
				
			||||||
 | 
					  virtual bool MaySwitchTransponder(const cChannel *channelP) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					protected:
 | 
				
			||||||
 | 
					  virtual bool SetChannelDevice(const cChannel *channelP, bool liveViewP);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // for recording
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  uchar *GetData(int *availableP = NULL);
 | 
				
			||||||
 | 
					  void SkipData(int countP);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					protected:
 | 
				
			||||||
 | 
					  virtual bool SetPid(cPidHandle *handleP, int typeP, bool onP);
 | 
				
			||||||
 | 
					  virtual bool OpenDvr(void);
 | 
				
			||||||
 | 
					  virtual void CloseDvr(void);
 | 
				
			||||||
 | 
					  virtual bool GetTSPacket(uchar *&dataP);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // for section filtering
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  virtual int OpenFilter(u_short pidP, u_char tidP, u_char maskP);
 | 
				
			||||||
 | 
					  virtual void CloseFilter(int handleP);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // for transponder lock
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  virtual bool HasLock(int timeoutMsP) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // for common interface
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  virtual bool HasInternalCam(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // for internal device interface
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  virtual void WriteData(u_char *bufferP, int lengthP);
 | 
				
			||||||
 | 
					  virtual unsigned int CheckData(void);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // __SATIP_DEVICE_H
 | 
				
			||||||
							
								
								
									
										23
									
								
								deviceif.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								deviceif.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * deviceif.h: SAT>IP plugin for the Video Disk Recorder
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * See the README file for copyright information and how to reach the author.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __SATIP_DEVICEIF_H
 | 
				
			||||||
 | 
					#define __SATIP_DEVICEIF_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class cSatipDeviceIf {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  cSatipDeviceIf() {}
 | 
				
			||||||
 | 
					  virtual ~cSatipDeviceIf() {}
 | 
				
			||||||
 | 
					  virtual void WriteData(u_char *bufferP, int lengthP) = 0;
 | 
				
			||||||
 | 
					  virtual unsigned int CheckData(void) = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  cSatipDeviceIf(const cSatipDeviceIf&);
 | 
				
			||||||
 | 
					  cSatipDeviceIf& operator=(const cSatipDeviceIf&);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // __SATIP_DEVICEIF_H
 | 
				
			||||||
							
								
								
									
										283
									
								
								discover.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										283
									
								
								discover.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,283 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * discover.c: SAT>IP plugin for the Video Disk Recorder
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * See the README file for copyright information and how to reach the author.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "common.h"
 | 
				
			||||||
 | 
					#include "config.h"
 | 
				
			||||||
 | 
					#include "socket.h"
 | 
				
			||||||
 | 
					#include "discover.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cSatipDiscover *cSatipDiscover::instanceS = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char *cSatipDiscover::bcastAddressS = "239.255.255.250";
 | 
				
			||||||
 | 
					const char *cSatipDiscover::bcastMessageS = "M-SEARCH * HTTP/1.1\r\n"                  \
 | 
				
			||||||
 | 
					                                            "HOST: 239.255.255.250:1900\r\n"           \
 | 
				
			||||||
 | 
					                                            "MAN: \"ssdp:discover\"\r\n"               \
 | 
				
			||||||
 | 
					                                            "ST: urn:ses-com:device:SatIPServer:1\r\n" \
 | 
				
			||||||
 | 
					                                            "MX: 2\r\n\r\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cSatipDiscover *cSatipDiscover::GetInstance(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (!instanceS)
 | 
				
			||||||
 | 
					     instanceS = new cSatipDiscover();
 | 
				
			||||||
 | 
					  return instanceS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cSatipDiscover::Initialize(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipDiscover::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipDiscover::Destroy(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipDiscover::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  DELETE_POINTER(instanceS);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					size_t cSatipDiscover::WriteCallback(void *ptrP, size_t sizeP, size_t nmembP, void *dataP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  cSatipDiscover *obj = reinterpret_cast<cSatipDiscover *>(dataP);
 | 
				
			||||||
 | 
					  size_t len = sizeP * nmembP;
 | 
				
			||||||
 | 
					  //debug("cSatipDiscover::%s(%zu)", __FUNCTION__, len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  char *s, *p = (char *)ptrP;
 | 
				
			||||||
 | 
					  char *r = strtok_r(p, "\r\n", &s);
 | 
				
			||||||
 | 
					  char *desc = NULL, *model = NULL, *addr = NULL;
 | 
				
			||||||
 | 
					  while (r) {
 | 
				
			||||||
 | 
					    //debug("cSatipDiscover::%s(%zu): %s", __FUNCTION__, len, r);
 | 
				
			||||||
 | 
					    // <friendlyName>OctopusNet</friendlyName>
 | 
				
			||||||
 | 
					    if (startswith(r, "<friendlyName"))
 | 
				
			||||||
 | 
					       desc = StripTags(r);
 | 
				
			||||||
 | 
					    // <satip:X_SATIPCAP xmlns:satip="urn:ses-com:satip">DVBT-2</satip:X_SATIPCAP>
 | 
				
			||||||
 | 
					    if (startswith(r, "<satip:X_SATIPCAP"))
 | 
				
			||||||
 | 
					       model = StripTags(r);
 | 
				
			||||||
 | 
					    r = strtok_r(NULL, "\r\n", &s);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  if (obj) {
 | 
				
			||||||
 | 
					     CURLcode res = CURLE_OK;
 | 
				
			||||||
 | 
					     SATIP_CURL_EASY_GETINFO(obj->handleM, CURLINFO_PRIMARY_IP, &addr);
 | 
				
			||||||
 | 
					     obj->AddServer(addr, desc, model);
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return len;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cSatipDiscover::cSatipDiscover()
 | 
				
			||||||
 | 
					: cThread("SAT>IP discover"),
 | 
				
			||||||
 | 
					  mutexM(),
 | 
				
			||||||
 | 
					  handleM(curl_easy_init()),
 | 
				
			||||||
 | 
					  socketM(new cSatipSocket()),
 | 
				
			||||||
 | 
					  sleepM(),
 | 
				
			||||||
 | 
					  probeIntervalM(0),
 | 
				
			||||||
 | 
					  serversM(new cSatipServers())
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipDiscover::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  // Start the thread
 | 
				
			||||||
 | 
					  Start();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cSatipDiscover::~cSatipDiscover()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipDiscover::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  cMutexLock MutexLock(&mutexM);
 | 
				
			||||||
 | 
					  sleepM.Signal();
 | 
				
			||||||
 | 
					  if (Running())
 | 
				
			||||||
 | 
					     Cancel(3);
 | 
				
			||||||
 | 
					  // Free allocated memory
 | 
				
			||||||
 | 
					  DELETENULL(socketM);
 | 
				
			||||||
 | 
					  DELETENULL(serversM);
 | 
				
			||||||
 | 
					  if (handleM)
 | 
				
			||||||
 | 
					     curl_easy_cleanup(handleM);
 | 
				
			||||||
 | 
					  handleM = NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipDiscover::Action(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipDiscover::%s(): entering", __FUNCTION__);
 | 
				
			||||||
 | 
					  // Do the thread loop
 | 
				
			||||||
 | 
					  while (Running()) {
 | 
				
			||||||
 | 
					        if (probeIntervalM.TimedOut()) {
 | 
				
			||||||
 | 
					           probeIntervalM.Set(eProbeIntervalMs);
 | 
				
			||||||
 | 
					           Probe();
 | 
				
			||||||
 | 
					           Janitor();
 | 
				
			||||||
 | 
					           }
 | 
				
			||||||
 | 
					        // to avoid busy loop and reduce cpu load
 | 
				
			||||||
 | 
					        sleepM.Wait(10);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					  debug("cSatipDiscover::%s(): exiting", __FUNCTION__);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipDiscover::Janitor(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipDiscover::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  cMutexLock MutexLock(&mutexM);
 | 
				
			||||||
 | 
					  for (cSatipServer *srv = serversM->First(); srv; srv = serversM->Next(srv)) {
 | 
				
			||||||
 | 
					      if (srv->LastSeen() > eProbeIntervalMs * 2) {
 | 
				
			||||||
 | 
					         info("Removing device %s (%s %s)", srv->Description(), srv->Address(), srv->Model());
 | 
				
			||||||
 | 
					         serversM->Del(srv);
 | 
				
			||||||
 | 
					         }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipDiscover::Probe(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipDiscover::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  if (socketM && socketM->Open(eDiscoveryPort)) {
 | 
				
			||||||
 | 
					     cTimeMs timeout(eProbeTimeoutMs);
 | 
				
			||||||
 | 
					     socketM->Write(bcastAddressS, reinterpret_cast<const unsigned char *>(bcastMessageS), strlen(bcastMessageS));
 | 
				
			||||||
 | 
					     while (Running() && !timeout.TimedOut()) {
 | 
				
			||||||
 | 
					           Read();
 | 
				
			||||||
 | 
					           // to avoid busy loop and reduce cpu load
 | 
				
			||||||
 | 
					           sleepM.Wait(100);
 | 
				
			||||||
 | 
					           }
 | 
				
			||||||
 | 
					     socketM->Close();
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipDiscover::Read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipDiscover::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  if (socketM) {
 | 
				
			||||||
 | 
					     unsigned char *buf = MALLOC(unsigned char, eProbeBufferSize + 1);
 | 
				
			||||||
 | 
					     if (buf) {
 | 
				
			||||||
 | 
					        memset(buf, 0, eProbeBufferSize + 1);
 | 
				
			||||||
 | 
					        int len = socketM->Read(buf, eProbeBufferSize);
 | 
				
			||||||
 | 
					        if (len > 0) {
 | 
				
			||||||
 | 
					           //debug("cSatipDiscover::%s(): len=%d", __FUNCTION__, len);
 | 
				
			||||||
 | 
					           bool status = false;
 | 
				
			||||||
 | 
					           char *s, *p = reinterpret_cast<char *>(buf), *location = NULL;
 | 
				
			||||||
 | 
					           char *r = strtok_r(p, "\r\n", &s);
 | 
				
			||||||
 | 
					           while (r) {
 | 
				
			||||||
 | 
					                 //debug("cSatipDiscover::%s(): %s", __FUNCTION__, r);
 | 
				
			||||||
 | 
					                 // Check the status code
 | 
				
			||||||
 | 
					                 // HTTP/1.1 200 OK
 | 
				
			||||||
 | 
					                 if (!status && startswith(r, "HTTP/1.1 200 OK")) {
 | 
				
			||||||
 | 
					                     status = true;
 | 
				
			||||||
 | 
					                     }
 | 
				
			||||||
 | 
					                 // Check the location data
 | 
				
			||||||
 | 
					                 // LOCATION: http://192.168.0.115:8888/octonet.xml
 | 
				
			||||||
 | 
					                 if (status && startswith(r, "LOCATION:")) {
 | 
				
			||||||
 | 
					                     location = compactspace(r + 9);
 | 
				
			||||||
 | 
					                     debug("cSatipDiscover::%s(): location='%s'", __FUNCTION__, location);
 | 
				
			||||||
 | 
					                     break;
 | 
				
			||||||
 | 
					                     }
 | 
				
			||||||
 | 
					                 r = strtok_r(NULL, "\r\n", &s);
 | 
				
			||||||
 | 
					                 }
 | 
				
			||||||
 | 
					           if (handleM && !isempty(location)) {
 | 
				
			||||||
 | 
					              long rc = 0;
 | 
				
			||||||
 | 
					              CURLcode res = CURLE_OK;
 | 
				
			||||||
 | 
					#ifdef DEBUG
 | 
				
			||||||
 | 
					              // Verbose output
 | 
				
			||||||
 | 
					              SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_VERBOSE, 1L);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					              // Set callback
 | 
				
			||||||
 | 
					              SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipDiscover::WriteCallback);
 | 
				
			||||||
 | 
					              SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					              // No progress meter and no signaling
 | 
				
			||||||
 | 
					              SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_NOPROGRESS, 1L);
 | 
				
			||||||
 | 
					              SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_NOSIGNAL, 1L);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					              // Set timeouts
 | 
				
			||||||
 | 
					              SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_TIMEOUT_MS, (long)eConnectTimeoutMs);
 | 
				
			||||||
 | 
					              SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_CONNECTTIMEOUT_MS, (long)eConnectTimeoutMs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					              // Set user-agent
 | 
				
			||||||
 | 
					              SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_USERAGENT, *cString::sprintf("vdr-%s/%s", PLUGIN_NAME_I18N, VERSION));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					              // Set URL
 | 
				
			||||||
 | 
					              SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_URL, location);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					              // Fetch the data
 | 
				
			||||||
 | 
					              SATIP_CURL_EASY_PERFORM(handleM);
 | 
				
			||||||
 | 
					              SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_RESPONSE_CODE, &rc);
 | 
				
			||||||
 | 
					              if (rc != 200)
 | 
				
			||||||
 | 
					                 error("Discovery detected invalid status code: %ld", rc);
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					           }
 | 
				
			||||||
 | 
					        free(buf);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipDiscover::AddServer(const char *addrP, const char *descP, const char * modelP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipDiscover::%s(%s, %s, %s)", __FUNCTION__, addrP, descP, modelP);
 | 
				
			||||||
 | 
					  cMutexLock MutexLock(&mutexM);
 | 
				
			||||||
 | 
					  if (serversM) {
 | 
				
			||||||
 | 
					     cSatipServer *tmp = new cSatipServer(addrP, descP, modelP);
 | 
				
			||||||
 | 
					     // Validate against existing servers
 | 
				
			||||||
 | 
					     bool found = false;
 | 
				
			||||||
 | 
					     for (cSatipServer *s = serversM->First(); s; s = serversM->Next(s)) {
 | 
				
			||||||
 | 
					         if (s->Compare(*tmp) == 0) {
 | 
				
			||||||
 | 
					            found = true;
 | 
				
			||||||
 | 
					            s->Update();
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					         }
 | 
				
			||||||
 | 
					     if (!found) {
 | 
				
			||||||
 | 
					        info("Adding device %s (%s %s)", tmp->Description(), tmp->Address(), tmp->Model());
 | 
				
			||||||
 | 
					        serversM->Add(tmp);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					     else
 | 
				
			||||||
 | 
					        DELETENULL(tmp);
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cSatipDiscover::IsValidServer(cSatipServer *serverP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipDiscover::%s(%d)", __FUNCTION__);
 | 
				
			||||||
 | 
					  cMutexLock MutexLock(&mutexM);
 | 
				
			||||||
 | 
					  for (cSatipServer *srv = serversM->First(); srv; srv = serversM->Next(srv)) {
 | 
				
			||||||
 | 
					      if (srv == serverP)
 | 
				
			||||||
 | 
					         return true;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					  return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cSatipServer *cSatipDiscover::GetServer(int modelP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipDiscover::%s(%d)", __FUNCTION__, modelP);
 | 
				
			||||||
 | 
					  cMutexLock MutexLock(&mutexM);
 | 
				
			||||||
 | 
					  for (cSatipServer *srv = serversM->First(); srv; srv = serversM->Next(srv)) {
 | 
				
			||||||
 | 
					      if (srv->Match(modelP))
 | 
				
			||||||
 | 
					         return srv;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					  return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cSatipServers *cSatipDiscover::GetServers(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipDiscover::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  cMutexLock MutexLock(&mutexM);
 | 
				
			||||||
 | 
					  return serversM;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cString cSatipDiscover::GetServerList(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipDiscover::%s(%d)", __FUNCTION__, modelP);
 | 
				
			||||||
 | 
					  cMutexLock MutexLock(&mutexM);
 | 
				
			||||||
 | 
					  cString list = "";
 | 
				
			||||||
 | 
					  for (cSatipServer *srv = serversM->First(); srv; srv = serversM->Next(srv))
 | 
				
			||||||
 | 
					      list = cString::sprintf("%s%s:%s:%s\n", *list, srv->Address(), srv->Model(), srv->Description());
 | 
				
			||||||
 | 
					  return list;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int cSatipDiscover::NumProvidedSystems(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipDiscover::%s(%d)", __FUNCTION__, modelP);
 | 
				
			||||||
 | 
					  cMutexLock MutexLock(&mutexM);
 | 
				
			||||||
 | 
					  int count = 0;
 | 
				
			||||||
 | 
					  for (cSatipServer *srv = serversM->First(); srv; srv = serversM->Next(srv)) {
 | 
				
			||||||
 | 
					      count += srv->Satellite();
 | 
				
			||||||
 | 
					      count += srv->Terrestrial();
 | 
				
			||||||
 | 
					      count += srv->Terrestrial2();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					  return count;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										129
									
								
								discover.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								discover.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,129 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * discover.h: SAT>IP plugin for the Video Disk Recorder
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * See the README file for copyright information and how to reach the author.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __SATIP_DISCOVER_H
 | 
				
			||||||
 | 
					#define __SATIP_DISCOVER_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <curl/curl.h>
 | 
				
			||||||
 | 
					#include <curl/easy.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <vdr/thread.h>
 | 
				
			||||||
 | 
					#include <vdr/tools.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "socket.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class cSatipServer : public cListObject {
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  enum eSatipServer {
 | 
				
			||||||
 | 
					    eSatipServerDVBS2 = 0,
 | 
				
			||||||
 | 
					    eSatipServerDVBT,
 | 
				
			||||||
 | 
					    eSatipServerDVBT2,
 | 
				
			||||||
 | 
					    eSatipServerCount
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  cString addressM;
 | 
				
			||||||
 | 
					  cString descriptionM;
 | 
				
			||||||
 | 
					  cString modelM;
 | 
				
			||||||
 | 
					  int modelCountM[eSatipServerCount];
 | 
				
			||||||
 | 
					  int modelTypeM;
 | 
				
			||||||
 | 
					  cTimeMs lastSeenM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  enum eSatipModelType {
 | 
				
			||||||
 | 
					    eSatipModelTypeDVBS2 = 0x01,
 | 
				
			||||||
 | 
					    eSatipModelTypeDVBT  = 0x02,
 | 
				
			||||||
 | 
					    eSatipModelTypeDVBT2 = 0x04,
 | 
				
			||||||
 | 
					    eSatipModelTypeMask  = 0x0F
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  cSatipServer(const char *addressP, const char *descriptionP, const char *modelP) : addressM(addressP), descriptionM(descriptionP), modelM(modelP), modelTypeM(eSatipModelTypeMask), lastSeenM(0)
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    memset(modelCountM, 0, sizeof(modelCountM));
 | 
				
			||||||
 | 
					    if (isempty(*modelM))
 | 
				
			||||||
 | 
					       modelM = "DVBS-1,DVBT2-1";
 | 
				
			||||||
 | 
					    char *s, *p = strdup(*modelM);
 | 
				
			||||||
 | 
					    char *r = strtok_r(p, ",", &s);
 | 
				
			||||||
 | 
					    while (r) {
 | 
				
			||||||
 | 
					          if (strstr(r, "DVBS2")) {
 | 
				
			||||||
 | 
					             modelTypeM |= cSatipServer::eSatipModelTypeDVBS2;
 | 
				
			||||||
 | 
					             if (char *c = strstr(r, "-"))
 | 
				
			||||||
 | 
					                modelCountM[eSatipServerDVBS2] = atoi(++c);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          if (strstr(r, "DVBT2")) {
 | 
				
			||||||
 | 
					             modelTypeM |= cSatipServer::eSatipModelTypeDVBT | cSatipServer::eSatipModelTypeDVBT2;
 | 
				
			||||||
 | 
					             if (char *c = strstr(r, "-"))
 | 
				
			||||||
 | 
					                modelCountM[eSatipServerDVBT2] = atoi(++c);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          if (strstr(r, "DVBT")) {
 | 
				
			||||||
 | 
					             modelTypeM |= cSatipServer::eSatipModelTypeDVBT;
 | 
				
			||||||
 | 
					             if (char *c = strstr(r, "-"))
 | 
				
			||||||
 | 
					                modelCountM[eSatipServerDVBT] = atoi(++c);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          r = strtok_r(NULL, ",", &s);
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					    free(p);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  virtual int Compare(const cListObject &listObjectP) const { const cSatipServer *s = (const cSatipServer *)&listObjectP; return strcasecmp(*addressM, *s->addressM); }
 | 
				
			||||||
 | 
					  const char *Description() { return *descriptionM; }
 | 
				
			||||||
 | 
					  const char *Address() { return *addressM; }
 | 
				
			||||||
 | 
					  const char *Model(void) { return modelM; }
 | 
				
			||||||
 | 
					  int ModelType(void) { return modelTypeM; }
 | 
				
			||||||
 | 
					  bool Match(int modelP) { return ((modelP & eSatipModelTypeMask) & modelTypeM); }
 | 
				
			||||||
 | 
					  int Satellite() { return (modelTypeM & eSatipModelTypeDVBS2) ? modelCountM[eSatipServerDVBS2] : 0; }
 | 
				
			||||||
 | 
					  int Terrestrial() { return (modelTypeM & eSatipModelTypeDVBT) ? modelCountM[eSatipServerDVBT] : 0; }
 | 
				
			||||||
 | 
					  int Terrestrial2() { return (modelTypeM & eSatipModelTypeDVBT2) ? modelCountM[eSatipServerDVBT2] : 0; }
 | 
				
			||||||
 | 
					  int LastSeen(void) { return lastSeenM.Elapsed(); }
 | 
				
			||||||
 | 
					  void Update(void) { lastSeenM.Set(); }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class cSatipServers : public cList<cSatipServer> {
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class cSatipDiscover : public cThread {
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  enum {
 | 
				
			||||||
 | 
					    eConnectTimeoutMs = 1500, // in milliseconds
 | 
				
			||||||
 | 
					    eDiscoveryPort    = 1900,
 | 
				
			||||||
 | 
					    eProbeBufferSize  = 1024, // in bytes
 | 
				
			||||||
 | 
					    eProbeTimeoutMs   = 2000, // in milliseconds
 | 
				
			||||||
 | 
					    eProbeIntervalMs  = 60000 // in milliseconds
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  static cSatipDiscover *instanceS;
 | 
				
			||||||
 | 
					  static const char *bcastAddressS;
 | 
				
			||||||
 | 
					  static const char *bcastMessageS;
 | 
				
			||||||
 | 
					  static size_t WriteCallback(void *ptrP, size_t sizeP, size_t nmembP, void *dataP);
 | 
				
			||||||
 | 
					  cMutex mutexM;
 | 
				
			||||||
 | 
					  CURL *handleM;
 | 
				
			||||||
 | 
					  cSatipSocket *socketM;
 | 
				
			||||||
 | 
					  cCondWait sleepM;
 | 
				
			||||||
 | 
					  cTimeMs probeIntervalM;
 | 
				
			||||||
 | 
					  cSatipServers *serversM;
 | 
				
			||||||
 | 
					  void Janitor(void);
 | 
				
			||||||
 | 
					  void Probe(void);
 | 
				
			||||||
 | 
					  void Read(void);
 | 
				
			||||||
 | 
					  void AddServer(const char *addrP, const char *descP, const char *modelP);
 | 
				
			||||||
 | 
					  // constructor
 | 
				
			||||||
 | 
					  cSatipDiscover();
 | 
				
			||||||
 | 
					  // to prevent copy constructor and assignment
 | 
				
			||||||
 | 
					  cSatipDiscover(const cSatipDiscover&);
 | 
				
			||||||
 | 
					  cSatipDiscover& operator=(const cSatipDiscover&);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					protected:
 | 
				
			||||||
 | 
					  virtual void Action(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  static cSatipDiscover *GetInstance(void);
 | 
				
			||||||
 | 
					  static bool Initialize(void);
 | 
				
			||||||
 | 
					  static void Destroy(void);
 | 
				
			||||||
 | 
					  virtual ~cSatipDiscover();
 | 
				
			||||||
 | 
					  bool IsValidServer(cSatipServer *serverP);
 | 
				
			||||||
 | 
					  cSatipServer *GetServer(int modelP);
 | 
				
			||||||
 | 
					  cSatipServers *GetServers(void);
 | 
				
			||||||
 | 
					  cString GetServerList(void);
 | 
				
			||||||
 | 
					  int NumProvidedSystems(void);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // __SATIP_DISCOVER_H
 | 
				
			||||||
							
								
								
									
										141
									
								
								po/de_DE.po
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								po/de_DE.po
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,141 @@
 | 
				
			|||||||
 | 
					# VDR plugin language source file.
 | 
				
			||||||
 | 
					# Copyright (C) 2007-2014 Rolf Ahrenberg & Antti Seppala
 | 
				
			||||||
 | 
					# This file is distributed under the same license as the iptv package.
 | 
				
			||||||
 | 
					# Frank Neumann, 2014
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					msgid ""
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					"Project-Id-Version: vdr-satip 0.0.1\n"
 | 
				
			||||||
 | 
					"Report-Msgid-Bugs-To: <see README>\n"
 | 
				
			||||||
 | 
					"POT-Creation-Date: 2014-03-08 03:08+0200\n"
 | 
				
			||||||
 | 
					"PO-Revision-Date: 2014-03-08 03:08+0200\n"
 | 
				
			||||||
 | 
					"Last-Translator: Frank Neumann <fnu@yavdr.org>\n"
 | 
				
			||||||
 | 
					"Language-Team: German <vdr@linuxtv.org>\n"
 | 
				
			||||||
 | 
					"Language: de\n"
 | 
				
			||||||
 | 
					"MIME-Version: 1.0\n"
 | 
				
			||||||
 | 
					"Content-Type: text/plain; charset=UTF-8\n"
 | 
				
			||||||
 | 
					"Content-Transfer-Encoding: 8bit\n"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "PAT (0x00)"
 | 
				
			||||||
 | 
					msgstr "PAT (0x00)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "NIT (0x40)"
 | 
				
			||||||
 | 
					msgstr "NIT (0x40)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "SDT (0x42)"
 | 
				
			||||||
 | 
					msgstr "SDT (0x42)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "EIT (0x4E/0x4F)"
 | 
				
			||||||
 | 
					msgstr "EIT (0x4E/0x4F)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "EIT (0x5X)"
 | 
				
			||||||
 | 
					msgstr "EIT (0x5X)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "EIT (0x6X)"
 | 
				
			||||||
 | 
					msgstr "EIT (0x6X)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "TDT (0x70)"
 | 
				
			||||||
 | 
					msgstr "TDT (0x70)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "SAT>IP Devices"
 | 
				
			||||||
 | 
					msgstr "SAT>IP Geräte"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "SAT>IP Device"
 | 
				
			||||||
 | 
					msgstr "SAT>IP Gerät"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Button$Scan"
 | 
				
			||||||
 | 
					msgstr "Starte Kanalsuche"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "SAT>IP Information"
 | 
				
			||||||
 | 
					msgstr "SAT>IP Informationen"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "General"
 | 
				
			||||||
 | 
					msgstr "Allgemein"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Pids"
 | 
				
			||||||
 | 
					msgstr "Pids"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Filters"
 | 
				
			||||||
 | 
					msgstr "Filter"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Bits/bytes"
 | 
				
			||||||
 | 
					msgstr "Bits/Bytes"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "SAT>IP information not available!"
 | 
				
			||||||
 | 
					msgstr "Keine SAT>IP Informationen verfügbar!"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Enable EPG scanning"
 | 
				
			||||||
 | 
					msgstr "Aktiviere EPG Aktualisierung"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid ""
 | 
				
			||||||
 | 
					"Define whether the EPG background scanning shall be used.\n"
 | 
				
			||||||
 | 
					"\n"
 | 
				
			||||||
 | 
					"This setting disables the automatic EIT scanning functionality for all SAT>IP devices."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					"Definiert ob EPG im Hintergrund aktualisiert werden soll oder nicht.\n"
 | 
				
			||||||
 | 
					"\n"
 | 
				
			||||||
 | 
					"Diese Einstellung schaltet die automatische EIT Aktualisierung für alle SAT>IP Geräte."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Disabled filters"
 | 
				
			||||||
 | 
					msgstr "Deaktivierte Filter"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "none"
 | 
				
			||||||
 | 
					msgstr "keine"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid ""
 | 
				
			||||||
 | 
					"Define number of section filters to be disabled.\n"
 | 
				
			||||||
 | 
					"\n"
 | 
				
			||||||
 | 
					"Certain section filters might cause some unwanted behaviour to VDR such as time being falsely synchronized. By black-listing the filters here useful section data can be left intact for VDR to process."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					"Bestimme die Anzahl der Abschnittsfilter die deaktiviert werden sollen.\n"
 | 
				
			||||||
 | 
					"\n"
 | 
				
			||||||
 | 
					"Bestimmte Abschnittsfilter können unerwünschtes Verhalten mit VDR, z.B. falsche Zeit-Synchronisation, verursachen. Durch das Ausblenden einzelner Filter können nützliche Daten dieser Abschnitte für den VDR erhalten werden."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Filter"
 | 
				
			||||||
 | 
					msgstr "Filter"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Define an ill-behaving filter to be blacklisted."
 | 
				
			||||||
 | 
					msgstr "Bestimme einen fehlerhaften Filter der ausgeblendet werden soll."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Active SAT>IP devices:"
 | 
				
			||||||
 | 
					msgstr "Aktive SAT>IP Geräte:"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Help"
 | 
				
			||||||
 | 
					msgstr "Hilfe"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "off"
 | 
				
			||||||
 | 
					msgstr "aus"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "on"
 | 
				
			||||||
 | 
					msgstr "ein"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "auto"
 | 
				
			||||||
 | 
					msgstr "auto"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "SISO"
 | 
				
			||||||
 | 
					msgstr "SISO"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "MISO"
 | 
				
			||||||
 | 
					msgstr "MISO"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Nid"
 | 
				
			||||||
 | 
					msgstr "Nid"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Tid"
 | 
				
			||||||
 | 
					msgstr "Tid"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Rid"
 | 
				
			||||||
 | 
					msgstr "Rid"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "SignalSource"
 | 
				
			||||||
 | 
					msgstr "Signalquelle"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "PilotTones"
 | 
				
			||||||
 | 
					msgstr "Pilottöne"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "T2SystemId"
 | 
				
			||||||
 | 
					msgstr "T2-Systemkennung"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "SISO/MISO"
 | 
				
			||||||
 | 
					msgstr "SISO/MISO"
 | 
				
			||||||
							
								
								
									
										140
									
								
								po/fi_FI.po
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								po/fi_FI.po
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,140 @@
 | 
				
			|||||||
 | 
					# VDR plugin language source file.
 | 
				
			||||||
 | 
					# Copyright (C) 2007-2014 Rolf Ahrenberg & Antti Seppala
 | 
				
			||||||
 | 
					# This file is distributed under the same license as the iptv package.
 | 
				
			||||||
 | 
					# Rolf Ahrenberg, 2014
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					msgid ""
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					"Project-Id-Version: vdr-satip 0.0.1\n"
 | 
				
			||||||
 | 
					"Report-Msgid-Bugs-To: <see README>\n"
 | 
				
			||||||
 | 
					"POT-Creation-Date: 2014-03-08 03:08+0200\n"
 | 
				
			||||||
 | 
					"PO-Revision-Date: 2014-03-08 03:08+0200\n"
 | 
				
			||||||
 | 
					"Last-Translator: Rolf Ahrenberg\n"
 | 
				
			||||||
 | 
					"Language-Team: Finnish <vdr@linuxtv.org>\n"
 | 
				
			||||||
 | 
					"Language: fi\n"
 | 
				
			||||||
 | 
					"MIME-Version: 1.0\n"
 | 
				
			||||||
 | 
					"Content-Type: text/plain; charset=UTF-8\n"
 | 
				
			||||||
 | 
					"Content-Transfer-Encoding: 8bit\n"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "PAT (0x00)"
 | 
				
			||||||
 | 
					msgstr "PAT (0x00)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "NIT (0x40)"
 | 
				
			||||||
 | 
					msgstr "NIT (0x40)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "SDT (0x42)"
 | 
				
			||||||
 | 
					msgstr "SDT (0x42)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "EIT (0x4E/0x4F)"
 | 
				
			||||||
 | 
					msgstr "EIT (0x4E/0x4F)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "EIT (0x5X)"
 | 
				
			||||||
 | 
					msgstr "EIT (0x5X)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "EIT (0x6X)"
 | 
				
			||||||
 | 
					msgstr "EIT (0x6X)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "TDT (0x70)"
 | 
				
			||||||
 | 
					msgstr "TDT (0x70)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "SAT>IP Devices"
 | 
				
			||||||
 | 
					msgstr "SAT>IP-laitteet"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "SAT>IP Device"
 | 
				
			||||||
 | 
					msgstr "SAT>IP-laite"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Button$Scan"
 | 
				
			||||||
 | 
					msgstr "Kanavahaku"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "SAT>IP Information"
 | 
				
			||||||
 | 
					msgstr "SAT>IP-tiedot"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "General"
 | 
				
			||||||
 | 
					msgstr "Yleiset"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Pids"
 | 
				
			||||||
 | 
					msgstr "Pidit"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Filters"
 | 
				
			||||||
 | 
					msgstr "Suodattimet"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Bits/bytes"
 | 
				
			||||||
 | 
					msgstr "Bitit/tavut"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "SAT>IP information not available!"
 | 
				
			||||||
 | 
					msgstr "SAT>IP-tietoja ei saatavilla!"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Enable EPG scanning"
 | 
				
			||||||
 | 
					msgstr "Käytä ohjelmaoppaan taustapäivitystä"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid ""
 | 
				
			||||||
 | 
					"Define whether the EPG background scanning shall be used.\n"
 | 
				
			||||||
 | 
					"\n"
 | 
				
			||||||
 | 
					"This setting disables the automatic EIT scanning functionality for all SAT>IP devices."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					"Määrittele ohjelmaoppaan taustapäivityksen olemassaolo.\n"
 | 
				
			||||||
 | 
					"\n"
 | 
				
			||||||
 | 
					"Tällä asetuksella saadaan otettua automaattinen EIT-datan päivitys pois päältä kaikilta SAT>IP-laitteilta."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Disabled filters"
 | 
				
			||||||
 | 
					msgstr "Käytöstä poistetut suodattimet"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "none"
 | 
				
			||||||
 | 
					msgstr "tyhjä"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid ""
 | 
				
			||||||
 | 
					"Define number of section filters to be disabled.\n"
 | 
				
			||||||
 | 
					"\n"
 | 
				
			||||||
 | 
					"Certain section filters might cause some unwanted behaviour to VDR such as time being falsely synchronized. By black-listing the filters here useful section data can be left intact for VDR to process."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					"Määrittele käytöstä poistettavien suodattimien lukumäärä sektioille.\n"
 | 
				
			||||||
 | 
					"\n"
 | 
				
			||||||
 | 
					"Tietyt sektiot saattavat aiheuttaa virheellistä toimintaa VDR:ssä, esimerkiksi asettavat väärän kellonajan, ja näiden poistaminen auttaa VDR:ää toimimaan kunnolla jäljelle jäävien sektioiden kanssa."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Filter"
 | 
				
			||||||
 | 
					msgstr "Suodatin"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Define an ill-behaving filter to be blacklisted."
 | 
				
			||||||
 | 
					msgstr "Määrittele käytöstä poistettava suodatin, joka lisätään mustalle listalle."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Active SAT>IP devices:"
 | 
				
			||||||
 | 
					msgstr "Aktiiviset SAT>IP-laitteet:"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Help"
 | 
				
			||||||
 | 
					msgstr "Opaste"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "off"
 | 
				
			||||||
 | 
					msgstr "pois"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "on"
 | 
				
			||||||
 | 
					msgstr "päällä"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "auto"
 | 
				
			||||||
 | 
					msgstr "auto"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "SISO"
 | 
				
			||||||
 | 
					msgstr "SISO"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "MISO"
 | 
				
			||||||
 | 
					msgstr "MISO"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Nid"
 | 
				
			||||||
 | 
					msgstr "Verkko-ID"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Tid"
 | 
				
			||||||
 | 
					msgstr "Lähete-ID"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Rid"
 | 
				
			||||||
 | 
					msgstr "Radio-ID"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "SignalSource"
 | 
				
			||||||
 | 
					msgstr "Signaalin lähde"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "PilotTones"
 | 
				
			||||||
 | 
					msgstr "Pilottiäänet"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "T2SystemId"
 | 
				
			||||||
 | 
					msgstr "T2-järjestelmä"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "SISO/MISO"
 | 
				
			||||||
 | 
					msgstr "SISO/MISO"
 | 
				
			||||||
							
								
								
									
										291
									
								
								satip.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										291
									
								
								satip.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,291 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * satip.c: A plugin for the Video Disk Recorder
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * See the README file for copyright information and how to reach the author.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <getopt.h>
 | 
				
			||||||
 | 
					#include <vdr/plugin.h>
 | 
				
			||||||
 | 
					#include "common.h"
 | 
				
			||||||
 | 
					#include "config.h"
 | 
				
			||||||
 | 
					#include "device.h"
 | 
				
			||||||
 | 
					#include "discover.h"
 | 
				
			||||||
 | 
					#include "setup.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(APIVERSNUM) && APIVERSNUM < 20000
 | 
				
			||||||
 | 
					#error "VDR-2.0.0 API version or greater is required!"
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GITVERSION
 | 
				
			||||||
 | 
					#define GITVERSION ""
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					       const char VERSION[]     = "0.0.1" GITVERSION;
 | 
				
			||||||
 | 
					static const char DESCRIPTION[] = trNOOP("SAT>IP Devices");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class cPluginSatip : public cPlugin {
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  unsigned int deviceCountM;
 | 
				
			||||||
 | 
					  cSatipDiscover *discoverM;
 | 
				
			||||||
 | 
					  int ParseFilters(const char *valueP, int *filtersP);
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  cPluginSatip(void);
 | 
				
			||||||
 | 
					  virtual ~cPluginSatip();
 | 
				
			||||||
 | 
					  virtual const char *Version(void) { return VERSION; }
 | 
				
			||||||
 | 
					  virtual const char *Description(void) { return tr(DESCRIPTION); }
 | 
				
			||||||
 | 
					  virtual const char *CommandLineHelp(void);
 | 
				
			||||||
 | 
					  virtual bool ProcessArgs(int argc, char *argv[]);
 | 
				
			||||||
 | 
					  virtual bool Initialize(void);
 | 
				
			||||||
 | 
					  virtual bool Start(void);
 | 
				
			||||||
 | 
					  virtual void Stop(void);
 | 
				
			||||||
 | 
					  virtual void Housekeeping(void);
 | 
				
			||||||
 | 
					  virtual void MainThreadHook(void);
 | 
				
			||||||
 | 
					  virtual cString Active(void);
 | 
				
			||||||
 | 
					  virtual time_t WakeupTime(void);
 | 
				
			||||||
 | 
					  virtual const char *MainMenuEntry(void) { return NULL; }
 | 
				
			||||||
 | 
					  virtual cOsdObject *MainMenuAction(void);
 | 
				
			||||||
 | 
					  virtual cMenuSetupPage *SetupMenu(void);
 | 
				
			||||||
 | 
					  virtual bool SetupParse(const char *Name, const char *Value);
 | 
				
			||||||
 | 
					  virtual bool Service(const char *Id, void *Data = NULL);
 | 
				
			||||||
 | 
					  virtual const char **SVDRPHelpPages(void);
 | 
				
			||||||
 | 
					  virtual cString SVDRPCommand(const char *Command, const char *Option, int &ReplyCode);
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cPluginSatip::cPluginSatip(void)
 | 
				
			||||||
 | 
					: deviceCountM(1),
 | 
				
			||||||
 | 
					  discoverM(NULL)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cPluginSatip::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  // Initialize any member variables here.
 | 
				
			||||||
 | 
					  // DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL
 | 
				
			||||||
 | 
					  // VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cPluginSatip::~cPluginSatip()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cPluginSatip::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  // Clean up after yourself!
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char *cPluginSatip::CommandLineHelp(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cPluginSatip::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  // Return a string that describes all known command line options.
 | 
				
			||||||
 | 
					  return "  -d <num>, --devices=<number> number of devices to be created\n";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cPluginSatip::ProcessArgs(int argc, char *argv[])
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cPluginSatip::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  // Implement command line argument processing here if applicable.
 | 
				
			||||||
 | 
					  static const struct option long_options[] = {
 | 
				
			||||||
 | 
					    { "devices", required_argument, NULL, 'd' },
 | 
				
			||||||
 | 
					    { NULL,      no_argument,       NULL,  0  }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int c;
 | 
				
			||||||
 | 
					  while ((c = getopt_long(argc, argv, "d:", long_options, NULL)) != -1) {
 | 
				
			||||||
 | 
					    switch (c) {
 | 
				
			||||||
 | 
					      case 'd':
 | 
				
			||||||
 | 
					           deviceCountM = atoi(optarg);
 | 
				
			||||||
 | 
					           break;
 | 
				
			||||||
 | 
					      default:
 | 
				
			||||||
 | 
					           return false;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cPluginSatip::Initialize(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cPluginSatip::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  // Initialize any background activities the plugin shall perform.
 | 
				
			||||||
 | 
					  if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK)
 | 
				
			||||||
 | 
					     error("Unable to initialize CURL");
 | 
				
			||||||
 | 
					  SatipConfig.SetConfigDirectory(cPlugin::ResourceDirectory(PLUGIN_NAME_I18N));
 | 
				
			||||||
 | 
					  cSatipDiscover::GetInstance()->Initialize();
 | 
				
			||||||
 | 
					  return cSatipDevice::Initialize(deviceCountM);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cPluginSatip::Start(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cPluginSatip::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  // Start any background activities the plugin shall perform.
 | 
				
			||||||
 | 
					  curl_version_info_data *data = curl_version_info(CURLVERSION_NOW);
 | 
				
			||||||
 | 
					  cString info = cString::sprintf("Using CURL %s", data->version);
 | 
				
			||||||
 | 
					  for (int i = 0; data->protocols[i]; ++i) {
 | 
				
			||||||
 | 
					      // Supported protocols: HTTP(S), RTSP, FILE
 | 
				
			||||||
 | 
					      if (startswith(data->protocols[i], "rtsp"))
 | 
				
			||||||
 | 
					         info = cString::sprintf("%s %s", *info, data->protocols[i]);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					  info("%s", *info);
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cPluginSatip::Stop(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cPluginSatip::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  // Stop any background activities the plugin is performing.
 | 
				
			||||||
 | 
					  cSatipDevice::Shutdown();
 | 
				
			||||||
 | 
					  cSatipDiscover::GetInstance()->Destroy();
 | 
				
			||||||
 | 
					  curl_global_cleanup();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cPluginSatip::Housekeeping(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cPluginSatip::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  // Perform any cleanup or other regular tasks.
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cPluginSatip::MainThreadHook(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cPluginSatip::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  // Perform actions in the context of the main program thread.
 | 
				
			||||||
 | 
					  // WARNING: Use with great care - see PLUGINS.html!
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cString cPluginSatip::Active(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cPluginSatip::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  // Return a message string if shutdown should be postponed
 | 
				
			||||||
 | 
					  return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					time_t cPluginSatip::WakeupTime(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cPluginSatip::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  // Return custom wakeup time for shutdown script
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cOsdObject *cPluginSatip::MainMenuAction(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cPluginSatip::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  // Perform the action when selected from the main VDR menu.
 | 
				
			||||||
 | 
					  return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cMenuSetupPage *cPluginSatip::SetupMenu(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cPluginSatip::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  // Return a setup menu in case the plugin supports one.
 | 
				
			||||||
 | 
					  return new cSatipPluginSetup();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int cPluginSatip::ParseFilters(const char *valueP, int *filtersP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cPluginSatip::%s(%s)", __FUNCTION__, valueP);
 | 
				
			||||||
 | 
					  char buffer[256];
 | 
				
			||||||
 | 
					  int n = 0;
 | 
				
			||||||
 | 
					  while (valueP && *valueP && (n < SECTION_FILTER_TABLE_SIZE)) {
 | 
				
			||||||
 | 
					    strn0cpy(buffer, valueP, sizeof(buffer));
 | 
				
			||||||
 | 
					    int i = atoi(buffer);
 | 
				
			||||||
 | 
					    //debug("cPluginSatip::%s(): filters[%d]=%d", __FUNCTION__, n, i);
 | 
				
			||||||
 | 
					    if (i >= 0)
 | 
				
			||||||
 | 
					       filtersP[n++] = i;
 | 
				
			||||||
 | 
					    if ((valueP = strchr(valueP, ' ')) != NULL)
 | 
				
			||||||
 | 
					       valueP++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  return n;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cPluginSatip::SetupParse(const char *nameP, const char *valueP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cPluginSatip::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  // Parse your own setup parameters and store their values.
 | 
				
			||||||
 | 
					  if (!strcasecmp(nameP, "EnableEITScan"))
 | 
				
			||||||
 | 
					     SatipConfig.SetEITScan(atoi(valueP));
 | 
				
			||||||
 | 
					  else if (!strcasecmp(nameP, "DisabledFilters")) {
 | 
				
			||||||
 | 
					     int DisabledFilters[SECTION_FILTER_TABLE_SIZE];
 | 
				
			||||||
 | 
					     for (unsigned int i = 0; i < ARRAY_SIZE(DisabledFilters); ++i)
 | 
				
			||||||
 | 
					         DisabledFilters[i] = -1;
 | 
				
			||||||
 | 
					     unsigned int DisabledFiltersCount = ParseFilters(valueP, DisabledFilters);
 | 
				
			||||||
 | 
					     for (unsigned int i = 0; i < DisabledFiltersCount; ++i)
 | 
				
			||||||
 | 
					         SatipConfig.SetDisabledFilters(i, DisabledFilters[i]);
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					     return false;
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cPluginSatip::Service(const char *idP, void *dataP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cPluginSatip::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char **cPluginSatip::SVDRPHelpPages(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cPluginSatip::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  static const char *HelpPages[] = {
 | 
				
			||||||
 | 
					    "INFO [ <page> ] [ <card index> ]\n"
 | 
				
			||||||
 | 
					    "    Prints SAT>IP device information and statistics.\n"
 | 
				
			||||||
 | 
					    "    The output can be narrowed using optional \"page\""
 | 
				
			||||||
 | 
					    "    option: 1=general 2=pids 3=section filters.\n",
 | 
				
			||||||
 | 
					    "MODE\n"
 | 
				
			||||||
 | 
					    "    Toggles between bit or byte information mode.\n",
 | 
				
			||||||
 | 
					    "LIST\n"
 | 
				
			||||||
 | 
					    "    Lists active SAT>IP servers.\n",
 | 
				
			||||||
 | 
					    "CONT\n"
 | 
				
			||||||
 | 
					    "    Shows SAT>IP device count.\n",
 | 
				
			||||||
 | 
					    NULL
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  return HelpPages;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cString cPluginSatip::SVDRPCommand(const char *commandP, const char *optionP, int &replyCodeP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cPluginSatip::%s(%s, %s)", __FUNCTION__, commandP, optionP);
 | 
				
			||||||
 | 
					  if (strcasecmp(commandP, "INFO") == 0) {
 | 
				
			||||||
 | 
					     int index = cDevice::ActualDevice()->CardIndex();
 | 
				
			||||||
 | 
					     int page = SATIP_DEVICE_INFO_ALL;
 | 
				
			||||||
 | 
					     char *opt = strdup(optionP);
 | 
				
			||||||
 | 
					     char *num = skipspace(opt);
 | 
				
			||||||
 | 
					     char *option = num;
 | 
				
			||||||
 | 
					     while (*option && !isspace(*option))
 | 
				
			||||||
 | 
					           ++option;
 | 
				
			||||||
 | 
					     if (*option) {
 | 
				
			||||||
 | 
					        *option = 0;
 | 
				
			||||||
 | 
					        option = skipspace(++option);
 | 
				
			||||||
 | 
					        if (isnumber(option))
 | 
				
			||||||
 | 
					           index = atoi(option);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					     if (isnumber(num)) {
 | 
				
			||||||
 | 
					        page = atoi(num);
 | 
				
			||||||
 | 
					        if ((page < SATIP_DEVICE_INFO_ALL) || (page > SATIP_DEVICE_INFO_FILTERS))
 | 
				
			||||||
 | 
					           page = SATIP_DEVICE_INFO_ALL;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					     free(opt);
 | 
				
			||||||
 | 
					     cSatipDevice *device = cSatipDevice::GetSatipDevice(index);
 | 
				
			||||||
 | 
					     if (device) {
 | 
				
			||||||
 | 
					        return device->GetInformation(page);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					     else {
 | 
				
			||||||
 | 
					        replyCodeP = 550; // Requested action not taken
 | 
				
			||||||
 | 
					        return cString("SAT>IP information not available!");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					  else if (strcasecmp(commandP, "MODE") == 0) {
 | 
				
			||||||
 | 
					     unsigned int mode = !SatipConfig.GetUseBytes();
 | 
				
			||||||
 | 
					     SatipConfig.SetUseBytes(mode);
 | 
				
			||||||
 | 
					     return cString::sprintf("SAT>IP information mode: %s\n", mode ? "bytes" : "bits");
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					  else if (strcasecmp(commandP, "LIST") == 0) {
 | 
				
			||||||
 | 
					     cString list = cSatipDiscover::GetInstance()->GetServerList();
 | 
				
			||||||
 | 
					     if (!isempty(list)) {
 | 
				
			||||||
 | 
					        return list;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					     else {
 | 
				
			||||||
 | 
					        replyCodeP = 550; // Requested action not taken
 | 
				
			||||||
 | 
					        return cString("No SAT>IP devices detected!");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					  else if (strcasecmp(commandP, "CONT") == 0) {
 | 
				
			||||||
 | 
					     return cString::sprintf("SAT>IP device count: %u", cSatipDevice::Count());
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VDRPLUGINCREATOR(cPluginSatip); // Don't touch this!
 | 
				
			||||||
							
								
								
									
										406
									
								
								sectionfilter.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										406
									
								
								sectionfilter.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,406 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * sectionfilter.c: SAT>IP plugin for the Video Disk Recorder
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * See the README file for copyright information and how to reach the author.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "config.h"
 | 
				
			||||||
 | 
					#include "sectionfilter.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cSatipSectionFilter::cSatipSectionFilter(int deviceIndexP, uint16_t pidP, uint8_t tidP, uint8_t maskP)
 | 
				
			||||||
 | 
					: pusiSeenM(0),
 | 
				
			||||||
 | 
					  feedCcM(0),
 | 
				
			||||||
 | 
					  doneqM(0),
 | 
				
			||||||
 | 
					  secBufM(NULL),
 | 
				
			||||||
 | 
					  secBufpM(0),
 | 
				
			||||||
 | 
					  secLenM(0),
 | 
				
			||||||
 | 
					  tsFeedpM(0),
 | 
				
			||||||
 | 
					  pidM(pidP),
 | 
				
			||||||
 | 
					  deviceIndexM(deviceIndexP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipSectionFilter::%s(%d, %d)", __FUNCTION__, deviceIndexM, pidM);
 | 
				
			||||||
 | 
					  int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  memset(secBufBaseM,     0, sizeof(secBufBaseM));
 | 
				
			||||||
 | 
					  memset(filterValueM,    0, sizeof(filterValueM));
 | 
				
			||||||
 | 
					  memset(filterMaskM,     0, sizeof(filterMaskM));
 | 
				
			||||||
 | 
					  memset(filterModeM,     0, sizeof(filterModeM));
 | 
				
			||||||
 | 
					  memset(maskAndModeM,    0, sizeof(maskAndModeM));
 | 
				
			||||||
 | 
					  memset(maskAndNotModeM, 0, sizeof(maskAndNotModeM));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  filterValueM[0] = tidP;
 | 
				
			||||||
 | 
					  filterMaskM[0] = maskP;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Invert the filter
 | 
				
			||||||
 | 
					  for (i = 0; i < DMX_MAX_FILTER_SIZE; ++i)
 | 
				
			||||||
 | 
					      filterValueM[i] ^= 0xFF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint8_t mask, mode, doneq = 0;
 | 
				
			||||||
 | 
					  for (i = 0; i < DMX_MAX_FILTER_SIZE; ++i) {
 | 
				
			||||||
 | 
					      mode = filterModeM[i];
 | 
				
			||||||
 | 
					      mask = filterMaskM[i];
 | 
				
			||||||
 | 
					      maskAndModeM[i] = (uint8_t)(mask & mode);
 | 
				
			||||||
 | 
					      maskAndNotModeM[i] = (uint8_t)(mask & ~mode);
 | 
				
			||||||
 | 
					      doneq |= maskAndNotModeM[i];
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					  doneqM = doneq ? 1 : 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Create sockets
 | 
				
			||||||
 | 
					  socketM[0] = socketM[1] = -1;
 | 
				
			||||||
 | 
					  if (socketpair(AF_UNIX, SOCK_DGRAM, 0, socketM) != 0) {
 | 
				
			||||||
 | 
					     char tmp[64];
 | 
				
			||||||
 | 
					     error("Opening section filter sockets failed (device=%d pid=%d): %s", deviceIndexM, pidM, strerror_r(errno, tmp, sizeof(tmp)));
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					  else if ((fcntl(socketM[0], F_SETFL, O_NONBLOCK) != 0) || (fcntl(socketM[1], F_SETFL, O_NONBLOCK) != 0)) {
 | 
				
			||||||
 | 
					     char tmp[64];
 | 
				
			||||||
 | 
					     error("Setting section filter socket to non-blocking mode failed (device=%d pid=%d): %s", deviceIndexM, pidM, strerror_r(errno, tmp, sizeof(tmp)));
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cSatipSectionFilter::~cSatipSectionFilter()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipSectionFilter::%s(%d, %d)", __FUNCTION__, deviceIndexM, pidM);
 | 
				
			||||||
 | 
					  int tmp = socketM[1];
 | 
				
			||||||
 | 
					  socketM[1] = -1;
 | 
				
			||||||
 | 
					  if (tmp >= 0)
 | 
				
			||||||
 | 
					     close(tmp);
 | 
				
			||||||
 | 
					  tmp = socketM[0];
 | 
				
			||||||
 | 
					  socketM[0] = -1;
 | 
				
			||||||
 | 
					  if (tmp >= 0)
 | 
				
			||||||
 | 
					     close(tmp);
 | 
				
			||||||
 | 
					  secBufM = NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline uint16_t cSatipSectionFilter::GetLength(const uint8_t *dataP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  return (uint16_t)(3 + ((dataP[1] & 0x0f) << 8) + dataP[2]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipSectionFilter::New(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  tsFeedpM = secBufpM = secLenM = 0;
 | 
				
			||||||
 | 
					  secBufM = secBufBaseM;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int cSatipSectionFilter::Filter(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (secBufM) {
 | 
				
			||||||
 | 
					     int i;
 | 
				
			||||||
 | 
					     uint8_t neq = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     for (i = 0; i < DMX_MAX_FILTER_SIZE; ++i) {
 | 
				
			||||||
 | 
					         uint8_t calcxor = (uint8_t)(filterValueM[i] ^ secBufM[i]);
 | 
				
			||||||
 | 
					         if (maskAndModeM[i] & calcxor)
 | 
				
			||||||
 | 
					            return 0;
 | 
				
			||||||
 | 
					         neq |= (maskAndNotModeM[i] & calcxor);
 | 
				
			||||||
 | 
					         }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     if (doneqM && !neq)
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     // There is no data in the read socket, more can be written
 | 
				
			||||||
 | 
					     if ((socketM[0] >= 0) && (socketM[1] >= 0) /*&& !select_single_desc(socketM[0], 0, false)*/) {
 | 
				
			||||||
 | 
					        ssize_t len = write(socketM[1], secBufM, secLenM);
 | 
				
			||||||
 | 
					        ERROR_IF(len < 0, "write()");
 | 
				
			||||||
 | 
					        // Update statistics
 | 
				
			||||||
 | 
					        AddSectionStatistic(len, 1);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline int cSatipSectionFilter::Feed(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (Filter() < 0)
 | 
				
			||||||
 | 
					     return -1;
 | 
				
			||||||
 | 
					  secLenM = 0;
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int cSatipSectionFilter::CopyDump(const uint8_t *bufP, uint8_t lenP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  uint16_t limit, seclen, n;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (tsFeedpM >= DMX_MAX_SECFEED_SIZE)
 | 
				
			||||||
 | 
					     return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (tsFeedpM + lenP > DMX_MAX_SECFEED_SIZE)
 | 
				
			||||||
 | 
					     lenP = (uint8_t)(DMX_MAX_SECFEED_SIZE - tsFeedpM);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (lenP <= 0)
 | 
				
			||||||
 | 
					     return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  memcpy(secBufBaseM + tsFeedpM, bufP, lenP);
 | 
				
			||||||
 | 
					  tsFeedpM = uint16_t(tsFeedpM + lenP);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  limit = tsFeedpM;
 | 
				
			||||||
 | 
					  if (limit > DMX_MAX_SECFEED_SIZE)
 | 
				
			||||||
 | 
					     return -1; // internal error should never happen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Always set secbuf
 | 
				
			||||||
 | 
					  secBufM = secBufBaseM + secBufpM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (n = 0; secBufpM + 2 < limit; ++n) {
 | 
				
			||||||
 | 
					      seclen = GetLength(secBufM);
 | 
				
			||||||
 | 
					      if ((seclen <= 0) || (seclen > DMX_MAX_SECTION_SIZE) || ((seclen + secBufpM) > limit))
 | 
				
			||||||
 | 
					         return 0;
 | 
				
			||||||
 | 
					      secLenM = seclen;
 | 
				
			||||||
 | 
					      if (pusiSeenM)
 | 
				
			||||||
 | 
					         Feed();
 | 
				
			||||||
 | 
					      secBufpM = uint16_t(secBufpM + seclen);
 | 
				
			||||||
 | 
					      secBufM += seclen;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipSectionFilter::Process(const uint8_t* dataP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (dataP[0] != TS_SYNC_BYTE)
 | 
				
			||||||
 | 
					     return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Stop if not the PID this filter is looking for
 | 
				
			||||||
 | 
					  if (ts_pid(dataP) != pidM)
 | 
				
			||||||
 | 
					     return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint8_t count = payload(dataP);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Check if no payload or out of range
 | 
				
			||||||
 | 
					  if (count == 0)
 | 
				
			||||||
 | 
					     return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Payload start
 | 
				
			||||||
 | 
					  uint8_t p = (uint8_t)(TS_SIZE - count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint8_t cc = (uint8_t)(dataP[3] & 0x0f);
 | 
				
			||||||
 | 
					  int ccok = ((feedCcM + 1) & 0x0f) == cc;
 | 
				
			||||||
 | 
					  feedCcM = cc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int dc_i = 0;
 | 
				
			||||||
 | 
					  if (dataP[3] & 0x20) {
 | 
				
			||||||
 | 
					     // Adaption field present, check for discontinuity_indicator
 | 
				
			||||||
 | 
					     if ((dataP[4] > 0) && (dataP[5] & 0x80))
 | 
				
			||||||
 | 
					        dc_i = 1;
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!ccok || dc_i) {
 | 
				
			||||||
 | 
					     // Discontinuity detected. Reset pusiSeenM = 0 to
 | 
				
			||||||
 | 
					     // stop feeding of suspicious data until next PUSI=1 arrives
 | 
				
			||||||
 | 
					     pusiSeenM = 0;
 | 
				
			||||||
 | 
					     New();
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (dataP[1] & 0x40) {
 | 
				
			||||||
 | 
					     // PUSI=1 (is set), section boundary is here
 | 
				
			||||||
 | 
					     if (count > 1 && dataP[p] < count) {
 | 
				
			||||||
 | 
					        const uint8_t *before = &dataP[p + 1];
 | 
				
			||||||
 | 
					        uint8_t before_len = dataP[p];
 | 
				
			||||||
 | 
					        const uint8_t *after = &before[before_len];
 | 
				
			||||||
 | 
					        uint8_t after_len = (uint8_t)(count - 1 - before_len);
 | 
				
			||||||
 | 
					        CopyDump(before, before_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Before start of new section, set pusiSeenM = 1
 | 
				
			||||||
 | 
					        pusiSeenM = 1;
 | 
				
			||||||
 | 
					        New();
 | 
				
			||||||
 | 
					        CopyDump(after, after_len);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					  else {
 | 
				
			||||||
 | 
					     // PUSI=0 (is not set), no section boundary
 | 
				
			||||||
 | 
					     CopyDump(&dataP[p], count);
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cSatipSectionFilterHandler::cSatipSectionFilterHandler(int deviceIndexP, unsigned int bufferLenP)
 | 
				
			||||||
 | 
					: cThread("SAT>IP section handler", true),
 | 
				
			||||||
 | 
					  mutexM(),
 | 
				
			||||||
 | 
					  deviceIndexM(deviceIndexP),
 | 
				
			||||||
 | 
					  processedM(false),
 | 
				
			||||||
 | 
					  ringBufferM(new cRingBufferLinear(bufferLenP, TS_SIZE, false, *cString::sprintf("SAT>IP SECTION HANDLER %d", deviceIndexP)))
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipSectionFilterHandler::%s(%d)", __FUNCTION__, deviceIndexM);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Initialize filter pointers
 | 
				
			||||||
 | 
					  memset(filtersM, 0, sizeof(filtersM));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Create input buffer
 | 
				
			||||||
 | 
					  if (ringBufferM) {
 | 
				
			||||||
 | 
					     ringBufferM->SetTimeouts(100, 100);
 | 
				
			||||||
 | 
					     ringBufferM->SetIoThrottle();
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					     error("Failed to allocate buffer for section filter handler (device=%d): ", deviceIndexM);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Start();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cSatipSectionFilterHandler::~cSatipSectionFilterHandler()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipSectionFilterHandler::%s(%d)", __FUNCTION__, deviceIndexM);
 | 
				
			||||||
 | 
					  Stop();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  DELETE_POINTER(ringBufferM);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Destroy all filters
 | 
				
			||||||
 | 
					  cMutexLock MutexLock(&mutexM);
 | 
				
			||||||
 | 
					  for (int i = 0; i < eMaxSecFilterCount; ++i)
 | 
				
			||||||
 | 
					      Delete(i);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cSatipSectionFilterHandler::Stop(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipSectionFilterHandler::%s(%d): entering", __FUNCTION__, deviceIndexM);
 | 
				
			||||||
 | 
					  // Stop thread
 | 
				
			||||||
 | 
					  if (Running())
 | 
				
			||||||
 | 
					     Cancel(3);
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipSectionFilterHandler::Action(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipSectionFilterHandler::%s(%d): entering", __FUNCTION__, deviceIndexM);
 | 
				
			||||||
 | 
					  // Do the thread loop
 | 
				
			||||||
 | 
					  while (Running()) {
 | 
				
			||||||
 | 
					        // Read one TS packet
 | 
				
			||||||
 | 
					        if (ringBufferM) {
 | 
				
			||||||
 | 
					           int len = 0;
 | 
				
			||||||
 | 
					           if (processedM) {
 | 
				
			||||||
 | 
					              ringBufferM->Del(TS_SIZE);
 | 
				
			||||||
 | 
					              processedM = false;
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					           uchar *p = ringBufferM->Get(len);
 | 
				
			||||||
 | 
					           if (p && (len >= TS_SIZE)) {
 | 
				
			||||||
 | 
					              if (*p != TS_SYNC_BYTE) {
 | 
				
			||||||
 | 
					                 for (int i = 1; i < len; ++i) {
 | 
				
			||||||
 | 
					                     if (p[i] == TS_SYNC_BYTE) {
 | 
				
			||||||
 | 
					                        len = i;
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                     }
 | 
				
			||||||
 | 
					                 ringBufferM->Del(len);
 | 
				
			||||||
 | 
					                 debug("cSatipSectionFilterHandler::%s(%d): Skipped %d bytes to sync on TS packet", __FUNCTION__, deviceIndexM, len);
 | 
				
			||||||
 | 
					                 continue;
 | 
				
			||||||
 | 
					                 }
 | 
				
			||||||
 | 
					              // Process TS packet through all filters
 | 
				
			||||||
 | 
					              mutexM.Lock();
 | 
				
			||||||
 | 
					              for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
 | 
				
			||||||
 | 
					                  if (filtersM[i])
 | 
				
			||||||
 | 
					                     filtersM[i]->Process(p);
 | 
				
			||||||
 | 
					                  }
 | 
				
			||||||
 | 
					              mutexM.Unlock();
 | 
				
			||||||
 | 
					              processedM = true;
 | 
				
			||||||
 | 
					              continue;
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					           }
 | 
				
			||||||
 | 
					        cCondWait::SleepMs(10); // to avoid busy loop and reduce cpu load
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					  debug("cSatipSectionFilterHandler::%s(%d): exiting", __FUNCTION__, deviceIndexM);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cString cSatipSectionFilterHandler::GetInformation(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipSectionFilterHandler::%s(%d)", __FUNCTION__, deviceIndexM);
 | 
				
			||||||
 | 
					  // loop through active section filters
 | 
				
			||||||
 | 
					  cMutexLock MutexLock(&mutexM);
 | 
				
			||||||
 | 
					  cString s = "";
 | 
				
			||||||
 | 
					  unsigned int count = 0;
 | 
				
			||||||
 | 
					  for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
 | 
				
			||||||
 | 
					      if (filtersM[i]) {
 | 
				
			||||||
 | 
					         s = cString::sprintf("%sFilter %d: %s Pid=0x%02X (%s)\n", *s, i,
 | 
				
			||||||
 | 
					                              *filtersM[i]->GetSectionStatistic(), filtersM[i]->GetPid(),
 | 
				
			||||||
 | 
					                              id_pid(filtersM[i]->GetPid()));
 | 
				
			||||||
 | 
					         if (++count > SATIP_STATS_ACTIVE_FILTERS_COUNT)
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					         }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					  return s;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cSatipSectionFilterHandler::Delete(unsigned int indexP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipSectionFilterHandler::%s(%d): index=%d", __FUNCTION__, deviceIndexM, indexP);
 | 
				
			||||||
 | 
					  if ((indexP < eMaxSecFilterCount) && filtersM[indexP]) {
 | 
				
			||||||
 | 
					     //debug("cSatipSectionFilterHandler::%s(%d): found %d", __FUNCTION__, deviceIndexM, indexP);
 | 
				
			||||||
 | 
					     cSatipSectionFilter *tmp = filtersM[indexP];
 | 
				
			||||||
 | 
					     filtersM[indexP] = NULL;
 | 
				
			||||||
 | 
					     delete tmp;
 | 
				
			||||||
 | 
					     return true;
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					  return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cSatipSectionFilterHandler::IsBlackListed(u_short pidP, u_char tidP, u_char maskP) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipSectionFilterHandler::%s(%d): pid=%d tid=%02X mask=%02X", __FUNCTION__, deviceIndexM, pidP, tidP, maskP);
 | 
				
			||||||
 | 
					  // loop through section filter table
 | 
				
			||||||
 | 
					  for (int i = 0; i < SECTION_FILTER_TABLE_SIZE; ++i) {
 | 
				
			||||||
 | 
					      int index = SatipConfig.GetDisabledFilters(i);
 | 
				
			||||||
 | 
					      // Check if matches
 | 
				
			||||||
 | 
					      if ((index >= 0) && (index < SECTION_FILTER_TABLE_SIZE) &&
 | 
				
			||||||
 | 
					          (section_filter_table[index].pid == pidP) && (section_filter_table[index].tid == tidP) &&
 | 
				
			||||||
 | 
					          (section_filter_table[index].mask == maskP)) {
 | 
				
			||||||
 | 
					         //debug("cSatipSectionFilterHandler::%s(%d): found %s", __FUNCTION__, deviceIndexM, section_filter_table[index].description);
 | 
				
			||||||
 | 
					         return true;
 | 
				
			||||||
 | 
					         }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					  return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int cSatipSectionFilterHandler::Open(u_short pidP, u_char tidP, u_char maskP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  // Lock
 | 
				
			||||||
 | 
					  cMutexLock MutexLock(&mutexM);
 | 
				
			||||||
 | 
					  // Blacklist check, refuse certain filters
 | 
				
			||||||
 | 
					  if (IsBlackListed(pidP, tidP, maskP))
 | 
				
			||||||
 | 
					     return -1;
 | 
				
			||||||
 | 
					  // Search the next free filter slot
 | 
				
			||||||
 | 
					  for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
 | 
				
			||||||
 | 
					      if (!filtersM[i]) {
 | 
				
			||||||
 | 
					         filtersM[i] = new cSatipSectionFilter(deviceIndexM, pidP, tidP, maskP);
 | 
				
			||||||
 | 
					         //debug("cSatipSectionFilterHandler::%s(%d): pid=%d tid=%02X mask=%02X handle=%d index=%u", __FUNCTION__, deviceIndexM, pidP, tidP, maskP, filtersM[i]->GetFd(), i);
 | 
				
			||||||
 | 
					         return filtersM[i]->GetFd();
 | 
				
			||||||
 | 
					         }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					  // No free filter slot found
 | 
				
			||||||
 | 
					  return -1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipSectionFilterHandler::Close(int handleP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  // Lock
 | 
				
			||||||
 | 
					  cMutexLock MutexLock(&mutexM);
 | 
				
			||||||
 | 
					  // Search the filter for deletion
 | 
				
			||||||
 | 
					  for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
 | 
				
			||||||
 | 
					      if (filtersM[i] && (handleP == filtersM[i]->GetFd())) {
 | 
				
			||||||
 | 
					         //debug("cSatipSectionFilterHandler::%s(%d): pid=%d handle=%d index=%u", __FUNCTION__, deviceIndexM, filtersM[i]->GetPid(), filtersM[i]->GetFd(), i);
 | 
				
			||||||
 | 
					         Delete(i);
 | 
				
			||||||
 | 
					         break;
 | 
				
			||||||
 | 
					         }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int cSatipSectionFilterHandler::GetPid(int handleP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  // Lock
 | 
				
			||||||
 | 
					  cMutexLock MutexLock(&mutexM);
 | 
				
			||||||
 | 
					  // Search the filter for data
 | 
				
			||||||
 | 
					  for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
 | 
				
			||||||
 | 
					      if (filtersM[i] && (handleP == filtersM[i]->GetFd())) {
 | 
				
			||||||
 | 
					         //debug("cSatipSectionFilterHandler::%s(%d): pid=%d handle=%d index=%u", __FUNCTION__, deviceIndexM, filtersM[i]->GetPid(), filtersM[i]->GetFd(), i);
 | 
				
			||||||
 | 
					         return filtersM[i]->GetPid();
 | 
				
			||||||
 | 
					         }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					  return -1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipSectionFilterHandler::Write(uchar *bufferP, int lengthP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipSectionFilterHandler::%s(%d): length=%d", __FUNCTION__, deviceIndexM, lengthP);
 | 
				
			||||||
 | 
					  // Fill up the buffer
 | 
				
			||||||
 | 
					  if (ringBufferM) {
 | 
				
			||||||
 | 
					     int len = ringBufferM->Put(bufferP, lengthP);
 | 
				
			||||||
 | 
					     if (len != lengthP)
 | 
				
			||||||
 | 
					        ringBufferM->ReportOverflow(lengthP - len);
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										91
									
								
								sectionfilter.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								sectionfilter.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,91 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * sectionfilter.h: SAT>IP plugin for the Video Disk Recorder
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * See the README file for copyright information and how to reach the author.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __SATIP_SECTIONFILTER_H
 | 
				
			||||||
 | 
					#define __SATIP_SECTIONFILTER_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __FreeBSD__
 | 
				
			||||||
 | 
					#include <sys/socket.h>
 | 
				
			||||||
 | 
					#endif // __FreeBSD__
 | 
				
			||||||
 | 
					#include <vdr/device.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "common.h"
 | 
				
			||||||
 | 
					#include "statistics.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class cSatipSectionFilter : public cSatipSectionStatistics {
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  enum dmx_limits {
 | 
				
			||||||
 | 
					    DMX_MAX_FILTER_SIZE  = 18,
 | 
				
			||||||
 | 
					    DMX_MAX_SECTION_SIZE = 4096,
 | 
				
			||||||
 | 
					    DMX_MAX_SECFEED_SIZE = (DMX_MAX_SECTION_SIZE + TS_SIZE)
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int pusiSeenM;
 | 
				
			||||||
 | 
					  int feedCcM;
 | 
				
			||||||
 | 
					  int doneqM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint8_t *secBufM;
 | 
				
			||||||
 | 
					  uint8_t secBufBaseM[DMX_MAX_SECFEED_SIZE];
 | 
				
			||||||
 | 
					  uint16_t secBufpM;
 | 
				
			||||||
 | 
					  uint16_t secLenM;
 | 
				
			||||||
 | 
					  uint16_t tsFeedpM;
 | 
				
			||||||
 | 
					  uint16_t pidM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int deviceIndexM;
 | 
				
			||||||
 | 
					  int socketM[2];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint8_t filterValueM[DMX_MAX_FILTER_SIZE];
 | 
				
			||||||
 | 
					  uint8_t filterMaskM[DMX_MAX_FILTER_SIZE];
 | 
				
			||||||
 | 
					  uint8_t filterModeM[DMX_MAX_FILTER_SIZE];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint8_t maskAndModeM[DMX_MAX_FILTER_SIZE];
 | 
				
			||||||
 | 
					  uint8_t maskAndNotModeM[DMX_MAX_FILTER_SIZE];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  inline uint16_t GetLength(const uint8_t *dataP);
 | 
				
			||||||
 | 
					  void New(void);
 | 
				
			||||||
 | 
					  int Filter(void);
 | 
				
			||||||
 | 
					  inline int Feed(void);
 | 
				
			||||||
 | 
					  int CopyDump(const uint8_t *bufP, uint8_t lenP);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  // constructor & destructor
 | 
				
			||||||
 | 
					  cSatipSectionFilter(int deviceIndexP, uint16_t pidP, uint8_t tidP, uint8_t maskP);
 | 
				
			||||||
 | 
					  virtual ~cSatipSectionFilter();
 | 
				
			||||||
 | 
					  void Process(const uint8_t* dataP);
 | 
				
			||||||
 | 
					  int GetFd(void) { return socketM[0]; }
 | 
				
			||||||
 | 
					  uint16_t GetPid(void) const { return pidM; }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class cSatipSectionFilterHandler : public cThread {
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  enum {
 | 
				
			||||||
 | 
					    eMaxSecFilterCount = 32
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  cMutex mutexM;
 | 
				
			||||||
 | 
					  int deviceIndexM;
 | 
				
			||||||
 | 
					  bool processedM;
 | 
				
			||||||
 | 
					  cRingBufferLinear *ringBufferM;
 | 
				
			||||||
 | 
					  cSatipSectionFilter *filtersM[eMaxSecFilterCount];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool Delete(unsigned int indexP);
 | 
				
			||||||
 | 
					  bool IsBlackListed(u_short pidP, u_char tidP, u_char maskP) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					protected:
 | 
				
			||||||
 | 
					  virtual void Action(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  cSatipSectionFilterHandler(int deviceIndexP, unsigned int bufferLenP);
 | 
				
			||||||
 | 
					  virtual ~cSatipSectionFilterHandler();
 | 
				
			||||||
 | 
					  bool Stop(void);
 | 
				
			||||||
 | 
					  cString GetInformation(void);
 | 
				
			||||||
 | 
					  int Open(u_short pidP, u_char tidP, u_char maskP);
 | 
				
			||||||
 | 
					  void Close(int handleP);
 | 
				
			||||||
 | 
					  int GetPid(int handleP);
 | 
				
			||||||
 | 
					  void Write(u_char *bufferP, int lengthP);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // __SATIP_SECTIONFILTER_H
 | 
				
			||||||
							
								
								
									
										335
									
								
								setup.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										335
									
								
								setup.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,335 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * setup.c: SAT>IP plugin for the Video Disk Recorder
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * See the README file for copyright information and how to reach the author.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <vdr/status.h>
 | 
				
			||||||
 | 
					#include <vdr/menu.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "common.h"
 | 
				
			||||||
 | 
					#include "config.h"
 | 
				
			||||||
 | 
					#include "device.h"
 | 
				
			||||||
 | 
					#include "discover.h"
 | 
				
			||||||
 | 
					#include "setup.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// --- cSatipMenuScan ---------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class cSatipMenuScan : public cOsdMenu
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  enum {
 | 
				
			||||||
 | 
					    INFO_TIMEOUT_MS = 2000
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  cString textM;
 | 
				
			||||||
 | 
					  cTimeMs timeoutM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  cSatipMenuScan(cSatipServer *serverP);
 | 
				
			||||||
 | 
					  virtual ~cSatipMenuScan();
 | 
				
			||||||
 | 
					  virtual void Display(void);
 | 
				
			||||||
 | 
					  virtual eOSState ProcessKey(eKeys keyP);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cSatipMenuScan::cSatipMenuScan(cSatipServer *serverP)
 | 
				
			||||||
 | 
					: cOsdMenu(tr("SAT>IP Device")),
 | 
				
			||||||
 | 
					  textM("")
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  SetMenuCategory(mcText);
 | 
				
			||||||
 | 
					  if (serverP) {
 | 
				
			||||||
 | 
					     if (serverP->Model())
 | 
				
			||||||
 | 
					        textM = cString::sprintf("%s\nModel:\t%s", *textM, serverP->Model());
 | 
				
			||||||
 | 
					     if (serverP->Address())
 | 
				
			||||||
 | 
					        textM = cString::sprintf("%s\nAddress:\t%s", *textM, serverP->Address());
 | 
				
			||||||
 | 
					     if (serverP->Description())
 | 
				
			||||||
 | 
					        textM = cString::sprintf("%s\nDescription:\t%s", *textM, serverP->Description());
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					  SetHelp(tr("Button$Scan"), NULL, NULL, NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cSatipMenuScan::~cSatipMenuScan()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipMenuScan::Display(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  cOsdMenu::Display();
 | 
				
			||||||
 | 
					  DisplayMenu()->SetText(textM, true);
 | 
				
			||||||
 | 
					  if (*textM)
 | 
				
			||||||
 | 
					     cStatus::MsgOsdTextItem(textM);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					eOSState cSatipMenuScan::ProcessKey(eKeys keyP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  eOSState state = cOsdMenu::ProcessKey(keyP);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (state == osUnknown) {
 | 
				
			||||||
 | 
					     switch (keyP) {
 | 
				
			||||||
 | 
					       case kOk:  return osBack;
 | 
				
			||||||
 | 
					       case kRed:
 | 
				
			||||||
 | 
					       default:   state = osContinue;
 | 
				
			||||||
 | 
					                  break;
 | 
				
			||||||
 | 
					       }
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					  return state;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// --- cSatipMenuInfo ---------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class cSatipServerItem : public cOsdItem {
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  cSatipServer *serverM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  cSatipServerItem(cSatipServer *serverP);
 | 
				
			||||||
 | 
					  cSatipServer *Server(void) { return serverM; }
 | 
				
			||||||
 | 
					  virtual void SetMenuItem(cSkinDisplayMenu *displayMenuP, int indexP, bool currentP, bool selectableP);
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cSatipServerItem::cSatipServerItem(cSatipServer *serverP)
 | 
				
			||||||
 | 
					: serverM(serverP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  SetSelectable(true);
 | 
				
			||||||
 | 
					  // Must begin with a '#' character!
 | 
				
			||||||
 | 
					  SetText(*cString::sprintf("# %s (%s)\t%s", serverM->Address(), serverM->Model(), serverM->Description()));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipServerItem::SetMenuItem(cSkinDisplayMenu *displayMenuP, int indexP, bool currentP, bool selectableP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (displayMenuP)
 | 
				
			||||||
 | 
					     displayMenuP->SetItem(Text(), indexP, currentP, selectableP);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// --- cSatipMenuInfo ---------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class cSatipMenuInfo : public cOsdMenu
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  enum {
 | 
				
			||||||
 | 
					    INFO_TIMEOUT_MS = 2000
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  cString textM;
 | 
				
			||||||
 | 
					  cTimeMs timeoutM;
 | 
				
			||||||
 | 
					  unsigned int pageM;
 | 
				
			||||||
 | 
					  void UpdateInfo();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  cSatipMenuInfo();
 | 
				
			||||||
 | 
					  virtual ~cSatipMenuInfo();
 | 
				
			||||||
 | 
					  virtual void Display(void);
 | 
				
			||||||
 | 
					  virtual eOSState ProcessKey(eKeys keyP);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cSatipMenuInfo::cSatipMenuInfo()
 | 
				
			||||||
 | 
					: cOsdMenu(tr("SAT>IP Information")),
 | 
				
			||||||
 | 
					  textM(""),
 | 
				
			||||||
 | 
					  timeoutM(),
 | 
				
			||||||
 | 
					  pageM(SATIP_DEVICE_INFO_GENERAL)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  SetMenuCategory(mcText);
 | 
				
			||||||
 | 
					  timeoutM.Set(INFO_TIMEOUT_MS);
 | 
				
			||||||
 | 
					  UpdateInfo();
 | 
				
			||||||
 | 
					  SetHelp(tr("General"), tr("Pids"), tr("Filters"), tr("Bits/bytes"));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cSatipMenuInfo::~cSatipMenuInfo()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipMenuInfo::UpdateInfo()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  cSatipDevice *device = cSatipDevice::GetSatipDevice(cDevice::ActualDevice()->CardIndex());
 | 
				
			||||||
 | 
					  if (device)
 | 
				
			||||||
 | 
					     textM = device->GetInformation(pageM);
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					     textM = cString(tr("SAT>IP information not available!"));
 | 
				
			||||||
 | 
					  Display();
 | 
				
			||||||
 | 
					  timeoutM.Set(INFO_TIMEOUT_MS);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipMenuInfo::Display(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  cOsdMenu::Display();
 | 
				
			||||||
 | 
					  DisplayMenu()->SetText(textM, true);
 | 
				
			||||||
 | 
					  if (*textM)
 | 
				
			||||||
 | 
					     cStatus::MsgOsdTextItem(textM);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					eOSState cSatipMenuInfo::ProcessKey(eKeys keyP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  switch (int(keyP)) {
 | 
				
			||||||
 | 
					    case kUp|k_Repeat:
 | 
				
			||||||
 | 
					    case kUp:
 | 
				
			||||||
 | 
					    case kDown|k_Repeat:
 | 
				
			||||||
 | 
					    case kDown:
 | 
				
			||||||
 | 
					    case kLeft|k_Repeat:
 | 
				
			||||||
 | 
					    case kLeft:
 | 
				
			||||||
 | 
					    case kRight|k_Repeat:
 | 
				
			||||||
 | 
					    case kRight:
 | 
				
			||||||
 | 
					                  DisplayMenu()->Scroll(NORMALKEY(keyP) == kUp || NORMALKEY(keyP) == kLeft, NORMALKEY(keyP) == kLeft || NORMALKEY(keyP) == kRight);
 | 
				
			||||||
 | 
					                  cStatus::MsgOsdTextItem(NULL, NORMALKEY(keyP) == kUp || NORMALKEY(keyP) == kLeft);
 | 
				
			||||||
 | 
					                  return osContinue;
 | 
				
			||||||
 | 
					    default: break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  eOSState state = cOsdMenu::ProcessKey(keyP);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (state == osUnknown) {
 | 
				
			||||||
 | 
					     switch (keyP) {
 | 
				
			||||||
 | 
					       case kOk:     return osBack;
 | 
				
			||||||
 | 
					       case kRed:    pageM = SATIP_DEVICE_INFO_GENERAL;
 | 
				
			||||||
 | 
					                     UpdateInfo();
 | 
				
			||||||
 | 
					                     break;
 | 
				
			||||||
 | 
					       case kGreen:  pageM = SATIP_DEVICE_INFO_PIDS;
 | 
				
			||||||
 | 
					                     UpdateInfo();
 | 
				
			||||||
 | 
					                     break;
 | 
				
			||||||
 | 
					       case kYellow: pageM = SATIP_DEVICE_INFO_FILTERS;
 | 
				
			||||||
 | 
					                     UpdateInfo();
 | 
				
			||||||
 | 
					                     break;
 | 
				
			||||||
 | 
					       case kBlue:   SatipConfig.SetUseBytes(SatipConfig.GetUseBytes() ? 0 : 1);
 | 
				
			||||||
 | 
					                     UpdateInfo();
 | 
				
			||||||
 | 
					                     break;
 | 
				
			||||||
 | 
					       default:      if (timeoutM.TimedOut())
 | 
				
			||||||
 | 
					                        UpdateInfo();
 | 
				
			||||||
 | 
					                     state = osContinue;
 | 
				
			||||||
 | 
					                     break;
 | 
				
			||||||
 | 
					       }
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					  return state;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// --- cSatipPluginSetup ------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cSatipPluginSetup::cSatipPluginSetup()
 | 
				
			||||||
 | 
					: deviceCountM(0),
 | 
				
			||||||
 | 
					  eitScanM(SatipConfig.GetEITScan()),
 | 
				
			||||||
 | 
					  numDisabledFiltersM(SatipConfig.GetDisabledFiltersCount())
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipPluginSetup::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  if (numDisabledFiltersM > SECTION_FILTER_TABLE_SIZE)
 | 
				
			||||||
 | 
					     numDisabledFiltersM = SECTION_FILTER_TABLE_SIZE;
 | 
				
			||||||
 | 
					  for (int i = 0; i < SECTION_FILTER_TABLE_SIZE; ++i) {
 | 
				
			||||||
 | 
					      disabledFilterIndexesM[i] = SatipConfig.GetDisabledFilters(i);
 | 
				
			||||||
 | 
					      disabledFilterNamesM[i] = tr(section_filter_table[i].description);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					  SetMenuCategory(mcSetupPlugins);
 | 
				
			||||||
 | 
					  Setup();
 | 
				
			||||||
 | 
					  SetHelp(NULL, NULL, NULL, trVDR("Button$Info"));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipPluginSetup::Setup(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int current = Current();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Clear();
 | 
				
			||||||
 | 
					  helpM.Clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Add(new cMenuEditBoolItem(tr("Enable EPG scanning"), &eitScanM));
 | 
				
			||||||
 | 
					  helpM.Append(tr("Define whether the EPG background scanning shall be used.\n\nThis setting disables the automatic EIT scanning functionality for all SAT>IP devices."));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Add(new cMenuEditIntItem(tr("Disabled filters"), &numDisabledFiltersM, 0, SECTION_FILTER_TABLE_SIZE, tr("none")));
 | 
				
			||||||
 | 
					  helpM.Append(tr("Define number of section filters to be disabled.\n\nCertain section filters might cause some unwanted behaviour to VDR such as time being falsely synchronized. By black-listing the filters here useful section data can be left intact for VDR to process."));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (int i = 0; i < numDisabledFiltersM; ++i) {
 | 
				
			||||||
 | 
					      Add(new cMenuEditStraItem(*cString::sprintf(" %s %d", tr("Filter"), i + 1), &disabledFilterIndexesM[i], SECTION_FILTER_TABLE_SIZE, disabledFilterNamesM));
 | 
				
			||||||
 | 
					      helpM.Append(tr("Define an ill-behaving filter to be blacklisted."));
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Add(new cOsdItem(tr("Active SAT>IP devices:"), osUnknown, false));
 | 
				
			||||||
 | 
					  helpM.Append("");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  cSatipServers *servers = cSatipDiscover::GetInstance()->GetServers();
 | 
				
			||||||
 | 
					  deviceCountM = servers->Count();
 | 
				
			||||||
 | 
					  for (cSatipServer *s = servers->First(); s; s = servers->Next(s)) {
 | 
				
			||||||
 | 
					      Add(new cSatipServerItem(s));
 | 
				
			||||||
 | 
					      helpM.Append("");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  SetCurrent(Get(current));
 | 
				
			||||||
 | 
					  Display();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					eOSState cSatipPluginSetup::ChannelScan(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipPluginSetup::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  if (HasSubMenu() || Count() == 0)
 | 
				
			||||||
 | 
					     return osContinue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  cSatipServerItem *item = reinterpret_cast<cSatipServerItem *>(Get(Current()));
 | 
				
			||||||
 | 
					  if (item && cSatipDiscover::GetInstance()->IsValidServer(item->Server()))
 | 
				
			||||||
 | 
					     return AddSubMenu(new cSatipMenuScan(item->Server()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return osContinue;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					eOSState cSatipPluginSetup::ShowInfo(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipPluginSetup::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  if (HasSubMenu() || Count() == 0)
 | 
				
			||||||
 | 
					     return osContinue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return AddSubMenu(new cSatipMenuInfo());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					eOSState cSatipPluginSetup::ProcessKey(eKeys keyP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  bool hadSubMenu = HasSubMenu();
 | 
				
			||||||
 | 
					  int oldNumDisabledFilters = numDisabledFiltersM;
 | 
				
			||||||
 | 
					  eOSState state = cMenuSetupPage::ProcessKey(keyP);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Ugly hack with hardcoded '#' character :(
 | 
				
			||||||
 | 
					  const char *p = Get(Current())->Text();
 | 
				
			||||||
 | 
					  if (!hadSubMenu && !HasSubMenu() && (*p == '#') && (keyP == kOk))
 | 
				
			||||||
 | 
					     return ChannelScan();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (state == osUnknown) {
 | 
				
			||||||
 | 
					     switch (keyP) {
 | 
				
			||||||
 | 
					       case kBlue: return ShowInfo();
 | 
				
			||||||
 | 
					       case kInfo: if (Current() < helpM.Size())
 | 
				
			||||||
 | 
					                      return AddSubMenu(new cMenuText(cString::sprintf("%s - %s '%s'", tr("Help"), trVDR("Plugin"), PLUGIN_NAME_I18N), helpM[Current()]));
 | 
				
			||||||
 | 
					       default:    state = osContinue; break;
 | 
				
			||||||
 | 
					       }
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if ((keyP == kNone) && (cSatipDiscover::GetInstance()->GetServers()->Count() != deviceCountM))
 | 
				
			||||||
 | 
					     Setup();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if ((keyP != kNone) && (numDisabledFiltersM != oldNumDisabledFilters)) {
 | 
				
			||||||
 | 
					     while ((numDisabledFiltersM < oldNumDisabledFilters) && (oldNumDisabledFilters > 0))
 | 
				
			||||||
 | 
					           disabledFilterIndexesM[--oldNumDisabledFilters] = -1;
 | 
				
			||||||
 | 
					     Setup();
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return state;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipPluginSetup::StoreFilters(const char *nameP, int *valuesP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  char buffer[SECTION_FILTER_TABLE_SIZE * 4];
 | 
				
			||||||
 | 
					  char *q = buffer;
 | 
				
			||||||
 | 
					  for (int i = 0; i < SECTION_FILTER_TABLE_SIZE; ++i) {
 | 
				
			||||||
 | 
					      char s[3];
 | 
				
			||||||
 | 
					      if (valuesP[i] < 0)
 | 
				
			||||||
 | 
					         break;
 | 
				
			||||||
 | 
					      if (q > buffer)
 | 
				
			||||||
 | 
					         *q++ = ' ';
 | 
				
			||||||
 | 
					      snprintf(s, sizeof(s), "%d", valuesP[i]);
 | 
				
			||||||
 | 
					      strncpy(q, s, strlen(s));
 | 
				
			||||||
 | 
					      q += strlen(s);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					  *q = 0;
 | 
				
			||||||
 | 
					  debug("cSatipPluginSetup::%s(%s, %s)", __FUNCTION__, nameP, buffer);
 | 
				
			||||||
 | 
					  SetupStore(nameP, buffer);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipPluginSetup::Store(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  // Store values into setup.conf
 | 
				
			||||||
 | 
					  SetupStore("EnableEITScan", eitScanM);
 | 
				
			||||||
 | 
					  StoreFilters("DisabledFilters", disabledFilterIndexesM);
 | 
				
			||||||
 | 
					  // Update global config
 | 
				
			||||||
 | 
					  SatipConfig.SetEITScan(eitScanM);
 | 
				
			||||||
 | 
					  for (int i = 0; i < SECTION_FILTER_TABLE_SIZE; ++i)
 | 
				
			||||||
 | 
					      SatipConfig.SetDisabledFilters(i, disabledFilterIndexesM[i]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										38
									
								
								setup.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								setup.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * setup.h: SAT>IP plugin for the Video Disk Recorder
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * See the README file for copyright information and how to reach the author.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __SATIP_SETUP_H
 | 
				
			||||||
 | 
					#define __SATIP_SETUP_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <vdr/menuitems.h>
 | 
				
			||||||
 | 
					#include <vdr/sourceparams.h>
 | 
				
			||||||
 | 
					#include "common.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class cSatipPluginSetup : public cMenuSetupPage
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  int deviceCountM;
 | 
				
			||||||
 | 
					  int eitScanM;
 | 
				
			||||||
 | 
					  int numDisabledFiltersM;
 | 
				
			||||||
 | 
					  int disabledFilterIndexesM[SECTION_FILTER_TABLE_SIZE];
 | 
				
			||||||
 | 
					  const char *disabledFilterNamesM[SECTION_FILTER_TABLE_SIZE];
 | 
				
			||||||
 | 
					  cVector<const char*> helpM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  eOSState ChannelScan(void);
 | 
				
			||||||
 | 
					  eOSState ShowInfo(void);
 | 
				
			||||||
 | 
					  void Setup(void);
 | 
				
			||||||
 | 
					  void StoreFilters(const char *nameP, int *valuesP);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					protected:
 | 
				
			||||||
 | 
					  virtual eOSState ProcessKey(eKeys keyP);
 | 
				
			||||||
 | 
					  virtual void Store(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  cSatipPluginSetup();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // __SATIP_SETUP_H
 | 
				
			||||||
							
								
								
									
										233
									
								
								socket.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										233
									
								
								socket.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,233 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * socket.c: SAT>IP plugin for the Video Disk Recorder
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * See the README file for copyright information and how to reach the author.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					#include <sys/socket.h>
 | 
				
			||||||
 | 
					#include <net/if.h>
 | 
				
			||||||
 | 
					#include <netdb.h>
 | 
				
			||||||
 | 
					#include <fcntl.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <vdr/device.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "common.h"
 | 
				
			||||||
 | 
					#include "config.h"
 | 
				
			||||||
 | 
					#include "socket.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cSatipSocket::cSatipSocket()
 | 
				
			||||||
 | 
					: socketPortM(0),
 | 
				
			||||||
 | 
					  socketDescM(-1)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipSocket::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  memset(&sockAddrM, 0, sizeof(sockAddrM));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cSatipSocket::~cSatipSocket()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipSocket::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  // Close the socket
 | 
				
			||||||
 | 
					  Close();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cSatipSocket::Open(const int portP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipSocket::%s(%d)", __FUNCTION__, portP);
 | 
				
			||||||
 | 
					  // Bind to the socket if it is not active already
 | 
				
			||||||
 | 
					  if (socketDescM < 0) {
 | 
				
			||||||
 | 
					     socklen_t len = sizeof(sockAddrM);
 | 
				
			||||||
 | 
					     // Create socket
 | 
				
			||||||
 | 
					     socketDescM = socket(PF_INET, SOCK_DGRAM, 0);
 | 
				
			||||||
 | 
					     ERROR_IF_RET(socketDescM < 0, "socket()", return false);
 | 
				
			||||||
 | 
					     // Make it use non-blocking I/O to avoid stuck read calls
 | 
				
			||||||
 | 
					     ERROR_IF_FUNC(fcntl(socketDescM, F_SETFL, O_NONBLOCK), "fcntl(O_NONBLOCK)",
 | 
				
			||||||
 | 
					                   Close(), return false);
 | 
				
			||||||
 | 
					     // Allow multiple sockets to use the same PORT number
 | 
				
			||||||
 | 
					     int yes = 1;
 | 
				
			||||||
 | 
					     ERROR_IF_FUNC(setsockopt(socketDescM, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0,
 | 
				
			||||||
 | 
					                   "setsockopt(SO_REUSEADDR)", Close(), return false);
 | 
				
			||||||
 | 
					     // Bind socket
 | 
				
			||||||
 | 
					     memset(&sockAddrM, 0, sizeof(sockAddrM));
 | 
				
			||||||
 | 
					     sockAddrM.sin_family = AF_INET;
 | 
				
			||||||
 | 
					     sockAddrM.sin_port = htons((uint16_t)(portP & 0xFFFF));
 | 
				
			||||||
 | 
					     sockAddrM.sin_addr.s_addr = htonl(INADDR_ANY);
 | 
				
			||||||
 | 
					     ERROR_IF_FUNC(bind(socketDescM, (struct sockaddr *)&sockAddrM, sizeof(sockAddrM)) < 0,
 | 
				
			||||||
 | 
					                   "bind()", Close(), return false);
 | 
				
			||||||
 | 
					     // Update socket port
 | 
				
			||||||
 | 
					     ERROR_IF_FUNC(getsockname(socketDescM,(struct sockaddr*)&sockAddrM, &len) < 0,
 | 
				
			||||||
 | 
					                   "getsockname()", Close(), return false);
 | 
				
			||||||
 | 
					     socketPortM = ntohs(sockAddrM.sin_port);
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipSocket::Close(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipSocket::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  // Check if socket exists
 | 
				
			||||||
 | 
					  if (socketDescM >= 0) {
 | 
				
			||||||
 | 
					     close(socketDescM);
 | 
				
			||||||
 | 
					     socketDescM = -1;
 | 
				
			||||||
 | 
					     socketPortM = 0;
 | 
				
			||||||
 | 
					     memset(&sockAddrM, 0, sizeof(sockAddrM));
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cSatipSocket::Flush(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipSocket::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  if (socketDescM < 0) {
 | 
				
			||||||
 | 
					     const unsigned int len = 65535;
 | 
				
			||||||
 | 
					     unsigned char *buf = MALLOC(unsigned char, len);
 | 
				
			||||||
 | 
					     if (buf) {
 | 
				
			||||||
 | 
					        int i = 0;
 | 
				
			||||||
 | 
					        do {
 | 
				
			||||||
 | 
					           // Sanity check
 | 
				
			||||||
 | 
					           if (++i > 10)
 | 
				
			||||||
 | 
					              break;
 | 
				
			||||||
 | 
					        } while (Read(buf, len));
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					  return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int cSatipSocket::Read(unsigned char *bufferAddrP, unsigned int bufferLenP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipSocket::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  // Error out if socket not initialized
 | 
				
			||||||
 | 
					  if (socketDescM <= 0) {
 | 
				
			||||||
 | 
					     error("Invalid socket in cSatipUdpSocket::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					     return -1;
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					  int len = 0;
 | 
				
			||||||
 | 
					  // Read data from socket in a loop
 | 
				
			||||||
 | 
					  do {
 | 
				
			||||||
 | 
					    socklen_t addrlen = sizeof(sockAddrM);
 | 
				
			||||||
 | 
					    struct msghdr msgh;
 | 
				
			||||||
 | 
					    struct iovec iov;
 | 
				
			||||||
 | 
					    char cbuf[256];
 | 
				
			||||||
 | 
					    len = 0;
 | 
				
			||||||
 | 
					    // Initialize iov and msgh structures
 | 
				
			||||||
 | 
					    memset(&msgh, 0, sizeof(struct msghdr));
 | 
				
			||||||
 | 
					    iov.iov_base = bufferAddrP;
 | 
				
			||||||
 | 
					    iov.iov_len = bufferLenP;
 | 
				
			||||||
 | 
					    msgh.msg_control = cbuf;
 | 
				
			||||||
 | 
					    msgh.msg_controllen = sizeof(cbuf);
 | 
				
			||||||
 | 
					    msgh.msg_name = &sockAddrM;
 | 
				
			||||||
 | 
					    msgh.msg_namelen = addrlen;
 | 
				
			||||||
 | 
					    msgh.msg_iov  = &iov;
 | 
				
			||||||
 | 
					    msgh.msg_iovlen = 1;
 | 
				
			||||||
 | 
					    msgh.msg_flags = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (socketDescM && bufferAddrP && (bufferLenP > 0))
 | 
				
			||||||
 | 
					       len = (int)recvmsg(socketDescM, &msgh, MSG_DONTWAIT);
 | 
				
			||||||
 | 
					    if (len > 0)
 | 
				
			||||||
 | 
					       return len;
 | 
				
			||||||
 | 
					    } while (len > 0);
 | 
				
			||||||
 | 
					  ERROR_IF_RET(len < 0 && errno != EAGAIN, "recvmsg()", return -1);
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int cSatipSocket::ReadVideo(unsigned char *bufferAddrP, unsigned int bufferLenP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipSocket::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  int len = Read(bufferAddrP, bufferLenP);
 | 
				
			||||||
 | 
					  if (len > 0) {
 | 
				
			||||||
 | 
					     if (bufferAddrP[0] == TS_SYNC_BYTE)
 | 
				
			||||||
 | 
					        return len;
 | 
				
			||||||
 | 
					     else if (len > 3) {
 | 
				
			||||||
 | 
					        // http://tools.ietf.org/html/rfc3550
 | 
				
			||||||
 | 
					        // http://tools.ietf.org/html/rfc2250
 | 
				
			||||||
 | 
					        // Version
 | 
				
			||||||
 | 
					        unsigned int v = (bufferAddrP[0] >> 6) & 0x03;
 | 
				
			||||||
 | 
					        // Extension bit
 | 
				
			||||||
 | 
					        unsigned int x = (bufferAddrP[0] >> 4) & 0x01;
 | 
				
			||||||
 | 
					        // CSCR count
 | 
				
			||||||
 | 
					        unsigned int cc = bufferAddrP[0] & 0x0F;
 | 
				
			||||||
 | 
					        // Payload type: MPEG2 TS = 33
 | 
				
			||||||
 | 
					        //unsigned int pt = bufferAddrP[1] & 0x7F;
 | 
				
			||||||
 | 
					        // Header lenght
 | 
				
			||||||
 | 
					        unsigned int headerlen = (3 + cc) * (unsigned int)sizeof(uint32_t);
 | 
				
			||||||
 | 
					        // Check if extension
 | 
				
			||||||
 | 
					        if (x) {
 | 
				
			||||||
 | 
					           // Extension header length
 | 
				
			||||||
 | 
					           unsigned int ehl = (((bufferAddrP[headerlen + 2] & 0xFF) << 8) |
 | 
				
			||||||
 | 
					                               (bufferAddrP[headerlen + 3] & 0xFF));
 | 
				
			||||||
 | 
					           // Update header length
 | 
				
			||||||
 | 
					           headerlen += (ehl + 1) * (unsigned int)sizeof(uint32_t);
 | 
				
			||||||
 | 
					           }
 | 
				
			||||||
 | 
					        // Check that rtp is version 2 and payload contains multiple of TS packet data
 | 
				
			||||||
 | 
					        if ((v == 2) && (((len - headerlen) % TS_SIZE) == 0) &&
 | 
				
			||||||
 | 
					            (bufferAddrP[headerlen] == TS_SYNC_BYTE)) {
 | 
				
			||||||
 | 
					           // Set argument point to payload in read buffer
 | 
				
			||||||
 | 
					           memmove(bufferAddrP, &bufferAddrP[headerlen], (len - headerlen));
 | 
				
			||||||
 | 
					           return (len - headerlen);
 | 
				
			||||||
 | 
					           }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int cSatipSocket::ReadApplication(unsigned char *bufferAddrP, unsigned int bufferLenP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipSocket::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  int len = Read(bufferAddrP, bufferLenP);
 | 
				
			||||||
 | 
					  int offset = 0;
 | 
				
			||||||
 | 
					  while (len > 0) {
 | 
				
			||||||
 | 
					        // Version
 | 
				
			||||||
 | 
					        unsigned int v = (bufferAddrP[offset] >> 6) & 0x03;
 | 
				
			||||||
 | 
					         // Padding
 | 
				
			||||||
 | 
					        //unsigned int p = (bufferAddrP[offset] >> 5) & 0x01;
 | 
				
			||||||
 | 
					        // Subtype
 | 
				
			||||||
 | 
					        //unsigned int st = bufferAddrP[offset] & 0x1F;
 | 
				
			||||||
 | 
					        // Payload type
 | 
				
			||||||
 | 
					        unsigned int pt = bufferAddrP[offset + 1] & 0xFF;
 | 
				
			||||||
 | 
					        // Lenght
 | 
				
			||||||
 | 
					        unsigned int length = ((bufferAddrP[offset + 2] & 0xFF) << 8) | (bufferAddrP[offset + 3] & 0xFF);
 | 
				
			||||||
 | 
					        // Convert it to bytes
 | 
				
			||||||
 | 
					        length = (length + 1) * 4;
 | 
				
			||||||
 | 
					        // V=2, APP = 204
 | 
				
			||||||
 | 
					        if ((v == 2) && (pt == 204)) {
 | 
				
			||||||
 | 
					           // SSCR/CSCR
 | 
				
			||||||
 | 
					           //unsigned int ssrc = ((bufferAddrP[offset + 4] & 0xFF) << 24) | ((bufferAddrP[offset + 5] & 0xFF) << 16) |
 | 
				
			||||||
 | 
					           //                     ((bufferAddrP[offset + 6] & 0xFF) << 8) | (bufferAddrP[offset + 7] & 0xFF);
 | 
				
			||||||
 | 
					           // Name
 | 
				
			||||||
 | 
					           if ((bufferAddrP[offset +  8] == 'S') && (bufferAddrP[offset +  9] == 'E') &&
 | 
				
			||||||
 | 
					               (bufferAddrP[offset + 10] == 'S') && (bufferAddrP[offset + 11] == '1')) {
 | 
				
			||||||
 | 
					              // Identifier
 | 
				
			||||||
 | 
					              //unsigned int id = ((bufferAddrP[offset + 12] & 0xFF) << 8) | (bufferAddrP[offset + 13] & 0xFF);
 | 
				
			||||||
 | 
					              // String length
 | 
				
			||||||
 | 
					              int string_length = ((bufferAddrP[offset + 14] & 0xFF) << 8) | (bufferAddrP[offset + 15] & 0xFF);
 | 
				
			||||||
 | 
					              if (string_length > 0) {
 | 
				
			||||||
 | 
					                 // Set argument point to payload in read buffer
 | 
				
			||||||
 | 
					                 memmove(bufferAddrP, &bufferAddrP[offset + 16], string_length);
 | 
				
			||||||
 | 
					                 return string_length;
 | 
				
			||||||
 | 
					                 }
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					           }
 | 
				
			||||||
 | 
					        offset += length;
 | 
				
			||||||
 | 
					        len -= length;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cSatipSocket::Write(const char *addrP, const unsigned char *bufferAddrP, unsigned int bufferLenP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipSocket::%s(%s)", __FUNCTION__, addrP);
 | 
				
			||||||
 | 
					  // Error out if socket not initialized
 | 
				
			||||||
 | 
					  if (socketDescM <= 0) {
 | 
				
			||||||
 | 
					     error("cSatipSocket::%s(): Invalid socket", __FUNCTION__);
 | 
				
			||||||
 | 
					     return false;
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					  struct sockaddr_in sockAddr;
 | 
				
			||||||
 | 
					  memset(&sockAddr, 0, sizeof(sockAddr));
 | 
				
			||||||
 | 
					  sockAddr.sin_family = AF_INET;
 | 
				
			||||||
 | 
					  sockAddr.sin_port = htons((uint16_t)(socketPortM & 0xFFFF));
 | 
				
			||||||
 | 
					  sockAddr.sin_addr.s_addr = inet_addr(addrP);
 | 
				
			||||||
 | 
					  ERROR_IF_RET(sendto(socketDescM, bufferAddrP, bufferLenP, 0, (struct sockaddr *)&sockAddr, sizeof(sockAddr)) < 0, "sendto()", return false);
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										34
									
								
								socket.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								socket.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * socket.h: SAT>IP plugin for the Video Disk Recorder
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * See the README file for copyright information and how to reach the author.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __SATIP_SOCKET_H
 | 
				
			||||||
 | 
					#define __SATIP_SOCKET_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <arpa/inet.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class cSatipSocket {
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  int socketPortM;
 | 
				
			||||||
 | 
					  int socketDescM;
 | 
				
			||||||
 | 
					  struct sockaddr_in sockAddrM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  cSatipSocket();
 | 
				
			||||||
 | 
					  ~cSatipSocket();
 | 
				
			||||||
 | 
					  bool Open(const int portP = 0);
 | 
				
			||||||
 | 
					  void Close(void);
 | 
				
			||||||
 | 
					  int Port(void) { return socketPortM; }
 | 
				
			||||||
 | 
					  bool IsOpen(void) { return (socketDescM >= 0); }
 | 
				
			||||||
 | 
					  bool Flush(void);
 | 
				
			||||||
 | 
					  int Read(unsigned char *bufferAddrP, unsigned int bufferLenP);
 | 
				
			||||||
 | 
					  int ReadVideo(unsigned char *bufferAddrP, unsigned int bufferLenP);
 | 
				
			||||||
 | 
					  int ReadApplication(unsigned char *bufferAddrP, unsigned int bufferLenP);
 | 
				
			||||||
 | 
					  bool Write(const char *addrP, const unsigned char *bufferAddrP, unsigned int bufferLenP);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // __SATIP_SOCKET_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										384
									
								
								source.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										384
									
								
								source.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,384 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * source.c: SAT>IP plugin for the Video Disk Recorder
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * See the README file for copyright information and how to reach the author.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <ctype.h>
 | 
				
			||||||
 | 
					#include "common.h"
 | 
				
			||||||
 | 
					#include "source.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// --- cSatipParameterMaps ----------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const tSatipParameterMap SatipBandwidthValues[] = {
 | 
				
			||||||
 | 
					  {    5, "5 MHz",     "bw=5"     },
 | 
				
			||||||
 | 
					  {    6, "6 MHz",     "bw=6"     },
 | 
				
			||||||
 | 
					  {    7, "7 MHz",     "bw=7"     },
 | 
				
			||||||
 | 
					  {    8, "8 MHz",     "bw=8"     },
 | 
				
			||||||
 | 
					  {   10, "10 MHz",    "bw=10"    },
 | 
				
			||||||
 | 
					  { 1712, "1.712 MHz", "bw=1.712" },
 | 
				
			||||||
 | 
					  {   -1, NULL,        NULL       }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const tSatipParameterMap SatipPilotTonesValues[] = {
 | 
				
			||||||
 | 
					  {   0, trNOOP("off"),  "plts=off" },
 | 
				
			||||||
 | 
					  {   1, trNOOP("on"),   "plts=on"  },
 | 
				
			||||||
 | 
					  { 999, trNOOP("auto"), ""         },
 | 
				
			||||||
 | 
					  {  -1, NULL,           NULL       }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const tSatipParameterMap SatipSisoMisoValues[] = {
 | 
				
			||||||
 | 
					  {   0, trNOOP("SISO"), "sm=0" },
 | 
				
			||||||
 | 
					  {   1, trNOOP("MISO"), "sm=1" },
 | 
				
			||||||
 | 
					  { 999, trNOOP("auto"), ""     },
 | 
				
			||||||
 | 
					  {  -1, NULL,           NULL   }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const tSatipParameterMap SatipCodeRateValues[] = {
 | 
				
			||||||
 | 
					  {   0, trNOOP("none"), ""        },
 | 
				
			||||||
 | 
					  {  12, "1/2",          "fec=12"  },
 | 
				
			||||||
 | 
					  {  23, "2/3",          "fec=23"  },
 | 
				
			||||||
 | 
					  {  34, "3/4",          "fec=34"  },
 | 
				
			||||||
 | 
					  {  35, "3/5",          "fec=35"  },
 | 
				
			||||||
 | 
					  {  45, "4/5",          "fec=45"  },
 | 
				
			||||||
 | 
					  {  56, "5/6",          "fec=56"  },
 | 
				
			||||||
 | 
					  {  78, "7/8",          "fec=78"  },
 | 
				
			||||||
 | 
					  {  89, "8/9",          "fec=89"  },
 | 
				
			||||||
 | 
					  { 910, "9/10",         "fec=910" },
 | 
				
			||||||
 | 
					  { 999, trNOOP("auto"), ""        },
 | 
				
			||||||
 | 
					  {  -1, NULL,           NULL      }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const tSatipParameterMap SatipModulationValues[] = {
 | 
				
			||||||
 | 
					  {   2, "QPSK",         "mtype=qpsk"   },
 | 
				
			||||||
 | 
					  {   5, "8PSK",         "mtype=8psk"   },
 | 
				
			||||||
 | 
					  {  16, "QAM16",        "mtype=16qam"  },
 | 
				
			||||||
 | 
					  {  64, "QAM64",        "mtype=64qam"  },
 | 
				
			||||||
 | 
					  { 256, "QAM256",       "mtype=256qam" },
 | 
				
			||||||
 | 
					  { 999, trNOOP("auto"), ""             },
 | 
				
			||||||
 | 
					  {  -1, NULL,           NULL           }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const tSatipParameterMap SatipSystemValuesSat[] = {
 | 
				
			||||||
 | 
					  {   0, "DVB-S",  "msys=dvbs"  },
 | 
				
			||||||
 | 
					  {   1, "DVB-S2", "msys=dvbs2" },
 | 
				
			||||||
 | 
					  {  -1, NULL,     NULL         }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const tSatipParameterMap SatipSystemValuesTerr[] = {
 | 
				
			||||||
 | 
					  {   0, "DVB-T",  "msys=dvbt"  },
 | 
				
			||||||
 | 
					  {   1, "DVB-T2", "msys=dvbt2" },
 | 
				
			||||||
 | 
					  {  -1, NULL,     NULL         }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const tSatipParameterMap SatipTransmissionValues[] = {
 | 
				
			||||||
 | 
					  {   1, "1K",           "tmode=1k"  },
 | 
				
			||||||
 | 
					  {   2, "2K",           "tmode=2k"  },
 | 
				
			||||||
 | 
					  {   4, "4K",           "tmode=4k"  },
 | 
				
			||||||
 | 
					  {   8, "8K",           "tmode=8k"  },
 | 
				
			||||||
 | 
					  {  16, "16K",          "tmode=16k" },
 | 
				
			||||||
 | 
					  {  32, "32K",          "tmode=32k" },
 | 
				
			||||||
 | 
					  { 999, trNOOP("auto"), ""          },
 | 
				
			||||||
 | 
					  {  -1, NULL,           NULL        }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const tSatipParameterMap SatipGuardValues[] = {
 | 
				
			||||||
 | 
					  {     4, "1/4",          "gi=14"    },
 | 
				
			||||||
 | 
					  {     8, "1/8",          "gi=18"    },
 | 
				
			||||||
 | 
					  {    16, "1/16",         "gi=116"   },
 | 
				
			||||||
 | 
					  {    32, "1/32",         "gi=132"   },
 | 
				
			||||||
 | 
					  {   128, "1/128",        "gi=1128"  },
 | 
				
			||||||
 | 
					  { 19128, "19/128",       "gi=19128" },
 | 
				
			||||||
 | 
					  { 19256, "19/256",       "gi=19256" },
 | 
				
			||||||
 | 
					  {   999, trNOOP("auto"), ""         },
 | 
				
			||||||
 | 
					  {    -1, NULL,           NULL       }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const tSatipParameterMap SatipRollOffValues[] = {
 | 
				
			||||||
 | 
					  {  0, trNOOP("auto"), ""        },
 | 
				
			||||||
 | 
					  { 20, "0.20",         "ro=0.20" },
 | 
				
			||||||
 | 
					  { 25, "0.25",         "ro=0.25" },
 | 
				
			||||||
 | 
					  { 35, "0.35",         "ro=0.35" },
 | 
				
			||||||
 | 
					  { -1, NULL,            NULL     }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int SatipUserIndex(int valueP, const tSatipParameterMap *mapP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  const tSatipParameterMap *map = mapP;
 | 
				
			||||||
 | 
					  while (map && map->userValue != -1) {
 | 
				
			||||||
 | 
					        if (map->userValue == valueP)
 | 
				
			||||||
 | 
					           return map - mapP;
 | 
				
			||||||
 | 
					        map++;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					  return -1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int SatipMapToUser(int valueP, const tSatipParameterMap *mapP, const char **strP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int n = SatipUserIndex(valueP, mapP);
 | 
				
			||||||
 | 
					  if (n >= 0) {
 | 
				
			||||||
 | 
					     if (strP)
 | 
				
			||||||
 | 
					        *strP = tr(mapP[n].userString);
 | 
				
			||||||
 | 
					     return mapP[n].userValue;
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					  return -1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// --- cMenuEditSatipItem -----------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class cMenuEditSatipItem : public cMenuEditItem {
 | 
				
			||||||
 | 
					protected:
 | 
				
			||||||
 | 
					  int *valueM;
 | 
				
			||||||
 | 
					  const tSatipParameterMap *mapM;
 | 
				
			||||||
 | 
					  const char *zeroStringM;
 | 
				
			||||||
 | 
					  virtual void Set(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  cMenuEditSatipItem(const char *nameP, int *valueP, const tSatipParameterMap *mapP, const char *zeroStringP = NULL);
 | 
				
			||||||
 | 
					  virtual eOSState ProcessKey(eKeys keyP);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cMenuEditSatipItem::cMenuEditSatipItem(const char *nameP, int *valueP, const tSatipParameterMap *mapP, const char *zeroStringP)
 | 
				
			||||||
 | 
					: cMenuEditItem(nameP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  valueM = valueP;
 | 
				
			||||||
 | 
					  mapM = mapP;
 | 
				
			||||||
 | 
					  zeroStringM = zeroStringP;
 | 
				
			||||||
 | 
					  Set();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cMenuEditSatipItem::Set(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  const char *s = NULL;
 | 
				
			||||||
 | 
					  int n = SatipMapToUser(*valueM, mapM, &s);
 | 
				
			||||||
 | 
					  if (n == 0 && zeroStringM)
 | 
				
			||||||
 | 
					     SetValue(zeroStringM);
 | 
				
			||||||
 | 
					  else if (n >= 0) {
 | 
				
			||||||
 | 
					     if (s)
 | 
				
			||||||
 | 
					        SetValue(s);
 | 
				
			||||||
 | 
					     else {
 | 
				
			||||||
 | 
					        char buf[16];
 | 
				
			||||||
 | 
					        snprintf(buf, sizeof(buf), "%d", n);
 | 
				
			||||||
 | 
					        SetValue(buf);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					     SetValue("???");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					eOSState cMenuEditSatipItem::ProcessKey(eKeys keyP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  eOSState state = cMenuEditItem::ProcessKey(keyP);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (state == osUnknown) {
 | 
				
			||||||
 | 
					     int newValue = *valueM;
 | 
				
			||||||
 | 
					     int n = SatipUserIndex(*valueM, mapM);
 | 
				
			||||||
 | 
					     if (NORMALKEY(keyP) == kLeft) { // TODO might want to increase the delta if repeated quickly?
 | 
				
			||||||
 | 
					        if (n-- > 0)
 | 
				
			||||||
 | 
					           newValue = mapM[n].userValue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					     else if (NORMALKEY(keyP) == kRight) {
 | 
				
			||||||
 | 
					        if (mapM[++n].userValue >= 0)
 | 
				
			||||||
 | 
					           newValue = mapM[n].userValue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					     else
 | 
				
			||||||
 | 
					        return state;
 | 
				
			||||||
 | 
					     if (newValue != *valueM) {
 | 
				
			||||||
 | 
					        *valueM = newValue;
 | 
				
			||||||
 | 
					        Set();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					     state = osContinue;
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					  return state;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// --- cSatipTransponderParameters --------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cSatipTransponderParameters::cSatipTransponderParameters(const char *parametersP)
 | 
				
			||||||
 | 
					: polarizationM('H'),
 | 
				
			||||||
 | 
					  bandwidthM(8),
 | 
				
			||||||
 | 
					  coderateHM(0),
 | 
				
			||||||
 | 
					  systemM(0),
 | 
				
			||||||
 | 
					  modulationM(999),
 | 
				
			||||||
 | 
					  transmissionM(8),
 | 
				
			||||||
 | 
					  guardM(999),
 | 
				
			||||||
 | 
					  rollOffM(0),
 | 
				
			||||||
 | 
					  streamIdM(0),
 | 
				
			||||||
 | 
					  t2SystemIdM(0),
 | 
				
			||||||
 | 
					  sisoMisoM(999),
 | 
				
			||||||
 | 
					  pilotTonesM(0),
 | 
				
			||||||
 | 
					  signalSourceM(1)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  Parse(parametersP);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int cSatipTransponderParameters::PrintParameter(char *ptrP, char nameP, int valueP) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  return (valueP >= 0 && valueP != 999) ? sprintf(ptrP, "%c%d", nameP, valueP) : 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int cSatipTransponderParameters::PrintString(char *ptrP, int valueP, const tSatipParameterMap *mapP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int n = SatipUserIndex(valueP, mapP);
 | 
				
			||||||
 | 
					  return (n >= 0) ? sprintf(ptrP, "&%s", tr(mapP[n].satipString)) : 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cString cSatipTransponderParameters::UrlParameters(char typeP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  char buffer[255];
 | 
				
			||||||
 | 
					  char *q = buffer;
 | 
				
			||||||
 | 
					  *q = 0;
 | 
				
			||||||
 | 
					#define ST(s) if (strchr(s, typeP) && (strchr(s, '0' + systemM + 1) || strchr(s, '*')))
 | 
				
			||||||
 | 
					  ST("Z *") q += sprintf(q,     "&src=%d",     signalSourceM);
 | 
				
			||||||
 | 
					  ST("Z *") q += sprintf(q,     "&pol=%c",     tolower(polarizationM));
 | 
				
			||||||
 | 
					  ST(" Y2") q += sprintf(q,     "&plp=%d",     streamIdM);
 | 
				
			||||||
 | 
					  ST(" Y2") q += sprintf(q,     "&t2id=%d",    t2SystemIdM);
 | 
				
			||||||
 | 
					  ST(" Y*") q += PrintString(q, bandwidthM,    SatipBandwidthValues);
 | 
				
			||||||
 | 
					  ST(" Y*") q += PrintString(q, guardM,        SatipGuardValues);
 | 
				
			||||||
 | 
					  ST("ZY*") q += PrintString(q, coderateHM,    SatipCodeRateValues);
 | 
				
			||||||
 | 
					  ST("Z 2") q += PrintString(q, pilotTonesM,   SatipPilotTonesValues);
 | 
				
			||||||
 | 
					  ST("Z 2") q += PrintString(q, modulationM,   SatipModulationValues);
 | 
				
			||||||
 | 
					  ST(" Y*") q += PrintString(q, modulationM,   SatipModulationValues);
 | 
				
			||||||
 | 
					  ST("Z 2") q += PrintString(q, rollOffM,      SatipRollOffValues);
 | 
				
			||||||
 | 
					  ST("Z *") q += PrintString(q, systemM,       SatipSystemValuesSat);
 | 
				
			||||||
 | 
					  ST(" Y*") q += PrintString(q, systemM,       SatipSystemValuesTerr);
 | 
				
			||||||
 | 
					  ST(" Y*") q += PrintString(q, transmissionM, SatipTransmissionValues);
 | 
				
			||||||
 | 
					  ST(" Y2") q += PrintString(q, sisoMisoM,     SatipSisoMisoValues);
 | 
				
			||||||
 | 
					#undef ST
 | 
				
			||||||
 | 
					  return buffer;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cString cSatipTransponderParameters::ToString(char typeP) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  char buffer[64];
 | 
				
			||||||
 | 
					  char *q = buffer;
 | 
				
			||||||
 | 
					  *q = 0;
 | 
				
			||||||
 | 
					#define ST(s) if (strchr(s, typeP) && (strchr(s, '0' + systemM + 1) || strchr(s, '*')))
 | 
				
			||||||
 | 
					  ST("Z *") q += sprintf(q, "%c", polarizationM);
 | 
				
			||||||
 | 
					  ST(" Y*") q += PrintParameter(q, 'B', bandwidthM);
 | 
				
			||||||
 | 
					  ST("ZY*") q += PrintParameter(q, 'C', coderateHM);
 | 
				
			||||||
 | 
					  ST(" Y*") q += PrintParameter(q, 'G', guardM);
 | 
				
			||||||
 | 
					  ST("Z 2") q += PrintParameter(q, 'M', modulationM);
 | 
				
			||||||
 | 
					  ST(" Y*") q += PrintParameter(q, 'M', modulationM);
 | 
				
			||||||
 | 
					  ST("Z 2") q += PrintParameter(q, 'N', pilotTonesM);
 | 
				
			||||||
 | 
					  ST("Z 2") q += PrintParameter(q, 'O', rollOffM);
 | 
				
			||||||
 | 
					  ST(" Y2") q += PrintParameter(q, 'P', streamIdM);
 | 
				
			||||||
 | 
					  ST(" Y2") q += PrintParameter(q, 'Q', t2SystemIdM);
 | 
				
			||||||
 | 
					  ST("ZY*") q += PrintParameter(q, 'S', systemM);
 | 
				
			||||||
 | 
					  ST(" Y*") q += PrintParameter(q, 'T', transmissionM);
 | 
				
			||||||
 | 
					  ST(" Y2") q += PrintParameter(q, 'X', sisoMisoM);
 | 
				
			||||||
 | 
					  ST("Z *") q += PrintParameter(q, 'Z', signalSourceM);
 | 
				
			||||||
 | 
					#undef ST
 | 
				
			||||||
 | 
					  return buffer;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char *cSatipTransponderParameters::ParseParameter(const char *strP, int &valueP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (*++strP) {
 | 
				
			||||||
 | 
					     char *p = NULL;
 | 
				
			||||||
 | 
					     errno = 0;
 | 
				
			||||||
 | 
					     int n = strtol(strP, &p, 10);
 | 
				
			||||||
 | 
					     if (!errno && p != strP) {
 | 
				
			||||||
 | 
					        valueP = n;
 | 
				
			||||||
 | 
					        if (valueP >= 0)
 | 
				
			||||||
 | 
					           return p;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					  error("invalid value for parameter '%c'", *(strP - 1));
 | 
				
			||||||
 | 
					  return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cSatipTransponderParameters::Parse(const char *strP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  while (strP && *strP) {
 | 
				
			||||||
 | 
					        int ignoreThis;
 | 
				
			||||||
 | 
					        switch (toupper(*strP)) {
 | 
				
			||||||
 | 
					          case 'B': strP = ParseParameter(strP, bandwidthM);    break;
 | 
				
			||||||
 | 
					          case 'C': strP = ParseParameter(strP, coderateHM);    break;
 | 
				
			||||||
 | 
					          case 'G': strP = ParseParameter(strP, guardM);        break;
 | 
				
			||||||
 | 
					          case 'H': polarizationM = 'H'; strP++;                break;
 | 
				
			||||||
 | 
					          case 'L': polarizationM = 'L'; strP++;                break;
 | 
				
			||||||
 | 
					          case 'M': strP = ParseParameter(strP, modulationM);   break;
 | 
				
			||||||
 | 
					          case 'N': strP = ParseParameter(strP, pilotTonesM);   break;
 | 
				
			||||||
 | 
					          case 'O': strP = ParseParameter(strP, rollOffM);      break;
 | 
				
			||||||
 | 
					          case 'P': strP = ParseParameter(strP, streamIdM);     break;
 | 
				
			||||||
 | 
					          case 'Q': strP = ParseParameter(strP, t2SystemIdM);   break;
 | 
				
			||||||
 | 
					          case 'R': polarizationM = 'R'; strP++;                break;
 | 
				
			||||||
 | 
					          case 'S': strP = ParseParameter(strP, systemM);       break;
 | 
				
			||||||
 | 
					          case 'T': strP = ParseParameter(strP, transmissionM); break;
 | 
				
			||||||
 | 
					          case 'V': polarizationM = 'V'; strP++;                break;
 | 
				
			||||||
 | 
					          case 'X': strP = ParseParameter(strP, sisoMisoM);     break;
 | 
				
			||||||
 | 
					          case 'Z': strP = ParseParameter(strP, signalSourceM); break;
 | 
				
			||||||
 | 
					          case 'D': strP = ParseParameter(strP, ignoreThis);    break; /* silently ignore coderate low priority */
 | 
				
			||||||
 | 
					          case 'I': strP = ParseParameter(strP, ignoreThis);    break; /* silently ignore inversion */
 | 
				
			||||||
 | 
					          case 'Y': strP = ParseParameter(strP, ignoreThis);    break; /* silently ignore hierarchy */
 | 
				
			||||||
 | 
					          default: esyslog("ERROR: unknown parameter key '%c'", *strP);
 | 
				
			||||||
 | 
					                   return false;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// --- cSatipSourceParam ------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cSatipSourceParam::cSatipSourceParam(char sourceP, const char *descriptionP)
 | 
				
			||||||
 | 
					: cSourceParam(sourceP, descriptionP),
 | 
				
			||||||
 | 
					  paramM(0),
 | 
				
			||||||
 | 
					  nidM(0),
 | 
				
			||||||
 | 
					  tidM(0),
 | 
				
			||||||
 | 
					  ridM(0),
 | 
				
			||||||
 | 
					  srateM(0),
 | 
				
			||||||
 | 
					  dataM(),
 | 
				
			||||||
 | 
					  stpM()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipSourceParam::%s(%c, %s)", __FUNCTION__, sourceP, descriptionP);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipSourceParam::SetData(cChannel *channelP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipSourceParam::%s(%s)", __FUNCTION__, channelP->Parameters());
 | 
				
			||||||
 | 
					  dataM = *channelP;
 | 
				
			||||||
 | 
					  nidM = dataM.Nid();
 | 
				
			||||||
 | 
					  tidM = dataM.Tid();
 | 
				
			||||||
 | 
					  ridM = dataM.Rid();
 | 
				
			||||||
 | 
					  srateM = dataM.Srate();
 | 
				
			||||||
 | 
					  stpM.Parse(dataM.Parameters());
 | 
				
			||||||
 | 
					  paramM = 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipSourceParam::GetData(cChannel *channelP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipSourceParam::%s(%s)", __FUNCTION__, channelP->Parameters());
 | 
				
			||||||
 | 
					  channelP->SetTransponderData(channelP->Source(), channelP->Frequency(), srateM, stpM.ToString(Source()), true);
 | 
				
			||||||
 | 
					  channelP->SetId(nidM, tidM, channelP->Sid(), ridM);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cOsdItem *cSatipSourceParam::GetOsdItem(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  char type = Source();
 | 
				
			||||||
 | 
					  const tSatipParameterMap *SatipSystemValues = type == 'Z' ? SatipSystemValuesSat : SatipSystemValuesTerr;
 | 
				
			||||||
 | 
					#define ST(s) if (strchr(s, type))
 | 
				
			||||||
 | 
					  switch (paramM++) {
 | 
				
			||||||
 | 
					    case  0:           return new cMenuEditIntItem(      tr("Nid"),         &nidM, 0);
 | 
				
			||||||
 | 
					    case  1:           return new cMenuEditIntItem(      tr("Tid"),         &tidM, 0);
 | 
				
			||||||
 | 
					    case  2:           return new cMenuEditIntItem(      tr("Rid"),         &ridM, 0);
 | 
				
			||||||
 | 
					    case  3: ST("Z ")  return new cMenuEditIntItem(  trVDR("Srate"),        &srateM);                                      else return GetOsdItem();
 | 
				
			||||||
 | 
					    case  4: ST("Z ")  return new cMenuEditIntItem(     tr("SignalSource"), &stpM.signalSourceM, 1, 255);                  else return GetOsdItem();
 | 
				
			||||||
 | 
					    case  5: ST("Z ")  return new cMenuEditChrItem(  trVDR("Polarization"), &stpM.polarizationM, "HVLR");                  else return GetOsdItem();
 | 
				
			||||||
 | 
					    case  6: ST("Z ")  return new cMenuEditSatipItem(trVDR("Rolloff"),      &stpM.rollOffM,      SatipRollOffValues);      else return GetOsdItem();
 | 
				
			||||||
 | 
					    case  7: ST("Z ")  return new cMenuEditSatipItem(   tr("PilotTones"),   &stpM.pilotTonesM,   SatipPilotTonesValues);   else return GetOsdItem();
 | 
				
			||||||
 | 
					    case  8: ST("ZY")  return new cMenuEditSatipItem(trVDR("System"),       &stpM.systemM,       SatipSystemValues);       else return GetOsdItem();
 | 
				
			||||||
 | 
					    case  9: ST("ZY")  return new cMenuEditSatipItem(trVDR("Modulation"),   &stpM.modulationM,   SatipModulationValues);   else return GetOsdItem();
 | 
				
			||||||
 | 
					    case 10: ST("ZY")  return new cMenuEditSatipItem(trVDR("CoderateH"),    &stpM.coderateHM,    SatipCodeRateValues);     else return GetOsdItem();
 | 
				
			||||||
 | 
					    case 11: ST(" Y")  return new cMenuEditSatipItem(trVDR("Bandwidth"),    &stpM.bandwidthM,    SatipBandwidthValues);    else return GetOsdItem();
 | 
				
			||||||
 | 
					    case 12: ST(" Y")  return new cMenuEditSatipItem(trVDR("Transmission"), &stpM.transmissionM, SatipTransmissionValues); else return GetOsdItem();
 | 
				
			||||||
 | 
					    case 13: ST(" Y")  return new cMenuEditSatipItem(trVDR("Guard"),        &stpM.guardM,        SatipGuardValues);        else return GetOsdItem();
 | 
				
			||||||
 | 
					    case 14: ST(" Y")  return new cMenuEditIntItem(  trVDR("StreamId"),     &stpM.streamIdM,     0, 255);                  else return GetOsdItem();
 | 
				
			||||||
 | 
					    case 15: ST(" Y")  return new cMenuEditIntItem(     tr("T2SystemId"),   &stpM.t2SystemIdM,   0, 65535);                else return GetOsdItem();
 | 
				
			||||||
 | 
					    case 16: ST(" Y")  return new cMenuEditSatipItem(   tr("SISO/MISO"),    &stpM.sisoMisoM,     SatipSisoMisoValues);     else return GetOsdItem();
 | 
				
			||||||
 | 
					    default: return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#undef ST
 | 
				
			||||||
 | 
					  return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										93
									
								
								source.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								source.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,93 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * source.h: SAT>IP plugin for the Video Disk Recorder
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * See the README file for copyright information and how to reach the author.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __SATIP_SOURCE_H
 | 
				
			||||||
 | 
					#define __SATIP_SOURCE_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <vdr/menuitems.h>
 | 
				
			||||||
 | 
					#include <vdr/sourceparams.h>
 | 
				
			||||||
 | 
					#include "common.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct tSatipParameterMap {
 | 
				
			||||||
 | 
					  int userValue;
 | 
				
			||||||
 | 
					  const char *userString;
 | 
				
			||||||
 | 
					  const char *satipString;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class cSatipTransponderParameters {
 | 
				
			||||||
 | 
					  friend class cSatipSourceParam;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  char polarizationM;
 | 
				
			||||||
 | 
					  int bandwidthM;
 | 
				
			||||||
 | 
					  int coderateHM;
 | 
				
			||||||
 | 
					  int systemM;
 | 
				
			||||||
 | 
					  int modulationM;
 | 
				
			||||||
 | 
					  int transmissionM;
 | 
				
			||||||
 | 
					  int guardM;
 | 
				
			||||||
 | 
					  int rollOffM;
 | 
				
			||||||
 | 
					  int streamIdM;
 | 
				
			||||||
 | 
					  int t2SystemIdM;
 | 
				
			||||||
 | 
					  int sisoMisoM;
 | 
				
			||||||
 | 
					  int pilotTonesM;
 | 
				
			||||||
 | 
					  int signalSourceM;
 | 
				
			||||||
 | 
					  int PrintParameter(char *ptrP, char nameP, int valueP) const;
 | 
				
			||||||
 | 
					  int PrintString(char *ptrP, int valueP, const tSatipParameterMap *mapP);
 | 
				
			||||||
 | 
					  const char *ParseParameter(const char *strP, int &valueP);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  cSatipTransponderParameters(const char *parametersP = NULL);
 | 
				
			||||||
 | 
					  char Polarization(void) const { return polarizationM; }
 | 
				
			||||||
 | 
					  int Bandwidth(void) const { return bandwidthM; }
 | 
				
			||||||
 | 
					  int CoderateH(void) const { return coderateHM; }
 | 
				
			||||||
 | 
					  int System(void) const { return systemM; }
 | 
				
			||||||
 | 
					  int Modulation(void) const { return modulationM; }
 | 
				
			||||||
 | 
					  int Transmission(void) const { return transmissionM; }
 | 
				
			||||||
 | 
					  int Guard(void) const { return guardM; }
 | 
				
			||||||
 | 
					  int RollOff(void) const { return rollOffM; }
 | 
				
			||||||
 | 
					  int StreamId(void) const { return streamIdM; }
 | 
				
			||||||
 | 
					  int T2SystemId(void) const { return t2SystemIdM; }
 | 
				
			||||||
 | 
					  int SisoMiso(void) const { return sisoMisoM; }
 | 
				
			||||||
 | 
					  int PilotTones(void) const { return pilotTonesM; }
 | 
				
			||||||
 | 
					  int SignalSource(void) const { return signalSourceM; }
 | 
				
			||||||
 | 
					  void SetPolarization(char polarizationP) { polarizationM = polarizationP; }
 | 
				
			||||||
 | 
					  void SetBandwidth(int bandwidthP) { bandwidthM = bandwidthP; }
 | 
				
			||||||
 | 
					  void SetCoderateH(int coderateHP) { coderateHM = coderateHP; }
 | 
				
			||||||
 | 
					  void SetSystem(int systemP) { systemM = systemP; }
 | 
				
			||||||
 | 
					  void SetModulation(int modulationP) { modulationM = modulationP; }
 | 
				
			||||||
 | 
					  void SetTransmission(int transmissionP) { transmissionM = transmissionP; }
 | 
				
			||||||
 | 
					  void SetGuard(int guardP) { guardM = guardP; }
 | 
				
			||||||
 | 
					  void SetRollOff(int rollOffP) { rollOffM = rollOffP; }
 | 
				
			||||||
 | 
					  void SetStreamId(int streamIdP) { streamIdM = streamIdP; }
 | 
				
			||||||
 | 
					  void SetT2SystemId(int t2SystemIdP) { t2SystemIdM = t2SystemIdP; }
 | 
				
			||||||
 | 
					  void SetSisoMiso(int sisoMisoP) { sisoMisoM = sisoMisoP; }
 | 
				
			||||||
 | 
					  void SetPilotTones(int pilotTonesP) { pilotTonesM = pilotTonesP; }
 | 
				
			||||||
 | 
					  void SetSignalSource(int signalSourceP) { signalSourceM = signalSourceP; }
 | 
				
			||||||
 | 
					  cString UrlParameters(char typeP);
 | 
				
			||||||
 | 
					  cString ToString(char typeP) const;
 | 
				
			||||||
 | 
					  bool Parse(const char *strP);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class cSatipSourceParam : public cSourceParam
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  int paramM;
 | 
				
			||||||
 | 
					  int nidM;
 | 
				
			||||||
 | 
					  int tidM;
 | 
				
			||||||
 | 
					  int ridM;
 | 
				
			||||||
 | 
					  int srateM;
 | 
				
			||||||
 | 
					  cChannel dataM;
 | 
				
			||||||
 | 
					  cSatipTransponderParameters stpM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  cSatipSourceParam(char sourceP, const char *descriptionP);
 | 
				
			||||||
 | 
					  virtual void SetData(cChannel *channelP);
 | 
				
			||||||
 | 
					  virtual void GetData(cChannel *channelP);
 | 
				
			||||||
 | 
					  virtual cOsdItem *GetOsdItem(void);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // __SATIP_SOURCE_H
 | 
				
			||||||
							
								
								
									
										219
									
								
								statistics.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										219
									
								
								statistics.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,219 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * statistics.c: SAT>IP plugin for the Video Disk Recorder
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * See the README file for copyright information and how to reach the author.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <limits.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "common.h"
 | 
				
			||||||
 | 
					#include "statistics.h"
 | 
				
			||||||
 | 
					#include "config.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Section statistics class
 | 
				
			||||||
 | 
					cSatipSectionStatistics::cSatipSectionStatistics()
 | 
				
			||||||
 | 
					: filteredDataM(0),
 | 
				
			||||||
 | 
					  numberOfCallsM(0),
 | 
				
			||||||
 | 
					  timerM(),
 | 
				
			||||||
 | 
					  mutexM()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipSectionStatistics::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cSatipSectionStatistics::~cSatipSectionStatistics()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipSectionStatistics::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cString cSatipSectionStatistics::GetSectionStatistic()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipSectionStatistics::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  cMutexLock MutexLock(&mutexM);
 | 
				
			||||||
 | 
					  uint64_t elapsed = timerM.Elapsed(); /* in milliseconds */
 | 
				
			||||||
 | 
					  timerM.Set();
 | 
				
			||||||
 | 
					  long bitrate = elapsed ? (long)(1000.0L * filteredDataM / KILOBYTE(1) / elapsed) : 0L;
 | 
				
			||||||
 | 
					  if (!SatipConfig.GetUseBytes())
 | 
				
			||||||
 | 
					     bitrate *= 8;
 | 
				
			||||||
 | 
					  // no trailing linefeed here!
 | 
				
			||||||
 | 
					  cString s = cString::sprintf("%4ld (%4ld k%s/s)", numberOfCallsM, bitrate,
 | 
				
			||||||
 | 
					                               SatipConfig.GetUseBytes() ? "B" : "bit");
 | 
				
			||||||
 | 
					  filteredDataM = numberOfCallsM = 0;
 | 
				
			||||||
 | 
					  return s;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipSectionStatistics::AddSectionStatistic(long bytesP, long callsP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipSectionStatistics::%s(%ld, %ld)", __FUNCTION__, bytesP, callsP);
 | 
				
			||||||
 | 
					  cMutexLock MutexLock(&mutexM);
 | 
				
			||||||
 | 
					  filteredDataM += bytesP;
 | 
				
			||||||
 | 
					  numberOfCallsM += callsP;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// --- cSatipPidStatistics ----------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Device statistics class
 | 
				
			||||||
 | 
					cSatipPidStatistics::cSatipPidStatistics()
 | 
				
			||||||
 | 
					: timerM(),
 | 
				
			||||||
 | 
					  mutexM()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipPidStatistics::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  const int numberOfElements = sizeof(mostActivePidsM) / sizeof(pidStruct);
 | 
				
			||||||
 | 
					  for (int i = 0; i < numberOfElements; ++i) {
 | 
				
			||||||
 | 
					      mostActivePidsM[i].pid = -1;
 | 
				
			||||||
 | 
					      mostActivePidsM[i].dataAmount = 0L;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cSatipPidStatistics::~cSatipPidStatistics()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipPidStatistics::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cString cSatipPidStatistics::GetPidStatistic()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipPidStatistics::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  cMutexLock MutexLock(&mutexM);
 | 
				
			||||||
 | 
					  const int numberOfElements = sizeof(mostActivePidsM) / sizeof(pidStruct);
 | 
				
			||||||
 | 
					  uint64_t elapsed = timerM.Elapsed(); /* in milliseconds */
 | 
				
			||||||
 | 
					  timerM.Set();
 | 
				
			||||||
 | 
					  cString s("Active pids:\n");
 | 
				
			||||||
 | 
					  for (int i = 0; i < numberOfElements; ++i) {
 | 
				
			||||||
 | 
					      if (mostActivePidsM[i].pid >= 0) {
 | 
				
			||||||
 | 
					         long bitrate = elapsed ? (long)(1000.0L * mostActivePidsM[i].dataAmount / KILOBYTE(1) / elapsed) : 0L;
 | 
				
			||||||
 | 
					         if (!SatipConfig.GetUseBytes())
 | 
				
			||||||
 | 
					            bitrate *= 8;
 | 
				
			||||||
 | 
					         s = cString::sprintf("%sPid %d: %4d (%4ld k%s/s)\n", *s, i,
 | 
				
			||||||
 | 
					                              mostActivePidsM[i].pid, bitrate,
 | 
				
			||||||
 | 
					                              SatipConfig.GetUseBytes() ? "B" : "bit");
 | 
				
			||||||
 | 
					         }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					  for (int i = 0; i < numberOfElements; ++i) {
 | 
				
			||||||
 | 
					      mostActivePidsM[i].pid = -1;
 | 
				
			||||||
 | 
					      mostActivePidsM[i].dataAmount = 0L;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					  return s;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int cSatipPidStatistics::SortPids(const void* data1P, const void* data2P)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipPidStatistics::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  const pidStruct *comp1 = reinterpret_cast<const pidStruct*>(data1P);
 | 
				
			||||||
 | 
					  const pidStruct *comp2 = reinterpret_cast<const pidStruct*>(data2P);
 | 
				
			||||||
 | 
					  if (comp1->dataAmount > comp2->dataAmount)
 | 
				
			||||||
 | 
					     return -1;
 | 
				
			||||||
 | 
					  if (comp1->dataAmount < comp2->dataAmount)
 | 
				
			||||||
 | 
					     return 1;
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipPidStatistics::AddPidStatistic(int pidP, long payloadP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipPidStatistics::%s(%ld, %ld)", __FUNCTION__, pidP, payloadP);
 | 
				
			||||||
 | 
					  cMutexLock MutexLock(&mutexM);
 | 
				
			||||||
 | 
					  const int numberOfElements = sizeof(mostActivePidsM) / sizeof(pidStruct);
 | 
				
			||||||
 | 
					  // If our statistic already is in the array, update it and quit
 | 
				
			||||||
 | 
					  for (int i = 0; i < numberOfElements; ++i) {
 | 
				
			||||||
 | 
					      if (mostActivePidsM[i].pid == pidP) {
 | 
				
			||||||
 | 
					         mostActivePidsM[i].dataAmount += payloadP;
 | 
				
			||||||
 | 
					         // Now re-sort the array and quit
 | 
				
			||||||
 | 
					         qsort(mostActivePidsM, numberOfElements, sizeof(pidStruct), SortPids);
 | 
				
			||||||
 | 
					         return;
 | 
				
			||||||
 | 
					         }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					  // Apparently our pid isn't in the array. Replace the last element with this
 | 
				
			||||||
 | 
					  // one if new payload is greater
 | 
				
			||||||
 | 
					  if (mostActivePidsM[numberOfElements - 1].dataAmount < payloadP) {
 | 
				
			||||||
 | 
					      mostActivePidsM[numberOfElements - 1].pid = pidP;
 | 
				
			||||||
 | 
					      mostActivePidsM[numberOfElements - 1].dataAmount = payloadP;
 | 
				
			||||||
 | 
					     // Re-sort
 | 
				
			||||||
 | 
					     qsort(mostActivePidsM, numberOfElements, sizeof(pidStruct), SortPids);
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// --- cSatipTunerStatistics --------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Tuner statistics class
 | 
				
			||||||
 | 
					cSatipTunerStatistics::cSatipTunerStatistics()
 | 
				
			||||||
 | 
					: dataBytesM(0),
 | 
				
			||||||
 | 
					  timerM(),
 | 
				
			||||||
 | 
					  mutexM()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipTunerStatistics::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cSatipTunerStatistics::~cSatipTunerStatistics()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipTunerStatistics::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cString cSatipTunerStatistics::GetTunerStatistic()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipTunerStatistics::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  cMutexLock MutexLock(&mutexM);
 | 
				
			||||||
 | 
					  uint64_t elapsed = timerM.Elapsed(); /* in milliseconds */
 | 
				
			||||||
 | 
					  timerM.Set();
 | 
				
			||||||
 | 
					  long bitrate = elapsed ? (long)(1000.0L * dataBytesM / KILOBYTE(1) / elapsed) : 0L;
 | 
				
			||||||
 | 
					  if (!SatipConfig.GetUseBytes())
 | 
				
			||||||
 | 
					     bitrate *= 8;
 | 
				
			||||||
 | 
					  cString s = cString::sprintf("%ld k%s/s", bitrate, SatipConfig.GetUseBytes() ? "B" : "bit");
 | 
				
			||||||
 | 
					  dataBytesM = 0;
 | 
				
			||||||
 | 
					  return s;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipTunerStatistics::AddTunerStatistic(long bytesP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipTunerStatistics::%s(%ld)", __FUNCTION__, bytesP);
 | 
				
			||||||
 | 
					  cMutexLock MutexLock(&mutexM);
 | 
				
			||||||
 | 
					  dataBytesM += bytesP;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Buffer statistics class
 | 
				
			||||||
 | 
					cSatipBufferStatistics::cSatipBufferStatistics()
 | 
				
			||||||
 | 
					: dataBytesM(0),
 | 
				
			||||||
 | 
					  freeSpaceM(0),
 | 
				
			||||||
 | 
					  usedSpaceM(0),
 | 
				
			||||||
 | 
					  timerM(),
 | 
				
			||||||
 | 
					  mutexM()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipBufferStatistics::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cSatipBufferStatistics::~cSatipBufferStatistics()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipBufferStatistics::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cString cSatipBufferStatistics::GetBufferStatistic()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipBufferStatistics::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  cMutexLock MutexLock(&mutexM);
 | 
				
			||||||
 | 
					  uint64_t elapsed = timerM.Elapsed(); /* in milliseconds */
 | 
				
			||||||
 | 
					  timerM.Set();
 | 
				
			||||||
 | 
					  long bitrate = elapsed ? (long)(1000.0L * dataBytesM / KILOBYTE(1) / elapsed) : 0L;
 | 
				
			||||||
 | 
					  long totalSpace = SATIP_BUFFER_SIZE;
 | 
				
			||||||
 | 
					  float percentage = (float)((float)usedSpaceM / (float)totalSpace * 100.0);
 | 
				
			||||||
 | 
					  long totalKilos = totalSpace / KILOBYTE(1);
 | 
				
			||||||
 | 
					  long usedKilos = usedSpaceM / KILOBYTE(1);
 | 
				
			||||||
 | 
					  if (!SatipConfig.GetUseBytes()) {
 | 
				
			||||||
 | 
					     bitrate *= 8;
 | 
				
			||||||
 | 
					     totalKilos *= 8;
 | 
				
			||||||
 | 
					     usedKilos *= 8;
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					  cString s = cString::sprintf("Buffer bitrate: %ld k%s/s\nBuffer usage: %ld/%ld k%s (%2.1f%%)\n", bitrate,
 | 
				
			||||||
 | 
					                               SatipConfig.GetUseBytes() ? "B" : "bit", usedKilos, totalKilos,
 | 
				
			||||||
 | 
					                               SatipConfig.GetUseBytes() ? "B" : "bit", percentage);
 | 
				
			||||||
 | 
					  dataBytesM = 0;
 | 
				
			||||||
 | 
					  usedSpaceM = 0;
 | 
				
			||||||
 | 
					  return s;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipBufferStatistics::AddBufferStatistic(long bytesP, long usedP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipBufferStatistics::%s(%ld, %ld)", __FUNCTION__, bytesP, usedP);
 | 
				
			||||||
 | 
					  cMutexLock MutexLock(&mutexM);
 | 
				
			||||||
 | 
					  dataBytesM += bytesP;
 | 
				
			||||||
 | 
					  if (usedP > usedSpaceM)
 | 
				
			||||||
 | 
					     usedSpaceM = usedP;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										87
									
								
								statistics.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								statistics.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,87 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * statistics.h: SAT>IP plugin for the Video Disk Recorder
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * See the README file for copyright information and how to reach the author.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __SATIP_STATISTICS_H
 | 
				
			||||||
 | 
					#define __SATIP_STATISTICS_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <vdr/thread.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Section statistics
 | 
				
			||||||
 | 
					class cSatipSectionStatistics {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  cSatipSectionStatistics();
 | 
				
			||||||
 | 
					  virtual ~cSatipSectionStatistics();
 | 
				
			||||||
 | 
					  cString GetSectionStatistic();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					protected:
 | 
				
			||||||
 | 
					  void AddSectionStatistic(long bytesP, long callsP);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  long filteredDataM;
 | 
				
			||||||
 | 
					  long numberOfCallsM;
 | 
				
			||||||
 | 
					  cTimeMs timerM;
 | 
				
			||||||
 | 
					  cMutex mutexM;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Pid statistics
 | 
				
			||||||
 | 
					class cSatipPidStatistics {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  cSatipPidStatistics();
 | 
				
			||||||
 | 
					  virtual ~cSatipPidStatistics();
 | 
				
			||||||
 | 
					  cString GetPidStatistic();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					protected:
 | 
				
			||||||
 | 
					  void AddPidStatistic(int pidP, long payloadP);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  struct pidStruct {
 | 
				
			||||||
 | 
					    int  pid;
 | 
				
			||||||
 | 
					    long dataAmount;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  pidStruct mostActivePidsM[SATIP_STATS_ACTIVE_PIDS_COUNT];
 | 
				
			||||||
 | 
					  cTimeMs timerM;
 | 
				
			||||||
 | 
					  cMutex mutexM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  static int SortPids(const void* data1P, const void* data2P);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Tuner statistics
 | 
				
			||||||
 | 
					class cSatipTunerStatistics {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  cSatipTunerStatistics();
 | 
				
			||||||
 | 
					  virtual ~cSatipTunerStatistics();
 | 
				
			||||||
 | 
					  cString GetTunerStatistic();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					protected:
 | 
				
			||||||
 | 
					  void AddTunerStatistic(long bytesP);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  long dataBytesM;
 | 
				
			||||||
 | 
					  cTimeMs timerM;
 | 
				
			||||||
 | 
					  cMutex mutexM;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Buffer statistics
 | 
				
			||||||
 | 
					class cSatipBufferStatistics {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  cSatipBufferStatistics();
 | 
				
			||||||
 | 
					  virtual ~cSatipBufferStatistics();
 | 
				
			||||||
 | 
					  cString GetBufferStatistic();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					protected:
 | 
				
			||||||
 | 
					  void AddBufferStatistic(long bytesP, long usedP);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  long dataBytesM;
 | 
				
			||||||
 | 
					  long freeSpaceM;
 | 
				
			||||||
 | 
					  long usedSpaceM;
 | 
				
			||||||
 | 
					  cTimeMs timerM;
 | 
				
			||||||
 | 
					  cMutex mutexM;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // __SATIP_STATISTICS_H
 | 
				
			||||||
							
								
								
									
										482
									
								
								tuner.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										482
									
								
								tuner.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,482 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * tuner.c: SAT>IP plugin for the Video Disk Recorder
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * See the README file for copyright information and how to reach the author.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "common.h"
 | 
				
			||||||
 | 
					#include "config.h"
 | 
				
			||||||
 | 
					#include "tuner.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cSatipTuner::cSatipTuner(cSatipDeviceIf &deviceP, unsigned int packetLenP)
 | 
				
			||||||
 | 
					: cThread("SAT>IP tuner"),
 | 
				
			||||||
 | 
					  sleepM(),
 | 
				
			||||||
 | 
					  deviceM(&deviceP),
 | 
				
			||||||
 | 
					  packetBufferLenM(packetLenP),
 | 
				
			||||||
 | 
					  rtpSocketM(new cSatipSocket()),
 | 
				
			||||||
 | 
					  rtcpSocketM(new cSatipSocket()),
 | 
				
			||||||
 | 
					  streamAddrM(""),
 | 
				
			||||||
 | 
					  streamParamM(""),
 | 
				
			||||||
 | 
					  mutexM(),
 | 
				
			||||||
 | 
					  handleM(NULL),
 | 
				
			||||||
 | 
					  headerListM(NULL),
 | 
				
			||||||
 | 
					  keepAliveM(),
 | 
				
			||||||
 | 
					  pidUpdateCacheM(),
 | 
				
			||||||
 | 
					  timeoutM(eKeepAliveIntervalMs),
 | 
				
			||||||
 | 
					  openedM(false),
 | 
				
			||||||
 | 
					  tunedM(false),
 | 
				
			||||||
 | 
					  hasLockM(false),
 | 
				
			||||||
 | 
					  signalStrengthM(-1),
 | 
				
			||||||
 | 
					  signalQualityM(-1),
 | 
				
			||||||
 | 
					  streamIdM(-1),
 | 
				
			||||||
 | 
					  pidUpdatedM(false),
 | 
				
			||||||
 | 
					  pidsM()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipTuner::%s(%d)", __FUNCTION__, packetBufferLenM);
 | 
				
			||||||
 | 
					  // Allocate packet buffer
 | 
				
			||||||
 | 
					  packetBufferM = MALLOC(unsigned char, packetBufferLenM);
 | 
				
			||||||
 | 
					  if (packetBufferM)
 | 
				
			||||||
 | 
					     memset(packetBufferM, 0, packetBufferLenM);
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					     error("MALLOC() failed for packet buffer");
 | 
				
			||||||
 | 
					  // Start thread
 | 
				
			||||||
 | 
					  Start();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cSatipTuner::~cSatipTuner()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipTuner::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  // Stop thread
 | 
				
			||||||
 | 
					  sleepM.Signal();
 | 
				
			||||||
 | 
					  if (Running())
 | 
				
			||||||
 | 
					     Cancel(3);
 | 
				
			||||||
 | 
					  Close();
 | 
				
			||||||
 | 
					  // Free allocated memory
 | 
				
			||||||
 | 
					  free(packetBufferM);
 | 
				
			||||||
 | 
					  DELETENULL(rtcpSocketM);
 | 
				
			||||||
 | 
					  DELETENULL(rtpSocketM);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					size_t cSatipTuner::HeaderCallback(void *ptrP, size_t sizeP, size_t nmembP, void *dataP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  cSatipTuner *obj = reinterpret_cast<cSatipTuner *>(dataP);
 | 
				
			||||||
 | 
					  size_t len = sizeP * nmembP;
 | 
				
			||||||
 | 
					  //debug("cSatipTuner::%s(%zu)", __FUNCTION__, len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int id = -1, timeout = -1;
 | 
				
			||||||
 | 
					  char *s, *p = (char *)ptrP;
 | 
				
			||||||
 | 
					  char *r = strtok_r(p, "\r\n", &s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  while (r) {
 | 
				
			||||||
 | 
					        //debug("cSatipTuner::%s(%zu): %s", __FUNCTION__, len, r);
 | 
				
			||||||
 | 
					        if (strstr(r, "com.ses.streamID")) {
 | 
				
			||||||
 | 
					           if (sscanf(r, "com.ses.streamID: %11d", &id) != 1)
 | 
				
			||||||
 | 
					              id = -1;
 | 
				
			||||||
 | 
					           }
 | 
				
			||||||
 | 
					        else if (strstr(r, "Session:")) {
 | 
				
			||||||
 | 
					           int session = -1;
 | 
				
			||||||
 | 
					           if (sscanf(r, "Session: %11d;timeout=%11d", &session, &timeout) != 2)
 | 
				
			||||||
 | 
					              timeout = -1;
 | 
				
			||||||
 | 
					           }
 | 
				
			||||||
 | 
					        r = strtok_r(NULL, "\r\n", &s);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (id >= 0 && obj)
 | 
				
			||||||
 | 
					     obj->SetStreamInfo(id, timeout);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return len;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipTuner::Action(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipTuner::%s(): entering", __FUNCTION__);
 | 
				
			||||||
 | 
					  cTimeMs timeout(0);
 | 
				
			||||||
 | 
					  // Increase priority
 | 
				
			||||||
 | 
					  SetPriority(-1);
 | 
				
			||||||
 | 
					  // Do the thread loop
 | 
				
			||||||
 | 
					  while (packetBufferM && Running()) {
 | 
				
			||||||
 | 
					        int length = -1;
 | 
				
			||||||
 | 
					        unsigned int size = min(deviceM->CheckData(), packetBufferLenM);
 | 
				
			||||||
 | 
					        if (tunedM && (size > 0)) {
 | 
				
			||||||
 | 
					           // Update pids
 | 
				
			||||||
 | 
					           UpdatePids();
 | 
				
			||||||
 | 
					           // Remember the heart beat
 | 
				
			||||||
 | 
					           KeepAlive();
 | 
				
			||||||
 | 
					           // Read reception statistics
 | 
				
			||||||
 | 
					           if (rtcpSocketM && rtcpSocketM->IsOpen()) {
 | 
				
			||||||
 | 
					              unsigned char buf[1450];
 | 
				
			||||||
 | 
					              memset(buf, 0, sizeof(buf));
 | 
				
			||||||
 | 
					              if (rtcpSocketM->ReadApplication(buf, sizeof(buf)) > 0) {
 | 
				
			||||||
 | 
					                 ParseReceptionParameters((const char *)buf);
 | 
				
			||||||
 | 
					                 timeout.Set(eReConnectTimeoutMs);
 | 
				
			||||||
 | 
					                 }
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					           // Read data
 | 
				
			||||||
 | 
					           if (rtpSocketM && rtpSocketM->IsOpen())
 | 
				
			||||||
 | 
					              length = rtpSocketM->ReadVideo(packetBufferM, size);
 | 
				
			||||||
 | 
					           }
 | 
				
			||||||
 | 
					        if (length > 0) {
 | 
				
			||||||
 | 
					           AddTunerStatistic(length);
 | 
				
			||||||
 | 
					           deviceM->WriteData(packetBufferM, length);
 | 
				
			||||||
 | 
					           timeout.Set(eReConnectTimeoutMs);
 | 
				
			||||||
 | 
					           }
 | 
				
			||||||
 | 
					        else {
 | 
				
			||||||
 | 
					           // Reconnect if necessary
 | 
				
			||||||
 | 
					           if (openedM && !tunedM && timeout.TimedOut()) {
 | 
				
			||||||
 | 
					              Disconnect();
 | 
				
			||||||
 | 
					              Connect();
 | 
				
			||||||
 | 
					              timeout.Set(eReConnectTimeoutMs);
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					           sleepM.Wait(10); // to avoid busy loop and reduce cpu load
 | 
				
			||||||
 | 
					           }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					  debug("cSatipTuner::%s(): exiting", __FUNCTION__);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cSatipTuner::Open(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipTuner::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  if (Connect()) {
 | 
				
			||||||
 | 
					     openedM = true;
 | 
				
			||||||
 | 
					     return true;
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					  return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cSatipTuner::Close(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipTuner::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  openedM = false;
 | 
				
			||||||
 | 
					  Disconnect();
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cSatipTuner::Connect(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  cMutexLock MutexLock(&mutexM);
 | 
				
			||||||
 | 
					  debug("cSatipTuner::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Initialize the curl session
 | 
				
			||||||
 | 
					  if (!handleM)
 | 
				
			||||||
 | 
					     handleM = curl_easy_init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (handleM && !isempty(*streamAddrM)) {
 | 
				
			||||||
 | 
					     cString uri, control, transport, range;
 | 
				
			||||||
 | 
					     CURLcode res = CURLE_OK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     // Just retune
 | 
				
			||||||
 | 
					     if (tunedM && (streamIdM >= 0)) {
 | 
				
			||||||
 | 
					        debug("cSatipTuner::%s(): retune", __FUNCTION__);
 | 
				
			||||||
 | 
					        uri = cString::sprintf("rtsp://%s/stream=%d", *streamAddrM, streamIdM);
 | 
				
			||||||
 | 
					        SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, *uri);
 | 
				
			||||||
 | 
					        SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_PLAY);
 | 
				
			||||||
 | 
					        SATIP_CURL_EASY_PERFORM(handleM);
 | 
				
			||||||
 | 
					        if (!ValidateLatestResponse())
 | 
				
			||||||
 | 
					           return false;
 | 
				
			||||||
 | 
					        // Flush any old content
 | 
				
			||||||
 | 
					        if (rtpSocketM)
 | 
				
			||||||
 | 
					           rtpSocketM->Flush();
 | 
				
			||||||
 | 
					        keepAliveM.Set(eKeepAliveIntervalMs);
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef DEBUG
 | 
				
			||||||
 | 
					     // Verbose output
 | 
				
			||||||
 | 
					     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_VERBOSE, 1L);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     // Set callback
 | 
				
			||||||
 | 
					     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_HEADERFUNCTION, cSatipTuner::HeaderCallback);
 | 
				
			||||||
 | 
					     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEHEADER, this);
 | 
				
			||||||
 | 
					     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     // No progress meter and no signaling
 | 
				
			||||||
 | 
					     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_NOPROGRESS, 1L);
 | 
				
			||||||
 | 
					     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_NOSIGNAL, 1L);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     // Set timeouts
 | 
				
			||||||
 | 
					     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_TIMEOUT_MS, (long)eConnectTimeoutMs);
 | 
				
			||||||
 | 
					     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_CONNECTTIMEOUT_MS, (long)eConnectTimeoutMs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     // Set user-agent
 | 
				
			||||||
 | 
					     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_USERAGENT, *cString::sprintf("vdr-%s/%s", PLUGIN_NAME_I18N, VERSION));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     // Set URL
 | 
				
			||||||
 | 
					     char *p = curl_easy_unescape(handleM, *streamAddrM, 0, NULL);
 | 
				
			||||||
 | 
					     streamAddrM = p;
 | 
				
			||||||
 | 
					     curl_free(p);
 | 
				
			||||||
 | 
					     uri = cString::sprintf("rtsp://%s/", *streamAddrM);
 | 
				
			||||||
 | 
					     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_URL, *uri);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     // Open sockets
 | 
				
			||||||
 | 
					     int i = 100;
 | 
				
			||||||
 | 
					     while (i-- > 0) {
 | 
				
			||||||
 | 
					           if (rtpSocketM->Open() && rtcpSocketM->Open(rtpSocketM->Port() + 1))
 | 
				
			||||||
 | 
					              break;
 | 
				
			||||||
 | 
					           rtpSocketM->Close();
 | 
				
			||||||
 | 
					           rtcpSocketM->Close();
 | 
				
			||||||
 | 
					           }
 | 
				
			||||||
 | 
					     if ((rtpSocketM->Port() <= 0) || (rtcpSocketM->Port() <= 0)) {
 | 
				
			||||||
 | 
					        error("Cannot open required ports!");
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     // Request server options: "&pids=all" for the whole mux
 | 
				
			||||||
 | 
					     uri = cString::sprintf("rtsp://%s/?%s&pids=0", *streamAddrM, *streamParamM);
 | 
				
			||||||
 | 
					     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, *uri);
 | 
				
			||||||
 | 
					     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_OPTIONS);
 | 
				
			||||||
 | 
					     SATIP_CURL_EASY_PERFORM(handleM);
 | 
				
			||||||
 | 
					     if (!ValidateLatestResponse())
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     // Setup media stream
 | 
				
			||||||
 | 
					     transport = cString::sprintf("RTP/AVP;unicast;client_port=%d-%d", rtpSocketM->Port(), rtcpSocketM->Port());
 | 
				
			||||||
 | 
					     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_TRANSPORT, *transport);
 | 
				
			||||||
 | 
					     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_SETUP);
 | 
				
			||||||
 | 
					     SATIP_CURL_EASY_PERFORM(handleM);
 | 
				
			||||||
 | 
					     if (!ValidateLatestResponse())
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     // Start playing
 | 
				
			||||||
 | 
					     uri = cString::sprintf("rtsp://%s/stream=%d", *streamAddrM, streamIdM);
 | 
				
			||||||
 | 
					     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, *uri);
 | 
				
			||||||
 | 
					     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_PLAY);
 | 
				
			||||||
 | 
					     SATIP_CURL_EASY_PERFORM(handleM);
 | 
				
			||||||
 | 
					     if (!ValidateLatestResponse())
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     keepAliveM.Set(eKeepAliveIntervalMs);
 | 
				
			||||||
 | 
					     tunedM = true;
 | 
				
			||||||
 | 
					     return true;
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cSatipTuner::Disconnect(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  cMutexLock MutexLock(&mutexM);
 | 
				
			||||||
 | 
					  debug("cSatipTuner::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Terminate curl session
 | 
				
			||||||
 | 
					  if (handleM) {
 | 
				
			||||||
 | 
					     // Teardown rtsp session
 | 
				
			||||||
 | 
					     if (!isempty(*streamAddrM) && streamIdM >= 0) {
 | 
				
			||||||
 | 
					        CURLcode res = CURLE_OK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        cString uri = cString::sprintf("rtsp://%s/stream=%d", *streamAddrM, streamIdM);
 | 
				
			||||||
 | 
					        SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, *uri);
 | 
				
			||||||
 | 
					        SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_TEARDOWN);
 | 
				
			||||||
 | 
					        SATIP_CURL_EASY_PERFORM(handleM);
 | 
				
			||||||
 | 
					        ValidateLatestResponse();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     // Cleanup curl stuff
 | 
				
			||||||
 | 
					     if (headerListM) {
 | 
				
			||||||
 | 
					        curl_slist_free_all(headerListM);
 | 
				
			||||||
 | 
					        headerListM = NULL;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					     curl_easy_cleanup(handleM);
 | 
				
			||||||
 | 
					     handleM = NULL;
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Close the listening sockets
 | 
				
			||||||
 | 
					  rtpSocketM->Close();
 | 
				
			||||||
 | 
					  rtcpSocketM->Close();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Reset signal parameters
 | 
				
			||||||
 | 
					  hasLockM = false;
 | 
				
			||||||
 | 
					  signalStrengthM = -1;
 | 
				
			||||||
 | 
					  signalQualityM = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  tunedM = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cSatipTuner::ValidateLatestResponse(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipTuner::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  if (handleM) {
 | 
				
			||||||
 | 
					     long rc = 0;
 | 
				
			||||||
 | 
					     CURLcode res = CURLE_OK;
 | 
				
			||||||
 | 
					     SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_RESPONSE_CODE, &rc);
 | 
				
			||||||
 | 
					     if (rc == 200)
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					     else if (rc != 0)
 | 
				
			||||||
 | 
					        error("Tuner detected invalid status code: %ld", rc);
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipTuner::ParseReceptionParameters(const char *paramP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipTuner::%s(%s)", __FUNCTION__, paramP);
 | 
				
			||||||
 | 
					  // DVB-S2:
 | 
				
			||||||
 | 
					  // ver=<major>.<minor>;src=<srcID>;tuner=<feID>,<level>,<lock>,<quality>,<frequency>,<polarisation>,<system>,<type>,<pilots>,<roll_off>,<symbol_rate>,<fec_inner>;pids=<pid0>,...,<pidn>
 | 
				
			||||||
 | 
					  // DVB-T2:
 | 
				
			||||||
 | 
					  // ver=1.1;tuner=<feID>,<level>,<lock>,<quality>,<freq>,<bw>,<msys>,<tmode>,<mtype>,<gi>,<fec>,<plp>,<t2id>,<sm>;pids=<pid0>,...,<pidn>
 | 
				
			||||||
 | 
					  if (!isempty(paramP)) {
 | 
				
			||||||
 | 
					     char *s = strdup(paramP);
 | 
				
			||||||
 | 
					     char *c = strstr(s, ";tuner=");
 | 
				
			||||||
 | 
					     if (c)  {
 | 
				
			||||||
 | 
					        int value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // level:
 | 
				
			||||||
 | 
					        // Numerical value between 0 and 255
 | 
				
			||||||
 | 
					        // An incoming L-band satellite signal of
 | 
				
			||||||
 | 
					        // -25dBm corresponds to 224
 | 
				
			||||||
 | 
					        // -65dBm corresponds to 32
 | 
				
			||||||
 | 
					        // No signal corresponds to 0
 | 
				
			||||||
 | 
					        c = strstr(c, ",");
 | 
				
			||||||
 | 
					        value = atoi(++c);
 | 
				
			||||||
 | 
					        // Scale value to 0-100
 | 
				
			||||||
 | 
					        signalStrengthM = (value >= 0) ? (value * 100 / 255) : -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // lock:
 | 
				
			||||||
 | 
					        // lock Set to one of the following values:
 | 
				
			||||||
 | 
					        // "0" the frontend is not locked
 | 
				
			||||||
 | 
					        // "1" the frontend is locked
 | 
				
			||||||
 | 
					        c = strstr(c, ",");
 | 
				
			||||||
 | 
					        hasLockM = atoi(++c);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // quality:
 | 
				
			||||||
 | 
					        // Numerical value between 0 and 15
 | 
				
			||||||
 | 
					        // Lowest value corresponds to highest error rate
 | 
				
			||||||
 | 
					        // The value 15 shall correspond to
 | 
				
			||||||
 | 
					        // -a BER lower than 2x10-4 after Viterbi for DVB-S
 | 
				
			||||||
 | 
					        // -a PER lower than 10-7 for DVB-S2
 | 
				
			||||||
 | 
					        c = strstr(c, ",");
 | 
				
			||||||
 | 
					        value = atoi(++c);
 | 
				
			||||||
 | 
					        // Scale value to 0-100
 | 
				
			||||||
 | 
					        signalQualityM = (hasLockM && (value >= 0)) ? (value * 100 / 15) : 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					     free(s);
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cSatipTuner::SetStreamInfo(int idP, int timeoutP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  cMutexLock MutexLock(&mutexM);
 | 
				
			||||||
 | 
					  debug("cSatipTuner::%s(%d, %d)", __FUNCTION__, idP, timeoutP);
 | 
				
			||||||
 | 
					  streamIdM = idP;
 | 
				
			||||||
 | 
					  timeoutM = timeoutP > 0 ? timeoutP * 1000L : eKeepAliveIntervalMs;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cSatipTuner::SetSource(const char* addressP, const char *parameterP, const int indexP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipTuner::%s(%s, %s, %d)", __FUNCTION__, addressP, parameterP, indexP);
 | 
				
			||||||
 | 
					  if (!isempty(addressP) && !isempty(parameterP)) {
 | 
				
			||||||
 | 
					     // Update stream address and parameter
 | 
				
			||||||
 | 
					     streamAddrM = addressP;
 | 
				
			||||||
 | 
					     streamParamM = parameterP;
 | 
				
			||||||
 | 
					     // Reconnect
 | 
				
			||||||
 | 
					     Connect();
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cSatipTuner::SetPid(int pidP, int typeP, bool onP)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  debug("cSatipTuner::%s(%d, %d, %d)", __FUNCTION__, pidP, typeP, onP);
 | 
				
			||||||
 | 
					  cMutexLock MutexLock(&mutexM);
 | 
				
			||||||
 | 
					  bool found = false;
 | 
				
			||||||
 | 
					  for (int i = 0; i < pidsM.Size(); ++i) {
 | 
				
			||||||
 | 
					      if (pidsM[i] == pidP) {
 | 
				
			||||||
 | 
					         found = true;
 | 
				
			||||||
 | 
					         if (!onP) {
 | 
				
			||||||
 | 
					            pidsM.Remove(i);
 | 
				
			||||||
 | 
					            pidUpdatedM = true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					         break;
 | 
				
			||||||
 | 
					         }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					  if (onP && !found) {
 | 
				
			||||||
 | 
					      pidsM.Append(pidP);
 | 
				
			||||||
 | 
					      pidUpdatedM = true;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					  pidUpdateCacheM.Set(ePidUpdateIntervalMs);
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cSatipTuner::UpdatePids(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  cMutexLock MutexLock(&mutexM);
 | 
				
			||||||
 | 
					  if (pidUpdateCacheM.TimedOut() && pidUpdatedM && pidsM.Size() && tunedM && handleM && !isempty(*streamAddrM) && (streamIdM > 0)) {
 | 
				
			||||||
 | 
					     debug("cSatipTuner::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					     CURLcode res = CURLE_OK;
 | 
				
			||||||
 | 
					     //cString uri = cString::sprintf("rtsp://%s/stream=%d?%spids=%d", *streamAddrM, streamIdM, onP ? "add" : "del", pidP);
 | 
				
			||||||
 | 
					     cString uri = cString::sprintf("rtsp://%s/stream=%d?pids=", *streamAddrM, streamIdM);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     for (int i = 0; i < pidsM.Size(); ++i)
 | 
				
			||||||
 | 
					         uri = cString::sprintf("%s%d%s", *uri, pidsM[i], (i == (pidsM.Size() - 1)) ? "" : ",");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, *uri);
 | 
				
			||||||
 | 
					     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_PLAY);
 | 
				
			||||||
 | 
					     SATIP_CURL_EASY_PERFORM(handleM);
 | 
				
			||||||
 | 
					     if (ValidateLatestResponse()) {
 | 
				
			||||||
 | 
					        keepAliveM.Set(eKeepAliveIntervalMs);
 | 
				
			||||||
 | 
					        pidUpdatedM = false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					     else
 | 
				
			||||||
 | 
					        Disconnect();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     return true;
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cSatipTuner::KeepAlive(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  cMutexLock MutexLock(&mutexM);
 | 
				
			||||||
 | 
					  if (tunedM && handleM && keepAliveM.TimedOut()) {
 | 
				
			||||||
 | 
					     debug("cSatipTuner::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					     CURLcode res = CURLE_OK;
 | 
				
			||||||
 | 
					     cString uri = cString::sprintf("rtsp://%s/stream=%d", *streamAddrM, streamIdM);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, *uri);
 | 
				
			||||||
 | 
					     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_OPTIONS);
 | 
				
			||||||
 | 
					     SATIP_CURL_EASY_PERFORM(handleM);
 | 
				
			||||||
 | 
					     if (ValidateLatestResponse())
 | 
				
			||||||
 | 
					        keepAliveM.Set(eKeepAliveIntervalMs);
 | 
				
			||||||
 | 
					     else
 | 
				
			||||||
 | 
					        Disconnect();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     return true;
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int cSatipTuner::SignalStrength(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipTuner::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  return signalStrengthM;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int cSatipTuner::SignalQuality(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipTuner::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  return signalQualityM;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool cSatipTuner::HasLock(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipTuner::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  return tunedM && hasLockM;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cString cSatipTuner::GetSignalStatus(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipTuner::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  return cString::sprintf("lock=%d strength=%d quality=%d", HasLock(), SignalStrength(), SignalQuality());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cString cSatipTuner::GetInformation(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  //debug("cSatipTuner::%s()", __FUNCTION__);
 | 
				
			||||||
 | 
					  return tunedM ? cString::sprintf("rtsp://%s/?%s [stream=%d]", *streamAddrM, *streamParamM, streamIdM) : "connection failed";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										87
									
								
								tuner.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								tuner.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,87 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * tuner.h: SAT>IP plugin for the Video Disk Recorder
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * See the README file for copyright information and how to reach the author.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __SATIP_TUNER_H
 | 
				
			||||||
 | 
					#define __SATIP_TUNER_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <curl/curl.h>
 | 
				
			||||||
 | 
					#include <curl/easy.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef CURLOPT_RTSPHEADER
 | 
				
			||||||
 | 
					#error "libcurl is missing required RTSP support"
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <vdr/thread.h>
 | 
				
			||||||
 | 
					#include <vdr/tools.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "deviceif.h"
 | 
				
			||||||
 | 
					#include "statistics.h"
 | 
				
			||||||
 | 
					#include "socket.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class cSatipTuner : public cThread, public cSatipTunerStatistics {
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  enum {
 | 
				
			||||||
 | 
					    eConnectTimeoutMs    = 1500,  // in milliseconds
 | 
				
			||||||
 | 
					    ePidUpdateIntervalMs = 100,   // in milliseconds
 | 
				
			||||||
 | 
					    eReConnectTimeoutMs  = 5000,  // in milliseconds
 | 
				
			||||||
 | 
					    eKeepAliveIntervalMs = 600000 // in milliseconds
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static size_t HeaderCallback(void *ptrP, size_t sizeP, size_t nmembP, void *dataP);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  cCondWait sleepM;
 | 
				
			||||||
 | 
					  cSatipDeviceIf* deviceM;
 | 
				
			||||||
 | 
					  unsigned char* packetBufferM;
 | 
				
			||||||
 | 
					  unsigned int packetBufferLenM;
 | 
				
			||||||
 | 
					  cSatipSocket *rtpSocketM;
 | 
				
			||||||
 | 
					  cSatipSocket *rtcpSocketM;
 | 
				
			||||||
 | 
					  cString streamAddrM;
 | 
				
			||||||
 | 
					  cString streamParamM;
 | 
				
			||||||
 | 
					  cMutex mutexM;
 | 
				
			||||||
 | 
					  CURL *handleM;
 | 
				
			||||||
 | 
					  struct curl_slist *headerListM;
 | 
				
			||||||
 | 
					  cTimeMs keepAliveM;
 | 
				
			||||||
 | 
					  cTimeMs signalInfoCacheM;
 | 
				
			||||||
 | 
					  cTimeMs pidUpdateCacheM;
 | 
				
			||||||
 | 
					  int timeoutM;
 | 
				
			||||||
 | 
					  bool openedM;
 | 
				
			||||||
 | 
					  bool tunedM;
 | 
				
			||||||
 | 
					  bool hasLockM;
 | 
				
			||||||
 | 
					  int signalStrengthM;
 | 
				
			||||||
 | 
					  int signalQualityM;
 | 
				
			||||||
 | 
					  int streamIdM;
 | 
				
			||||||
 | 
					  bool pidUpdatedM;
 | 
				
			||||||
 | 
					  cVector<int> pidsM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool Connect(void);
 | 
				
			||||||
 | 
					  bool Disconnect(void);
 | 
				
			||||||
 | 
					  bool ValidateLatestResponse(void);
 | 
				
			||||||
 | 
					  void ParseReceptionParameters(const char *paramP);
 | 
				
			||||||
 | 
					  void SetStreamInfo(int idP, int timeoutP);
 | 
				
			||||||
 | 
					  bool KeepAlive(void);
 | 
				
			||||||
 | 
					  bool UpdateSignalInfoCache(void);
 | 
				
			||||||
 | 
					  bool UpdatePids(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					protected:
 | 
				
			||||||
 | 
					  virtual void Action(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  cSatipTuner(cSatipDeviceIf &deviceP, unsigned int packetLenP);
 | 
				
			||||||
 | 
					  virtual ~cSatipTuner();
 | 
				
			||||||
 | 
					  bool IsTuned(void) const { return tunedM; }
 | 
				
			||||||
 | 
					  bool SetSource(const char* addressP, const char *parameterP, const int indexP);
 | 
				
			||||||
 | 
					  bool SetPid(int pidP, int typeP, bool onP);
 | 
				
			||||||
 | 
					  bool Open(void);
 | 
				
			||||||
 | 
					  bool Close(void);
 | 
				
			||||||
 | 
					  int SignalStrength(void);
 | 
				
			||||||
 | 
					  int SignalQuality(void);
 | 
				
			||||||
 | 
					  bool HasLock(void);
 | 
				
			||||||
 | 
					  cString GetSignalStatus(void);
 | 
				
			||||||
 | 
					  cString GetInformation(void);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // __SATIP_TUNER_H
 | 
				
			||||||
		Reference in New Issue
	
	Block a user