Thursday, October 21, 2010

Realtek ALC888 sound issues in Ubuntu 10.10

I own a Fujitsu Siemens Amilo Si 3655 laptop computer which has Realtek ALC 888 audio mixer. Everything was working fine until one on 10/10/10 at 10:10 GMT I downloaded Ubuntu 10.10 and installed it in 10 minutes 10 seconds on my notebook. I encountered an strange issue. I couldn't hear any sound from the notebook's built in speakers, but when I plugged in earphones into the stereo jack, the sound worked perfectly in the earphones. I never had this kind of issue when I was using Ubuntu 10.04. I searched through Ubuntu Forums but none of the tricks worked. I ran the command ubuntu-bug audio and reported the bug to launchpad. While browsing the bugs with the same sound card on launchpad I came across a comment that advised me to edit the /etc/modprobe.d/alsa-base.conf file and append two lines given below, to it.
alias snd-card-0 snd-hda-intel
options snd-hda-intel model=auto
I did the same by running sudo gedit /etc/modprobe.d/alsa-base.conf in a terminal and adding those two lines at the end of the file and saving it.
As soon as I restarted the computer, I heard the Ubuntu Login sound that pops on the login screen!!! So if you have a Fujitsu Siemens Amilo Si3655 or any other notebook that uses Realtek ALC888, just follow the step above and get your internal speakers working.

Thursday, October 14, 2010

scanf() is nasty!! Is it?



If you have begun C programming, chances are you have already faced or you will very soon face the nasty behaviour of scanf while inputting characters. If you have faced this problem and didn't get a solution yet, read on. If you haven't faced this problem, you'll do very soon, so read on :P

The problem
Consider the following C program:

#include <stdio.h>
int main(){
    char ch[10];
    int i[10], j=0;
    while(j<10){
      printf("Please enter a character: ");
      scanf("%c",&ch[j]);
      printf("Please enter an integer: ");
      scanf("%d",&i[j]);
      j++;
     }  
    j=0;
    printf("Char\tInt\n");
    printf("____\t____\n");
    while(j<10){
    printf("%c\t%d\n",ch[j],i[j]);
    j++;
    }
    return 0;
    } 

The program is very simple. It takes a character and a number as input, 10 times and then outputs them neatly in a table format. Is it so? The program code looks like that. Now compile the program with gcc and run it. The behaviour you'll see is unexpected! Then what went wrong?

The cause
We have used the format specifier %c with the first scanf. That is the root of the problem! What happens is that, when you enter a character, for example a and press enter, actually two characters go into the standard input stream. First is the a and second is the \n i.e. the newline character corresponding to your enter press. %c reads the single character i.e. a and stores it in the variable. Next you enter anything as integer, say 1. The second scanf skips the \n that was left after the because it doesn't look like an integer. Then it encounters 1 which is followed by a \n so it stores the 1 into the integer variable. In the next iteration of the loop the %c in the scanf directly takes the \n from the stdin that was entered after the 1 and you don't even get a chance to enter a character. This process goes on and on and you never get a chance to enter any character. You are prompted to enter integer only, during each iteration of the loop. Hope you got it ;-) To confirm, just enter %d as the format specifier of printf instead of %c for the character variable in line 16. You'll get the ASCII value of newline character i.e. 10 printed neatly in the table in place of characters in the output.

The solution
There are several solutions to this problem.
The first one I saw in a forum was to clean the stdin. A funcion proposed to do that was as follows:
void clean_stdin(void)
{
int c;

do
{
c = fgetc(stdin);
}
while (c != '\n' && c != EOF);
}
and you're supposed to call this after every time you scanf a characer with the %c format specifier. I tried it, and it worked.
Another solution is the put a getchar() line after every scanf. It will take the trailing newline character and put into oblivion :P
Yet another solution, that I loved was to put a trailing space before the %c like this:
scanf(" %c",&ch[j]);
What the space before %c do, is that, it makes the scanf skip any kind of trailing whitespaces and then reads any non-whitespace character and puts into the character variable.
In fact, as you now know the reason of the issue you can develop as many solutions as you want.