--- /dev/null
+Jaroslav Kysela <perex@suse.cz>
--- /dev/null
+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
\ No newline at end of file
--- /dev/null
+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 *~
+
--- /dev/null
+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)
--- /dev/null
+#!/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
--- /dev/null
+/*****************************************************************************
+ 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);
+}
--- /dev/null
+/*****************************************************************************
+ envy24control.c - Env24 chipset (ICE1712) control utility
+ 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"
+
+int card = 0;
+snd_ctl_t *card_ctl = NULL;
+snd_ctl_hw_info_t hw_info;
+ice1712_eeprom_t card_eeprom;
+
+GtkWidget *window;
+
+GtkWidget *mixer_mix_drawing;
+GtkWidget *mixer_clear_peaks_button;
+GtkWidget *mixer_drawing[20];
+GtkObject *mixer_adj[20][2];
+GtkWidget *mixer_vscale[20][2];
+GtkWidget *mixer_solo_toggle[20][2];
+GtkWidget *mixer_mute_toggle[20][2];
+GtkWidget *mixer_stereo_toggle[20];
+
+GtkWidget *router_radio[10][12];
+
+GtkWidget *hw_master_clock_xtal_radio;
+GtkWidget *hw_master_clock_spdif_radio;
+GtkWidget *hw_master_clock_word_radio;
+GtkWidget *hw_master_clock_status_label;
+
+GtkObject *hw_volume_change_adj;
+GtkWidget *hw_volume_change_spin;
+
+GtkWidget *hw_spdif_profi_nonaudio_radio;
+GtkWidget *hw_spdif_profi_audio_radio;
+
+GtkWidget *hw_profi_stream_stereo_radio;
+GtkWidget *hw_profi_stream_notid_radio;
+
+GtkWidget *hw_profi_emphasis_none_radio;
+GtkWidget *hw_profi_emphasis_5015_radio;
+GtkWidget *hw_profi_emphasis_ccitt_radio;
+GtkWidget *hw_profi_emphasis_notid_radio;
+
+GtkWidget *hw_consumer_copyright_on_radio;
+GtkWidget *hw_consumer_copyright_off_radio;
+
+GtkWidget *hw_consumer_copy_1st_radio;
+GtkWidget *hw_consumer_copy_original_radio;
+
+GtkWidget *hw_consumer_emphasis_none_radio;
+GtkWidget *hw_consumer_emphasis_5015_radio;
+
+GtkWidget *hw_consumer_category_dat_radio;
+GtkWidget *hw_consumer_category_pcm_radio;
+GtkWidget *hw_consumer_category_cd_radio;
+GtkWidget *hw_consumer_category_general_radio;
+
+GtkWidget *hw_spdif_professional_radio;
+GtkWidget *hw_spdif_consumer_radio;
+GtkWidget *hw_spdif_output_notebook;
+
+GtkWidget *hw_spdif_input_coaxial_radio;
+GtkWidget *hw_spdif_input_optical_radio;
+
+
+
+static void create_mixer_frame(GtkWidget *fixed, int stream)
+{
+ GtkWidget *frame;
+ GtkWidget *fixed1;
+ GtkObject *adj;
+ GtkWidget *vscale;
+ GtkWidget *drawing;
+ GtkWidget *label;
+ GtkWidget *toggle;
+ GtkWidget *hseparator;
+ char str[64], drawname[32];
+
+ if (stream <= 10) {
+ sprintf(str, "PCM Out %i", stream);
+ } else if (stream <= 18) {
+ sprintf(str, "H/W In %i", stream - 10);
+ } else if (stream == 19) {
+ strcpy(str, "S/PDIF In L");
+ } else if (stream == 20) {
+ strcpy(str, "S/PDIF In R");
+ } else {
+ strcpy(str, "???");
+ }
+
+ frame = gtk_frame_new(str);
+ gtk_widget_show(frame);
+ gtk_fixed_put(GTK_FIXED(fixed), frame, 2 + (stream - 1) * 102, 2);
+ gtk_widget_set_uposition(frame, 2 + (stream - 1) * 102, 2);
+ gtk_widget_set_usize(frame, 98, 288);
+ gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
+
+ fixed1 = gtk_fixed_new();
+ gtk_widget_show(fixed1);
+ gtk_container_add(GTK_CONTAINER(frame), fixed1);
+
+ adj = gtk_adjustment_new(96, 0, 96, 1, 16, 0);
+ mixer_adj[stream-1][0] = adj;
+ vscale = gtk_vscale_new(GTK_ADJUSTMENT(adj));
+ mixer_vscale[stream-1][0] = vscale;
+ gtk_widget_show(vscale);
+ gtk_fixed_put(GTK_FIXED(fixed1), vscale, 8, 8);
+ gtk_widget_set_uposition(vscale, 7, 8);
+ gtk_widget_set_usize(vscale, 18, 146);
+ gtk_scale_set_value_pos(GTK_SCALE(vscale), GTK_POS_BOTTOM);
+ gtk_scale_set_digits(GTK_SCALE(vscale), 0);
+ gtk_signal_connect(GTK_OBJECT(adj), "value_changed",
+ GTK_SIGNAL_FUNC(mixer_adjust), (gpointer)((stream << 16) + 0));
+
+ drawing = gtk_drawing_area_new();
+ mixer_drawing[stream-1] = drawing;
+ sprintf(drawname, "Mixer%i", stream);
+ gtk_widget_set_name(drawing, drawname);
+ gtk_widget_show(drawing);
+ gtk_signal_connect(GTK_OBJECT(drawing), "expose_event",
+ (GtkSignalFunc)level_meters_expose_event, NULL);
+ gtk_signal_connect(GTK_OBJECT(drawing), "configure_event",
+ (GtkSignalFunc)level_meters_configure_event, NULL);
+ gtk_widget_set_events(drawing, GDK_EXPOSURE_MASK);
+ gtk_fixed_put(GTK_FIXED(fixed1), drawing, 24, 9);
+ gtk_widget_set_uposition(drawing, 24, 9);
+ gtk_widget_set_usize(drawing, 45, 130);
+
+ adj = gtk_adjustment_new(96, 0, 96, 1, 16, 0);
+ mixer_adj[stream-1][1] = adj;
+ vscale = gtk_vscale_new(GTK_ADJUSTMENT(adj));
+ mixer_vscale[stream-1][1] = vscale;
+ gtk_widget_show(vscale);
+ gtk_fixed_put(GTK_FIXED(fixed1), vscale, 70, 8);
+ gtk_widget_set_uposition(vscale, 69, 8);
+ gtk_widget_set_usize(vscale, 18, 146);
+ gtk_scale_set_value_pos(GTK_SCALE(vscale), GTK_POS_BOTTOM);
+ gtk_scale_set_digits(GTK_SCALE(vscale), 0);
+ gtk_signal_connect(GTK_OBJECT(adj), "value_changed",
+ GTK_SIGNAL_FUNC(mixer_adjust), (gpointer)((stream << 16) + 1));
+
+ label = gtk_label_new("Left");
+ gtk_widget_show(label);
+ gtk_fixed_put(GTK_FIXED(fixed1), label, 0, 160);
+ gtk_widget_set_uposition(label, 0, 160);
+ gtk_widget_set_usize(label, 41, 16);
+
+ label = gtk_label_new("Right");
+ gtk_widget_show(label);
+ gtk_fixed_put(GTK_FIXED(fixed1), label, 45, 160);
+ gtk_widget_set_uposition(label, 45, 160);
+ gtk_widget_set_usize(label, 41, 16);
+
+ toggle = gtk_toggle_button_new_with_label("On");
+ mixer_solo_toggle[stream-1][0] = toggle;
+ gtk_widget_show(toggle);
+ gtk_fixed_put(GTK_FIXED(fixed1), toggle, 8, 176);
+ gtk_widget_set_uposition(toggle, 8, 176);
+ gtk_widget_set_usize(toggle, 36, 22);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), FALSE);
+ gtk_signal_connect(GTK_OBJECT(toggle), "toggled",
+ (GtkSignalFunc)mixer_toggled_solo, (gpointer)((stream << 16) + 0));
+
+ toggle = gtk_toggle_button_new_with_label("On");
+ mixer_solo_toggle[stream-1][1] = toggle;
+ gtk_widget_show(toggle);
+ gtk_fixed_put(GTK_FIXED(fixed1), toggle, 48, 176);
+ gtk_widget_set_uposition(toggle, 48, 176);
+ gtk_widget_set_usize(toggle, 36, 22);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), FALSE);
+ gtk_signal_connect(GTK_OBJECT(toggle), "toggled",
+ (GtkSignalFunc)mixer_toggled_solo, (gpointer)((stream << 16) + 1));
+
+ toggle = gtk_toggle_button_new_with_label("Mute");
+ mixer_mute_toggle[stream-1][0] = toggle;
+ gtk_widget_show(toggle);
+ gtk_fixed_put(GTK_FIXED(fixed1), toggle, 8, 202);
+ gtk_widget_set_uposition(toggle, 8, 202);
+ gtk_widget_set_usize(toggle, 36, 22);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), TRUE);
+ gtk_signal_connect(GTK_OBJECT(toggle), "toggled",
+ (GtkSignalFunc)mixer_toggled_mute, (gpointer)((stream << 16) + 0));
+
+ toggle = gtk_toggle_button_new_with_label("Mute");
+ mixer_mute_toggle[stream-1][1] = toggle;
+ gtk_widget_show(toggle);
+ gtk_fixed_put(GTK_FIXED(fixed1), toggle, 48, 202);
+ gtk_widget_set_uposition(toggle, 48, 202);
+ gtk_widget_set_usize(toggle, 36, 22);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), TRUE);
+ gtk_signal_connect(GTK_OBJECT(toggle), "toggled",
+ (GtkSignalFunc)mixer_toggled_mute, (gpointer)((stream << 16) + 1));
+
+ hseparator = gtk_hseparator_new();
+ gtk_widget_show(hseparator);
+ gtk_fixed_put(GTK_FIXED(fixed1), hseparator, 0, 222);
+ gtk_widget_set_uposition(hseparator, 0, 222);
+ gtk_widget_set_usize(hseparator, 92, 16);
+
+ toggle = gtk_toggle_button_new_with_label("Stereo Gang");
+ mixer_stereo_toggle[stream-1] = toggle;
+ gtk_widget_show(toggle);
+ gtk_fixed_put(GTK_FIXED(fixed1), toggle, 3, 235);
+ gtk_widget_set_uposition(toggle, 3, 235);
+ gtk_widget_set_usize(toggle, 88, 32);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), TRUE);
+}
+
+static void create_mixer(GtkWidget *main, GtkWidget *notebook, int page)
+{
+ GtkWidget *label;
+ GtkWidget *hpaned;
+ GtkWidget *frame;
+ GtkWidget *fixed;
+ GtkWidget *drawing;
+ GtkWidget *hseparator;
+ GtkWidget *button;
+ GtkWidget *scrollwin;
+ GtkWidget *viewport;
+ int stream;
+
+ hpaned = gtk_hpaned_new();
+ gtk_widget_show(hpaned);
+ gtk_container_add(GTK_CONTAINER(notebook), hpaned);
+ gtk_paned_set_gutter_size(GTK_PANED(hpaned), 4);
+ gtk_paned_set_position(GTK_PANED(hpaned), 108);
+ label = gtk_label_new("Monitor Mixer");
+ gtk_widget_show(label);
+ gtk_notebook_set_tab_label(GTK_NOTEBOOK(notebook), gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), page), label);
+
+ /* create digital mixer frame */
+ frame = gtk_frame_new("Digital Mixer");
+ gtk_widget_show(frame);
+ gtk_container_add(GTK_CONTAINER(hpaned), frame);
+ gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
+
+ /* create controls in the digital mixer frame */
+ fixed = gtk_fixed_new();
+ gtk_widget_show(fixed);
+ gtk_container_add(GTK_CONTAINER(frame), fixed);
+
+ drawing = gtk_drawing_area_new();
+ mixer_mix_drawing = drawing;
+ gtk_widget_set_name(drawing, "DigitalMixer");
+ gtk_signal_connect(GTK_OBJECT(drawing), "expose_event",
+ (GtkSignalFunc)level_meters_expose_event, NULL);
+ gtk_signal_connect(GTK_OBJECT(drawing), "configure_event",
+ (GtkSignalFunc)level_meters_configure_event, NULL);
+ gtk_widget_set_events(drawing, GDK_EXPOSURE_MASK);
+ gtk_widget_show(drawing);
+ gtk_fixed_put(GTK_FIXED(fixed), drawing, 4, 2);
+ gtk_widget_set_uposition(drawing, 4, 2);
+ gtk_widget_set_usize(drawing, 98, 226);
+
+ label = gtk_label_new("Left");
+ gtk_widget_show(label);
+ gtk_fixed_put(GTK_FIXED(fixed), label, 0, 232);
+ gtk_widget_set_uposition(label, 0, 232);
+ gtk_widget_set_usize(label, 34, 16);
+
+ label = gtk_label_new("Right");
+ gtk_widget_show(label);
+ gtk_fixed_put(GTK_FIXED(fixed), label, 60, 232);
+ gtk_widget_set_uposition(label, 60, 232);
+ gtk_widget_set_usize(label, 34, 16);
+
+ hseparator = gtk_hseparator_new();
+ gtk_widget_show(hseparator);
+ gtk_fixed_put(GTK_FIXED(fixed), hseparator, 0, 244);
+ gtk_widget_set_uposition(hseparator, 0, 244);
+ gtk_widget_set_usize(hseparator, 104, 16);
+
+ button = gtk_button_new_with_label("Reset Peaks");
+ mixer_clear_peaks_button = button;
+ gtk_widget_show(button);
+ gtk_fixed_put(GTK_FIXED(fixed), button, 3, 256);
+ gtk_widget_set_uposition(button, 3, 256);
+ gtk_widget_set_usize(button, 98, 35);
+ gtk_signal_connect(GTK_OBJECT(button), "clicked",
+ GTK_SIGNAL_FUNC(level_meters_reset_peaks), NULL);
+
+ /* build scrolling area */
+ scrollwin = gtk_scrolled_window_new(NULL, NULL);
+ gtk_widget_show(scrollwin);
+ gtk_container_add(GTK_CONTAINER(hpaned), scrollwin);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), GTK_POLICY_ALWAYS, GTK_POLICY_NEVER);
+
+ viewport = gtk_viewport_new(NULL, NULL);
+ gtk_widget_show(viewport);
+ gtk_container_add(GTK_CONTAINER(scrollwin), viewport);
+
+ fixed = gtk_fixed_new();
+ gtk_widget_show(fixed);
+ gtk_container_add(GTK_CONTAINER(viewport), fixed);
+
+ for (stream = 1; stream <= 20; stream++)
+ create_mixer_frame(fixed, stream);
+}
+
+static void create_router_frame(GtkWidget *fixed, int stream)
+{
+ GtkWidget *frame;
+ GtkWidget *fixed1;
+ GtkWidget *radio;
+ GtkWidget *hseparator;
+ GSList *group = NULL;
+ char str[64], str1[64];
+ int idx;
+ static char *table[10] = {
+ "S/PDIF In L",
+ "S/PDIF In R",
+ "H/W In 1",
+ "H/W In 2",
+ "H/W In 3",
+ "H/W In 4",
+ "H/W In 5",
+ "H/W In 6",
+ "H/W In 7",
+ "H/W In 8"
+ };
+
+ if (stream <= 8) {
+ sprintf(str, "H/W Out %i (%s)", stream, stream & 1 ? "L" : "R");
+ } else if (stream == 9) {
+ strcpy(str, "S/PDIF Out L");
+ } else if (stream == 10) {
+ strcpy(str, "S/PDIF Out R");
+ } else {
+ strcpy(str, "???");
+ }
+ sprintf(str1, "PCM Out %i", stream);
+
+ frame = gtk_frame_new(str);
+ gtk_widget_show(frame);
+ gtk_fixed_put(GTK_FIXED(fixed), frame, 2 + (stream - 1) * 101, 2);
+ gtk_widget_set_uposition(frame, 2 + (stream - 1) * 101, 2);
+ gtk_widget_set_usize(frame, 98, 284);
+
+ fixed1 = gtk_fixed_new();
+ gtk_widget_show(fixed1);
+ gtk_container_add(GTK_CONTAINER(frame), fixed1);
+
+ radio = gtk_radio_button_new_with_label(group, str1);
+ router_radio[stream-1][0] = radio;
+ group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));
+ gtk_widget_show(radio);
+ gtk_fixed_put(GTK_FIXED(fixed1), radio, 0, 0);
+ gtk_widget_set_uposition(radio, 0, 0);
+ gtk_widget_set_usize(radio, 93, 24);
+ gtk_signal_connect(GTK_OBJECT(radio), "toggled",
+ (GtkSignalFunc)patchbay_toggled, (gpointer)((stream << 16) + 0));
+
+ hseparator = gtk_hseparator_new();
+ gtk_widget_show(hseparator);
+ gtk_fixed_put(GTK_FIXED(fixed1), hseparator, 0, 21);
+ gtk_widget_set_uposition(hseparator, 0, 21);
+ gtk_widget_set_usize(hseparator, 94, 16);
+
+ if (stream == 1 || stream == 2 || stream == 9 || stream == 10) {
+ radio = gtk_radio_button_new_with_label(group, stream & 1 ? "Digital Mix L" : "Digital Mix R");
+ router_radio[stream-1][1] = radio;
+ group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));
+ gtk_widget_show(radio);
+ gtk_fixed_put(GTK_FIXED(fixed1), radio, 0, 32);
+ gtk_widget_set_uposition(radio, 0, 32);
+ gtk_widget_set_usize(radio, 93, 24);
+ gtk_signal_connect(GTK_OBJECT(radio), "toggled",
+ (GtkSignalFunc)patchbay_toggled, (gpointer)((stream << 16) + 1));
+ }
+
+ hseparator = gtk_hseparator_new();
+ gtk_widget_show(hseparator);
+ gtk_fixed_put(GTK_FIXED(fixed1), hseparator, 0, 52);
+ gtk_widget_set_uposition(hseparator, 0, 52);
+ gtk_widget_set_usize(hseparator, 94, 16);
+
+ for (idx = 0; idx < 10; idx++) {
+ radio = gtk_radio_button_new_with_label(group, table[idx]);
+ router_radio[stream-1][2+idx] = radio;
+ group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));
+ gtk_widget_show(radio);
+ gtk_fixed_put(GTK_FIXED(fixed1), radio, 0, 64 + (idx * 20));
+ gtk_widget_set_uposition(radio, 0, 64 + (idx * 20));
+ gtk_widget_set_usize(radio, 93, 24);
+ gtk_signal_connect(GTK_OBJECT(radio), "toggled",
+ (GtkSignalFunc)patchbay_toggled, (gpointer)((stream << 16) + 2 + idx));
+ }
+}
+
+static void create_router(GtkWidget *main, GtkWidget *notebook, int page)
+{
+ GtkWidget *label;
+ GtkWidget *scrollwin;
+ GtkWidget *viewport;
+ GtkWidget *fixed;
+ int stream;
+
+ scrollwin = gtk_scrolled_window_new(NULL, NULL);
+ gtk_widget_show(scrollwin);
+ gtk_container_add(GTK_CONTAINER(notebook), scrollwin);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), GTK_POLICY_ALWAYS, GTK_POLICY_NEVER);
+ label = gtk_label_new("Patchbay / Router");
+ gtk_widget_show(label);
+ gtk_notebook_set_tab_label(GTK_NOTEBOOK(notebook), gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), page), label);
+ viewport = gtk_viewport_new(NULL, NULL);
+ gtk_widget_show(viewport);
+ gtk_container_add(GTK_CONTAINER(scrollwin), viewport);
+ fixed = gtk_fixed_new();
+ gtk_widget_show(fixed);
+ gtk_container_add(GTK_CONTAINER(viewport), fixed);
+
+ for (stream = 1; stream <= 10; stream++)
+ create_router_frame(fixed, stream);
+}
+
+static void create_master_clock(GtkWidget *fixed)
+{
+ GtkWidget *frame;
+ GtkWidget *fixed1;
+ GtkWidget *radio;
+ GtkWidget *viewport;
+ GtkWidget *fixed2;
+ GtkWidget *label;
+ GSList *group = NULL;
+
+ frame = gtk_frame_new("Master Clock");
+ gtk_widget_show(frame);
+ gtk_fixed_put(GTK_FIXED(fixed), frame, 8, 8);
+ gtk_widget_set_uposition(frame, 8, 8);
+ gtk_widget_set_usize(frame, 111, 125);
+
+ fixed1 = gtk_fixed_new();
+ gtk_widget_show(fixed1);
+ gtk_container_add(GTK_CONTAINER(frame), fixed1);
+
+ radio = gtk_radio_button_new_with_label(group, "Internal Xtal");
+ hw_master_clock_xtal_radio = radio;
+ group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));
+ gtk_widget_show(radio);
+ gtk_fixed_put(GTK_FIXED(fixed1), radio, 8, 0);
+ gtk_widget_set_uposition(radio, 8, 0);
+ gtk_widget_set_usize(radio, 92, 24);
+ gtk_signal_connect(GTK_OBJECT(radio), "toggled",
+ (GtkSignalFunc)master_clock_toggled, (gpointer)"Xtal");
+
+ radio = gtk_radio_button_new_with_label(group, "S/PDIF In");
+ hw_master_clock_spdif_radio = radio;
+ group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));
+ gtk_widget_show(radio);
+ gtk_fixed_put(GTK_FIXED(fixed1), radio, 8, 24);
+ gtk_widget_set_uposition(radio, 8, 24);
+ gtk_widget_set_usize(radio, 92, 24);
+ gtk_signal_connect(GTK_OBJECT(radio), "toggled",
+ (GtkSignalFunc)master_clock_toggled, (gpointer)"SPDIF");
+
+ if (card_eeprom.subvendor != ICE1712_SUBDEVICE_DELTA1010)
+ return;
+
+ radio = gtk_radio_button_new_with_label(group, "Word Clock");
+ hw_master_clock_word_radio = radio;
+ group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));
+ gtk_widget_show(radio);
+ gtk_fixed_put(GTK_FIXED(fixed1), radio, 8, 48);
+ gtk_widget_set_uposition(radio, 8, 48);
+ gtk_widget_set_usize(radio, 92, 24);
+ gtk_signal_connect(GTK_OBJECT(radio), "toggled",
+ (GtkSignalFunc)master_clock_toggled, (gpointer)"WordClock");
+
+ viewport = gtk_viewport_new(NULL, NULL);
+ gtk_widget_show(viewport);
+ gtk_fixed_put(GTK_FIXED(fixed1), viewport, 9, 75);
+ gtk_widget_set_uposition(viewport, 9, 75);
+ gtk_widget_set_usize(viewport, 90, 26);
+
+ fixed2 = gtk_fixed_new();
+ gtk_widget_show(fixed2);
+ gtk_container_add(GTK_CONTAINER(viewport), fixed2);
+
+ label = gtk_label_new("Locked");
+ hw_master_clock_status_label = label;
+ gtk_widget_show(label);
+ gtk_fixed_put(GTK_FIXED(fixed2), label, 0, 3);
+ gtk_widget_set_uposition(label, 0, 3);
+ gtk_widget_set_usize(label, 86, 16);
+}
+
+static void create_volume_change(GtkWidget *fixed)
+{
+ GtkWidget *frame;
+ GtkWidget *fixed1;
+ GtkObject *adj;
+ GtkWidget *spin;
+ GtkWidget *label;
+
+ frame = gtk_frame_new("Volume Change");
+ gtk_widget_show(frame);
+ gtk_fixed_put(GTK_FIXED(fixed), frame, 8, 144);
+ gtk_widget_set_uposition(frame, 8, 144);
+ gtk_widget_set_usize(frame, 111, 132);
+
+ fixed1 = gtk_fixed_new();
+ gtk_widget_show(fixed1);
+ gtk_container_add(GTK_CONTAINER(frame), fixed1);
+
+ adj = gtk_adjustment_new(16, 0, 255, 1, 10, 10);
+ hw_volume_change_adj = adj;
+ spin = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 1, 0);
+ hw_volume_change_spin = spin;
+ gtk_widget_show(spin);
+ gtk_fixed_put(GTK_FIXED(fixed1), spin, 48, 40);
+ gtk_widget_set_uposition(spin, 48, 40);
+ gtk_widget_set_usize(spin, 53, 22);
+ gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(spin), TRUE);
+ gtk_signal_connect(GTK_OBJECT(adj), "value_changed",
+ GTK_SIGNAL_FUNC(volume_change_rate_adj), NULL);
+
+ label = gtk_label_new("Rate:");
+ gtk_widget_show(label);
+ gtk_fixed_put(GTK_FIXED(fixed1), label, 0, 3);
+ gtk_widget_set_uposition(label, 0, 42);
+ gtk_widget_set_usize(label, 41, 16);
+}
+
+static void create_spdif_output_settings_profi_data(GtkWidget *fixed)
+{
+ GtkWidget *frame;
+ GtkWidget *fixed1;
+ GtkWidget *radio;
+ GSList *group = NULL;
+
+ frame = gtk_frame_new("Data Mode");
+ gtk_widget_show(frame);
+ gtk_fixed_put(GTK_FIXED(fixed), frame, 10, 10);
+ gtk_widget_set_uposition(frame, 10, 10);
+ gtk_widget_set_usize(frame, 100, 81);
+
+ fixed1 = gtk_fixed_new();
+ gtk_widget_show(fixed1);
+ gtk_container_add(GTK_CONTAINER(frame), fixed1);
+
+ radio = gtk_radio_button_new_with_label(group, "Non-audio");
+ hw_spdif_profi_nonaudio_radio = radio;
+ group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));
+ gtk_widget_show(radio);
+ gtk_fixed_put(GTK_FIXED(fixed1), radio, 8, 8);
+ gtk_widget_set_uposition(radio, 8, 8);
+ gtk_widget_set_usize(radio, 84, 24);
+ gtk_signal_connect(GTK_OBJECT(radio), "toggled",
+ (GtkSignalFunc)profi_data_toggled, (gpointer)"Non-audio");
+
+ radio = gtk_radio_button_new_with_label(group, "Audio");
+ hw_spdif_profi_audio_radio = radio;
+ group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));
+ gtk_widget_show(radio);
+ gtk_fixed_put(GTK_FIXED(fixed1), radio, 8, 32);
+ gtk_widget_set_uposition(radio, 8, 32);
+ gtk_widget_set_usize(radio, 84, 24);
+ gtk_signal_connect(GTK_OBJECT(radio), "toggled",
+ (GtkSignalFunc)profi_data_toggled, (gpointer)"Audio");
+}
+
+static void create_spdif_output_settings_profi_stream(GtkWidget *fixed)
+{
+ GtkWidget *frame;
+ GtkWidget *fixed1;
+ GtkWidget *radio;
+ GSList *group = NULL;
+
+ frame = gtk_frame_new("Stream");
+ gtk_widget_show(frame);
+ gtk_fixed_put(GTK_FIXED(fixed), frame, 120, 10);
+ gtk_widget_set_uposition(frame, 120, 10);
+ gtk_widget_set_usize(frame, 116, 81);
+
+ fixed1 = gtk_fixed_new();
+ gtk_widget_show(fixed1);
+ gtk_container_add(GTK_CONTAINER(frame), fixed1);
+
+ radio = gtk_radio_button_new_with_label(group, "Stereophonic");
+ hw_profi_stream_stereo_radio = radio;
+ group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));
+ gtk_widget_show(radio);
+ gtk_fixed_put(GTK_FIXED(fixed1), radio, 8, 8);
+ gtk_widget_set_uposition(radio, 8, 8);
+ gtk_widget_set_usize(radio, 96, 24);
+ gtk_signal_connect(GTK_OBJECT(radio), "toggled",
+ (GtkSignalFunc)profi_stream_toggled, (gpointer)"Stereo");
+
+ radio = gtk_radio_button_new_with_label(group, "Not indicated");
+ hw_profi_stream_notid_radio = radio;
+ group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));
+ gtk_widget_show(radio);
+ gtk_fixed_put(GTK_FIXED(fixed1), radio, 8, 32);
+ gtk_widget_set_uposition(radio, 8, 32);
+ gtk_widget_set_usize(radio, 96, 24);
+ gtk_signal_connect(GTK_OBJECT(radio), "toggled",
+ (GtkSignalFunc)profi_stream_toggled, (gpointer)"NOTID");
+}
+
+static void create_spdif_output_settings_profi_emphasis(GtkWidget *fixed)
+{
+ GtkWidget *frame;
+ GtkWidget *fixed1;
+ GtkWidget *radio;
+ GSList *group = NULL;
+
+ frame = gtk_frame_new("Emphasis");
+ gtk_widget_show(frame);
+ gtk_fixed_put(GTK_FIXED(fixed), frame, 10, 10);
+ gtk_widget_set_uposition(frame, 246, 10);
+ gtk_widget_set_usize(frame, 114, 131);
+
+ fixed1 = gtk_fixed_new();
+ gtk_widget_show(fixed1);
+ gtk_container_add(GTK_CONTAINER(frame), fixed1);
+
+ radio = gtk_radio_button_new_with_label(group, "No emphasis");
+ hw_profi_emphasis_none_radio = radio;
+ group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));
+ gtk_widget_show(radio);
+ gtk_fixed_put(GTK_FIXED(fixed1), radio, 8, 8);
+ gtk_widget_set_uposition(radio, 8, 8);
+ gtk_widget_set_usize(radio, 94, 24);
+ gtk_signal_connect(GTK_OBJECT(radio), "toggled",
+ (GtkSignalFunc)profi_emphasis_toggled, (gpointer)"No");
+
+ radio = gtk_radio_button_new_with_label(group, "50/15us");
+ hw_profi_emphasis_5015_radio = radio;
+ group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));
+ gtk_widget_show(radio);
+ gtk_fixed_put(GTK_FIXED(fixed1), radio, 8, 32);
+ gtk_widget_set_uposition(radio, 8, 32);
+ gtk_widget_set_usize(radio, 94, 24);
+ gtk_signal_connect(GTK_OBJECT(radio), "toggled",
+ (GtkSignalFunc)profi_emphasis_toggled, (gpointer)"5015");
+
+ radio = gtk_radio_button_new_with_label(group, "CCITT J.17");
+ hw_profi_emphasis_ccitt_radio = radio;
+ group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));
+ gtk_widget_show(radio);
+ gtk_fixed_put(GTK_FIXED(fixed1), radio, 8, 56);
+ gtk_widget_set_uposition(radio, 8, 56);
+ gtk_widget_set_usize(radio, 94, 24);
+ gtk_signal_connect(GTK_OBJECT(radio), "toggled",
+ (GtkSignalFunc)profi_emphasis_toggled, (gpointer)"CCITT");
+
+ radio = gtk_radio_button_new_with_label(group, "Not indicated");
+ hw_profi_emphasis_notid_radio = radio;
+ group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));
+ gtk_widget_show(radio);
+ gtk_fixed_put(GTK_FIXED(fixed1), radio, 8, 80);
+ gtk_widget_set_uposition(radio, 8, 80);
+ gtk_widget_set_usize(radio, 94, 24);
+ gtk_signal_connect(GTK_OBJECT(radio), "toggled",
+ (GtkSignalFunc)profi_emphasis_toggled, (gpointer)"NOTID");
+}
+
+static void create_spdif_output_settings_profi(GtkWidget *notebook, int page)
+{
+ GtkWidget *fixed;
+ GtkWidget *label;
+
+ fixed = gtk_fixed_new();
+ gtk_widget_show(fixed);
+ gtk_container_add(GTK_CONTAINER(notebook), fixed);
+ label = gtk_label_new("Professional");
+ gtk_widget_show(label);
+ gtk_notebook_set_tab_label(GTK_NOTEBOOK(notebook), gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), page), label);
+
+ create_spdif_output_settings_profi_data(fixed);
+ create_spdif_output_settings_profi_stream(fixed);
+ create_spdif_output_settings_profi_emphasis(fixed);
+}
+
+static void create_spdif_output_settings_consumer_copyright(GtkWidget *fixed)
+{
+ GtkWidget *frame;
+ GtkWidget *fixed1;
+ GtkWidget *radio;
+ GSList *group = NULL;
+
+ frame = gtk_frame_new("Copyright");
+ gtk_widget_show(frame);
+ gtk_fixed_put(GTK_FIXED(fixed), frame, 10, 10);
+ gtk_widget_set_uposition(frame, 10, 10);
+ gtk_widget_set_usize(frame, 124, 79);
+
+ fixed1 = gtk_fixed_new();
+ gtk_widget_show(fixed1);
+ gtk_container_add(GTK_CONTAINER(frame), fixed1);
+
+ radio = gtk_radio_button_new_with_label(group, "Copyrighted");
+ hw_consumer_copyright_on_radio = radio;
+ group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));
+ gtk_widget_show(radio);
+ gtk_fixed_put(GTK_FIXED(fixed1), radio, 8, 8);
+ gtk_widget_set_uposition(radio, 8, 8);
+ gtk_widget_set_usize(radio, 106, 24);
+ gtk_signal_connect(GTK_OBJECT(radio), "toggled",
+ (GtkSignalFunc)consumer_copyright_toggled, (gpointer)"Copyright");
+
+ radio = gtk_radio_button_new_with_label(group, "Copy permitted");
+ hw_consumer_copyright_off_radio = radio;
+ group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));
+ gtk_widget_show(radio);
+ gtk_fixed_put(GTK_FIXED(fixed1), radio, 8, 32);
+ gtk_widget_set_uposition(radio, 8, 32);
+ gtk_widget_set_usize(radio, 106, 24);
+ gtk_signal_connect(GTK_OBJECT(radio), "toggled",
+ (GtkSignalFunc)consumer_copyright_toggled, (gpointer)"Permitted");
+}
+
+static void create_spdif_output_settings_consumer_copy(GtkWidget *fixed)
+{
+ GtkWidget *frame;
+ GtkWidget *fixed1;
+ GtkWidget *radio;
+ GSList *group = NULL;
+
+ frame = gtk_frame_new("Copy");
+ gtk_widget_show(frame);
+ gtk_fixed_put(GTK_FIXED(fixed), frame, 10, 96);
+ gtk_widget_set_uposition(frame, 10, 96);
+ gtk_widget_set_usize(frame, 124, 79);
+
+ fixed1 = gtk_fixed_new();
+ gtk_widget_show(fixed1);
+ gtk_container_add(GTK_CONTAINER(frame), fixed1);
+
+ radio = gtk_radio_button_new_with_label(group, "1-st generation");
+ hw_consumer_copy_1st_radio = radio;
+ group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));
+ gtk_widget_show(radio);
+ gtk_fixed_put(GTK_FIXED(fixed1), radio, 8, 8);
+ gtk_widget_set_uposition(radio, 8, 8);
+ gtk_widget_set_usize(radio, 106, 24);
+ gtk_signal_connect(GTK_OBJECT(radio), "toggled",
+ (GtkSignalFunc)consumer_copy_toggled, (gpointer)"1st");
+
+ radio = gtk_radio_button_new_with_label(group, "Original");
+ hw_consumer_copy_original_radio = radio;
+ group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));
+ gtk_widget_show(radio);
+ gtk_fixed_put(GTK_FIXED(fixed1), radio, 8, 32);
+ gtk_widget_set_uposition(radio, 8, 32);
+ gtk_widget_set_usize(radio, 106, 24);
+ gtk_signal_connect(GTK_OBJECT(radio), "toggled",
+ (GtkSignalFunc)consumer_copy_toggled, (gpointer)"Original");
+}
+
+static void create_spdif_output_settings_consumer_emphasis(GtkWidget *fixed)
+{
+ GtkWidget *frame;
+ GtkWidget *fixed1;
+ GtkWidget *radio;
+ GSList *group = NULL;
+
+ frame = gtk_frame_new("Emphasis");
+ gtk_widget_show(frame);
+ gtk_fixed_put(GTK_FIXED(fixed), frame, 144, 10);
+ gtk_widget_set_uposition(frame, 144, 10);
+ gtk_widget_set_usize(frame, 130, 80);
+
+ fixed1 = gtk_fixed_new();
+ gtk_widget_show(fixed1);
+ gtk_container_add(GTK_CONTAINER(frame), fixed1);
+
+ radio = gtk_radio_button_new_with_label(group, "No emphasis");
+ hw_consumer_emphasis_none_radio = radio;
+ group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));
+ gtk_widget_show(radio);
+ gtk_fixed_put(GTK_FIXED(fixed1), radio, 8, 8);
+ gtk_widget_set_uposition(radio, 8, 8);
+ gtk_widget_set_usize(radio, 92, 24);
+ gtk_signal_connect(GTK_OBJECT(radio), "toggled",
+ (GtkSignalFunc)consumer_emphasis_toggled, (gpointer)"No");
+
+ radio = gtk_radio_button_new_with_label(group, "50/15us");
+ hw_consumer_emphasis_5015_radio = radio;
+ group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));
+ gtk_widget_show(radio);
+ gtk_fixed_put(GTK_FIXED(fixed1), radio, 8, 32);
+ gtk_widget_set_uposition(radio, 8, 32);
+ gtk_widget_set_usize(radio, 92, 24);
+ gtk_signal_connect(GTK_OBJECT(radio), "toggled",
+ (GtkSignalFunc)consumer_emphasis_toggled, (gpointer)"5015");
+}
+
+static void create_spdif_output_settings_consumer_category(GtkWidget *fixed)
+{
+ GtkWidget *frame;
+ GtkWidget *fixed1;
+ GtkWidget *radio;
+ GSList *group = NULL;
+
+ frame = gtk_frame_new("Category");
+ gtk_widget_show(frame);
+ gtk_fixed_put(GTK_FIXED(fixed), frame, 283, 10);
+ gtk_widget_set_uposition(frame, 283, 10);
+ gtk_widget_set_usize(frame, 130, 126);
+
+ fixed1 = gtk_fixed_new();
+ gtk_widget_show(fixed1);
+ gtk_container_add(GTK_CONTAINER(frame), fixed1);
+
+ radio = gtk_radio_button_new_with_label(group, "DAT");
+ hw_consumer_category_dat_radio = radio;
+ group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));
+ gtk_widget_show(radio);
+ gtk_fixed_put(GTK_FIXED(fixed1), radio, 8, 8);
+ gtk_widget_set_uposition(radio, 8, 8);
+ gtk_widget_set_usize(radio, 102, 24);
+ gtk_signal_connect(GTK_OBJECT(radio), "toggled",
+ (GtkSignalFunc)consumer_category_toggled, (gpointer)"DAT");
+
+ radio = gtk_radio_button_new_with_label(group, "PCM encoder");
+ hw_consumer_category_pcm_radio = radio;
+ group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));
+ gtk_widget_show(radio);
+ gtk_fixed_put(GTK_FIXED(fixed1), radio, 8, 32);
+ gtk_widget_set_uposition(radio, 8, 32);
+ gtk_widget_set_usize(radio, 102, 24);
+ gtk_signal_connect(GTK_OBJECT(radio), "toggled",
+ (GtkSignalFunc)consumer_category_toggled, (gpointer)"PCM");
+
+ radio = gtk_radio_button_new_with_label(group, "CD (ICE-908)");
+ hw_consumer_category_cd_radio = radio;
+ group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));
+ gtk_widget_show(radio);
+ gtk_fixed_put(GTK_FIXED(fixed1), radio, 8, 56);
+ gtk_widget_set_uposition(radio, 8, 56);
+ gtk_widget_set_usize(radio, 102, 24);
+ gtk_signal_connect(GTK_OBJECT(radio), "toggled",
+ (GtkSignalFunc)consumer_category_toggled, (gpointer)"CD");
+
+ radio = gtk_radio_button_new_with_label(group, "General");
+ hw_consumer_category_general_radio = radio;
+ group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));
+ gtk_widget_show(radio);
+ gtk_fixed_put(GTK_FIXED(fixed1), radio, 8, 80);
+ gtk_widget_set_uposition(radio, 8, 80);
+ gtk_widget_set_usize(radio, 102, 24);
+ gtk_signal_connect(GTK_OBJECT(radio), "toggled",
+ (GtkSignalFunc)consumer_category_toggled, (gpointer)"General");
+}
+
+static void create_spdif_output_settings_consumer(GtkWidget *notebook, int page)
+{
+ GtkWidget *fixed;
+ GtkWidget *label;
+
+ fixed = gtk_fixed_new();
+ gtk_widget_show(fixed);
+ gtk_container_add(GTK_CONTAINER(notebook), fixed);
+ label = gtk_label_new("Consumer");
+ gtk_widget_show(label);
+ gtk_notebook_set_tab_label(GTK_NOTEBOOK(notebook), gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), page), label);
+
+ create_spdif_output_settings_consumer_copyright(fixed);
+ create_spdif_output_settings_consumer_copy(fixed);
+ create_spdif_output_settings_consumer_emphasis(fixed);
+ create_spdif_output_settings_consumer_category(fixed);
+}
+
+static void create_spdif_output_settings(GtkWidget *fixed)
+{
+ GtkWidget *frame;
+ GtkWidget *fixed1;
+ GtkWidget *radio;
+ GtkWidget *notebook;
+ GSList *group = NULL;
+
+ frame = gtk_frame_new("S/PDIF Output Settings");
+ gtk_widget_show(frame);
+ gtk_fixed_put(GTK_FIXED(fixed), frame, 128, 8);
+ gtk_widget_set_uposition(frame, 128, 8);
+ gtk_widget_set_usize(frame, 442, 268);
+
+ fixed1 = gtk_fixed_new();
+ gtk_widget_show(fixed1);
+ gtk_container_add(GTK_CONTAINER(frame), fixed1);
+
+ radio = gtk_radio_button_new_with_label(group, "Professional");
+ hw_spdif_professional_radio = radio;
+ group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));
+ gtk_widget_show(radio);
+ gtk_fixed_put(GTK_FIXED(fixed1), radio, 24, 4);
+ gtk_widget_set_uposition(radio, 24, 4);
+ gtk_widget_set_usize(radio, 92, 24);
+ gtk_signal_connect(GTK_OBJECT(radio), "toggled",
+ (GtkSignalFunc)spdif_output_toggled, (gpointer)"Professional");
+
+ radio = gtk_radio_button_new_with_label(group, "Consumer");
+ hw_spdif_consumer_radio = radio;
+ group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));
+ gtk_widget_show(radio);
+ gtk_fixed_put(GTK_FIXED(fixed1), radio, 128, 4);
+ gtk_widget_set_uposition(radio, 128, 4);
+ gtk_widget_set_usize(radio, 92, 24);
+ gtk_signal_connect(GTK_OBJECT(radio), "toggled",
+ (GtkSignalFunc)spdif_output_toggled, (gpointer)"Consumer");
+
+ notebook = gtk_notebook_new();
+ hw_spdif_output_notebook = notebook;
+ gtk_widget_show(notebook);
+ gtk_fixed_put(GTK_FIXED(fixed1), notebook, 5, 31);
+ gtk_widget_set_uposition(notebook, 5, 31);
+ gtk_widget_set_usize(notebook, 427, 215);
+
+ create_spdif_output_settings_profi(notebook, 0);
+ create_spdif_output_settings_consumer(notebook, 1);
+}
+
+static void create_spdif_input_select(GtkWidget *fixed)
+{
+ GtkWidget *frame;
+ GtkWidget *fixed1;
+ GtkWidget *radio;
+ GSList *group = NULL;
+ int hide = 1;
+
+ if (card_eeprom.subvendor == ICE1712_SUBDEVICE_DELTADIO2496)
+ hide = 0;
+
+ frame = gtk_frame_new("S/PDIF Input");
+ gtk_widget_show(frame);
+ gtk_fixed_put(GTK_FIXED(fixed), frame, 579, 8);
+ gtk_widget_set_uposition(frame, 579, 8);
+ gtk_widget_set_usize(frame, 98, 79);
+
+ fixed1 = gtk_fixed_new();
+ gtk_widget_show(fixed1);
+ gtk_container_add(GTK_CONTAINER(frame), fixed1);
+
+ radio = gtk_radio_button_new_with_label(group, "Coaxial");
+ hw_spdif_input_coaxial_radio = radio;
+ group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));
+ gtk_widget_show(radio);
+ gtk_fixed_put(GTK_FIXED(fixed1), radio, 8, 8);
+ gtk_widget_set_uposition(radio, 8, 8);
+ gtk_widget_set_usize(radio, 82, 24);
+ gtk_signal_connect(GTK_OBJECT(radio), "toggled",
+ (GtkSignalFunc)spdif_input_toggled, (gpointer)"Coaxial");
+
+ radio = gtk_radio_button_new_with_label(group, "Optical");
+ hw_spdif_input_optical_radio = radio;
+ group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));
+ gtk_widget_show(radio);
+ gtk_fixed_put(GTK_FIXED(fixed1), radio, 8, 32);
+ gtk_widget_set_uposition(radio, 8, 32);
+ gtk_widget_set_usize(radio, 82, 24);
+ gtk_signal_connect(GTK_OBJECT(radio), "toggled",
+ (GtkSignalFunc)spdif_input_toggled, (gpointer)"Optical");
+
+ if (hide)
+ gtk_widget_hide_all(frame);
+}
+
+static void create_hardware(GtkWidget *main, GtkWidget *notebook, int page)
+{
+ GtkWidget *label;
+ GtkWidget *fixed;
+
+ fixed = gtk_fixed_new();
+ gtk_widget_show(fixed);
+ gtk_container_add(GTK_CONTAINER(notebook), fixed);
+ label = gtk_label_new("Hardware Settings");
+ gtk_widget_show(label);
+ gtk_notebook_set_tab_label(GTK_NOTEBOOK(notebook), gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), page), label);
+
+ create_master_clock(fixed);
+ create_volume_change(fixed);
+ create_spdif_output_settings(fixed);
+ create_spdif_input_select(fixed);
+}
+
+static void create_about(GtkWidget *main, GtkWidget *notebook, int page)
+{
+ GtkWidget *label;
+ GtkWidget *fixed;
+
+ fixed = gtk_fixed_new();
+ gtk_widget_show(fixed);
+ gtk_container_add(GTK_CONTAINER(notebook), fixed);
+ label = gtk_label_new("About");
+ gtk_widget_show(label);
+ gtk_notebook_set_tab_label(GTK_NOTEBOOK(notebook), gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), page), label);
+
+ /* create first line */
+ label = gtk_label_new("Envy24 Control Utility " VERSION);
+ gtk_widget_show(label);
+ gtk_fixed_put(GTK_FIXED(fixed), label, 0, 72);
+ gtk_widget_set_uposition(label, 0, 72);
+ gtk_widget_set_usize(label, 736, 16);
+
+ /* create second line */
+ label = gtk_label_new("A GTK Tool for Envy24 PCI Audio Chip");
+ gtk_widget_show(label);
+ gtk_fixed_put(GTK_FIXED(fixed), label, 0, 104);
+ gtk_widget_set_uposition(label, 0, 104);
+ gtk_widget_set_usize(label, 736, 16);
+
+ /* create third line */
+ label = gtk_label_new("Copyright (c) 2000 by Jaroslav Kysela <perex@suse.cz>");
+ gtk_widget_show(label);
+ gtk_fixed_put(GTK_FIXED(fixed), label, 0, 152);
+ gtk_widget_set_uposition(label, 0, 152);
+ gtk_widget_set_usize(label, 736, 16);
+}
+
+int main(int argc, char **argv)
+{
+ GtkWidget *notebook;
+ char name[32], title[128];
+ int err;
+ unsigned int cards_mask;
+ snd_control_t ctl;
+ // snd_mixer_filter_t filter;
+
+ /* Go through gtk initialization */
+ gtk_init(&argc, &argv);
+
+ card = snd_defaults_card();
+ cards_mask = snd_cards_mask();
+
+ while (1) {
+ sprintf(name, "envy24control%d", card);
+ if ((err = snd_ctl_hw_open(&card_ctl, name, card)) < 0) {
+ fprintf(stderr, "snd_ctl_open: %s\n", snd_strerror(err));
+ exit(EXIT_FAILURE);
+ }
+ if ((err = snd_ctl_hw_info(card_ctl, &hw_info)) < 0) {
+ fprintf(stderr, "snd_ctl_hw_info: %s\n", snd_strerror(err));
+ exit(EXIT_FAILURE);
+ }
+ if (hw_info.type == SND_CARD_TYPE_ICE1712)
+ break;
+ snd_ctl_close(card_ctl);
+ card_ctl = NULL;
+ cards_mask &= ~(1 << card);
+ for (card = 0; card < 32; card++)
+ if ((1 << card) & cards_mask)
+ break;
+ if (card >= 32)
+ break;
+ }
+ if (card_ctl == NULL) {
+ fprintf(stderr, "Unable to find ICE1712 soundcard...\n");
+ exit(EXIT_FAILURE);
+ }
+
+#if 0
+ memset(&filter, 0, sizeof(filter));
+ snd_mixer_set_bit(filter.read_cmds, SND_MIXER_READ_ELEMENT_VALUE, 1);
+ if ((err = snd_mixer_put_filter(card_mixer, &filter)) < 0) {
+ fprintf(stderr, "snd_mixer_set_filter: %s\n", snd_strerror(err));
+ exit(EXIT_FAILURE);
+ }
+#endif
+
+ memset(&ctl, 0, sizeof(ctl));
+ ctl.id.iface = SND_CONTROL_IFACE_CARD;
+ strcpy(ctl.id.name, "ICE1712 EEPROM");
+ if ((err = snd_ctl_cread(card_ctl, &ctl)) < 0) {
+ fprintf(stderr, "Unable to read EEPROM contents: %s\n", snd_strerror(err));
+ exit(EXIT_FAILURE);
+ }
+ memcpy(&card_eeprom, ctl.value.bytes.data, 32);
+
+ /* Initialize code */
+ level_meters_init();
+ patchbay_init();
+ hardware_init();
+
+ /* Make the title */
+ sprintf(title, "Envy24 Control Utility %s (%s)", VERSION, hw_info.longname);
+
+ /* Create the main window */
+ window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title(GTK_WINDOW(window), title);
+ gtk_signal_connect(GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) gtk_main_quit, NULL);
+ signal(SIGINT, (void *)gtk_main_quit);
+ gtk_widget_set_usize(window, 740, 340);
+ gtk_window_set_policy(GTK_WINDOW (window), FALSE, FALSE, FALSE);
+ gtk_widget_realize(window);
+
+ /* Create the notebook */
+ notebook = gtk_notebook_new();
+ gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
+ gtk_widget_show(notebook);
+ gtk_container_add(GTK_CONTAINER(window), notebook);
+
+ create_mixer(window, notebook, 0);
+ create_router(window, notebook, 1);
+ create_hardware(window, notebook, 2);
+ create_about(window, notebook, 3);
+
+ gdk_input_add(snd_ctl_poll_descriptor(card_ctl),
+ GDK_INPUT_READ,
+ control_input_callback,
+ NULL);
+ gtk_timeout_add(40, level_meters_timeout_callback, NULL);
+ gtk_timeout_add(100, master_clock_status_timeout_callback, NULL);
+
+ level_meters_postinit();
+ mixer_postinit();
+ patchbay_postinit();
+ hardware_postinit();
+
+ gtk_widget_show(window);
+ gtk_main();
+
+ snd_ctl_close(card_ctl);
+
+ return EXIT_SUCCESS;
+}
--- /dev/null
+#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);
--- /dev/null
+/*****************************************************************************
+ 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();
+}
--- /dev/null
+/*****************************************************************************
+ 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);
+}
--- /dev/null
+/*****************************************************************************
+ 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);
+}
--- /dev/null
+/*****************************************************************************
+ 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();
+}