コード例 #1
0
ファイル: pikrellcam.c プロジェクト: miraaz/pikrellcam
  /* vcb should be locked before calling video_record_start()
  */
void
video_record_start(VideoCircularBuffer *vcb, int start_state)
	{
	char	*s, *tag, *path, seq_buf[12];
	int		*seq;

	if (vcb->state == VCB_STATE_MANUAL_RECORD)
		return;

	if (start_state == VCB_STATE_MOTION_RECORD_START)
		{
		tag = pikrellcam.video_motion_tag;
		seq = &pikrellcam.video_motion_sequence;
		}
	else
		{
		tag = pikrellcam.video_manual_tag;
		seq = &pikrellcam.video_manual_sequence;
		}

	snprintf(seq_buf, sizeof(seq_buf), "%d", *seq);
	path = media_pathname(pikrellcam.video_dir, pikrellcam.video_filename,
						'N',  seq_buf,
						'M', tag);
	*seq += 1;
	dup_string(&pikrellcam.video_pathname, path);
	free(path);
	path = pikrellcam.video_pathname;

	if ((s = strstr(path, ".mp4")) != NULL && *(s + 4) == '\0')
		{
		asprintf(&path, "%s.h264", pikrellcam.video_pathname);
		dup_string(&pikrellcam.video_h264, path);
		free(path);
		path = pikrellcam.video_h264;
		pikrellcam.video_mp4box = TRUE;
		}
	else
		pikrellcam.video_mp4box = FALSE;

	if ((vcb->file = fopen(path, "w")) == NULL)
		log_printf("Could not create video file %s.  %m\n", path);
	else
		{
		log_printf("Video record: %s ...\n", path);
		vcb->state = start_state;
		}
	}
コード例 #2
0
ファイル: event.c プロジェクト: inscriptionweb/pikrellcam
  /* exec a command with the given arg.  Any strftime() % replacements should
  |  have been done before calling this so there will remain only pikrellcam
  |  specific $X conversions.  Change all '$X' to '%s' and printf in what we
  |  want according to X.
  */
static int
exec_command(char *command, char *arg, boolean wait, pid_t *pid)
	{
	struct tm *tm_now;
	CompositeVector *frame_vec = &motion_frame.final_preview_vector;
	char	specifier, *fmt, *fmt_arg, *copy, *cmd_line, *name, buf[BUFSIZ];
	int		t, i, status = 0;

	if (!command || !*command)
		return -1;

	copy = strdup(command);
	cmd_line = copy;
	while (   (fmt = strchr(copy, '$')) != NULL
	       && *(fmt + 1)
	      )
		{
		specifier = *(fmt + 1);
		*fmt++ = '%';
		*fmt = 's';
		switch (specifier)
			{
			case 'F':
				fmt_arg = arg ? arg : "";
				break;
			case 'H':
				fmt_arg = pikrellcam.hostname;
				break;
			case 'E':
				fmt_arg = pikrellcam.effective_user;
				break;
			case 'I':
				fmt_arg = pikrellcam.install_dir;
				break;
			case 's':
				fmt_arg = pikrellcam.still_last;
				break;
			case 'S':
				fmt_arg = pikrellcam.still_dir;
				break;
			case 'v':
				fmt_arg = pikrellcam.video_last;
				break;
			case 'V':
				fmt_arg = pikrellcam.video_dir;
				break;
			case 't':
				fmt_arg = pikrellcam.thumb_dir;
				break;
			case 'T':
				snprintf(buf, sizeof(buf), "%05d", time_lapse.series);
				name = media_pathname(pikrellcam.video_dir,
						pikrellcam.timelapse_video_name,
						'n',  buf, '\0', NULL);
				snprintf(buf, sizeof(buf), "%s", name);
				free(name);
				fmt_arg = buf;
				dup_string(&pikrellcam.timelapse_video_pending, fmt_arg);
				break;
			case 'l':
				snprintf(buf, sizeof(buf), "%05d", time_lapse.series);
				name = strdup(pikrellcam.timelapse_format);
				name = substitute_var(name, 'n', buf);
				name = substitute_var(name, 'N', "%05d");
				snprintf(buf, sizeof(buf), "%s", name);
				free(name);
				fmt_arg = buf;
				break;
			case 'L':
				fmt_arg = pikrellcam.timelapse_dir;
				break;
			case 'a':
				fmt_arg = pikrellcam.archive_dir;
				break;
			case 'm':
				fmt_arg = pikrellcam.media_dir;
				break;
			case 'M':
				fmt_arg = pikrellcam.mjpeg_filename;
				break;
			case 'P':
				fmt_arg = pikrellcam.command_fifo;
				break;
			case 'C':
				fmt_arg = pikrellcam.script_dir;
				break;
			case 'G':
				fmt_arg = pikrellcam.log_file;
				break;
			case 'N':
				snprintf(buf, sizeof(buf), "%05d", time_lapse.sequence);
				fmt_arg = buf;
				break;
			case 'n':
				snprintf(buf, sizeof(buf), "%05d", time_lapse.series);
				fmt_arg = buf;
				break;
			case 'i':	/* width of motion area */
				t = frame_vec->box_w;
				snprintf(buf, sizeof(buf), "%d", t);
				fmt_arg = buf;
				break;
			case 'J':	/* height of motion area */
				t = frame_vec->box_h;
				snprintf(buf, sizeof(buf), "%d", t);
				fmt_arg = buf;
				break;
			case 'K':	/* center X of motion area */
				t = frame_vec->x;
				snprintf(buf, sizeof(buf), "%d", t);
				fmt_arg = buf;
				break;
			case 'Y':	/* center Y of motion area */
				t = frame_vec->y;
				snprintf(buf, sizeof(buf), "%d", t);
				fmt_arg = buf;
				break;
			case 'D':	/* current_minute dawn sunrise sunset dusk */
				tm_now = localtime(&pikrellcam.t_now);
				snprintf(buf, sizeof(buf), "%d %d %d %d %d",
						tm_now->tm_hour * 60 + tm_now->tm_min,
						sun.dawn, sun.sunrise, sun.sunset, sun.dusk);
				fmt_arg = buf;
				break;
			case 'Z':
				fmt_arg = pikrellcam.version;
				break;

			default:
				fmt_arg = "?";
				break;
			}
		if (!fmt_arg || !fmt_arg)
			log_printf("  Bad fmt_arg %p for specifier %c\n", fmt_arg, specifier);
		asprintf(&cmd_line, copy, fmt_arg);
		free(copy);
		copy = cmd_line;
		}

	log_printf("execl:[%s]\n", cmd_line);

	if ((*pid = fork()) == 0)
		{			/* child - execute command in background */
		for (i = getdtablesize(); i > 2; --i)
			close(i);
		setsid();		/* new session group - ie detach */
		execl("/bin/sh", "sh", "-c", cmd_line, " &", NULL);
		_exit (EXIT_FAILURE);
		}
	else if (*pid < 0)
		{
		perror("Fork failed.");
		status = -1;
		}
	else if (wait)		/* If parent needs to wait */
		{
		if (waitpid (*pid, &status, 0) != *pid)
			status = -1;
		}
	free(cmd_line);
	return status;
	}
コード例 #3
0
ファイル: pikrellcam.c プロジェクト: miraaz/pikrellcam
void
command_process(char *command_line)
	{
	VideoCircularBuffer	*vcb = &video_circular_buffer;
	Command	*cmd;
	char	command[64], args[128], buf[32], *path;
	int		i, n;

	if (!command_line || *command_line == '\0')
		return;

	n = sscanf(command_line, "%63s %[^\n]", command, args);
	if (n < 1 || command[0] == '#')
		return;
	for (cmd = NULL, i = 0; i < COMMAND_SIZE; cmd = NULL, ++i)
		{
		cmd = &commands[i];
		if (!strcmp(command, cmd->name))
			{
			if (cmd->n_args != n - 1)
				{
				log_printf("Wrong number of args for command: %s\n", command);
				return;
				}
			break;
			}
		}
	if (!cmd)
		{
		if (   !config_set_option(command, args, FALSE)
		    && !mmalcam_config_parameter_set(command, args, TRUE)
	       )
			log_printf("Bad command: [%s] [%s]\n", command, args);
		return;
		}
	if (cmd->code != display_cmd)
		log_printf("command_process: %s\n", command_line);

	if (cmd->code < display_cmd && !display_is_default())
		{
		display_set_default();
		return;
		}

	switch (cmd->code)
		{
		case record:
			pthread_mutex_lock(&vcb->mutex);
			if (config_boolean_value(args) == TRUE)
				{
				if (vcb->pause)
					vcb->pause = FALSE;
				else
					{
					if (vcb->state == VCB_STATE_MOTION_RECORD)
						video_record_stop(vcb);
					video_record_start(vcb, VCB_STATE_MANUAL_RECORD_START);
					}
				}
			else
				video_record_stop(vcb);
			pthread_mutex_unlock(&vcb->mutex);
			break;

		case record_pause:
			/* Can pause manual record only.  Because of event_gap/capture
			|  times, I'm not even sure what it would mean to pause a
			|  motion record.
			*/
			pthread_mutex_lock(&vcb->mutex);
			if (vcb->state == VCB_STATE_MANUAL_RECORD)
				vcb->pause = vcb->pause ? FALSE : TRUE;
			else
				vcb->pause = FALSE;
			pthread_mutex_unlock(&vcb->mutex);
			break;

		case still:
			snprintf(buf, sizeof(buf), "%d", pikrellcam.still_sequence);
			path = media_pathname(pikrellcam.still_dir, pikrellcam.still_filename,
							'N',  buf,
							'\0', NULL);
			pikrellcam.still_sequence += 1;
			still_capture(path);
			free(path);
			break;

		case tl_start:
			if ((n = atoi(args)) < 1)
				n = 0;
			time_lapse.activated = TRUE;
			time_lapse.on_hold = FALSE;
			if (!time_lapse.event && n > 0)
				{
				time_lapse.sequence = 0;
				++time_lapse.series;
				time_lapse.event = event_add("timelapse",
							pikrellcam.t_now, n, timelapse_capture, NULL);
				}
			else if (n > 0)		/* Change the period */
				{
				time_lapse.event->time += (n - time_lapse.period);
				time_lapse.event->period = n;
				}
			if (n > 0)
				time_lapse.period = n;	/* n == 0 just sets on_hold FALSE */
			config_timelapse_save_status();	
			break;

		case tl_hold:
				config_set_boolean(&time_lapse.on_hold, args);
				config_timelapse_save_status();
			break;

		case tl_end:
			if (time_lapse.activated)
				{
				event_remove(time_lapse.event);
				time_lapse.event = NULL;
				time_lapse.activated = FALSE;
				time_lapse.on_hold = FALSE;
				config_timelapse_save_status();
				exec_no_wait(pikrellcam.on_timelapse_end_cmd, NULL);
				}
			break;

		case tl_inform_convert:
			if (!strcmp(args, "done"))
				{
				event_remove(time_lapse.inform_event);
				dup_string(&time_lapse.convert_name, "");
				time_lapse.convert_size = 0;
				}
			else
				{
				dup_string(&time_lapse.convert_name, args);
				time_lapse.inform_event = event_add("tl_inform_convert",
						pikrellcam.t_now, 5, timelapse_inform_convert, NULL);
				}
			break;

		case tl_show_status:
			config_set_boolean(&time_lapse.show_status, args);
			break;

		case display_cmd:
			display_command(args);
			break;

		case motion_cmd:
			motion_command(args);
			break;

		case motion_enable:
			n = motion_frame.motion_enable;
			config_set_boolean(&motion_frame.motion_enable, args);

			if (n && !motion_frame.motion_enable)
				{
				pthread_mutex_lock(&vcb->mutex);
				if (vcb->state == VCB_STATE_MOTION_RECORD)
					video_record_stop(vcb);
				pthread_mutex_unlock(&vcb->mutex);
				}
			break;

		case save_config:
			config_save(pikrellcam.config_file);
			break;

		case quit:
			config_timelapse_save_status();
			if (pikrellcam.config_modified)
				config_save(pikrellcam.config_file);
			display_quit();
			exit(0);
			break;

		default:
			log_printf("command in table with no action!\n");
			break;
		}
	}
コード例 #4
0
ファイル: pikrellcam.c プロジェクト: miraaz/pikrellcam
void
timelapse_capture(void)
	{
	char			*path, seq_buf[12], series_buf[12];
	int				n, nd;
	MMAL_STATUS_T	status;

	if (time_lapse.on_hold)
		return;

	/* still_capture()  also uses the still_jpeg_encoder, so wait if busy.
	*/
	for (n = 0; n < 5; ++n)
		{
		if (still_jpeg_encoder.file == NULL)
			break;
		usleep(50000);
		}
	if (still_jpeg_encoder.file != NULL)
		{
		log_printf("timelapse capture failed because jpeg encoder is busy.\n");
		return;
		}

	snprintf(seq_buf, sizeof(seq_buf), "%05d", time_lapse.sequence);
	snprintf(series_buf, sizeof(series_buf), "%05d", time_lapse.series);
	path = media_pathname(pikrellcam.timelapse_dir,
						pikrellcam.timelapse_format,
						'N',  seq_buf,
						'n',  series_buf);
	time_lapse.sequence += 1;

	if ((still_jpeg_encoder.file = fopen(path, "w")) == NULL)
		log_printf("Could not create timelapse file %s.  %m\n", path);
	else
		{
		if ((status = mmal_port_parameter_set_boolean(
						camera.component->output[CAMERA_CAPTURE_PORT],
						MMAL_PARAMETER_CAPTURE, 1)) != MMAL_SUCCESS)
			{
			fclose(still_jpeg_encoder.file);
			still_jpeg_encoder.file = NULL;
			log_printf("Timelapse capture startup failed. Status %s\n",
						mmal_status[status]);
			}
		else
			{
			log_printf("Timelapse still: %s\n", path);
			dup_string(&pikrellcam.timelapse_last_save, path);

			/* timelapse_capture() is an event call (inside the event loop)
			|  and we here add an event to the list.
			|  This only modifies the last event list next pointer, and
			|  the event loop is not there yet.
			*/
			nd = pikrellcam.notify_duration;
			if (nd > time_lapse.period - 3)
				nd = time_lapse.period / 2;
			if (nd > 1)
				nd *= EVENT_LOOP_FREQUENCY;
			else
				nd = EVENT_LOOP_FREQUENCY / 2;

			event_count_down_add("timelapse saved", nd,
					event_notify_expire, &pikrellcam.timelapse_notify);
			pikrellcam.timelapse_notify = TRUE;
			}
		}
	free(path);
	}