mirror of
				https://github.com/alsa-project/alsa-tools.git
				synced 2025-10-29 05:40:25 -04:00 
			
		
		
		
	Initial version
This commit is contained in:
		
						commit
						8785f9288e
					
				
					 12 changed files with 2694 additions and 0 deletions
				
			
		
							
								
								
									
										1
									
								
								envy24control/AUTHORS
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								envy24control/AUTHORS
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | ||||||
|  | Jaroslav Kysela <perex@suse.cz> | ||||||
							
								
								
									
										282
									
								
								envy24control/COPYING
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										282
									
								
								envy24control/COPYING
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,282 @@ | ||||||
|  | GNU GENERAL PUBLIC LICENSE | ||||||
|  | 
 | ||||||
|  | Version 2, June 1991  | ||||||
|  | 
 | ||||||
|  | Copyright (C) 1989, 1991 Free Software Foundation, Inc.   | ||||||
|  | 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA | ||||||
|  | 
 | ||||||
|  | Everyone is permitted to copy and distribute verbatim copies | ||||||
|  | of this license document, but changing it is not allowed. | ||||||
|  | 
 | ||||||
|  | Preamble | ||||||
|  | 
 | ||||||
|  | The licenses for most software are designed to take away your freedom to | ||||||
|  | share and change it. By contrast, the GNU General Public License is | ||||||
|  | intended to guarantee your freedom to share and change free software--to | ||||||
|  | make sure the software is free for all its users. This General Public | ||||||
|  | License applies to most of the Free Software Foundation's software and to | ||||||
|  | any other program whose authors commit to using it. (Some other | ||||||
|  | Free Software Foundation software is covered by the GNU Library General | ||||||
|  | Public License instead.) You can apply it to your programs, too.  | ||||||
|  | 
 | ||||||
|  | When we speak of free software, we are referring to freedom, not price. Our | ||||||
|  | General Public Licenses are designed to make sure that you have the | ||||||
|  | freedom to distribute copies of free software (and charge for this service | ||||||
|  | if you wish), that you receive source code or can get it if you want it, | ||||||
|  | that you can change the software or use pieces of it in new free programs; | ||||||
|  | and that you know you can do these things.  | ||||||
|  | 
 | ||||||
|  | To protect your rights, we need to make restrictions that forbid anyone to | ||||||
|  | deny you these rights or to ask you to surrender the rights. These | ||||||
|  | restrictions translate to certain responsibilities for you if you distribute | ||||||
|  | copies of the software, or if you modify it.  | ||||||
|  | 
 | ||||||
|  | For example, if you distribute copies of such a program, whether gratis or | ||||||
|  | for a fee, you must give the recipients all the rights that you have. You | ||||||
|  | must make sure that they, too, receive or can get the source code. And you | ||||||
|  | must show them these terms so they know their rights.  | ||||||
|  | 
 | ||||||
|  | We protect your rights with two steps: (1) copyright the software, and (2) | ||||||
|  | offer you this license which gives you legal permission to copy, | ||||||
|  | distribute and/or modify the software.  | ||||||
|  | 
 | ||||||
|  | Also, for each author's protection and ours, we want to make certain that | ||||||
|  | everyone understands that there is no warranty for this free software. | ||||||
|  | If the software is modified by someone else and passed on, we want its | ||||||
|  | recipients to know that what they have is not the original, so that any | ||||||
|  | problems introduced by others will not reflect on the original authors' | ||||||
|  | reputations.  | ||||||
|  | 
 | ||||||
|  | Finally, any free program is threatened constantly by software patents. We | ||||||
|  | wish to avoid the danger that redistributors of a free program will | ||||||
|  | individually obtain patent licenses, in effect making the program | ||||||
|  | proprietary. To prevent this, we have made it clear that any patent must be | ||||||
|  | licensed for everyone's free use or not licensed at all.  | ||||||
|  | 
 | ||||||
|  | The precise terms and conditions for copying, distribution and modification | ||||||
|  | follow.  | ||||||
|  | 
 | ||||||
|  | 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 | ||||||
							
								
								
									
										9
									
								
								envy24control/Makefile.am
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								envy24control/Makefile.am
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | ||||||
|  | bin_PROGRAMS = envy24control | ||||||
|  | envy24control_SOURCES = envy24control.c envy24control.h levelmeters.c \ | ||||||
|  |                         mixer.c patchbay.c hardware.c driverevents.c | ||||||
|  | envy24control_LDFLAGS = $(GTK_LIBS) | ||||||
|  | EXTRA_DIST = cvscompile | ||||||
|  | 
 | ||||||
|  | clean: | ||||||
|  | 	rm -rf .deps *~ | ||||||
|  | 
 | ||||||
							
								
								
									
										11
									
								
								envy24control/configure.in
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								envy24control/configure.in
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | ||||||
|  | AC_INIT(envy24control.c) | ||||||
|  | AM_INIT_AUTOMAKE(envy24control, 0.1.0) | ||||||
|  | AC_PROG_CC | ||||||
|  | AC_PROG_INSTALL | ||||||
|  | AC_HEADER_STDC | ||||||
|  | AM_PATH_GTK(1.0.1) | ||||||
|  | AM_PATH_ALSA(0.6.0) | ||||||
|  | CFLAGS="$CFLAGS $GTK_CFLAGS $ALSA_FLAGS" | ||||||
|  | LDFLAGS="$LDFLAGS $GTK_LIBS $ALSA_LIBS" | ||||||
|  | 
 | ||||||
|  | AC_OUTPUT(Makefile) | ||||||
							
								
								
									
										22
									
								
								envy24control/cvscompile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								envy24control/cvscompile
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | ||||||
|  | #!/bin/bash | ||||||
|  | 
 | ||||||
|  | share=/usr/share/automake/missing | ||||||
|  | 
 | ||||||
|  | aclocal $ACLOCAL_FLAGS | ||||||
|  | automake --foreign | ||||||
|  | if [ ! -r install-sh ]; then | ||||||
|  |   cp $share/install-sh . | ||||||
|  | fi | ||||||
|  | if [ ! -r mkinstalldirs ]; then | ||||||
|  |   cp $share/mkinstalldirs . | ||||||
|  | fi | ||||||
|  | if [ ! -r missing ]; then | ||||||
|  |   cp $share/missing . | ||||||
|  | fi | ||||||
|  | autoconf | ||||||
|  | export CFLAGS='-O2 -Wall -pipe -g' | ||||||
|  | echo "CFLAGS=$CFLAGS" | ||||||
|  | echo "./configure $@" | ||||||
|  | ./configure $@ | ||||||
|  | unset CFLAGS | ||||||
|  | make | ||||||
							
								
								
									
										83
									
								
								envy24control/driverevents.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								envy24control/driverevents.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,83 @@ | ||||||
|  | /*****************************************************************************
 | ||||||
|  |    driverevents.c - Events from the driver processing | ||||||
|  |    Copyright (C) 2000 by Jaroslav Kysela <perex@suse.cz> | ||||||
|  |     | ||||||
|  |    This program is free software; you can redistribute it and/or | ||||||
|  |    modify it under the terms of the GNU General Public License | ||||||
|  |    as published by the Free Software Foundation; either version 2 | ||||||
|  |    of the License, or (at your option) any later version. | ||||||
|  |     | ||||||
|  |    This program is distributed in the hope that it will be useful, | ||||||
|  |    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |    GNU General Public License for more details. | ||||||
|  |     | ||||||
|  |    You should have received a copy of the GNU General Public License | ||||||
|  |    along with this program; if not, write to the Free Software | ||||||
|  |    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. | ||||||
|  | ******************************************************************************/ | ||||||
|  | 
 | ||||||
|  | #include "envy24control.h" | ||||||
|  | 
 | ||||||
|  | static void control_value(snd_ctl_t *handle, void *private_data, snd_control_id_t *id) | ||||||
|  | { | ||||||
|  | 	if (id->iface == SND_CONTROL_IFACE_PCM) { | ||||||
|  | 		if (!strcmp(id->name, "Multi Track Route")) { | ||||||
|  | 			patchbay_update(); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 		if (!strcmp(id->name, "Multi Track S/PDIF Master")) { | ||||||
|  | 			master_clock_update(); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 		if (!strcmp(id->name, "Word Clock Sync")) { | ||||||
|  | 			master_clock_update(); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 		if (!strcmp(id->name, "Multi Track Volume Rate")) { | ||||||
|  | 			volume_change_rate_update(); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 		if (!strcmp(id->name, "S/PDIF Input Optical")) { | ||||||
|  | 			spdif_input_update(); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 		if (!strcmp(id->name, "Delta S/PDIF Output Defaults")) { | ||||||
|  | 			spdif_output_update(); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if (id->iface == SND_CONTROL_IFACE_MIXER) { | ||||||
|  | 		if (!strcmp(id->name, "Multi Playback Volume")) { | ||||||
|  | 			mixer_update_stream(id->index + 1, 1, 0); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 		if (!strcmp(id->name, "Multi Capture Volume")) { | ||||||
|  | 			mixer_update_stream(id->index + 11, 1, 0); | ||||||
|  | 			return; | ||||||
|  | 		}	 | ||||||
|  | 		if (!strcmp(id->name, "Multi Playback Switch")) { | ||||||
|  | 			mixer_update_stream(id->index + 1, 0, 1); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 		if (!strcmp(id->name, "Multi Capture Switch")) { | ||||||
|  | 			mixer_update_stream(id->index + 11, 0, 1); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static snd_ctl_callbacks_t control_callbacks = { | ||||||
|  | 	private_data: NULL, | ||||||
|  | 	rebuild: NULL,		/* FIXME!! */ | ||||||
|  | 	value: control_value, | ||||||
|  | 	change: NULL, | ||||||
|  | 	add: NULL, | ||||||
|  | 	remove: NULL, | ||||||
|  | 	reserved: { NULL, } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | void control_input_callback(gpointer data, gint source, GdkInputCondition condition) | ||||||
|  | { | ||||||
|  | 	snd_ctl_read(card_ctl, &control_callbacks); | ||||||
|  | } | ||||||
							
								
								
									
										1132
									
								
								envy24control/envy24control.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1132
									
								
								envy24control/envy24control.c
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										127
									
								
								envy24control/envy24control.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								envy24control/envy24control.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,127 @@ | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <signal.h> | ||||||
|  | #include <errno.h> | ||||||
|  | #include <gtk/gtk.h> | ||||||
|  | #include <sys/asoundlib.h> | ||||||
|  | 
 | ||||||
|  | #define ICE1712_SUBDEVICE_DELTA1010	0x121430d6 | ||||||
|  | #define ICE1712_SUBDEVICE_DELTADIO2496	0x121431d6 | ||||||
|  | #define ICE1712_SUBDEVICE_DELTA66	0x121432d6 | ||||||
|  | #define ICE1712_SUBDEVICE_DELTA44	0x121433d6 | ||||||
|  | 
 | ||||||
|  | typedef struct { | ||||||
|  | 	unsigned int subvendor;	/* PCI[2c-2f] */ | ||||||
|  | 	unsigned char size;	/* size of EEPROM image in bytes */ | ||||||
|  | 	unsigned char version;	/* must be 1 */ | ||||||
|  | 	unsigned char codec;	/* codec configuration PCI[60] */ | ||||||
|  | 	unsigned char aclink;	/* ACLink configuration PCI[61] */ | ||||||
|  | 	unsigned char i2sID;	/* PCI[62] */ | ||||||
|  | 	unsigned char spdif;	/* S/PDIF configuration PCI[63] */ | ||||||
|  | 	unsigned char gpiomask;	/* GPIO initial mask, 0 = write, 1 = don't */ | ||||||
|  | 	unsigned char gpiostate; /* GPIO initial state */ | ||||||
|  | 	unsigned char gpiodir;	/* GPIO direction state */ | ||||||
|  | 	unsigned short ac97main; | ||||||
|  | 	unsigned short ac97pcm; | ||||||
|  | 	unsigned short ac97rec; | ||||||
|  | 	unsigned char ac97recsrc; | ||||||
|  | 	unsigned char dacID[4];	/* I2S IDs for DACs */ | ||||||
|  | 	unsigned char adcID[4];	/* I2S IDs for ADCs */ | ||||||
|  | 	unsigned char extra[4]; | ||||||
|  | } ice1712_eeprom_t; | ||||||
|  | 
 | ||||||
|  | extern snd_ctl_t *card_ctl; | ||||||
|  | extern ice1712_eeprom_t card_eeprom; | ||||||
|  | 
 | ||||||
|  | extern GtkWidget *mixer_mix_drawing; | ||||||
|  | extern GtkWidget *mixer_clear_peaks_button; | ||||||
|  | extern GtkWidget *mixer_drawing[20]; | ||||||
|  | extern GtkObject *mixer_adj[20][2]; | ||||||
|  | extern GtkWidget *mixer_vscale[20][2]; | ||||||
|  | extern GtkWidget *mixer_solo_toggle[20][2]; | ||||||
|  | extern GtkWidget *mixer_mute_toggle[20][2]; | ||||||
|  | extern GtkWidget *mixer_stereo_toggle[20]; | ||||||
|  | 
 | ||||||
|  | extern GtkWidget *router_radio[10][12]; | ||||||
|  | 
 | ||||||
|  | extern GtkWidget *hw_master_clock_xtal_radio; | ||||||
|  | extern GtkWidget *hw_master_clock_spdif_radio; | ||||||
|  | extern GtkWidget *hw_master_clock_word_radio; | ||||||
|  | extern GtkWidget *hw_master_clock_status_label; | ||||||
|  | 
 | ||||||
|  | extern GtkObject *hw_volume_change_adj; | ||||||
|  | extern GtkWidget *hw_volume_change_spin; | ||||||
|  | 
 | ||||||
|  | extern GtkWidget *hw_spdif_profi_nonaudio_radio; | ||||||
|  | extern GtkWidget *hw_spdif_profi_audio_radio; | ||||||
|  | 
 | ||||||
|  | extern GtkWidget *hw_profi_stream_stereo_radio; | ||||||
|  | extern GtkWidget *hw_profi_stream_notid_radio; | ||||||
|  | 
 | ||||||
|  | extern GtkWidget *hw_profi_emphasis_none_radio; | ||||||
|  | extern GtkWidget *hw_profi_emphasis_5015_radio; | ||||||
|  | extern GtkWidget *hw_profi_emphasis_ccitt_radio; | ||||||
|  | extern GtkWidget *hw_profi_emphasis_notid_radio; | ||||||
|  | 
 | ||||||
|  | extern GtkWidget *hw_consumer_copyright_on_radio; | ||||||
|  | extern GtkWidget *hw_consumer_copyright_off_radio; | ||||||
|  | 
 | ||||||
|  | extern GtkWidget *hw_consumer_copy_1st_radio; | ||||||
|  | extern GtkWidget *hw_consumer_copy_original_radio; | ||||||
|  | 
 | ||||||
|  | extern GtkWidget *hw_consumer_emphasis_none_radio; | ||||||
|  | extern GtkWidget *hw_consumer_emphasis_5015_radio; | ||||||
|  | 
 | ||||||
|  | extern GtkWidget *hw_consumer_category_dat_radio; | ||||||
|  | extern GtkWidget *hw_consumer_category_pcm_radio; | ||||||
|  | extern GtkWidget *hw_consumer_category_cd_radio; | ||||||
|  | extern GtkWidget *hw_consumer_category_general_radio; | ||||||
|  | 
 | ||||||
|  | extern GtkWidget *hw_spdif_professional_radio; | ||||||
|  | extern GtkWidget *hw_spdif_consumer_radio; | ||||||
|  | extern GtkWidget *hw_spdif_output_notebook; | ||||||
|  | 
 | ||||||
|  | extern GtkWidget *hw_spdif_input_coaxial_radio; | ||||||
|  | extern GtkWidget *hw_spdif_input_optical_radio; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | gint level_meters_configure_event(GtkWidget *widget, GdkEventConfigure *event); | ||||||
|  | gint level_meters_expose_event(GtkWidget *widget, GdkEventExpose *event); | ||||||
|  | gint level_meters_timeout_callback(gpointer data); | ||||||
|  | void level_meters_reset_peaks(GtkButton *button, gpointer data); | ||||||
|  | void level_meters_init(void); | ||||||
|  | void level_meters_postinit(void); | ||||||
|  | 
 | ||||||
|  | void mixer_update_stream(int stream, int vol_flag, int sw_flag); | ||||||
|  | void mixer_toggled_solo(GtkWidget *togglebutton, gpointer data); | ||||||
|  | void mixer_toggled_mute(GtkWidget *togglebutton, gpointer data); | ||||||
|  | void mixer_adjust(GtkAdjustment *adj, gpointer data); | ||||||
|  | void mixer_postinit(void); | ||||||
|  | 
 | ||||||
|  | void patchbay_update(void); | ||||||
|  | void patchbay_toggled(GtkWidget *togglebutton, gpointer data); | ||||||
|  | void patchbay_init(void); | ||||||
|  | void patchbay_postinit(void); | ||||||
|  | 
 | ||||||
|  | void master_clock_update(void); | ||||||
|  | void master_clock_toggled(GtkWidget *togglebutton, gpointer data); | ||||||
|  | gint master_clock_status_timeout_callback(gpointer data); | ||||||
|  | void volume_change_rate_update(void); | ||||||
|  | void volume_change_rate_adj(GtkAdjustment *adj, gpointer data); | ||||||
|  | void profi_data_toggled(GtkWidget *togglebutton, gpointer data); | ||||||
|  | void profi_stream_toggled(GtkWidget *togglebutton, gpointer data); | ||||||
|  | void profi_emphasis_toggled(GtkWidget *togglebutton, gpointer data); | ||||||
|  | void consumer_copyright_toggled(GtkWidget *togglebutton, gpointer data); | ||||||
|  | void consumer_copy_toggled(GtkWidget *togglebutton, gpointer data); | ||||||
|  | void consumer_emphasis_toggled(GtkWidget *togglebutton, gpointer data); | ||||||
|  | void consumer_category_toggled(GtkWidget *togglebutton, gpointer data); | ||||||
|  | void spdif_output_update(void); | ||||||
|  | void spdif_output_toggled(GtkWidget *togglebutton, gpointer data); | ||||||
|  | void spdif_input_update(void); | ||||||
|  | void spdif_input_toggled(GtkWidget *togglebutton, gpointer data); | ||||||
|  | void hardware_init(void); | ||||||
|  | void hardware_postinit(void); | ||||||
|  | 
 | ||||||
|  | void control_input_callback(gpointer data, gint source, GdkInputCondition condition); | ||||||
|  | void mixer_input_callback(gpointer data, gint source, GdkInputCondition condition); | ||||||
							
								
								
									
										415
									
								
								envy24control/hardware.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										415
									
								
								envy24control/hardware.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,415 @@ | ||||||
|  | /*****************************************************************************
 | ||||||
|  |    hardware.c - Hardware Settings | ||||||
|  |    Copyright (C) 2000 by Jaroslav Kysela <perex@suse.cz> | ||||||
|  |     | ||||||
|  |    This program is free software; you can redistribute it and/or | ||||||
|  |    modify it under the terms of the GNU General Public License | ||||||
|  |    as published by the Free Software Foundation; either version 2 | ||||||
|  |    of the License, or (at your option) any later version. | ||||||
|  |     | ||||||
|  |    This program is distributed in the hope that it will be useful, | ||||||
|  |    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |    GNU General Public License for more details. | ||||||
|  |     | ||||||
|  |    You should have received a copy of the GNU General Public License | ||||||
|  |    along with this program; if not, write to the Free Software | ||||||
|  |    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. | ||||||
|  | ******************************************************************************/ | ||||||
|  | 
 | ||||||
|  | #include "envy24control.h" | ||||||
|  | 
 | ||||||
|  | static snd_control_t spdif_master; | ||||||
|  | static snd_control_t word_clock_sync; | ||||||
|  | static snd_control_t volume_rate; | ||||||
|  | static snd_control_t spdif_input; | ||||||
|  | static snd_control_t spdif_output; | ||||||
|  | 
 | ||||||
|  | #define toggle_set(widget, state) \ | ||||||
|  | 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), state); | ||||||
|  | 
 | ||||||
|  | static int is_active(GtkWidget *widget) | ||||||
|  | { | ||||||
|  | 	return GTK_TOGGLE_BUTTON(widget)->active ? 1 : 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void master_clock_update(void) | ||||||
|  | { | ||||||
|  | 	int err; | ||||||
|  | 	 | ||||||
|  | 	if ((err = snd_ctl_cread(card_ctl, &spdif_master)) < 0) | ||||||
|  | 		g_print("Unable to read S/PDIF master state: %s\n", snd_strerror(err)); | ||||||
|  | 	if (card_eeprom.subvendor == ICE1712_SUBDEVICE_DELTA1010) { | ||||||
|  | 		if ((err = snd_ctl_cread(card_ctl, &word_clock_sync)) < 0) | ||||||
|  | 			g_print("Unable to read word clock sync selection: %s\n", snd_strerror(err)); | ||||||
|  | 	} | ||||||
|  | 	if (spdif_master.value.integer.value[0]) { | ||||||
|  | 		if (word_clock_sync.value.integer.value[0]) { | ||||||
|  | 			toggle_set(hw_master_clock_word_radio, TRUE); | ||||||
|  | 		} else { | ||||||
|  | 			toggle_set(hw_master_clock_spdif_radio, TRUE); | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		toggle_set(hw_master_clock_xtal_radio, TRUE); | ||||||
|  | 	} | ||||||
|  | 	master_clock_status_timeout_callback(NULL); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void master_clock_spdif_master(int on) | ||||||
|  | { | ||||||
|  | 	int err; | ||||||
|  | 
 | ||||||
|  | 	spdif_master.value.integer.value[0] = on ? 1 : 0; | ||||||
|  | 	if ((err = snd_ctl_cwrite(card_ctl, &spdif_master)) < 0) | ||||||
|  | 		g_print("Unable to write S/PDIF master state: %s\n", snd_strerror(err)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void master_clock_word_select(int on) | ||||||
|  | { | ||||||
|  | 	int err; | ||||||
|  | 
 | ||||||
|  | 	if (card_eeprom.subvendor != ICE1712_SUBDEVICE_DELTA1010) | ||||||
|  | 		return; | ||||||
|  | 	word_clock_sync.value.integer.value[0] = on ? 1 : 0; | ||||||
|  | 	if ((err = snd_ctl_cwrite(card_ctl, &word_clock_sync)) < 0) | ||||||
|  | 		g_print("Unable to write word clock sync selection: %s\n", snd_strerror(err)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void master_clock_toggled(GtkWidget *togglebutton, gpointer data) | ||||||
|  | { | ||||||
|  | 	char *what = (char *) data; | ||||||
|  | 
 | ||||||
|  | 	if (!is_active(togglebutton)) | ||||||
|  | 		return; | ||||||
|  | 	if (!strcmp(what, "Xtal")) { | ||||||
|  | 		master_clock_spdif_master(0); | ||||||
|  | 	} else if (!strcmp(what, "SPDIF")) { | ||||||
|  | 		master_clock_spdif_master(1); | ||||||
|  | 		master_clock_word_select(0); | ||||||
|  | 	} else if (!strcmp(what, "WordClock")) { | ||||||
|  | 		master_clock_spdif_master(1); | ||||||
|  | 		master_clock_word_select(1); | ||||||
|  | 	} else { | ||||||
|  | 		g_print("master_clock_toggled: %s ???\n", what); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | gint master_clock_status_timeout_callback(gpointer data) | ||||||
|  | { | ||||||
|  | 	snd_control_t sw; | ||||||
|  | 	int err; | ||||||
|  | 	 | ||||||
|  | 	if (card_eeprom.subvendor != ICE1712_SUBDEVICE_DELTA1010) | ||||||
|  | 		return FALSE; | ||||||
|  | 	memset(&sw, 0, sizeof(sw)); | ||||||
|  | 	sw.id.iface = SND_CONTROL_IFACE_PCM; | ||||||
|  | 	strcpy(sw.id.name, "Word Clock Status"); | ||||||
|  | 	if ((err = snd_ctl_cread(card_ctl, &sw)) < 0) | ||||||
|  | 		g_print("Unable to determine word clock status: %s\n", snd_strerror(err)); | ||||||
|  | 	gtk_label_set_text(GTK_LABEL(hw_master_clock_status_label), | ||||||
|  | 			   sw.value.integer.value[0] ? "Locked" : "No signal"); | ||||||
|  | 	return TRUE; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void volume_change_rate_update(void) | ||||||
|  | { | ||||||
|  | 	int err; | ||||||
|  | 	 | ||||||
|  | 	if ((err = snd_ctl_cread(card_ctl, &volume_rate)) < 0) | ||||||
|  | 		g_print("Unable to read volume change rate: %s\n", snd_strerror(err)); | ||||||
|  | 	gtk_adjustment_set_value(GTK_ADJUSTMENT(hw_volume_change_adj), volume_rate.value.integer.value[0]); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void volume_change_rate_adj(GtkAdjustment *adj, gpointer data) | ||||||
|  | { | ||||||
|  | 	int err; | ||||||
|  | 	 | ||||||
|  | 	volume_rate.value.integer.value[0] = adj->value; | ||||||
|  | 	if ((err = snd_ctl_cwrite(card_ctl, &volume_rate)) < 0) | ||||||
|  | 		g_print("Unable to write volume change rate: %s\n", snd_strerror(err)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void spdif_output_update(void) | ||||||
|  | { | ||||||
|  | 	int err, val; | ||||||
|  | 	 | ||||||
|  | 	if (card_eeprom.subvendor == ICE1712_SUBDEVICE_DELTA44) | ||||||
|  | 		return; | ||||||
|  | 	if ((err = snd_ctl_cread(card_ctl, &spdif_output)) < 0) | ||||||
|  | 		g_print("Unable to read Delta S/PDIF output state: %s\n", snd_strerror(err)); | ||||||
|  | 	val = spdif_output.value.integer.value[0]; | ||||||
|  | 	if (val & 1) {		/* consumer */ | ||||||
|  | 		toggle_set(hw_spdif_consumer_radio, TRUE); | ||||||
|  | 		if (val & 8) { | ||||||
|  | 			toggle_set(hw_consumer_copyright_on_radio, TRUE); | ||||||
|  | 		} else { | ||||||
|  | 			toggle_set(hw_consumer_copyright_off_radio, TRUE); | ||||||
|  | 		} | ||||||
|  | 		if (val & 0x10) { | ||||||
|  | 			toggle_set(hw_consumer_emphasis_none_radio, TRUE); | ||||||
|  | 		} else { | ||||||
|  | 			toggle_set(hw_consumer_emphasis_5015_radio, TRUE); | ||||||
|  | 		} | ||||||
|  | 		switch (val & 0x60) { | ||||||
|  | 		case 0x00: toggle_set(hw_consumer_category_dat_radio, TRUE); break; | ||||||
|  | 		case 0x20: toggle_set(hw_consumer_category_pcm_radio, TRUE); break; | ||||||
|  | 		case 0x40: toggle_set(hw_consumer_category_cd_radio, TRUE); break; | ||||||
|  | 		case 0x60: toggle_set(hw_consumer_category_general_radio, TRUE); break; | ||||||
|  | 		} | ||||||
|  | 		if (val & 0x80) { | ||||||
|  | 			toggle_set(hw_consumer_copy_1st_radio, TRUE); | ||||||
|  | 		} else { | ||||||
|  | 			toggle_set(hw_consumer_copy_original_radio, TRUE); | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		toggle_set(hw_spdif_professional_radio, TRUE); | ||||||
|  | 		if (val & 2) { | ||||||
|  | 			toggle_set(hw_spdif_profi_audio_radio, TRUE); | ||||||
|  | 		} else { | ||||||
|  | 			toggle_set(hw_spdif_profi_nonaudio_radio, TRUE); | ||||||
|  | 		} | ||||||
|  | 		switch (val & 0x60) { | ||||||
|  | 		case 0x00: toggle_set(hw_profi_emphasis_ccitt_radio, TRUE); break; | ||||||
|  | 		case 0x20: toggle_set(hw_profi_emphasis_none_radio, TRUE); break; | ||||||
|  | 		case 0x40: toggle_set(hw_profi_emphasis_5015_radio, TRUE); break; | ||||||
|  | 		case 0x60: toggle_set(hw_profi_emphasis_notid_radio, TRUE); break; | ||||||
|  | 		} | ||||||
|  | 		if (val & 0x80) { | ||||||
|  | 			toggle_set(hw_profi_stream_notid_radio, TRUE); | ||||||
|  | 		} else { | ||||||
|  | 			toggle_set(hw_profi_stream_stereo_radio, TRUE); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void spdif_output_write(void) | ||||||
|  | { | ||||||
|  | 	int err; | ||||||
|  | 
 | ||||||
|  | 	if ((err = snd_ctl_cwrite(card_ctl, &spdif_output)) < 0) | ||||||
|  | 		g_print("Unable to write Delta S/PDIF Output Defaults: %s\n", snd_strerror(err)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void profi_data_toggled(GtkWidget *togglebutton, gpointer data) | ||||||
|  | { | ||||||
|  | 	char *str = (char *)data; | ||||||
|  | 	int val = spdif_output.value.integer.value[0]; | ||||||
|  | 	 | ||||||
|  | 	if (!is_active(togglebutton)) | ||||||
|  | 		return; | ||||||
|  | 	if (val & 1) | ||||||
|  | 		return; | ||||||
|  | 	if (!strcmp(str, "Audio")) { | ||||||
|  | 		val |= 0x02; | ||||||
|  | 	} else if (!strcmp(str, "Non-audio")) { | ||||||
|  | 		val &= ~0x02; | ||||||
|  | 	} | ||||||
|  | 	spdif_output.value.integer.value[0] = val; | ||||||
|  | 	spdif_output_write(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void profi_stream_toggled(GtkWidget *togglebutton, gpointer data) | ||||||
|  | { | ||||||
|  | 	char *str = (char *)data; | ||||||
|  | 	int val = spdif_output.value.integer.value[0]; | ||||||
|  | 	 | ||||||
|  | 	if (!is_active(togglebutton)) | ||||||
|  | 		return; | ||||||
|  | 	if (val & 1) | ||||||
|  | 		return; | ||||||
|  | 	if (!strcmp(str, "NOTID")) { | ||||||
|  | 		val |= 0x80; | ||||||
|  | 	} else if (!strcmp(str, "Stereo")) { | ||||||
|  | 		val &= ~0x80; | ||||||
|  | 	} | ||||||
|  | 	spdif_output.value.integer.value[0] = val; | ||||||
|  | 	spdif_output_write(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void profi_emphasis_toggled(GtkWidget *togglebutton, gpointer data) | ||||||
|  | { | ||||||
|  | 	char *str = (char *)data; | ||||||
|  | 	int val = spdif_output.value.integer.value[0]; | ||||||
|  | 	 | ||||||
|  | 	if (!is_active(togglebutton)) | ||||||
|  | 		return; | ||||||
|  | 	if (val & 1) | ||||||
|  | 		return; | ||||||
|  | 	if (!strcmp(str, "CCITT")) { | ||||||
|  | 		val &= ~0x60; | ||||||
|  | 	} else if (!strcmp(str, "No")) { | ||||||
|  | 		val &= ~0x60; | ||||||
|  | 		val |= 0x20; | ||||||
|  | 	} else if (!strcmp(str, "5015")) { | ||||||
|  | 		val &= ~0x60; | ||||||
|  | 		val |= 0x40; | ||||||
|  | 	} else if (!strcmp(str, "NOTID")) { | ||||||
|  | 		val |= 0x60; | ||||||
|  | 	} | ||||||
|  | 	spdif_output.value.integer.value[0] = val; | ||||||
|  | 	spdif_output_write(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void consumer_copyright_toggled(GtkWidget *togglebutton, gpointer data) | ||||||
|  | { | ||||||
|  | 	char *str = (char *)data; | ||||||
|  | 	int val = spdif_output.value.integer.value[0]; | ||||||
|  | 	 | ||||||
|  | 	if (!is_active(togglebutton)) | ||||||
|  | 		return; | ||||||
|  | 	if (!(val & 1)) | ||||||
|  | 		return; | ||||||
|  | 	if (!strcmp(str, "Copyright")) { | ||||||
|  | 		val |= 0x08; | ||||||
|  | 	} else if (!strcmp(str, "Permitted")) { | ||||||
|  | 		val &= ~0x08; | ||||||
|  | 	} | ||||||
|  | 	spdif_output.value.integer.value[0] = val; | ||||||
|  | 	spdif_output_write(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void consumer_copy_toggled(GtkWidget *togglebutton, gpointer data) | ||||||
|  | { | ||||||
|  | 	char *str = (char *)data; | ||||||
|  | 	int val = spdif_output.value.integer.value[0]; | ||||||
|  | 	 | ||||||
|  | 	if (!is_active(togglebutton)) | ||||||
|  | 		return; | ||||||
|  | 	if (!(val & 1)) | ||||||
|  | 		return; | ||||||
|  | 	if (!strcmp(str, "1st")) { | ||||||
|  | 		val |= 0x80; | ||||||
|  | 	} else if (!strcmp(str, "Original")) { | ||||||
|  | 		val &= ~0x80; | ||||||
|  | 	} | ||||||
|  | 	spdif_output.value.integer.value[0] = val; | ||||||
|  | 	spdif_output_write(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void consumer_emphasis_toggled(GtkWidget *togglebutton, gpointer data) | ||||||
|  | { | ||||||
|  | 	char *str = (char *)data; | ||||||
|  | 	int val = spdif_output.value.integer.value[0]; | ||||||
|  | 	 | ||||||
|  | 	if (!is_active(togglebutton)) | ||||||
|  | 		return; | ||||||
|  | 	if (!(val & 1)) | ||||||
|  | 		return; | ||||||
|  | 	if (!strcmp(str, "No")) { | ||||||
|  | 		val |= 0x10; | ||||||
|  | 	} else if (!strcmp(str, "5015")) { | ||||||
|  | 		val &= ~0x10; | ||||||
|  | 	} | ||||||
|  | 	spdif_output.value.integer.value[0] = val; | ||||||
|  | 	spdif_output_write(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void consumer_category_toggled(GtkWidget *togglebutton, gpointer data) | ||||||
|  | { | ||||||
|  | 	char *str = (char *)data; | ||||||
|  | 	int val = spdif_output.value.integer.value[0]; | ||||||
|  | 	 | ||||||
|  | 	if (!is_active(togglebutton)) | ||||||
|  | 		return; | ||||||
|  | 	if (!(val & 1)) | ||||||
|  | 		return; | ||||||
|  | 	if (!strcmp(str, "DAT")) { | ||||||
|  | 		val &= ~0x60; | ||||||
|  | 	} else if (!strcmp(str, "PCM")) { | ||||||
|  | 		val &= ~0x60; | ||||||
|  | 		val |= 0x20; | ||||||
|  | 	} else if (!strcmp(str, "CD")) { | ||||||
|  | 		val &= ~0x60; | ||||||
|  | 		val |= 0x40; | ||||||
|  | 	} else if (!strcmp(str, "General")) { | ||||||
|  | 		val |= 0x60; | ||||||
|  | 	} | ||||||
|  | 	spdif_output.value.integer.value[0] = val; | ||||||
|  | 	spdif_output_write(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void spdif_output_toggled(GtkWidget *togglebutton, gpointer data) | ||||||
|  | { | ||||||
|  | 	char *str = (char *)data; | ||||||
|  | 	int page; | ||||||
|  | 
 | ||||||
|  | 	if (is_active(togglebutton)) { | ||||||
|  | 		if (!strcmp(str, "Professional")) { | ||||||
|  | 			if (spdif_output.value.integer.value[0] & 0x01) { | ||||||
|  | 				/* default setup: audio, no emphasis */ | ||||||
|  | 				spdif_output.value.integer.value[0] = 0x22; | ||||||
|  | 			} | ||||||
|  | 			page = 0; | ||||||
|  | 		} else { | ||||||
|  | 			if (!(spdif_output.value.integer.value[0] & 0x01)) { | ||||||
|  | 				/* default setup: no emphasis, PCM encoder */ | ||||||
|  | 				spdif_output.value.integer.value[0] = 0x31; | ||||||
|  | 			} | ||||||
|  | 			page = 1; | ||||||
|  | 		} | ||||||
|  | 		spdif_output_write(); | ||||||
|  | 		gtk_notebook_set_page(GTK_NOTEBOOK(hw_spdif_output_notebook), page); | ||||||
|  | 		spdif_output_update(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void spdif_input_update(void) | ||||||
|  | { | ||||||
|  | 	int err; | ||||||
|  | 	 | ||||||
|  | 	if (card_eeprom.subvendor != ICE1712_SUBDEVICE_DELTADIO2496) | ||||||
|  | 		return; | ||||||
|  | 	if ((err = snd_ctl_cread(card_ctl, &spdif_input)) < 0) | ||||||
|  | 		g_print("Unable to read S/PDIF input switch: %s\n", snd_strerror(err)); | ||||||
|  | 	if (spdif_input.value.integer.value[0]) { | ||||||
|  | 		toggle_set(hw_spdif_input_optical_radio, TRUE); | ||||||
|  | 	} else { | ||||||
|  | 		toggle_set(hw_spdif_input_coaxial_radio, TRUE); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void spdif_input_toggled(GtkWidget *togglebutton, gpointer data) | ||||||
|  | { | ||||||
|  | 	int err; | ||||||
|  | 	char *str = (char *)data; | ||||||
|  | 	 | ||||||
|  | 	if (!is_active(togglebutton)) | ||||||
|  | 		return; | ||||||
|  | 	if (!strcmp(str, "Optical")) | ||||||
|  | 		spdif_input.value.integer.value[0] = 1; | ||||||
|  | 	else | ||||||
|  | 		spdif_input.value.integer.value[0] = 0; | ||||||
|  | 	if ((err = snd_ctl_cwrite(card_ctl, &spdif_input)) < 0) | ||||||
|  | 		g_print("Unable to write S/PDIF input switch: %s\n", snd_strerror(err)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void hardware_init(void) | ||||||
|  | { | ||||||
|  | 	memset(&spdif_master, 0, sizeof(spdif_master)); | ||||||
|  | 	spdif_master.id.iface = SND_CONTROL_IFACE_PCM; | ||||||
|  | 	strcpy(spdif_master.id.name, "Multi Track S/PDIF Master"); | ||||||
|  | 
 | ||||||
|  | 	memset(&word_clock_sync, 0, sizeof(spdif_master)); | ||||||
|  | 	word_clock_sync.id.iface = SND_CONTROL_IFACE_PCM; | ||||||
|  | 	strcpy(word_clock_sync.id.name, "Word Clock Sync"); | ||||||
|  | 
 | ||||||
|  | 	memset(&volume_rate, 0, sizeof(volume_rate)); | ||||||
|  | 	spdif_master.id.iface = SND_CONTROL_IFACE_PCM; | ||||||
|  | 	strcpy(volume_rate.id.name, "Multi Track Volume Rate"); | ||||||
|  | 
 | ||||||
|  | 	memset(&spdif_input, 0, sizeof(spdif_input)); | ||||||
|  | 	spdif_master.id.iface = SND_CONTROL_IFACE_PCM; | ||||||
|  | 	strcpy(spdif_input.id.name, "S/PDIF Input Optical"); | ||||||
|  | 
 | ||||||
|  | 	memset(&spdif_output, 0, sizeof(spdif_output)); | ||||||
|  | 	spdif_master.id.iface = SND_CONTROL_IFACE_PCM; | ||||||
|  | 	strcpy(spdif_output.id.name, "Delta S/PDIF Output Defaults"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void hardware_postinit(void) | ||||||
|  | { | ||||||
|  | 	master_clock_update(); | ||||||
|  | 	volume_change_rate_update(); | ||||||
|  | 	spdif_input_update(); | ||||||
|  | 	spdif_output_update(); | ||||||
|  | } | ||||||
							
								
								
									
										229
									
								
								envy24control/levelmeters.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										229
									
								
								envy24control/levelmeters.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,229 @@ | ||||||
|  | /*****************************************************************************
 | ||||||
|  |    levelmeters.c - Stereo level meters | ||||||
|  |    Copyright (C) 2000 by Jaroslav Kysela <perex@suse.cz> | ||||||
|  |     | ||||||
|  |    This program is free software; you can redistribute it and/or | ||||||
|  |    modify it under the terms of the GNU General Public License | ||||||
|  |    as published by the Free Software Foundation; either version 2 | ||||||
|  |    of the License, or (at your option) any later version. | ||||||
|  |     | ||||||
|  |    This program is distributed in the hope that it will be useful, | ||||||
|  |    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |    GNU General Public License for more details. | ||||||
|  |     | ||||||
|  |    You should have received a copy of the GNU General Public License | ||||||
|  |    along with this program; if not, write to the Free Software | ||||||
|  |    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. | ||||||
|  | ******************************************************************************/ | ||||||
|  | 
 | ||||||
|  | #include "envy24control.h" | ||||||
|  | 
 | ||||||
|  | static GdkGC *penGreenShadow[21] = { NULL, }; | ||||||
|  | static GdkGC *penGreenLight[21] = { NULL, }; | ||||||
|  | static GdkGC *penOrangeShadow[21] = { NULL, }; | ||||||
|  | static GdkGC *penOrangeLight[21] = { NULL, }; | ||||||
|  | static GdkGC *penRedShadow[21] = { NULL, }; | ||||||
|  | static GdkGC *penRedLight[21] = { NULL, }; | ||||||
|  | static GdkPixmap *pixmap[21] = { NULL, }; | ||||||
|  | static snd_control_t peaks; | ||||||
|  | 
 | ||||||
|  | static void update_peak_switch(void) | ||||||
|  | { | ||||||
|  | 	int err; | ||||||
|  | 
 | ||||||
|  | 	memset(&peaks, 0, sizeof(peaks)); | ||||||
|  | 	peaks.id.iface = SND_CONTROL_IFACE_MIXER; | ||||||
|  | 	strcpy(peaks.id.name, "Multi Track Peak"); | ||||||
|  | 	if ((err = snd_ctl_cread(card_ctl, &peaks)) < 0) | ||||||
|  | 		g_print("Unable to read peaks: %s\n", snd_strerror(err)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void get_levels(int idx, int *l1, int *l2) | ||||||
|  | { | ||||||
|  | 	*l1 = *l2 = 0; | ||||||
|  | 	 | ||||||
|  | 	if (idx == 0) { | ||||||
|  | 		*l1 = peaks.value.integer.value[4 + 20]; | ||||||
|  | 		*l2 = peaks.value.integer.value[4 + 21]; | ||||||
|  | 	} else { | ||||||
|  | 		*l1 = *l2 = peaks.value.integer.value[4 + idx - 1]; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static GdkGC *get_pen(int idx, int nRed, int nGreen, int nBlue) | ||||||
|  | { | ||||||
|  | 	GdkColor *c; | ||||||
|  | 	GdkGC *gc; | ||||||
|  | 	 | ||||||
|  | 	c = (GdkColor *)g_malloc(sizeof(GdkColor)); | ||||||
|  | 	c->red = nRed; | ||||||
|  | 	c->green = nGreen; | ||||||
|  | 	c->blue = nBlue; | ||||||
|  | 	gdk_color_alloc(gdk_colormap_get_system(), c); | ||||||
|  | 	gc = gdk_gc_new(pixmap[idx]); | ||||||
|  | 	gdk_gc_set_foreground(gc, c); | ||||||
|  | 	return gc; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int get_index(gchar *name) | ||||||
|  | { | ||||||
|  | 	int result; | ||||||
|  | 
 | ||||||
|  | 	if (!strcmp(name, "DigitalMixer")) | ||||||
|  | 		return 0; | ||||||
|  | 	result = atoi(name + 5); | ||||||
|  | 	if (result < 1 || result > 20) { | ||||||
|  | 		g_print("Wrong drawing area ID: %s\n", name); | ||||||
|  | 		gtk_main_quit(); | ||||||
|  | 	} | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void redraw_meters(int idx, int width, int height, int level1, int level2) | ||||||
|  | { | ||||||
|  | 	int stereo = idx == 0; | ||||||
|  | 	int segment_width = stereo ? (width / 2) - 8 : width - 12; | ||||||
|  | 	int segments = (height - 6) / 4; | ||||||
|  | 	int green_segments = (segments / 4) * 3; | ||||||
|  | 	int red_segments = 2; | ||||||
|  | 	int orange_segments = segments - green_segments - red_segments; | ||||||
|  | 	int seg; | ||||||
|  | 	int segs_on1 = ((segments * level1) + 128) / 255; | ||||||
|  | 	int segs_on2 = ((segments * level2) + 128) / 255; | ||||||
|  | 
 | ||||||
|  | 	// g_print("segs_on1 = %i (%i), segs_on2 = %i (%i)\n", segs_on1, level1, segs_on2, level2);
 | ||||||
|  | 	for (seg = 0; seg < green_segments; seg++) { | ||||||
|  | 		gdk_draw_rectangle(pixmap[idx], | ||||||
|  | 				   segs_on1 > 0 ? penGreenLight[idx] : penGreenShadow[idx], | ||||||
|  | 				   TRUE, | ||||||
|  | 				   6, 3 + ((segments - seg - 1) * 4), | ||||||
|  | 				   segment_width, | ||||||
|  | 				   3); | ||||||
|  | 		if (stereo) | ||||||
|  | 			gdk_draw_rectangle(pixmap[idx], | ||||||
|  | 					   segs_on2 > 0 ? penGreenLight[idx] : penGreenShadow[idx], | ||||||
|  | 					   TRUE, | ||||||
|  | 					   2 + (width / 2), | ||||||
|  | 					   3 + ((segments - seg - 1) * 4), | ||||||
|  | 					   segment_width, | ||||||
|  | 					   3); | ||||||
|  | 		segs_on1--; | ||||||
|  | 		segs_on2--; | ||||||
|  | 	} | ||||||
|  | 	for (seg = green_segments; seg < green_segments + orange_segments; seg++) { | ||||||
|  | 		gdk_draw_rectangle(pixmap[idx], | ||||||
|  | 				   segs_on1 > 0 ? penOrangeLight[idx] : penOrangeShadow[idx], | ||||||
|  | 				   TRUE, | ||||||
|  | 				   6, 3 + ((segments - seg - 1) * 4), | ||||||
|  | 				   segment_width, | ||||||
|  | 				   3); | ||||||
|  | 		if (stereo) | ||||||
|  | 			gdk_draw_rectangle(pixmap[idx], | ||||||
|  | 					   segs_on2 > 0 ? penOrangeLight[idx] : penOrangeShadow[idx], | ||||||
|  | 					   TRUE, | ||||||
|  | 					   2 + (width / 2), | ||||||
|  | 					   3 + ((segments - seg - 1) * 4), | ||||||
|  | 					   segment_width, | ||||||
|  | 					   3); | ||||||
|  | 		segs_on1--; | ||||||
|  | 		segs_on2--; | ||||||
|  | 	} | ||||||
|  | 	for (seg = green_segments + orange_segments; seg < segments; seg++) { | ||||||
|  | 		gdk_draw_rectangle(pixmap[idx], | ||||||
|  | 				   segs_on1 > 0 ? penRedLight[idx] : penRedShadow[idx], | ||||||
|  | 				   TRUE, | ||||||
|  | 				   6, 3 + ((segments - seg - 1) * 4), | ||||||
|  | 				   segment_width, | ||||||
|  | 				   3); | ||||||
|  | 		if (stereo) | ||||||
|  | 			gdk_draw_rectangle(pixmap[idx], | ||||||
|  | 					   segs_on2 > 0 ? penRedLight[idx] : penRedShadow[idx], | ||||||
|  | 					   TRUE, | ||||||
|  | 					   2 + (width / 2), | ||||||
|  | 					   3 + ((segments - seg - 1) * 4), | ||||||
|  | 					   segment_width, | ||||||
|  | 					   3); | ||||||
|  | 		segs_on1--; | ||||||
|  | 		segs_on2--; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | gint level_meters_configure_event(GtkWidget *widget, GdkEventConfigure *event) | ||||||
|  | { | ||||||
|  | 	int idx = get_index(gtk_widget_get_name(widget)); | ||||||
|  | 
 | ||||||
|  | 	if (pixmap[idx] != NULL) | ||||||
|  | 		gdk_pixmap_unref(pixmap[idx]); | ||||||
|  | 	pixmap[idx] = gdk_pixmap_new(widget->window, | ||||||
|  | 				     widget->allocation.width, | ||||||
|  | 				     widget->allocation.height, | ||||||
|  | 				     -1); | ||||||
|  | 	penGreenShadow[idx] = get_pen(idx, 0, 0x77ff, 0); | ||||||
|  | 	penGreenLight[idx] = get_pen(idx, 0, 0xffff, 0); | ||||||
|  | 	penOrangeShadow[idx] = get_pen(idx, 0xddff, 0x55ff, 0); | ||||||
|  | 	penOrangeLight[idx] = get_pen(idx, 0xffff, 0x99ff, 0); | ||||||
|  | 	penRedShadow[idx] = get_pen(idx, 0xaaff, 0, 0); | ||||||
|  | 	penRedLight[idx] = get_pen(idx, 0xffff, 0, 0); | ||||||
|  | 	gdk_draw_rectangle(pixmap[idx], | ||||||
|  | 			   widget->style->black_gc, | ||||||
|  | 			   TRUE, | ||||||
|  | 			   0, 0, | ||||||
|  | 			   widget->allocation.width, | ||||||
|  | 			   widget->allocation.height); | ||||||
|  | 	// g_print("configure: %i:%i\n", widget->allocation.width, widget->allocation.height);
 | ||||||
|  | 	redraw_meters(idx, widget->allocation.width, widget->allocation.height, 0, 0); | ||||||
|  | 	return TRUE; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | gint level_meters_expose_event(GtkWidget *widget, GdkEventExpose *event) | ||||||
|  | { | ||||||
|  | 	int idx = get_index(gtk_widget_get_name(widget)); | ||||||
|  | 	int l1, l2; | ||||||
|  | 	 | ||||||
|  | 	get_levels(idx, &l1, &l2); | ||||||
|  | 	redraw_meters(idx, widget->allocation.width, widget->allocation.height, l1, l2); | ||||||
|  | 	gdk_draw_pixmap(widget->window, | ||||||
|  | 			widget->style->black_gc, | ||||||
|  | 			pixmap[idx], | ||||||
|  | 			event->area.x, event->area.y, | ||||||
|  | 			event->area.x, event->area.y, | ||||||
|  | 			event->area.width, event->area.height); | ||||||
|  | 	return FALSE; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | gint level_meters_timeout_callback(gpointer data) | ||||||
|  | { | ||||||
|  | 	GtkWidget *widget; | ||||||
|  | 	int idx, l1, l2; | ||||||
|  | 
 | ||||||
|  | 	update_peak_switch(); | ||||||
|  | 	for (idx = 0; idx <= 20; idx++) { | ||||||
|  | 		get_levels(idx, &l1, &l2); | ||||||
|  | 		widget = idx == 0 ? mixer_mix_drawing : mixer_drawing[idx-1]; | ||||||
|  | 		if (!GTK_WIDGET_VISIBLE(widget)) | ||||||
|  | 			continue; | ||||||
|  | 		redraw_meters(idx, widget->allocation.width, widget->allocation.height, l1, l2); | ||||||
|  | 		gdk_draw_pixmap(widget->window, | ||||||
|  | 				widget->style->black_gc, | ||||||
|  | 				pixmap[idx], | ||||||
|  | 				0, 0, | ||||||
|  | 				0, 0, | ||||||
|  | 				widget->allocation.width, widget->allocation.height);	 | ||||||
|  | 	} | ||||||
|  | 	return TRUE; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void level_meters_reset_peaks(GtkButton *button, gpointer data) | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void level_meters_init(void) | ||||||
|  | { | ||||||
|  | 	memset(&peaks, 0, sizeof(peaks)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void level_meters_postinit(void) | ||||||
|  | { | ||||||
|  | 	level_meters_timeout_callback(NULL); | ||||||
|  | } | ||||||
							
								
								
									
										188
									
								
								envy24control/mixer.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										188
									
								
								envy24control/mixer.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,188 @@ | ||||||
|  | /*****************************************************************************
 | ||||||
|  |    mixer.c - mixer code | ||||||
|  |    Copyright (C) 2000 by Jaroslav Kysela <perex@suse.cz> | ||||||
|  |     | ||||||
|  |    This program is free software; you can redistribute it and/or | ||||||
|  |    modify it under the terms of the GNU General Public License | ||||||
|  |    as published by the Free Software Foundation; either version 2 | ||||||
|  |    of the License, or (at your option) any later version. | ||||||
|  |     | ||||||
|  |    This program is distributed in the hope that it will be useful, | ||||||
|  |    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |    GNU General Public License for more details. | ||||||
|  |     | ||||||
|  |    You should have received a copy of the GNU General Public License | ||||||
|  |    along with this program; if not, write to the Free Software | ||||||
|  |    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. | ||||||
|  | ******************************************************************************/ | ||||||
|  | 
 | ||||||
|  | #include "envy24control.h" | ||||||
|  | 
 | ||||||
|  | #define toggle_set(widget, state) \ | ||||||
|  | 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), state); | ||||||
|  | 
 | ||||||
|  | static int is_active(GtkWidget *widget) | ||||||
|  | { | ||||||
|  | 	return GTK_TOGGLE_BUTTON(widget)->active ? 1 : 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void mixer_update_stream(int stream, int vol_flag, int sw_flag) | ||||||
|  | { | ||||||
|  | 	snd_control_t vol, sw; | ||||||
|  | 	int err; | ||||||
|  | 	 | ||||||
|  | 	if (vol_flag) { | ||||||
|  | 		memset(&vol, 0, sizeof(vol)); | ||||||
|  | 		vol.id.iface = SND_CONTROL_IFACE_MIXER; | ||||||
|  | 		strcpy(vol.id.name, stream <= 10 ? "Multi Playback Volume" : "Multi Capture Volume"); | ||||||
|  | 		vol.id.index = (stream - 1) % 10; | ||||||
|  | 		if ((err = snd_ctl_cread(card_ctl, &vol)) < 0) | ||||||
|  | 			g_print("Unable to read multi playback volume: %s\n", snd_strerror(err)); | ||||||
|  | 		gtk_adjustment_set_value(GTK_ADJUSTMENT(mixer_adj[stream-1][0]), 96 - vol.value.integer.value[0]); | ||||||
|  | 		gtk_adjustment_set_value(GTK_ADJUSTMENT(mixer_adj[stream-1][1]), 96 - vol.value.integer.value[1]); | ||||||
|  | 		if (vol.value.integer.value[0] != vol.value.integer.value[1]) | ||||||
|  | 			toggle_set(mixer_stereo_toggle[stream-1], FALSE); | ||||||
|  | 	} | ||||||
|  | 	if (sw_flag) { | ||||||
|  | 		memset(&sw, 0, sizeof(sw)); | ||||||
|  | 		sw.id.iface = SND_CONTROL_IFACE_MIXER; | ||||||
|  | 		strcpy(sw.id.name, stream <= 10 ? "Multi Playback Switch" : "Multi Capture Switch"); | ||||||
|  | 		sw.id.index = (stream - 1) % 10; | ||||||
|  | 		if ((err = snd_ctl_cread(card_ctl, &sw)) < 0) | ||||||
|  | 			g_print("Unable to read multi playback switch: %s\n", snd_strerror(err)); | ||||||
|  | 		toggle_set(mixer_solo_toggle[stream-1][0], sw.value.integer.value[0] ? TRUE : FALSE); | ||||||
|  | 		toggle_set(mixer_solo_toggle[stream-1][1], sw.value.integer.value[1] ? TRUE : FALSE); | ||||||
|  | 		toggle_set(mixer_mute_toggle[stream-1][0], !sw.value.integer.value[0] ? TRUE : FALSE); | ||||||
|  | 		toggle_set(mixer_mute_toggle[stream-1][1], !sw.value.integer.value[1] ? TRUE : FALSE); | ||||||
|  | 		if (sw.value.integer.value[0] != sw.value.integer.value[1]) | ||||||
|  | 			toggle_set(mixer_stereo_toggle[stream-1], FALSE); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void set_switch1(int stream, int left, int right) | ||||||
|  | { | ||||||
|  | 	snd_control_t sw; | ||||||
|  | 	int err; | ||||||
|  | 	 | ||||||
|  | 	memset(&sw, 0, sizeof(sw)); | ||||||
|  | 	sw.id.iface = SND_CONTROL_IFACE_MIXER; | ||||||
|  | 	strcpy(sw.id.name, stream <= 10 ? "Multi Playback Switch" : "Multi Capture Switch"); | ||||||
|  | 	sw.id.index = (stream - 1) % 10; | ||||||
|  | 	if ((err = snd_ctl_cread(card_ctl, &sw)) < 0) | ||||||
|  | 		g_print("Unable to read multi switch: %s\n", snd_strerror(err)); | ||||||
|  | 	if (left >= 0) | ||||||
|  | 		sw.value.integer.value[0] = left != 0; | ||||||
|  | 	if (right >= 0) | ||||||
|  | 		sw.value.integer.value[1] = right != 0; | ||||||
|  | 	if ((err = snd_ctl_cwrite(card_ctl, &sw)) < 0 && err != -EBUSY) | ||||||
|  | 		g_print("Unable to write multi switch: %s\n", snd_strerror(err)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void mixer_toggled_solo(GtkWidget *togglebutton, gpointer data) | ||||||
|  | { | ||||||
|  | 	int stream = (long)data >> 16; | ||||||
|  | 	int button = (long)data & 1; | ||||||
|  | 	int stereo = is_active(mixer_stereo_toggle[stream-1]) ? 1 : 0; | ||||||
|  | 	int vol[2] = { -1, -1 }; | ||||||
|  | 
 | ||||||
|  | 	if (is_active(togglebutton)) { | ||||||
|  | 		if (is_active(mixer_mute_toggle[stream-1][button])) | ||||||
|  | 			toggle_set(mixer_mute_toggle[stream-1][button], FALSE); | ||||||
|  | 		vol[button] = 1; | ||||||
|  | 		if (stereo) { | ||||||
|  | 			if (!is_active(mixer_solo_toggle[stream-1][button ^ 1])) | ||||||
|  | 				toggle_set(mixer_solo_toggle[stream-1][button ^ 1], TRUE); | ||||||
|  | 			if (is_active(mixer_mute_toggle[stream-1][button ^ 1])) | ||||||
|  | 				toggle_set(mixer_mute_toggle[stream-1][button ^ 1], FALSE); | ||||||
|  | 			vol[button ^ 1] = 1; | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		if (!is_active(mixer_mute_toggle[stream-1][button])) | ||||||
|  | 			toggle_set(mixer_mute_toggle[stream-1][button], TRUE); | ||||||
|  | 		vol[button] = 0; | ||||||
|  | 		if (stereo) { | ||||||
|  | 			if (is_active(mixer_solo_toggle[stream-1][button ^ 1])) | ||||||
|  | 				toggle_set(mixer_solo_toggle[stream-1][button ^ 1], FALSE); | ||||||
|  | 			if (!is_active(mixer_mute_toggle[stream-1][button ^ 1])) | ||||||
|  | 				toggle_set(mixer_mute_toggle[stream-1][button ^ 1], TRUE); | ||||||
|  | 			vol[button ^ 1] = 0; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	set_switch1(stream, vol[0], vol[1]); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void mixer_toggled_mute(GtkWidget *togglebutton, gpointer data) | ||||||
|  | { | ||||||
|  | 	int stream = (long)data >> 16; | ||||||
|  | 	int button = (long)data & 1; | ||||||
|  | 	int stereo = is_active(mixer_stereo_toggle[stream-1]) ? 1 : 0; | ||||||
|  | 	int vol[2] = { -1, -1 }; | ||||||
|  | 
 | ||||||
|  | 	if (is_active(togglebutton)) { | ||||||
|  | 		if (is_active(mixer_solo_toggle[stream-1][button])) | ||||||
|  | 			toggle_set(mixer_solo_toggle[stream-1][button], FALSE); | ||||||
|  | 		vol[button] = 0; | ||||||
|  | 		if (stereo) { | ||||||
|  | 			if (!is_active(mixer_mute_toggle[stream-1][button ^ 1])) | ||||||
|  | 				toggle_set(mixer_mute_toggle[stream-1][button ^ 1], TRUE); | ||||||
|  | 			if (is_active(mixer_solo_toggle[stream-1][button ^ 1])) | ||||||
|  | 				toggle_set(mixer_solo_toggle[stream-1][button ^ 1], FALSE); | ||||||
|  | 			vol[button ^ 1] = 0; | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		if (!is_active(mixer_solo_toggle[stream-1][button])) | ||||||
|  | 			toggle_set(mixer_solo_toggle[stream-1][button], TRUE); | ||||||
|  | 		vol[button] = 1; | ||||||
|  | 		if (stereo) { | ||||||
|  | 			if (is_active(mixer_mute_toggle[stream-1][button ^ 1])) | ||||||
|  | 				toggle_set(mixer_mute_toggle[stream-1][button ^ 1], FALSE); | ||||||
|  | 			if (!is_active(mixer_solo_toggle[stream-1][button ^ 1])) | ||||||
|  | 				toggle_set(mixer_solo_toggle[stream-1][button ^ 1], TRUE); | ||||||
|  | 			vol[button ^ 1] = 1; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	set_switch1(stream, vol[0], vol[1]); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void set_volume1(int stream, int left, int right) | ||||||
|  | { | ||||||
|  | 	snd_control_t vol; | ||||||
|  | 	int err; | ||||||
|  | 	 | ||||||
|  | 	memset(&vol, 0, sizeof(vol)); | ||||||
|  | 	vol.id.iface = SND_CONTROL_IFACE_MIXER; | ||||||
|  | 	strcpy(vol.id.name, stream <= 10 ? "Multi Playback Volume" : "Multi Capture Volume"); | ||||||
|  | 	vol.id.index = (stream - 1) % 10; | ||||||
|  | 	if ((err = snd_ctl_cread(card_ctl, &vol)) < 0) | ||||||
|  | 		g_print("Unable to read multi volume: %s\n", snd_strerror(err)); | ||||||
|  | 	if (left >= 0) | ||||||
|  | 		vol.value.integer.value[0] = left; | ||||||
|  | 	if (right >= 0) | ||||||
|  | 		vol.value.integer.value[1] = right; | ||||||
|  | 	if ((err = snd_ctl_cwrite(card_ctl, &vol)) < 0 && err != -EBUSY) | ||||||
|  | 		g_print("Unable to write multi volume: %s\n", snd_strerror(err)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void mixer_adjust(GtkAdjustment *adj, gpointer data) | ||||||
|  | { | ||||||
|  | 	int stream = (long)data >> 16; | ||||||
|  | 	int button = (long)data & 1; | ||||||
|  | 	int stereo = is_active(mixer_stereo_toggle[stream-1]) ? 1 : 0; | ||||||
|  | 	int vol[2] = { -1, -1 }; | ||||||
|  | 	 | ||||||
|  | 	vol[button] = 96 - adj->value; | ||||||
|  | 	if (stereo) { | ||||||
|  | 		gtk_adjustment_set_value(GTK_ADJUSTMENT(mixer_adj[stream-1][button ^ 1]), adj->value); | ||||||
|  | 		vol[button ^ 1] = 96 - adj->value; | ||||||
|  | 	} | ||||||
|  | 	set_volume1(stream, vol[0], vol[1]); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void mixer_postinit(void) | ||||||
|  | { | ||||||
|  | 	int stream; | ||||||
|  | 
 | ||||||
|  | 	for (stream = 1; stream <= 20; stream++) | ||||||
|  | 		mixer_update_stream(stream, 1, 1); | ||||||
|  | } | ||||||
							
								
								
									
										195
									
								
								envy24control/patchbay.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										195
									
								
								envy24control/patchbay.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,195 @@ | ||||||
|  | /*****************************************************************************
 | ||||||
|  |    patchbay.c - patchbay/router code | ||||||
|  |    Copyright (C) 2000 by Jaroslav Kysela <perex@suse.cz> | ||||||
|  |     | ||||||
|  |    This program is free software; you can redistribute it and/or | ||||||
|  |    modify it under the terms of the GNU General Public License | ||||||
|  |    as published by the Free Software Foundation; either version 2 | ||||||
|  |    of the License, or (at your option) any later version. | ||||||
|  |     | ||||||
|  |    This program is distributed in the hope that it will be useful, | ||||||
|  |    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |    GNU General Public License for more details. | ||||||
|  |     | ||||||
|  |    You should have received a copy of the GNU General Public License | ||||||
|  |    along with this program; if not, write to the Free Software | ||||||
|  |    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. | ||||||
|  | ******************************************************************************/ | ||||||
|  | 
 | ||||||
|  | #include "envy24control.h" | ||||||
|  | 
 | ||||||
|  | static snd_control_t routes; | ||||||
|  | 
 | ||||||
|  | #define toggle_set(widget, state) \ | ||||||
|  | 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), state); | ||||||
|  | 
 | ||||||
|  | static int is_active(GtkWidget *widget) | ||||||
|  | { | ||||||
|  | 	return GTK_TOGGLE_BUTTON(widget)->active ? 1 : 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int get_toggle_index(int stream) | ||||||
|  | { | ||||||
|  | 	unsigned short psdout = routes.value.bytes.data[0] | | ||||||
|  | 				(routes.value.bytes.data[1] << 8); | ||||||
|  | 	unsigned short spdout = routes.value.bytes.data[2] | | ||||||
|  | 				(routes.value.bytes.data[3] << 8); | ||||||
|  | 	unsigned int capture = routes.value.bytes.data[4] | | ||||||
|  | 			       (routes.value.bytes.data[5] << 8) | | ||||||
|  | 			       (routes.value.bytes.data[6] << 16) | | ||||||
|  | 			       (routes.value.bytes.data[7] << 24); | ||||||
|  | 	int right = (stream - 1) & 1; | ||||||
|  | 	int source = (stream - 1) >> 1; | ||||||
|  | 
 | ||||||
|  | 	stream--; | ||||||
|  | 	if (stream < 0 || stream > 9) { | ||||||
|  | 		g_print("get_toggle_index (1)\n"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	if (stream < 8) {	/* SPDOUT */ | ||||||
|  | 		int psdout_shift = (source << 1) + (right ? 8 : 0); | ||||||
|  | 		int capture_shift = (source << 3) + (right ? 4 : 0); | ||||||
|  | 		int setup = (psdout >> psdout_shift) & 3; | ||||||
|  | 		int csetup = (capture >> capture_shift) & 15; | ||||||
|  | 		 | ||||||
|  | 		switch (setup) { | ||||||
|  | 		case 0:					/* PCM Out */ | ||||||
|  | 			return 0; | ||||||
|  | 		case 1:					/* digital mixer */ | ||||||
|  | 			if (stream == 0 || stream == 1) | ||||||
|  | 				return 1; | ||||||
|  | 			return 0; | ||||||
|  | 		case 2: | ||||||
|  | 			return (csetup & 7) + 4; | ||||||
|  | 		case 3: | ||||||
|  | 			if (csetup & 8) | ||||||
|  | 				return 3;		/* S/PDIF right */ | ||||||
|  | 			return 2;			/* S/PDIF left */ | ||||||
|  | 		} | ||||||
|  | 	} else {	/* SPDOUT */ | ||||||
|  | 		int spdout_shift = right ? 2 : 0; | ||||||
|  | 		int spdout_shift1 = right ? 12 : 8; | ||||||
|  | 		int setup = (spdout >> spdout_shift) & 3; | ||||||
|  | 		int setup1 = (spdout >> spdout_shift1) & 15; | ||||||
|  | 		 | ||||||
|  | 		switch (setup) { | ||||||
|  | 		case 0:					/* PCM Out */ | ||||||
|  | 			return 0; | ||||||
|  | 		case 1:					/* digital mixer */ | ||||||
|  | 			if (stream == 0 || stream == 1) | ||||||
|  | 				return 1; | ||||||
|  | 			return 0; | ||||||
|  | 		case 2: | ||||||
|  | 			return (setup1 & 7) + 4; | ||||||
|  | 		case 3: | ||||||
|  | 			if (setup1 & 8) | ||||||
|  | 				return 3;		/* S/PDIF right */ | ||||||
|  | 			return 2;			/* S/PDIF left */ | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void patchbay_update(void) | ||||||
|  | { | ||||||
|  | 	int stream, tidx, err; | ||||||
|  | 
 | ||||||
|  | 	if ((err = snd_ctl_cread(card_ctl, &routes)) < 0) { | ||||||
|  | 		g_print("Multi track routes read error: %s\n", snd_strerror(err)); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	for (stream = 1; stream <= 10; stream++) { | ||||||
|  | 		tidx = get_toggle_index(stream); | ||||||
|  | 		toggle_set(router_radio[stream - 1][tidx], TRUE); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void set_routes(int stream, int idx) | ||||||
|  | { | ||||||
|  | 	unsigned short psdout = routes.value.bytes.data[0] | | ||||||
|  | 				(routes.value.bytes.data[1] << 8); | ||||||
|  | 	unsigned short spdout = routes.value.bytes.data[2] | | ||||||
|  | 				(routes.value.bytes.data[3] << 8); | ||||||
|  | 	unsigned int capture = routes.value.bytes.data[4] | | ||||||
|  | 			       (routes.value.bytes.data[5] << 8) | | ||||||
|  | 			       (routes.value.bytes.data[6] << 16) | | ||||||
|  | 			       (routes.value.bytes.data[7] << 24); | ||||||
|  | 	int right = (stream - 1) & 1; | ||||||
|  | 	int source = (stream - 1) >> 1; | ||||||
|  | 	int err; | ||||||
|  | 
 | ||||||
|  | 	stream--; | ||||||
|  | 	if (stream < 0 || stream > 9) { | ||||||
|  | 		g_print("set_routes (1)\n"); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	if (stream < 8) {	/* SPDOUT */ | ||||||
|  | 		int psdout_shift = (source << 1) + (right ? 8 : 0); | ||||||
|  | 		int capture_shift = (source << 3) + (right ? 4 : 0); | ||||||
|  | 		psdout &= ~(3 << psdout_shift); | ||||||
|  | 		if (idx == 0) {				/* PCM Out */ | ||||||
|  | 			/* nothing */ ; | ||||||
|  | 		} else if (idx == 1) {			/* digital mixer */ | ||||||
|  | 			if (stream == 0 || stream == 1) | ||||||
|  | 				psdout |= 1 << psdout_shift; | ||||||
|  | 		} else if (idx == 2 || idx == 3) {	/* S/PDIF left & right */ | ||||||
|  | 			psdout |= 3 << psdout_shift; | ||||||
|  | 			capture &= ~(1 << (capture_shift + 3)); | ||||||
|  | 			capture |= (idx - 2) << (capture_shift + 3); | ||||||
|  | 		} else { | ||||||
|  | 			psdout |= 2 << psdout_shift; | ||||||
|  | 			capture &= ~(7 << capture_shift); | ||||||
|  | 			capture |= ((idx - 4) & 7) << capture_shift; | ||||||
|  | 		} | ||||||
|  | 	} else {	/* SPDOUT */ | ||||||
|  | 		int spdout_shift = right ? 2 : 0; | ||||||
|  | 		int spdout_shift1 = right ? 12 : 8; | ||||||
|  | 		spdout &= ~(3 << spdout_shift); | ||||||
|  | 		if (idx == 0) {				/* PCM Out 9 & 10 */ | ||||||
|  | 			/* nothing */ ; | ||||||
|  | 		} else if (idx == 1) {			/* digital mixer */ | ||||||
|  | 			spdout |= 1 << spdout_shift; | ||||||
|  | 		} else if (idx == 2 || idx == 3) {	/* S/PDIF left & right */ | ||||||
|  | 			spdout |= 3 << spdout_shift; | ||||||
|  | 			spdout &= ~(1 << (spdout_shift1 + 3)); | ||||||
|  | 			spdout |= (idx - 2) << (spdout_shift1 + 3); | ||||||
|  | 		} else { | ||||||
|  | 			spdout |= 2 << spdout_shift; | ||||||
|  | 			spdout &= ~(7 << spdout_shift1); | ||||||
|  | 			spdout |= ((idx - 4) & 7) << spdout_shift1; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	routes.value.bytes.data[0] = psdout & 0xff; | ||||||
|  | 	routes.value.bytes.data[1] = (psdout >> 8) & 0xff; | ||||||
|  | 	routes.value.bytes.data[2] = spdout & 0xff; | ||||||
|  | 	routes.value.bytes.data[3] = (spdout >> 8) & 0xff; | ||||||
|  | 	routes.value.bytes.data[4] = capture & 0xff; | ||||||
|  | 	routes.value.bytes.data[5] = (capture >> 8) & 0xff; | ||||||
|  | 	routes.value.bytes.data[6] = (capture >> 16) & 0xff; | ||||||
|  | 	routes.value.bytes.data[7] = (capture >> 24) & 0xff; | ||||||
|  | 	// g_print("psdout = 0x%x, spdout = 0x%x, capture = 0x%x\n", psdout, spdout, capture);
 | ||||||
|  | 	if ((err = snd_ctl_cwrite(card_ctl, &routes)) < 0) | ||||||
|  | 		g_print("Multi track route write error: %s\n", snd_strerror(err)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void patchbay_toggled(GtkWidget *togglebutton, gpointer data) | ||||||
|  | { | ||||||
|  | 	int stream = (long)data >> 16; | ||||||
|  | 	int what = (long)data & 0xffff; | ||||||
|  | 
 | ||||||
|  | 	if (is_active(togglebutton)) | ||||||
|  | 		set_routes(stream, what); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void patchbay_init(void) | ||||||
|  | { | ||||||
|  | 	memset(&routes, 0, sizeof(routes)); | ||||||
|  | 	routes.id.iface = SND_CONTROL_IFACE_MIXER; | ||||||
|  | 	strcpy(routes.id.name, "Multi Track Route"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void patchbay_postinit(void) | ||||||
|  | { | ||||||
|  | 	patchbay_update(); | ||||||
|  | } | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jaroslav Kysela
						Jaroslav Kysela