0

I am trying to make video looper in linux. For that i am using mplayer for videos. My program gets list of videos and images from directory and plays them. My problem is when i call mplayer or image viewer from c with char array parameters it is not working. For example,

system("eog -f /home/user/Desktop/Video/screenshot_0000.png");

or

system("mplayer -fs /home/user/Desktop/Video/video1.mov");

if i call this way it works. But when i get video list from directy and send them with char array it is not working. When i tried system() call it gives 'sh: 1: video1.mov not found' error and when i use exec() fuctions nothing happens.

Here is my code;

    #include <stdio.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sys/wait.h>
    #include <dirent.h>
    #include <string.h>

    #define FILE_PATH "/home/user/Desktop/Video/"

    char *getExt (const char *fspec) {
        char *e = strrchr (fspec, '.');
        if (e == NULL)
            e = ""; // fast method, could also use &(fspec[strlen(fspec)]).
        return e;
    }

    void get_list(char liste[][150])
    {
        DIR *d;
        struct dirent *dir;
        char *path = ("%s.",FILE_PATH);
        d = opendir(path);
        int counter=0;
        /*if(d != NULL)
        {
            while((dir=readdir(d))!= NULL)
            {
    //          printf("%s\n", dir->d_name);
                if(dir->d_type==DT_REG)
                    file_numbers++;
            }
            closedir(d);

        }
        char liste[file_numbers][150];*/
        d = opendir(path);
        if(d != NULL)
        {
            while((dir=readdir(d))!= NULL)
            {
    //          printf("%s\n", dir->d_name);
                if(dir->d_type==DT_REG)
                {   
                    strncpy(liste[counter],dir->d_name,150);
    //              printf("%s\n", liste[counter]);
                    counter++;
                }
            }
            closedir(d);

        }

    }

    int main ()
    {
        int status;
        pid_t child_pid, pid_w;
        DIR *d;
        struct dirent *dir;
        char *path = ("%s.",FILE_PATH);
        d = opendir(path);
        int file_numbers=0;
        int counter = 0;
        if(d != NULL)
        {
            while((dir=readdir(d))!= NULL)
            {
    //          printf("%s\n", dir->d_name);
                if(dir->d_type==DT_REG)
                    file_numbers++;
            }
            closedir(d);

        }
        char liste[file_numbers][150];
        get_list(liste);
        /*for(int i = 0; i< file_numbers;i++)
            printf("%s\n", liste[i]);*/

        while(1)
        {
            char *ext = getExt(liste[counter]); 
            //printf("eog -f %s/%s\n",PATH,liste[counter]);
            child_pid = fork();
            if(child_pid==0)
            {
                //printf("-eog -f %s/%s\n",PATH,liste[counter]);
                if(!strcmp(ext,".JPG") || !strcmp(ext,".jpg") || !strcmp(ext, ".gif") || !strcmp(ext,".png") || !strcmp(ext, ".PNG") || !strcmp(ext, ".GIF"))
                {   
                    //printf("eog -f %s%s\n",FILE_PATH,liste[counter]);
                    char command[1000];
                    strcpy(command,("eog -f %s%s",FILE_PATH,liste[counter]));
                    //printf("%s", command);
                    execl(command,command,NULL,NULL);
                    sleep(5);
                }           
                else if (!strcmp(ext,".mov") || !strcmp(ext, ".mp4") || !strcmp(ext, ".avi") || !strcmp(ext,".wmv"))
                {
                    //printf("mplayer -fs %s%s\n",FILE_PATH,liste[counter]);
                    char command[1000];
                    strcpy(command,("mplayer -fs %s%s",FILE_PATH,liste[counter]));
                    //printf("%s",command);
                    execl(command,command,NULL,NULL);
//                  system(command);

                }
                else 
                    printf("--%s%s",FILE_PATH,liste[counter]);      
            }
            else
            {
                pid_w = waitpid(child_pid,&status,0);
    //          system("eog -f /home/user/Desktop/Video/screenshot_0000.png");
    //                  sleep(5);
    //                  exit(EXIT_SUCCESS);
            }
            counter++;
            if(counter >=file_numbers)
                counter =0;

        }
    }
mehmet
  • 55
  • 1
  • 10
  • _But when i get video list from directy and send them with char array it is not working._ Are you sure you get it rightly? Did you check i.e. printing out? Önce verinin düzgün gelip gelmediği, sonra diğer adımlar. – Soner from The Ottoman Empire Jul 16 '17 at 12:14
  • 1
    What is `("%s.",FILE_PATH)` supposed to do? C doesn't have any string-formatting like Python. You need to have an array and use `snprintf` to "print" into the array. You have *lots* of these, and none will work as you think. I recommend you get a couple of [good beginners books](http://stackoverflow.com/questions/562303/the-definitive-c-book-guide-and-list) and start reading. – Some programmer dude Jul 16 '17 at 12:14
  • 1
    what's this: `strcpy(command,("mplayer -fs %s%s",FILE_PATH,liste[counter]));` and how did you get this idea? If this is supposed to format a string, use the function for formatting strings: `sprintf()` or better [`snprintf()`](https://linux.die.net/man/3/snprintf). –  Jul 16 '17 at 12:14
  • Interestingly this snippet kind of "works", but it copies `liste[counter]` to `command`. The *comma operator* discards the result of all other expressions (left side of the comma). Here you end up trying to *execute* one of your entries in `liste`. –  Jul 16 '17 at 12:16
  • these two lines: `char *path = ("%s.",FILE_PATH); d = opendir(path);` should be: `d = opendir( FILE_PATH );` It is very poor programming practice to not check for errors, the above line should be immediately followed by: `if( !d ) { perror( "opendir failed" ); exit( EXIT_FAILURE ); }` – user3629249 Jul 17 '17 at 14:24
  • when calling `system()`, always check the returned value to assure the operation was successful. – user3629249 Jul 17 '17 at 16:40
  • regarding your statement: *When i tried system() call it gives 'sh: 1: video1.mov not found' error* this is because the posted code is not including the 'path' due to several errors in the code. Otherwise, the error message would have included the 'path' – user3629249 Jul 17 '17 at 16:44
  • why is the posted code opening the directory in two different places? – user3629249 Jul 17 '17 at 16:47

2 Answers2

2

I'm not sure it's the only error, but it's the one that's obviously your immediate problem:

strcpy(command,("mplayer -fs %s%s",FILE_PATH,liste[counter]));

I don't know how you got the idea this would somehow format a string. What it does is to copy liste[counter] to command. The reason is that the second argument to your strcpy is a paranthesized expression:

("mplayer -fs %s%s",FILE_PATH,liste[counter])

It uses the comma operator (,) twice. The comma operator does the following:

1.) it evaluates both sides of the comma sequenced (first the left hand side, then the right hand side) 2.) its evaluation result is that of the right hand side, the other result is just discarded (*)

So, here

"mplayer -fs %s%s",FILE_PATH,liste[counter]

is exactly equivalent to just

liste[counter]

What you're looking for is snprintf():

snprintf(command, sizeof(command), "mplayer -fs %s%s", FILE_PATH, liste[counter]);

This will do what you obviously expected. On a side note, also observe how putting a blank after each comma makes this whole line a lot more readable, so I'd recommend you do the same.


(*) but the order of side effects is well-defined, that's what it's used for -- of course, here you don't have any side effects

0

calls to fork() can result in three different return states.

  1. currently executing the parent process and the returned value is the PID of the child process
  2. currently executing the child process and the returned value is 0
  3. no process was created, the returned value is -1

The posted code is failing to handle #3.

Suggest:

 child_pid = fork();
 switch( child_pid )
 {
     case 0:  // child
         ....
     break;

     case -1: // error
         perror( "fork failed" );
         exit( EXIT_FAILURE );
         break;

     default:  // parent
         pid_w = waitpid(child_pid,&status,0); 
         break;
 } // end switch()

calls to execl() need the following parameters:

  1. const char *path to the executable
  2. const char *first executable argument
  3. const char *second executable argument
  4. ....
  5. NULL

since you want to execute :`

eog -f %s%s",FILE_PATH,liste[counter]));

the call to execl() should look similar to:

char buffer[1024];
sprintf( "%s%s", FILE_PATH, liste[counter] );
execl( "eog", "eog", "-f", buffer, NULL );
// the 'execl()' function does not return 
// unless there was an error so:
perror( "execl failed" );
exit( EXIT_FAILURE );      // this exits child process when failure occurred
user3629249
  • 16,402
  • 1
  • 16
  • 17