summaryrefslogtreecommitdiffstats
path: root/recipes-multimedia
AgeCommit message (Expand)AuthorFilesLines
2017-12-21lightmediascanner: build mp4 pluginMatt Ranostay1-1/+4
2017-12-21libmp4v2: initial add 2.1.0Andreas Müller2-0/+58
2017-12-08recipes-multimedia: add recipe for agl-service-unicensChristian Gromm1-0/+19
2017-11-14Pulseaudio configuration fixesScott Murray4-6/+12
2017-11-14Fix pulseaudio service startRonan Le Martret1-1/+1
2017-11-03Rework PulseAudio / audiomanager config setup to allow over-ridesScott Murray7-61/+28
2017-07-05module-router: update SRCREV to include empty proplist description fixMatt Porter1-1/+1
2017-07-04Add mp3 support in lightmediascanner for AGL demoTadao Tanikawa1-0/+2
2017-06-27disable module-role-cork by defaultMatt Porter2-0/+31
2017-05-24Add audio management between Media Player and Radio.Toshiaki Isogai4-4/+33
2017-01-23Fix a bug in the audio managementNaoto Yamaguchi1-1/+1
2016-12-27Integrate GENIVI Audio Manager Plugins for CES2017 demo.Toshiaki Isogai8-0/+789
2016-12-21Adding patch to adjust volume of TTS engineNaoto Yamaguchi2-1/+34
2016-12-02TTS Engine: Added support for Japanese TTS engineNaoto Yamaguchi3-0/+116
2016-11-24TTS Engine: Added support for English TTS engineNaoto Yamaguchi2-0/+48
2016-11-24TTS Engine: Added support for HTS engineNaoto Yamaguchi1-0/+19
2015-08-22The starting point of layers for AGL Demo PlatformTadao Tanikawa1-0/+0
weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
#include <proc/readproc.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <proc/sysinfo.h>
#include <math.h>
#include <unistd.h>
#include <json-c/json.h>
#include <sys/types.h>
#include <signal.h>
#include <errno.h>

#define AFB_BINDING_VERSION 3
#include <afb/afb-binding.h>

struct pstat {
	long long unsigned int utime_ticks;
	long long unsigned int cutime_ticks;
	long long unsigned int stime_ticks;
	long long unsigned int cstime_ticks;
	long unsigned int cpu_total_time;
};

struct cpu_percentage {
	double ucpu_usage;
	double scpu_usage;
};

struct process_container {
	char *process_name;
	int euid;
	struct pstat pstat_values;
};

void get_process_list(afb_req_t request);
int fill_pstat(proc_t *proc_info, struct pstat *pstat);
void cpu_calculate(struct pstat*, struct pstat*, struct cpu_percentage *perc);
void fill_process_container(char* process_name, int euid, struct pstat *pstat_values, struct process_container *pc);

void get_process_list(afb_req_t request){

	struct pstat last_pstat_values, cur_pstat_values;
	struct cpu_percentage cpu_usage;
	struct process_container *process_obj, *elem = NULL;
	struct process_container *object_container[65535]; // array holding process objects
	struct json_object *ret_json, *json_array, *json_obj;
	ret_json = json_object_new_object();
	json_array = json_object_new_array();
	char state_str[2] = "\0";
	int i, ret;

	PROCTAB* proc = openproc(PROC_FILLMEM | PROC_FILLSTAT);
	if (!proc){
		AFB_REQ_ERROR(request, "Unable to open /proc!");
		afb_req_reply(request, NULL, "Failed", "Error processing arguments.");
		return;
	}

	memset(object_container, 0, sizeof(*object_container));
	proc_t* proc_info;
	while ((proc_info = readproc(proc, NULL)) != NULL) {
		ret = fill_pstat(proc_info, &last_pstat_values);
		if (ret < 0) {
			AFB_REQ_ERROR(request, "fill_pstat failed");
			continue;
		}
		process_obj = malloc(sizeof(*process_obj));
		if (process_obj == NULL) {
			AFB_REQ_ERROR(request, "allocation of process_obj failed");
			continue;
		}
		fill_process_container(proc_info->cmd, proc_info->euid, &last_pstat_values, process_obj);
		object_container[proc_info->tid] = process_obj;
		freeproc(proc_info);
	}

	sleep(1);

	closeproc(proc);
	proc = openproc(PROC_FILLMEM | PROC_FILLSTAT);
	if (!proc){
		AFB_REQ_ERROR(request, "Unable to open /proc!");
		afb_req_reply(request, NULL, "Failed", "Error processing arguments.");
		return;
	}

	while ((proc_info = readproc(proc, NULL)) != NULL) {
		ret = fill_pstat(proc_info, &cur_pstat_values);
		if (ret < 0) {
			AFB_REQ_ERROR(request, "fill_pstat failed");
			continue;
		}
		elem = object_container[proc_info->tid];
		if (elem) {
			cpu_calculate(&elem->pstat_values, &cur_pstat_values, &cpu_usage);
			json_obj = json_object_new_object();
			json_object_object_add(json_obj, "cmd", json_object_new_string(proc_info->cmd));
			json_object_object_add(json_obj, "tid", json_object_new_int(proc_info->tid));
			json_object_object_add(json_obj, "euid", json_object_new_int(proc_info->euid));
			json_object_object_add(json_obj, "scpu", json_object_new_double(cpu_usage.scpu_usage));
			json_object_object_add(json_obj, "ucpu", json_object_new_double(cpu_usage.ucpu_usage));
			json_object_object_add(json_obj, "resident_mem", json_object_new_double((proc_info->resident * getpagesize())/ pow(1024, 2)));
			state_str[0] = proc_info->state;
			json_object_object_add(json_obj, "state", json_object_new_string(state_str));
			json_object_array_add(json_array, json_obj);
		}
		freeproc(proc_info);
	}
	json_object_object_add(ret_json, "msgType", json_object_new_string("processList"));
	json_object_object_add(ret_json, "processes", json_array);
	afb_req_reply(request, ret_json, NULL, NULL);

	closeproc(proc);
}

void kill_process(afb_req_t request)
{
	struct json_object *ret_json;
	ret_json = json_object_new_object();
	json_object *queryJ = afb_req_json(request);
	int tid = json_object_get_int(queryJ);
	int ret;

	AFB_REQ_INFO(request, "killing %d\n", tid);
	/* XXX: add checks */
	ret = kill(tid, SIGTERM);
	if (ret < 0)
		afb_req_reply_f(request, NULL, "Failed", "Error %d", errno);
	/* we don't signal success, there's no use for it */
}

void get_extra_info(afb_req_t request)
{
	struct json_object *ret_json, *json_obj;
	json_object *req = afb_req_json(request);
	int tid = json_object_get_int(req);

	ret_json = json_object_new_object();
	json_obj = json_object_new_object();

	char path[32];
	char str_val[256];
	char param[80];

	sprintf(path, "/proc/%d/sched", tid);
	FILE *fsched = fopen(path, "r");

	if (fsched == NULL) {
		afb_req_reply(request, NULL, "Failed", "Error processing arguments.");
		return;
	}
	else {
		json_object_object_add(json_obj, "tid", json_object_new_int(tid));

		fscanf(fsched, "%255s", str_val);
		json_object_object_add(json_obj, "cmd", json_object_new_string(str_val));

		fscanf(fsched, "%*s"); // the '-' line
		while (!feof(fsched)) {
			fscanf(fsched, "%79s%*s%255s", param, str_val);
			if (strstr(param, "exec_start"))
				json_object_object_add(json_obj, "exec_start", json_object_new_string(str_val));
			else if (strstr(param, "vruntime"))
				json_object_object_add(json_obj, "vruntime", json_object_new_string(str_val));
			else if (strstr(param, "sum_exec_runtime"))
				json_object_object_add(json_obj, "sum_exec_runtime", json_object_new_string(str_val));
			else if (strstr(param, "prio"))
				json_object_object_add(json_obj, "prio", json_object_new_string(str_val));
		}
	}
	fclose(fsched);

	json_object_object_add(ret_json, "msgType", json_object_new_string("extraInfo"));
	json_object_object_add(ret_json, "info", json_obj);

	afb_req_reply(request, ret_json, NULL, NULL);
}

void get_load_avg(afb_req_t request)
{
	struct json_object *ret_json, *json_obj;
		float value = 1.;

	ret_json = json_object_new_object();
	json_obj = json_object_new_object();

	FILE *floadAvg = fopen("/proc/loadavg", "r");

	if (floadAvg == NULL) {
		afb_req_reply(request, NULL, "Failed", "Error processing arguments.");
		return;
	}
	else {
		fscanf(floadAvg, "%4f%4*f%4*f", &value);

		json_object_object_add(json_obj, "value", json_object_new_double(value));
		json_object_object_add(json_obj, "str", json_object_new_string("Load"));

		json_object_object_add(ret_json, "msgType", json_object_new_string("loadAvgInfo"));
		json_object_object_add(ret_json, "loadInfo", json_obj);
	}
	fclose(floadAvg);

	afb_req_reply(request, ret_json, NULL, NULL);
}

void get_netstat(afb_req_t request)
{
	struct json_object *ret_json, *json_obj;
	char names_str[1024], values_str[1024];
	char *pnames = names_str, *pvalues = values_str;

	FILE *fnetstat = fopen("/proc/net/netstat", "r");

	if (fnetstat == NULL) {
		afb_req_reply(request, NULL, "Failed", "Error processing arguments.");
		return;
	}

	do {
		pnames = fgets(pnames, 1024, fnetstat);
	} while (pnames && !feof(fnetstat) && strncmp(pnames, "IpExt: ", 7));
	if (feof(fnetstat)) {
		fclose(fnetstat);
		afb_req_reply(request, NULL, "Failed", "Parse error");
		return;
	}
	pvalues = fgets(pvalues, 1024, fnetstat);
	fclose(fnetstat);
	if (pvalues == NULL) {
		afb_req_reply(request, NULL, "Failed", "Parse error");
		return;
	}

	ret_json = json_object_new_object();
	json_obj = json_object_new_object();

	pnames += 7; pvalues += 7;
	while (pnames && pvalues) {
		char *name = strsep(&pnames, " ");
		char *value = strsep(&pvalues, " ");

		if (name && value) {
			AFB_REQ_INFO(request, "adding %s[%s]\n", name, value);
			json_object_object_add(json_obj, name, json_object_new_int(atoi(value)));
		}
	}
	json_object_object_add(ret_json, "msgType", json_object_new_string("netStatInfo"));
	json_object_object_add(ret_json, "netstat", json_obj);

	afb_req_reply(request, ret_json, NULL, NULL);
}

int fill_pstat(proc_t *proc_info, struct pstat *pstat_values)
{
	long unsigned int cpu_time[9];

	pstat_values->utime_ticks = proc_info->utime;
	pstat_values->cutime_ticks = proc_info->cutime;
	pstat_values->stime_ticks = proc_info->stime;
	pstat_values->cstime_ticks = proc_info->cstime;

	FILE *fstat = fopen("/proc/stat", "r");
	if (fstat == NULL)
		return -1;

	memset(cpu_time, 0, sizeof(cpu_time));
	fscanf(fstat, "%*s %lu %lu %lu %lu %*lu %lu %lu %lu %lu %lu",
		&cpu_time[0], &cpu_time[1], &cpu_time[2], &cpu_time[3],
		&cpu_time[4], &cpu_time[5], &cpu_time[6], &cpu_time[7],
		&cpu_time[8]);

	fclose(fstat);

	/*
	 * Returns total CPU time. It is a sum of user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice
	 *
	 *
	 */
	pstat_values->cpu_total_time = 0;
	for(int i = 0; i < 9; i++)
		pstat_values->cpu_total_time += cpu_time[i];

	return 0;
}

void cpu_calculate(struct pstat *last_pstat_values, struct pstat *cur_pstat_values, struct cpu_percentage *cpu_values)
{

	long unsigned int total_time_diff = cur_pstat_values->cpu_total_time - last_pstat_values->cpu_total_time;

	cpu_values->ucpu_usage = 100.0 * (((cur_pstat_values->utime_ticks + cur_pstat_values->cutime_ticks)
		- (last_pstat_values->utime_ticks + last_pstat_values->cutime_ticks)) / (double) total_time_diff);

	cpu_values->scpu_usage = 100.0 * (((cur_pstat_values->stime_ticks + cur_pstat_values->cstime_ticks)
		- (last_pstat_values->stime_ticks + last_pstat_values->cstime_ticks)) / (double) total_time_diff);
}

void fill_process_container(char *process_name, int euid, struct pstat *pstat_values, struct process_container *pc)
{
	pc->process_name = process_name;
	pc->euid = euid;
	pc->pstat_values = *pstat_values;
}

static const afb_verb_t _afb_verbs_taskmanager[] = {
	{
		.verb = "get_process_list",
		.callback = get_process_list,
		.auth = NULL,
		.info = "Get an array of all processes currently running on the system",
		.session = AFB_SESSION_NONE
	},
	{
		.verb = "kill_process",
		.callback = kill_process,
		.auth = NULL,
		.info = "Kill the process specified by tid",
		.session = AFB_SESSION_NONE
	},
	{
		.verb = "get_extra_info",
		.callback = get_extra_info,
		.auth = NULL,
		.info = "Get exta info about current process",
		.session = AFB_SESSION_NONE
	},
	{
		.verb = "get_load_avg",
		.callback = get_load_avg,
		.auth = NULL,
		.info = "Get exta info about system load average",
		.session = AFB_SESSION_NONE
	},
	{
		.verb = "get_netstat",
		.callback = get_netstat,
		.auth = NULL,
		.info = "Get network (IP) statistics",
		.session = AFB_SESSION_NONE
	},
	{ .verb = NULL }
};


const afb_binding_t afbBindingExport = {
	.api = "taskmanager",
	.specification = NULL,
	.info = "Task Manager service",
	.verbs = _afb_verbs_taskmanager,
	.noconcurrency = 0
};