我正在尝试在linux中制作视频looper。为此,我使用mplayer视频。我的程序从目录中获取视频和图像列表并播放它们。我的问题是当我用c数组参数从c调用mplayer或图像查看器时它无法正常工作。 例如,
system("eog -f /home/user/Desktop/Video/screenshot_0000.png");
或
system("mplayer -fs /home/user/Desktop/Video/video1.mov");
如果我这样打电话就行了。但是当我从directy获取视频列表并使用char数组发送它时它无法正常工作。当我尝试system()调用它给出'sh:1:video1.mov not found'错误,当我使用exec()函数时没有任何反应。
这是我的代码;
#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;
}
}
答案 0 :(得分:2)
我不确定这是唯一的错误,但这显然是你眼前的问题:
strcpy(command,("mplayer -fs %s%s",FILE_PATH,liste[counter]));
我不知道你是怎么想到这会以某种方式格式化一个字符串。它的作用是将liste[counter]
复制到command
。原因是你的strcpy
的第二个参数是一个带有paranthesized的表达式:
("mplayer -fs %s%s",FILE_PATH,liste[counter])
它使用逗号运算符(,
)两次。逗号运算符执行以下操作:
1。)它评估逗号顺序的两侧(首先是左侧,然后是右侧) 2.)其评估结果是右侧,其他结果只是丢弃(*)
所以,这里
"mplayer -fs %s%s",FILE_PATH,liste[counter]
完全等同于
liste[counter]
您要找的是snprintf()
:
snprintf(command, sizeof(command), "mplayer -fs %s%s", FILE_PATH, liste[counter]);
这将做你明显的期望。另外,还要观察每个逗号后面的空格是如何让整行更多更具可读性,所以我建议你也这样做。
(*)但副作用的顺序是明确定义的,这就是它的用途 - 当然,这里你没有任何副作用
答案 1 :(得分:0)
对fork()
的调用可能会导致三种不同的返回状态。
发布的代码未能处理#3。
推荐:
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()
对execl()
的调用需要以下参数:
因为你想执行:`
eog -f %s%s",FILE_PATH,liste[counter]));
对execl()
的调用应类似于:
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