⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 command.c

📁 Red-Button
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * command.c */#include <unistd.h>#include <stdio.h>#include <string.h>#include <stdbool.h>#include <stdint.h>#include <fcntl.h>#include "command.h"#include "assoc.h"#include "fs.h"#include "stream.h"#include "utils.h"/* max number of args that can be passed to a command (arbitrary) */#define ARGV_MAX	10/* the commands */bool cmd_assoc(struct listen_data *, FILE *, int, char **);bool cmd_astream(struct listen_data *, FILE *, int, char **);bool cmd_avstream(struct listen_data *, FILE *, int, char **);bool cmd_check(struct listen_data *, FILE *, int, char **);bool cmd_file(struct listen_data *, FILE *, int, char **);bool cmd_help(struct listen_data *, FILE *, int, char **);bool cmd_quit(struct listen_data *, FILE *, int, char **);bool cmd_vstream(struct listen_data *, FILE *, int, char **);static struct{	char *name;	char *args;	bool (*proc)(struct listen_data *, FILE *, int, char **);	char *help;} command[] ={	{ "assoc", "",				cmd_assoc,	"List component tag to PID mappings" },	{ "astream", "<ComponentTag>",		cmd_astream,	"Stream the given audio component tag" },	{ "avstream", "<AudioTag> <VideoTag>",	cmd_avstream,	"Stream the given audio and video component tags" },	{ "check", "<ContentReference>",	cmd_check,	"Check if the given file exists on the carousel" },	{ "exit", "",				cmd_quit,	"Close the connection" },	{ "file", "<ContentReference>",		cmd_file,	"Retrieve the given file from the carousel" },	{ "help", "",				cmd_help,	"List available commands" },	{ "quit", "",				cmd_quit,	"Close the connection" },	{ "vstream", "<ComponentTag>",		cmd_vstream,	"Stream the given video component tag" },	{ NULL, NULL, NULL, NULL }};/* send an OK/error code etc response down client_sock */#define SEND_RESPONSE(RC, MESSAGE)	fputs(#RC " " MESSAGE "\n", client)/* internal routines */char *external_filename(struct listen_data *, char *);char *canonical_filename(char *);/* * process the given command * return true if we should close the connection */boolprocess_command(struct listen_data *listen_data, FILE *client, char *cmd){	int argc;	char *argv[ARGV_MAX];	char term;	unsigned int cmd_len;	int i;	/* chop it into words, complicated by quoting */	argc = 0;	while(argc < ARGV_MAX && *cmd != '\0')	{		argv[argc++] = cmd;		/* do we need to find the next space, or the next quote */		if(*cmd == '\'' || *cmd == '"')		{			term = *cmd;			/* remove/skip the opening quote */			argv[argc-1] ++;			cmd ++;		}		else		{			/* stop at the next space */			term = ' ';		}		/* find the next terminating character */		while(*cmd != term && *cmd != '\0')			cmd ++;		/* if this is not the end, skip to the start of the next word */		if(*cmd != '\0')		{			/* terminate the last word */			*cmd = '\0';			/* move onto the next non-space character */			cmd = skip_ws(cmd + 1);		}	}	cmd_len = strlen(argv[0]);	for(i=0; command[i].name != NULL; i++)	{		if(strncmp(argv[0], command[i].name, cmd_len) == 0)			return (command[i].proc)(listen_data, client, argc, argv);	}	SEND_RESPONSE(500, "Unrecognised command");	return false;}/* * the commands * listen_data is global data needed by listener commands * client is where any response data should go * argc is the number of arguments passed to it * argv[0] is the command name (or the abreviation the user used) * return true if we should close the connection */#define CHECK_USAGE(ARGC, SYNTAX)		\if(argc != ARGC)				\{						\	SEND_RESPONSE(500, "Syntax: " SYNTAX);	\	return false;				\}/* * assoc * show the association/component tag to PID mappings * also shows the default audio and video PIDs * (just for debugging) */boolcmd_assoc(struct listen_data *listen_data, FILE *client, int argc, char *argv[]){	struct carousel *car = listen_data->carousel;	unsigned int i;	SEND_RESPONSE(200, "OK");	/* if this is ever used by rb-browser, you will need to send a length first */	fprintf(client, "Tag\tPID\tType\n");	fprintf(client, "===\t===\t====\n");	/* default audio and video PIDs */	fprintf(client, "(audio)\t%u\t%u\n", car->audio_pid, car->audio_type);	fprintf(client, "(video)\t%u\t%u\n", car->video_pid, car->video_type);	/* component tag mappings */	for(i=0; i<car->assoc.nassocs; i++)		fprintf(client, "%u\t%u\t%u\n", car->assoc.sids[i], car->assoc.pids[i], car->assoc.types[i]);	return false;}/* * astream <tag> * send the given audio stream down the connection * the tag should be an association/component_tag number as found in the PMT * the tag is converted to a PID and that PID is sent as a MPEG Transport Stream down the connection * if tag is -1, the default audio stream for the current service_id is sent */boolcmd_astream(struct listen_data *listen_data, FILE *client, int argc, char *argv[]){	struct carousel *car = listen_data->carousel;	int tag;	uint16_t pid;	uint8_t type;	int audio_fd;	int ts_fd;	char hdr[64];	CHECK_USAGE(2, "astream <ComponentTag>");	tag = strtol(argv[1], NULL, 0);	/* map the tag to a PID and stream type, or use the default */	if(tag == -1)	{		/* check we have a default stream */		if(car->audio_pid == 0)		{			SEND_RESPONSE(500, "Unable to find audio PID");			return false;		}		pid = car->audio_pid;		type = car->audio_type;	}	else	{		pid = stream2pid(&car->assoc, tag);		type = stream2type(&car->assoc, tag);	}	/* add the PID to the demux device */	if((audio_fd = add_demux_filter(car->demux_device, pid, DMX_PES_AUDIO)) < 0)	{		SEND_RESPONSE(500, "Unable to open audio PID");		return false;	}	/* we can now read a transport stream from the dvr device */	if((ts_fd = open(car->dvr_device, O_RDONLY)) < 0)	{		SEND_RESPONSE(500, "Unable to open DVB device");		close(audio_fd);		return false;	}	/* send the OK code */	SEND_RESPONSE(200, "OK");	/* tell the client what PID and stream type the component tag resolved to */	snprintf(hdr, sizeof(hdr), "AudioPID %u AudioType %u\n", pid, type);	fputs(hdr, client);	/* shovel the transport stream to client until the client closes or we get an error */	stream_ts(ts_fd, client);	/* clean up */	close(ts_fd);	close(audio_fd);	/* close the connection */	return true;}/* * vstream <tag> * send the given video stream down the connection * the tag should be an association/component_tag number as found in the PMT * the tag is converted to a PID and that PID is sent as a MPEG Transport Stream down the connection * if tag is -1, the default video stream for the current service_id is sent */boolcmd_vstream(struct listen_data *listen_data, FILE *client, int argc, char *argv[]){	struct carousel *car = listen_data->carousel;	int tag;	uint16_t pid;	uint8_t type;	int video_fd;	int ts_fd;	char hdr[64];	CHECK_USAGE(2, "vstream <ComponentTag>");	tag = strtol(argv[1], NULL, 0);	/* map the tag to a PID and stream type, or use the default */	if(tag == -1)	{		/* check we have a default stream */		if(car->video_pid == 0)		{			SEND_RESPONSE(500, "Unable to find video PID");			return false;		}		pid = car->video_pid;		type = car->video_type;	}	else	{		pid = stream2pid(&car->assoc, tag);		type = stream2type(&car->assoc, tag);	}	/* add the PID to the demux device */	if((video_fd = add_demux_filter(car->demux_device, pid, DMX_PES_VIDEO)) < 0)	{		SEND_RESPONSE(500, "Unable to open video PID");		return false;	}	/* we can now read a transport stream from the dvr device */	if((ts_fd = open(car->dvr_device, O_RDONLY)) < 0)	{		SEND_RESPONSE(500, "Unable to open DVB device");		close(video_fd);		return false;	}	/* send the OK code */	SEND_RESPONSE(200, "OK");	/* tell the client what PID and stream type the component tag resolved to */	snprintf(hdr, sizeof(hdr), "VideoPID %u VideoType %u\n", pid, type);	fputs(hdr, client);	/* shovel the transport stream down client_sock until the client closes it or we get an error */	stream_ts(ts_fd, client);	/* clean up */	close(ts_fd);	close(video_fd);	/* close the connection */	return true;}/* * avstream <audio_tag> <video_tag> * send the given audio and video streams down the connection * the tags should be association/component_tag numbers as found in the PMT * the tags are converted to PIDs and those PIDs are sent as a MPEG Transport Stream down the connection * if a tag is -1, the default audio or video stream for the current service_id is sent */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -