Changes for record volume...

This commit is contained in:
Jaroslav Kysela 1999-02-15 15:42:34 +00:00
parent 87c7c4f447
commit 88cdd83d0f
6 changed files with 132 additions and 24 deletions

View file

@ -47,6 +47,7 @@ struct mixer_channel {
int change; int change;
snd_mixer_channel_info_t i; snd_mixer_channel_info_t i;
snd_mixer_channel_t c; snd_mixer_channel_t c;
snd_mixer_channel_t cr;
struct mixer_channel *next; struct mixer_channel *next;
}; };

View file

@ -38,6 +38,7 @@ int linecount;
"{"|"}" return yytext[0]; "{"|"}" return yytext[0];
"("|")" return yytext[0]; "("|")" return yytext[0];
"["|"]" return yytext[0];
")"[ \t]*"{" return L_DOUBLE1; ")"[ \t]*"{" return L_DOUBLE1;
"," return yytext[0]; "," return yytext[0];
@ -108,9 +109,9 @@ true|on|yes return L_TRUE;
\'[^\']*\' { yytext[ strlen( yytext ) - 1 ] = 0; \'[^\']*\' { yytext[ strlen( yytext ) - 1 ] = 0;
yylval.s_value = strdup( &yytext[ 1 ] ); yylval.s_value = strdup( &yytext[ 1 ] );
return L_STRING; } return L_STRING; }
[a-z0-9/\~@-_\+=:\.]+ { yylval.s_value = strdup( yytext ); [a-z0-9/\~@-Za-z_\+=:\.]+ { yylval.s_value = strdup( yytext );
return L_STRING; } return L_STRING; }
$[a-z0-9/\~@-_\+=:\.]+ { yylval.s_value = strdup( getenv( &yytext[ 1 ] ) ); $[a-z0-9/\~@-Za-z_\+=:\.]+ { yylval.s_value = strdup( getenv( &yytext[ 1 ] ) );
return L_STRING; } return L_STRING; }
/* comments & whitespaces */ /* comments & whitespaces */

View file

@ -43,6 +43,7 @@ static void select_rawmidi(char *name);
static void select_mixer_channel(char *name); static void select_mixer_channel(char *name);
static void set_mixer_channel(int left, int right); static void set_mixer_channel(int left, int right);
static void set_mixer_channel_record(int left, int right);
static void set_mixer_channel_flags(unsigned int mask, unsigned int flags); static void set_mixer_channel_flags(unsigned int mask, unsigned int flags);
static void set_mixer_channel_end(void); static void set_mixer_channel_end(void);
@ -162,6 +163,7 @@ xmchls : xmchl
; ;
xmchl : L_INTEGER { set_mixer_channel( $1, -1 ); } xmchl : L_INTEGER { set_mixer_channel( $1, -1 ); }
| '[' L_INTEGER ']' { set_mixer_channel_record( $2, -1 ); }
| L_MUTE { set_mixer_channel_flags( SND_MIXER_FLG_MUTE_LEFT, SND_MIXER_FLG_MUTE_LEFT ); } | L_MUTE { set_mixer_channel_flags( SND_MIXER_FLG_MUTE_LEFT, SND_MIXER_FLG_MUTE_LEFT ); }
| L_RECORD { set_mixer_channel_flags( SND_MIXER_FLG_RECORD_LEFT, SND_MIXER_FLG_RECORD_LEFT ); } | L_RECORD { set_mixer_channel_flags( SND_MIXER_FLG_RECORD_LEFT, SND_MIXER_FLG_RECORD_LEFT ); }
| L_SWOUT { set_mixer_channel_flags( SND_MIXER_FLG_LTOR_OUT, SND_MIXER_FLG_LTOR_OUT ); } | L_SWOUT { set_mixer_channel_flags( SND_MIXER_FLG_LTOR_OUT, SND_MIXER_FLG_LTOR_OUT ); }
@ -174,6 +176,7 @@ xmchrs : xmchr
; ;
xmchr : L_INTEGER { set_mixer_channel( -1, $1 ); } xmchr : L_INTEGER { set_mixer_channel( -1, $1 ); }
| '[' L_INTEGER ']' { set_mixer_channel_record( -1, $2 ); }
| L_MUTE { set_mixer_channel_flags( SND_MIXER_FLG_MUTE_RIGHT, SND_MIXER_FLG_MUTE_RIGHT ); } | L_MUTE { set_mixer_channel_flags( SND_MIXER_FLG_MUTE_RIGHT, SND_MIXER_FLG_MUTE_RIGHT ); }
| L_RECORD { set_mixer_channel_flags( SND_MIXER_FLG_RECORD_RIGHT, SND_MIXER_FLG_RECORD_RIGHT ); } | L_RECORD { set_mixer_channel_flags( SND_MIXER_FLG_RECORD_RIGHT, SND_MIXER_FLG_RECORD_RIGHT ); }
| L_SWOUT { set_mixer_channel_flags( SND_MIXER_FLG_RTOL_OUT, SND_MIXER_FLG_RTOL_OUT ); } | L_SWOUT { set_mixer_channel_flags( SND_MIXER_FLG_RTOL_OUT, SND_MIXER_FLG_RTOL_OUT ); }
@ -186,6 +189,7 @@ xmchs : xmch
; ;
xmch : L_INTEGER { set_mixer_channel( $1, $1 ); } xmch : L_INTEGER { set_mixer_channel( $1, $1 ); }
| '[' L_INTEGER ']' { set_mixer_channel_record( $2, $2 ); }
| L_MUTE { set_mixer_channel_flags( SND_MIXER_FLG_MUTE, SND_MIXER_FLG_MUTE ); } | L_MUTE { set_mixer_channel_flags( SND_MIXER_FLG_MUTE, SND_MIXER_FLG_MUTE ); }
| L_RECORD { set_mixer_channel_flags( SND_MIXER_FLG_RECORD, SND_MIXER_FLG_RECORD ); } | L_RECORD { set_mixer_channel_flags( SND_MIXER_FLG_RECORD, SND_MIXER_FLG_RECORD ); }
| error { yyerror( "unknown keyword in mono channel section..." ); } | error { yyerror( "unknown keyword in mono channel section..." ); }
@ -417,6 +421,24 @@ static void set_mixer_channel(int left, int right)
} }
} }
static void set_mixer_channel_record(int left, int right)
{
if (left >= 0) {
if (Xmixerchannel->i.min > left || Xmixerchannel->i.max < left)
yyerror("Value out of range (%i-%i)...", Xmixerchannel->i.min, Xmixerchannel->i.max);
if (Xmixerchannel->cr.left != left)
Xmixerchannel->change = 1;
Xmixerchannel->cr.left = left;
}
if (right >= 0) {
if (Xmixerchannel->i.min > right || Xmixerchannel->i.max < right)
yyerror("Value out of range (%i-%i)...", Xmixerchannel->i.min, Xmixerchannel->i.max);
if (Xmixerchannel->cr.right != right)
Xmixerchannel->change = 1;
Xmixerchannel->cr.right = right;
}
}
static void set_mixer_channel_flags(unsigned int mask, unsigned int flags) static void set_mixer_channel_flags(unsigned int mask, unsigned int flags)
{ {
Xmixerchannelflags &= ~mask; Xmixerchannelflags &= ~mask;

View file

@ -360,6 +360,12 @@ int soundcard_setup_collect(int cardno)
error("MIXER channel read error (%s) - skipping", snd_strerror(err)); error("MIXER channel read error (%s) - skipping", snd_strerror(err));
break; break;
} }
if ((mixerchannel->i.caps & SND_MIXER_CINFO_CAP_RECORDVOLUME) &&
(err = snd_mixer_channel_record_read(mhandle, idx, &mixerchannel->cr)) < 0) {
free(mixerchannel);
error("MIXER channel record read error (%s) - skipping", snd_strerror(err));
break;
}
if (!mixerchannelprev) { if (!mixerchannelprev) {
mixer->channels = mixerchannel; mixer->channels = mixerchannel;
} else { } else {
@ -645,7 +651,7 @@ static void soundcard_setup_write_switch(FILE * out, int interface, const unsign
} }
static void soundcard_setup_write_mixer_channel(FILE * out, snd_mixer_channel_info_t * info, snd_mixer_channel_t * channel) static void soundcard_setup_write_mixer_channel(FILE * out, snd_mixer_channel_info_t * info, snd_mixer_channel_t * channel, snd_mixer_channel_t * record_channel)
{ {
fprintf(out, " ; Capabilities:%s%s%s%s%s%s%s%s%s%s%s%s%s.\n", fprintf(out, " ; Capabilities:%s%s%s%s%s%s%s%s%s%s%s%s%s.\n",
info->caps & SND_MIXER_CINFO_CAP_RECORD ? " record" : "", info->caps & SND_MIXER_CINFO_CAP_RECORD ? " record" : "",
@ -660,27 +666,39 @@ static void soundcard_setup_write_mixer_channel(FILE * out, snd_mixer_channel_in
info->caps & SND_MIXER_CINFO_CAP_SWITCH_OUT ? " switch-out" : "", info->caps & SND_MIXER_CINFO_CAP_SWITCH_OUT ? " switch-out" : "",
info->caps & SND_MIXER_CINFO_CAP_LTOR_IN ? " ltor-in" : "", info->caps & SND_MIXER_CINFO_CAP_LTOR_IN ? " ltor-in" : "",
info->caps & SND_MIXER_CINFO_CAP_RTOL_IN ? " rtol-in" : "", info->caps & SND_MIXER_CINFO_CAP_RTOL_IN ? " rtol-in" : "",
info->caps & SND_MIXER_CINFO_CAP_RECORDBYMUTE ? " record-by-mute" : ""); info->caps & SND_MIXER_CINFO_CAP_RECORDVOLUME ? " record-volume" : "");
fprintf(out, " ; Accepted channel range is from %i to %i.\n", info->min, info->max); fprintf(out, " ; Accepted channel range is from %i to %i.\n", info->min, info->max);
fprintf(out, " channel( \"%s\", ", info->name); fprintf(out, " channel( \"%s\", ", info->name);
if (info->caps & SND_MIXER_CINFO_CAP_STEREO) { if (info->caps & SND_MIXER_CINFO_CAP_STEREO) {
fprintf(out, "stereo( %i%s%s%s%s, %i%s%s%s%s )", char bufl[16] = "";
char bufr[16] = "";
if (info->caps & SND_MIXER_CINFO_CAP_RECORDVOLUME) {
sprintf(bufl, " [%i]", record_channel->left);
sprintf(bufr, " [%i]", record_channel->right);
}
fprintf(out, "stereo( %i%s%s%s%s%s, %i%s%s%s%s%s )",
channel->left, channel->left,
channel->flags & SND_MIXER_FLG_MUTE_LEFT ? " mute" : "", channel->flags & SND_MIXER_FLG_MUTE_LEFT ? " mute" : "",
channel->flags & SND_MIXER_FLG_RECORD_LEFT ? " record" : "", channel->flags & SND_MIXER_FLG_RECORD_LEFT ? " record" : "",
channel->flags & SND_MIXER_FLG_LTOR_OUT ? " swout" : "", bufl,
channel->flags & SND_MIXER_FLG_LTOR_IN ? " swin" : "", channel->flags & SND_MIXER_FLG_LTOR_OUT ? " swout" : "",
channel->flags & SND_MIXER_FLG_LTOR_IN ? " swin" : "",
channel->right, channel->right,
channel->flags & SND_MIXER_FLG_MUTE_RIGHT ? " mute" : "", channel->flags & SND_MIXER_FLG_MUTE_RIGHT ? " mute" : "",
channel->flags & SND_MIXER_FLG_RECORD_RIGHT ? " record" : "", channel->flags & SND_MIXER_FLG_RECORD_RIGHT ? " record" : "",
channel->flags & SND_MIXER_FLG_RTOL_OUT ? " swout" : "", bufr,
channel->flags & SND_MIXER_FLG_RTOL_IN ? " swin" : "" channel->flags & SND_MIXER_FLG_RTOL_OUT ? " swout" : "",
channel->flags & SND_MIXER_FLG_RTOL_IN ? " swin" : ""
); );
} else { } else {
fprintf(out, "mono( %i%s%s )", char buf[16] = "";
if (info->caps & SND_MIXER_CINFO_CAP_RECORDVOLUME)
sprintf(buf, " [%i]", (record_channel->left+record_channel->right) /2);
fprintf(out, "mono( %i%s%s%s )",
(channel->left + channel->right) / 2, (channel->left + channel->right) / 2,
channel->flags & SND_MIXER_FLG_MUTE ? " mute" : "", channel->flags & SND_MIXER_FLG_MUTE ? " mute" : "",
channel->flags & SND_MIXER_FLG_RECORD ? " record" : "" channel->flags & SND_MIXER_FLG_RECORD ? " record" : "",
buf
); );
} }
fprintf(out, " )\n"); fprintf(out, " )\n");
@ -717,7 +735,7 @@ int soundcard_setup_write(const char *cfgfile)
for (mixer = first->mixers; mixer; mixer = mixer->next) { for (mixer = first->mixers; mixer; mixer = mixer->next) {
fprintf(out, " mixer( \"%s\" ) {\n", mixer->info.name); fprintf(out, " mixer( \"%s\" ) {\n", mixer->info.name);
for (mixerchannel = mixer->channels; mixerchannel; mixerchannel = mixerchannel->next) for (mixerchannel = mixer->channels; mixerchannel; mixerchannel = mixerchannel->next)
soundcard_setup_write_mixer_channel(out, &mixerchannel->i, &mixerchannel->c); soundcard_setup_write_mixer_channel(out, &mixerchannel->i, &mixerchannel->c, &mixerchannel->cr);
for (mixersw = mixer->switches; mixersw; mixersw = mixersw->next) for (mixersw = mixer->switches; mixersw; mixersw = mixersw->next)
soundcard_setup_write_switch(out, SND_INTERFACE_MIXER, mixersw->s.name, mixersw->s.type, mixersw->s.low, mixersw->s.high, (void *) (&mixersw->s.value)); soundcard_setup_write_switch(out, SND_INTERFACE_MIXER, mixersw->s.name, mixersw->s.type, mixersw->s.low, mixersw->s.high, (void *) (&mixersw->s.value));
fprintf(out, " }\n"); fprintf(out, " }\n");
@ -825,6 +843,9 @@ int soundcard_setup_process(int cardno)
if (!soundcard_open_mix(&mixhandle, soundcard, mixer)) { if (!soundcard_open_mix(&mixhandle, soundcard, mixer)) {
if ((err = snd_mixer_channel_write(mixhandle, channel->no, &channel->c)) < 0) if ((err = snd_mixer_channel_write(mixhandle, channel->no, &channel->c)) < 0)
error("Mixer channel '%s' write error: %s", channel->i.name, snd_strerror(err)); error("Mixer channel '%s' write error: %s", channel->i.name, snd_strerror(err));
if ((channel->i.caps & SND_MIXER_CINFO_CAP_RECORDVOLUME) &&
(err = snd_mixer_channel_record_write(mixhandle, channel->no, &channel->cr)) < 0)
error("Mixer channel '%s' record write error: %s", channel->i.name, snd_strerror(err));
} }
if (mixhandle) { if (mixhandle) {
snd_mixer_close(mixhandle); snd_mixer_close(mixhandle);

View file

@ -67,6 +67,8 @@ mute left and right independently by using \fI,\fP and \fI.\fP respectively.
removed from the sources used for recording. This only works for valid removed from the sources used for recording. This only works for valid
input channels, of course. input channels, of course.
\fIR\fP toggle display of playback or record mixer.
\fIL\fP re-draws the screen. \fIL\fP re-draws the screen.
\fITAB\fP toggles the mode for volume display. See description for the \fITAB\fP toggles the mode for volume display. See description for the

View file

@ -97,6 +97,8 @@ static int mixer_first_vis_channel = 0;
static int mixer_focus_channel = 0; static int mixer_focus_channel = 0;
static int mixer_exact = 0; static int mixer_exact = 0;
static int mixer_record_volumes = 0;
static int mixer_lvolume_delta = 0; static int mixer_lvolume_delta = 0;
static int mixer_rvolume_delta = 0; static int mixer_rvolume_delta = 0;
static int mixer_balance_volumes = 0; static int mixer_balance_volumes = 0;
@ -301,9 +303,12 @@ static void mixer_update_cbar(int channel_index)
{0}; {0};
snd_mixer_channel_t cdata = snd_mixer_channel_t cdata =
{0}; {0};
snd_mixer_channel_t crdata =
{0};
int vleft, vright; int vleft, vright;
int x, y, i; int x, y, i;
int channel_record_volume;
/* set specified EXACT mode /* set specified EXACT mode
*/ */
@ -314,6 +319,7 @@ static void mixer_update_cbar(int channel_index)
*/ */
if (snd_mixer_channel_info(mixer_handle, channel_index, &cinfo) < 0) if (snd_mixer_channel_info(mixer_handle, channel_index, &cinfo) < 0)
mixer_abort(ERR_FCN, "snd_mixer_channel_info"); mixer_abort(ERR_FCN, "snd_mixer_channel_info");
channel_record_volume = (cinfo.caps & SND_MIXER_CINFO_CAP_RECORDVOLUME);
/* set new channel values /* set new channel values
*/ */
@ -326,14 +332,40 @@ static void mixer_update_cbar(int channel_index)
mixer_route_rtol_in || mixer_route_ltor_in)) { mixer_route_rtol_in || mixer_route_ltor_in)) {
if (snd_mixer_channel_read(mixer_handle, channel_index, &cdata) < 0) if (snd_mixer_channel_read(mixer_handle, channel_index, &cdata) < 0)
mixer_abort(ERR_FCN, "snd_mixer_channel_read"); mixer_abort(ERR_FCN, "snd_mixer_channel_read");
if (mixer_record_volumes && channel_record_volume &&
snd_mixer_channel_record_read(mixer_handle, channel_index, &crdata) < 0)
mixer_abort(ERR_FCN, "snd_mixer_channel_record_read");
cdata.flags &= ~SND_MIXER_FLG_DECIBEL; cdata.flags &= ~SND_MIXER_FLG_DECIBEL;
cdata.left = CLAMP(cdata.left + mixer_lvolume_delta, cinfo.min, cinfo.max); if (mixer_lvolume_delta) {
cdata.right = CLAMP(cdata.right + mixer_rvolume_delta, cinfo.min, cinfo.max); if (mixer_record_volumes) {
mixer_lvolume_delta = mixer_rvolume_delta = 0; if (channel_record_volume)
crdata.left = CLAMP(crdata.left + mixer_lvolume_delta, cinfo.min, cinfo.max);
}
else
cdata.left = CLAMP(cdata.left + mixer_lvolume_delta, cinfo.min, cinfo.max);
mixer_lvolume_delta = 0;
}
if (mixer_rvolume_delta) {
if (mixer_record_volumes) {
if (channel_record_volume)
crdata.right = CLAMP(crdata.right + mixer_rvolume_delta, cinfo.min, cinfo.max);
}
else
cdata.right = CLAMP(cdata.right + mixer_rvolume_delta, cinfo.min, cinfo.max);
mixer_rvolume_delta = 0;
}
if (mixer_balance_volumes) { if (mixer_balance_volumes) {
cdata.left = (cdata.left + cdata.right) / 2; if (mixer_record_volumes) {
cdata.right = cdata.left; if (channel_record_volume) {
crdata.left = (crdata.left + crdata.right) / 2;
crdata.right = crdata.left;
}
}
else {
cdata.left = (cdata.left + cdata.right) / 2;
cdata.right = cdata.left;
}
mixer_balance_volumes = 0; mixer_balance_volumes = 0;
} }
if (mixer_toggle_mute_left) { if (mixer_toggle_mute_left) {
@ -393,14 +425,29 @@ static void mixer_update_cbar(int channel_index)
if (snd_mixer_channel_write(mixer_handle, channel_index, &cdata) < 0) if (snd_mixer_channel_write(mixer_handle, channel_index, &cdata) < 0)
mixer_abort(ERR_FCN, "snd_mixer_channel_write"); mixer_abort(ERR_FCN, "snd_mixer_channel_write");
if (mixer_record_volumes && channel_record_volume &&
snd_mixer_channel_record_write(mixer_handle, channel_index, &crdata) < 0)
mixer_abort(ERR_FCN, "snd_mixer_channel_record_write");
} }
/* first, read values for the numbers to be displayed in /* first, read values for the numbers to be displayed in
* specified EXACT mode * specified EXACT mode
*/ */
if (snd_mixer_channel_read(mixer_handle, channel_index, &cdata) < 0) if (snd_mixer_channel_read(mixer_handle, channel_index, &cdata) < 0)
mixer_abort(ERR_FCN, "snd_mixer_ioctl_channel_read"); mixer_abort(ERR_FCN, "snd_mixer_ioctl_channel_read");
vleft = cdata.left; if (mixer_record_volumes) {
vright = cdata.right; if (channel_record_volume) {
if (snd_mixer_channel_record_read(mixer_handle, channel_index, &crdata) < 0)
mixer_abort(ERR_FCN, "snd_mixer_channel_record_read");
vleft = crdata.left;
vright = crdata.right;
}
else
vleft = vright = 0;
}
else {
vleft = cdata.left;
vright = cdata.right;
}
/* then, always use percentage values for the bars. if we don't do /* then, always use percentage values for the bars. if we don't do
* this, we will see aliasing effects on specific circumstances. * this, we will see aliasing effects on specific circumstances.
@ -413,6 +460,9 @@ static void mixer_update_cbar(int channel_index)
mixer_abort(ERR_FCN, "snd_mixer_exact"); mixer_abort(ERR_FCN, "snd_mixer_exact");
if (snd_mixer_channel_read(mixer_handle, channel_index, &cdata) < 0) if (snd_mixer_channel_read(mixer_handle, channel_index, &cdata) < 0)
mixer_abort(ERR_FCN, "snd_mixer_channel_read"); mixer_abort(ERR_FCN, "snd_mixer_channel_read");
if (mixer_record_volumes && channel_record_volume &&
snd_mixer_channel_record_read(mixer_handle, channel_index, &crdata) < 0)
mixer_abort(ERR_FCN, "snd_mixer_channel_record_read");
} }
/* get channel bar position /* get channel bar position
*/ */
@ -470,8 +520,8 @@ static void mixer_update_cbar(int channel_index)
dc = DC_CBAR_FULL_2; dc = DC_CBAR_FULL_2;
else else
dc = DC_CBAR_FULL_1; dc = DC_CBAR_FULL_1;
mvaddch(y, x + 3, mixer_dc(cdata.left > i * 100 / mixer_cbar_height ? dc : DC_CBAR_EMPTY)); mvaddch(y, x + 3, mixer_dc(vleft > i * 100 / mixer_cbar_height ? dc : DC_CBAR_EMPTY));
mvaddch(y, x + 4, mixer_dc(cdata.right > i * 100 / mixer_cbar_height ? dc : DC_CBAR_EMPTY)); mvaddch(y, x + 4, mixer_dc(vright > i * 100 / mixer_cbar_height ? dc : DC_CBAR_EMPTY));
y--; y--;
} }
@ -601,6 +651,10 @@ static void mixer_draw_frame(void)
if (strlen(string) > max_len) if (strlen(string) > max_len)
string[max_len] = 0; string[max_len] = 0;
mvaddstr(2, 2 + 6, string); mvaddstr(2, 2 + 6, string);
if (mixer_record_volumes)
mvaddstr(3, 2, "Record mixer");
else
mvaddstr(3, 2, " ");
} }
static void mixer_init(void) static void mixer_init(void)
@ -752,6 +806,7 @@ static int mixer_iteration(void)
break; break;
case 'm': case 'm':
case 'M': case 'M':
mixer_record_volumes = 0;
mixer_toggle_mute_left = 1; mixer_toggle_mute_left = 1;
mixer_toggle_mute_right = 1; mixer_toggle_mute_right = 1;
break; break;
@ -762,14 +817,18 @@ static int mixer_iteration(void)
break; break;
case '<': case '<':
case ',': case ',':
mixer_record_volumes = 0;
mixer_toggle_mute_left = 1; mixer_toggle_mute_left = 1;
break; break;
case '>': case '>':
case '.': case '.':
mixer_record_volumes = 0;
mixer_toggle_mute_right = 1; mixer_toggle_mute_right = 1;
break; break;
case 'R': case 'R':
case 'r': case 'r':
mixer_record_volumes = !mixer_record_volumes;
break;
case 'L': case 'L':
case 'l': case 'l':
mixer_clear(); mixer_clear();
@ -786,9 +845,11 @@ static int mixer_iteration(void)
mixer_toggle_rec_right = 1; mixer_toggle_rec_right = 1;
break; break;
case '1': case '1':
mixer_record_volumes = 0;
mixer_route_rtol_in = 1; mixer_route_rtol_in = 1;
break; break;
case '2': case '2':
mixer_record_volumes = 0;
mixer_route_ltor_in = 1; mixer_route_ltor_in = 1;
break; break;
} }