aboutsummaryrefslogtreecommitdiff
path: root/sys/i386/isa/sound/gustest/gpatinfo.c
blob: 17dcb12bb4f61778987b82dab31f4847263f1021 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/*
 *	gpatinfo.c: This program demonstrates the patch management
 *		    interface of the GUS driver.
 *
 *	NOTE! The patch manager interface is highly device dependent,
 *	      currently incompletely implemented prototype and
 *	      will change before final implementation.
 * 
 * $Id$
 */

#include <stdio.h>
#include <machine/ultrasound.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <fcntl.h>
#include "gmidi.h"

#define GUS_DEV 	gus_dev

#define patch_access(cmd, rec) \
	rec.command = cmd;\
	rec.device = gus_dev;\
	if (ioctl(seqfd, SNDCTL_PMGR_IFACE, &rec)==-1)\
	{\
		perror("/dev/sequencer(SNDCTL_PMGR_IFACE/" #cmd ")");\
		exit(-1);\
	}

SEQ_DEFINEBUF (2048);

int             seqfd;

int             gus_dev = -1;

/*
 * The function seqbuf_dump() must always be provided
 */

void
seqbuf_dump ()
{
  if (_seqbufptr)
    if (write (seqfd, _seqbuf, _seqbufptr) == -1)
      {
	perror ("write /dev/sequencer");
	exit (-1);
      }
  _seqbufptr = 0;
}

int
main (int argc, char *argv[])
{
  int             i, j, n;
  struct synth_info info;
  struct patch_info *patch;
  struct patmgr_info mgr, mgr2, mgr3;

  if ((seqfd = open ("/dev/sequencer", O_WRONLY, 0)) == -1)
    {
      perror ("/dev/sequencer");
      exit (-1);
    }

  if (ioctl (seqfd, SNDCTL_SEQ_NRSYNTHS, &n) == -1)
    {
      perror ("/dev/sequencer");
      exit (-1);
    }

/*
 * First locate the GUS device
 */

  for (i = 0; i < n; i++)
    {
      info.device = i;

      if (ioctl (seqfd, SNDCTL_SYNTH_INFO, &info) == -1)
	{
	  perror ("/dev/sequencer");
	  exit (-1);
	}

      if (info.synth_type == SYNTH_TYPE_SAMPLE
	  && info.synth_subtype == SAMPLE_TYPE_GUS)
	gus_dev = i;
    }

  if (gus_dev == -1)
    {
      fprintf (stderr, "Error: Gravis Ultrasound not detected\n");
      exit (-1);
    }

  printf("Gravis UltraSound device = %d\n", gus_dev);

 /*
  * Get type of the Patch Manager interface of the GUS device
  */

  patch_access(PM_GET_DEVTYPE, mgr);
  printf("Patch manager type: %d\n", mgr.parm1);

  if (mgr.parm1 != PMTYPE_WAVE)
  {
  	fprintf(stderr, "Hups, this program seems to be obsolete\n");
  	exit(-1);
  }

  /*
   * The GUS driver supports up to 256 different midi program numbers but
   * this limit can be changed before compiling the driver. The following
   * call returns the value compiled to the driver.
   */

  patch_access(PM_GET_PGMMAP, mgr);
  printf("Device supports %d midi programs.\n", mgr.parm1);

  /*
   * Each program can be undefined or it may have one or more patches.
   * A patch consists of header and the waveform data. If there is more
   * than one patch in a program, the right one is selected by checking the
   * note number when the program is played.
   *
   * The following call reads an array indexed by program number. Each
   * element defines the number of patches defined for the corresponding
   * program.
   */
  printf("Loaded programs:\n");

  for (i=0;i<mgr.parm1;i++)
  if (mgr.data.data8[i]) 
  {
     printf("%03d: %2d patches\n", i, mgr.data.data8[i]);

 /*
  * Next get the magic keys of the patches associated with this program.
  * This key can be used to access the patc data.
  */
     mgr2.parm1=i;
     patch_access(PM_GET_PGM_PATCHES, mgr2);
     for (j = 0;j<mgr2.parm1;j++)
     {
     	printf("\tPatch %d: %3d ", j, mgr2.data.data32[j]);

 /*
  * The last step is to read the patch header (without wave data).
  * The header is returned in the mgr3.data. The field parm1 returns
  * address of the wave data in tge GUS DRAM. Parm2 returns
  * size of the struct patch_info in the kernel.
  *
  * There is also the PM_SET_PATCH call which allows modification of the
  * header data. The only limitation is that the sample len cannot be
  * increased.
  */
     	mgr3.parm1 = mgr2.data.data32[j];
     	patch_access(PM_GET_PATCH, mgr3);
     	patch = (struct patch_info *)&mgr3.data; /* Pointer to the patch hdr */

     	printf("DRAM ptr = %7d, sample len =%6d bytes.\n", 
     		mgr3.parm1, patch->len);

     }
  }

  i = gus_dev;

  if (ioctl(seqfd, SNDCTL_SYNTH_MEMAVL, &i)==-1) exit(-1);
  printf("%d bytes of DRAM available for wave data\n", i);


  exit(0);
}