aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLoïc Collignon <loic.collignon@iot.bzh>2018-06-27 17:30:37 +0200
committerLoïc Collignon <loic.collignon@iot.bzh>2018-06-27 17:30:37 +0200
commit63dc51c35d26c837295ac0ef33c1b8e41353ea35 (patch)
tree24918fe062c14b29f1c69b2e024cb8d66d045c50
parentd9bb450ee8898cb810027897a32afd3adcb05d9f (diff)
Merge 'eel' into 'master'
Replace content from 'master' by content from 'eel' as it's the new version based on 4a on which new development will be done. Change-Id: I2966af7dcee59701ff3a344487c008d7e65e68ed Signed-off-by: Loïc Collignon <loic.collignon@iot.bzh>
-rw-r--r--.gitignore2
-rw-r--r--.gitmodules6
-rw-r--r--CMakeLists.txt23
m---------afb-helpers0
-rw-r--r--app/CMakeLists.txt57
-rw-r--r--app/Mixer.qml151
-rw-r--r--app/app.pri12
-rw-r--r--app/app.pro18
-rw-r--r--app/main.cpp27
-rw-r--r--app/mixer.cpp91
-rw-r--r--app/mixer.h54
-rw-r--r--app/paclient.cpp329
-rw-r--r--app/paclient.h97
-rw-r--r--app/pacontrolmodel.cpp208
-rw-r--r--app/pacontrolmodel.h92
m---------conf.d/app-templates0
-rwxr-xr-xconf.d/autobuild/agl/autobuild21
-rwxr-xr-xconf.d/autobuild/linux/autobuild67
-rw-r--r--conf.d/cmake/config.cmake201
-rw-r--r--conf.d/wgt/config.xml.in21
-rw-r--r--conf.d/wgt/icon.svg (renamed from package/icon.svg)0
-rw-r--r--mixer.pro3
-rw-r--r--package/config.xml.highlight .hll { background-color: #ffffcc } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-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 */
/*
 * Copyright (C) 2017-2018 "IoT.bzh"
 * Author Sebastien Douheret <sebastien@iot.bzh>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package xdsserver

import (
	"fmt"
	"net/http"
	"os"
	"regexp"
	"strconv"
	"strings"
	"time"

	common "gerrit.automotivelinux.org/gerrit/src/xds/xds-common.git"
	"gerrit.automotivelinux.org/gerrit/src/xds/xds-common.git/eows"
	"gerrit.automotivelinux.org/gerrit/src/xds/xds-server.git/lib/xsapiv1"
	"github.com/gin-gonic/gin"
	"github.com/kr/pty"
)

var execCommandID = 1

// ExecCmd executes remotely a command
func (s *APIService) execCmd(c *gin.Context) {
	var gdbPty, gdbTty *os.File
	var err error
	var args xsapiv1.ExecArgs
	if c.BindJSON(&args) != nil {
		common.APIError(c, "Invalid arguments")
		return
	}

	// TODO: add permission ?

	// Retrieve session info
	sess := s.sessions.Get(c)
	if sess == nil {
		common.APIError(c, "Unknown sessions")
		return
	}
	sop := sess.IOSocket
	if sop == nil {
		common.APIError(c, "Websocket not established")
		return
	}

	// Allow to pass id in url (/exec/:id) or as JSON argument
	idArg := c.Param("id")
	if idArg == "" {
		idArg = args.ID
	}
	if idArg == "" {
		common.APIError(c, "Invalid id")
		return
	}
	id, err := s.mfolders.ResolveID(idArg)
	if err != nil {
		common.APIError(c, err.Error())
		return
	}
	f := s.mfolders.Get(id)
	if f == nil {
		common.APIError(c, "Unknown id")
		return
	}
	fld := *f
	prj := fld.GetConfig()

	// Build command line
	cmd := []string{}

	// Reset by default LD_LIBRARY_PATH
	// With new AGL SDK, New environment-setup-*-agl-linux file checks if
	// LD_LIBRARY_PATH is set or not and not empty LD_LIBRARY_PATH is considered
	// as misconfigured and prevent to use SDK
	if !args.LdLibPathNoReset {
		cmd = append(cmd, "unset LD_LIBRARY_PATH; ")
	}

	// Setup env var regarding Sdk ID (used for example to setup cross toolchain)
	if envCmd := s.sdks.GetEnvCmd(args.SdkID, prj.DefaultSdk); len(envCmd) > 0 {
		cmd = append(cmd, envCmd...)
		cmd = append(cmd, "&&")
	} else {
		// It's an error if no envcmd found while a sdkid has been provided
		if args.SdkID != "" {
			common.APIError(c, "Unknown sdkid")
			return
		}
	}

	cmd = append(cmd, "cd", "\""+fld.GetFullPath(args.RPath)+"\"")
	// FIXME - add 'exec' prevents to use syntax:
	//       xds-exec -l debug -c xds-config.env -- "cd build && cmake .."
	//  but exec is mandatory to allow to pass correctly signals
	//  As workaround, exec is set for now on client side (eg. in xds-gdb)
	//cmd = append(cmd, "&&", "exec", args.Cmd)
	cmd = append(cmd, "&&", args.Cmd)

	// Process command arguments
	cmdArgs := make([]string, len(args.Args)+1)

	// Copy and Translate path from client to server
	for _, aa := range args.Args {
		if strings.Contains(aa, prj.ClientPath) {
			cmdArgs = append(cmdArgs, fld.ConvPathCli2Svr(aa))
		} else {
			cmdArgs = append(cmdArgs, aa)
		}
	}

	// Allocate pts if tty if used
	if args.TTY {
		gdbPty, gdbTty, err = pty.Open()
		if err != nil {
			common.APIError(c, err.Error())
			return
		}

		s.Log.Debugf("Client command tty: %v %v\n", gdbTty.Name(), gdbTty.Name())
		cmdArgs = append(cmdArgs, "--tty="+gdbTty.Name())
	}

	// Unique ID for each commands
	if args.CmdID == "" {
		args.CmdID = s.Config.ServerUID[:18] + "_" + strconv.Itoa(execCommandID)
		execCommandID++
	}

	// Create new execution over WS context
	execWS := eows.New(strings.Join(cmd, " "), cmdArgs, sop, sess.ID, args.CmdID)
	execWS.Log = s.Log
	execWS.OutSplit = eows.SplitChar

	// Append client project dir to environment
	execWS.Env = append(args.Env, "CLIENT_PROJECT_DIR="+prj.ClientPath)

	// Set command execution timeout
	if args.CmdTimeout == 0 {
		// 0 : default timeout
		// TODO get default timeout from server-config.json file
		execWS.CmdExecTimeout = 24 * 60 * 60 // 1 day
	} else {
		execWS.CmdExecTimeout = args.CmdTimeout
	}

	// Define callback for input (stdin)
	execWS.InputEvent = xsapiv1.ExecInEvent
	execWS.InputCB = func(e *eows.ExecOverWS, bStdin []byte) ([]byte, error) {

		stdin := string(bStdin)

		s.Log.Debugf("STDIN <<%v>>", strings.Replace(stdin, "\n", "\\n", -1))

		// Handle Ctrl-D
		if len(stdin) == 1 && stdin == "\x04" {
			// Close stdin
			errMsg := fmt.Errorf("close stdin: %v", stdin)
			return []byte{}, errMsg
		}

		// Set correct path
		data := e.UserData
		prjID := (*data)["ID"].(string)
		f := s.mfolders.Get(prjID)
		if f == nil {
			s.Log.Errorf("InputCB: Cannot get folder ID %s", prjID)
		} else {
			// Translate paths from client to server
			stdin = (*f).ConvPathCli2Svr(stdin)
		}
		return []byte(stdin), nil
	}

	// Define callback for output (stdout+stderr)
	execWS.OutputCB = func(e *eows.ExecOverWS, bStdout, bStderr []byte) {

		stdout := string(bStdout)
		stderr := string(bStderr)

		// IO socket can be nil when disconnected
		so := s.sessions.IOSocketGet(e.Sid)
		if so == nil {
			s.Log.Infof("%s not emitted: WS closed (sid:%s, CmdID:%s)", xsapiv1.ExecOutEvent, e.Sid, e.CmdID)
			return
		}

		// Retrieve project ID and RootPath
		data := e.UserData
		prjID := (*data)["ID"].(string)
		gdbServerTTY := (*data)["gdbServerTTY"].(string)

		f := s.mfolders.Get(prjID)
		if f == nil {
			s.Log.Errorf("OutputCB: Cannot get folder ID %s", prjID)
		} else {
			// Translate paths from server to client
			stdout = (*f).ConvPathSvr2Cli(stdout)
			stderr = (*f).ConvPathSvr2Cli(stderr)
		}

		s.Log.Debugf("%s emitted - WS sid[4:] %s - id:%s - prjID:%s", xsapiv1.ExecOutEvent, e.Sid[4:], e.CmdID, prjID)
		if stdout != "" {
			s.Log.Debugf("STDOUT <<%v>>", strings.Replace(stdout, "\n", "\\n", -1))
		}
		if stderr != "" {
			s.Log.Debugf("STDERR <<%v>>", strings.Replace(stderr, "\n", "\\n", -1))
		}

		// FIXME replace by .BroadcastTo a room
		err := (*so).Emit(xsapiv1.ExecOutEvent, xsapiv1.ExecOutMsg{
			CmdID:     e.CmdID,
			Timestamp: time.Now().String(),
			Stdout:    stdout,
			Stderr:    stderr,
		})
		if err != nil {
			s.Log.Errorf("WS Emit : %v", err)
		}

		// XXX - Workaround due to gdbserver bug that doesn't redirect
		// inferior output (https://bugs.eclipse.org/bugs/show_bug.cgi?id=437532#c13)
		if gdbServerTTY == "workaround" && len(stdout) > 1 && stdout[0] == '&' {

			// Extract and cleanup string like &"bla bla\n"
			re := regexp.MustCompile("&\"(.*)\"")
			rer := re.FindAllStringSubmatch(stdout, -1)
			out := ""
			if rer != nil && len(rer) > 0 {
				for _, o := range rer {
					if len(o) >= 1 {
						out = strings.Replace(o[1], "\\n", "\n", -1)
						out = strings.Replace(out, "\\r", "\r", -1)
						out = strings.Replace(out, "\\t", "\t", -1)

						s.Log.Debugf("STDOUT INFERIOR: <<%v>>", out)
						err := (*so).Emit(xsapiv1.ExecInferiorOutEvent, xsapiv1.ExecOutMsg{
							CmdID:     e.CmdID,
							Timestamp: time.Now().String(),
							Stdout:    out,
							Stderr:    "",
						})
						if err != nil {
							s.Log.Errorf("WS Emit : %v", err)
						}
					}
				}
			} else {
				s.Log.Errorf("INFERIOR out parsing error: stdout=<%v>", stdout)
			}
		}
	}

	// Define callback for output
	execWS.ExitCB = func(e *eows.ExecOverWS, code int, err error) {
		s.Log.Debugf("Command [Cmd ID %s] exited: code %d, error: %v", e.CmdID, code, err)

		defer LockXdsUpdateCounter(s.Context, false)
		// Close client tty
		defer func() {
			if gdbPty != nil {
				gdbPty.Close()
			}
			if gdbTty != nil {
				gdbTty.Close()
			}
		}()

		// IO socket can be nil when disconnected
		so := s.sessions.IOSocketGet(e.Sid)
		if so == nil {
			s.Log.Infof("%s not emitted - WS closed (id:%s)", xsapiv1.ExecExitEvent, e.CmdID)
			return
		}

		// Retrieve project ID and RootPath
		data := e.UserData
		prjID := (*data)["ID"].(string)
		exitImm := (*data)["ExitImmediate"].(bool)

		// XXX - workaround to be sure that Syncthing detected all changes
		if err := s.mfolders.ForceSync(prjID); err != nil {
			s.Log.Errorf("Error while syncing folder %s: %v", prjID, err)
		}
		if !exitImm {
			// Wait end of file sync
			// FIXME pass as argument
			tmo := 60
			for t := tmo; t > 0; t-- {
				s.Log.Debugf("Wait file in-sync for %s (%d/%d)", prjID, t, tmo)
				if sync, err := s.mfolders.IsFolderInSync(prjID); sync || err != nil {
					if err != nil {
						s.Log.Errorf("ERROR IsFolderInSync (%s): %v", prjID, err)
					}
					break
				}
				time.Sleep(time.Second)
			}
			s.Log.Debugf("OK file are synchronized.")
		}

		// FIXME replace by .BroadcastTo a room
		errSoEmit := (*so).Emit(xsapiv1.ExecExitEvent, xsapiv1.ExecExitMsg{
			CmdID:     e.CmdID,
			Timestamp: time.Now().String(),
			Code:      code,
			Error:     err,
		})
		if errSoEmit != nil {
			s.Log.Errorf("WS Emit : %v", errSoEmit)
		}
	}

	// User data (used within callbacks)
	data := make(map[string]interface{})
	data["ID"] = prj.ID
	data["ExitImmediate"] = args.ExitImmediate
	if args.TTY && args.TTYGdbserverFix {
		data["gdbServerTTY"] = "workaround"
	} else {
		data["gdbServerTTY"] = ""
	}
	execWS.UserData = &data

	// Start command execution
	s.Log.Infof("Execute [Cmd ID %s]: %v %v", execWS.CmdID, execWS.Cmd, execWS.Args)

	LockXdsUpdateCounter(s.Context, true)
	err = execWS.Start()
	if err != nil {
		LockXdsUpdateCounter(s.Context, false)
		common.APIError(c, err.Error())
		return
	}

	c.JSON(http.StatusOK, xsapiv1.ExecResult{Status: "OK", CmdID: execWS.CmdID})
}

// ExecCmd executes remotely a command
func (s *APIService) execSignalCmd(c *gin.Context) {
	var args xsapiv1.ExecSignalArgs

	if c.BindJSON(&args) != nil {
		common.APIError(c, "Invalid arguments")
		return
	}

	s.Log.Debugf("Signal %s for command ID %s", args.Signal, args.CmdID)

	e := eows.GetEows(args.CmdID)
	if e == nil {
		common.APIError(c, "unknown cmdID")
		return
	}

	err := e.Signal(args.Signal)
	if err != nil {
		common.APIError(c, err.Error())
		return
	}

	c.JSON(http.StatusOK, xsapiv1.ExecSigResult{Status: "OK", CmdID: args.CmdID})
}
n QVariant();
-
- const PaControl &control = m_controls[index.row()];
- if (role == CIndexRole)
- return control.cindex();
- else if (role == NameRole)
- return control.name();
- else if (role == DescRole)
- return control.desc();
- else if (role == TypeRole)
- return control.type();
- else if (role == ChannelRole)
- return control.channel();
- else if (role == CDescRole)
- return control.cdesc();
- else if (role == VolumeRole)
- return control.volume();
- return QVariant();
-}
-
-Qt::ItemFlags PaControlModel::flags(const QModelIndex &index) const
-{
- if (!index.isValid())
- return Qt::ItemIsEnabled;
-
- return QAbstractListModel::flags(index) | Qt::ItemIsEditable;
-}
-
-QHash<int, QByteArray> PaControlModel::roleNames() const {
- QHash<int, QByteArray> roles;
- roles[CIndexRole] = "cindex";
- roles[NameRole] = "name";
- roles[DescRole] = "desc";
- roles[TypeRole] = "type";
- roles[ChannelRole] = "channel";
- roles[CDescRole] = "cdesc";
- roles[VolumeRole] = "volume";
- return roles;
-}
diff --git a/app/pacontrolmodel.h b/app/pacontrolmodel.h
deleted file mode 100644
index 81eb70b..0000000
--- a/app/pacontrolmodel.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2016,2017 Konsulko Group
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <pulse/pulseaudio.h>
-
-#include <QtCore/QAbstractListModel>
-#include <QtCore/QList>
-
-class PaControlModel;
-
-class PaControl
-{
- public:
- PaControl(const quint32 &index, const QString &name, const QString &desc, const quint32 &type, const quint32 &channel, const QString &cdesc, const quint32 &volume);
-
- quint32 cindex() const;
- QString name() const;
- QString desc() const;
- quint32 type() const;
- quint32 channel() const;
- QString cdesc() const;
- quint32 volume() const;
- void setCIndex(const QVariant&);
- void setName(const QVariant&);
- void setDesc(const QVariant&);
- void setType(const QVariant&);
- void setChannel(const QVariant&);
- void setCDesc(const QVariant&);
- void setVolume(PaControlModel *, const QVariant&);
-
- private:
- quint32 m_cindex;
- QString m_name;
- QString m_desc;
- quint32 m_type;
- quint32 m_channel;
- QString m_cdesc;
- quint32 m_volume;
-};
-
-class PaControlModel : public QAbstractListModel
-{
- Q_OBJECT
- public:
- enum PaControlRoles {
- CIndexRole = Qt::UserRole + 1,
- NameRole,
- DescRole,
- TypeRole,
- ChannelRole,
- CDescRole,
- VolumeRole
- };
-
- PaControlModel(QObject *parent = 0);
-
- void addControl(const PaControl &control);
-
- int rowCount(const QModelIndex &parent = QModelIndex()) const;
-
- QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
-
- bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
-
- Qt::ItemFlags flags(const QModelIndex &index) const;
-
- public slots:
- void addOneControl(int cindex, QString name, QString desc, int type, int channel, const char *cdesc, int volume);
- void changeExternalVolume(uint32_t type, uint32_t cindex, uint32_t chan, uint32_t volume);
-
- signals:
- void volumeChanged(uint32_t type, uint32_t index, uint32_t channel, uint32_t volume);
-
- protected:
- QHash<int, QByteArray> roleNames() const;
- private:
- QList<PaControl> m_controls;
- pa_context *pa_ctx;
-};
diff --git a/conf.d/app-templates b/conf.d/app-templates
new file mode 160000
+Subproject 1f2944eea3a418ec02920673a390ed4b5d417a2
diff --git a/conf.d/autobuild/agl/autobuild b/conf.d/autobuild/agl/autobuild
new file mode 100755
index 0000000..ea352e7
--- /dev/null
+++ b/conf.d/autobuild/agl/autobuild
@@ -0,0 +1,21 @@
+#!/bin/bash
+
+SOURCE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/../../../"
+BUILD_DIR=$( echo "$2" | cut -d'=' -f2 )
+
+# HACK: alias should be expanded in script for cmake to work properly
+shopt -s expand_aliases
+# HACK: source again the SDK because of the alias
+source $SDKTARGETSYSROOT/../../environment-setup-*
+
+pushd $BUILD_DIR
+
+ cmake $SOURCE_DIR
+ make
+
+ if [ "$1" == "package" ]; then
+ make widget
+ fi
+
+popd
+
diff --git a/conf.d/autobuild/linux/autobuild b/conf.d/autobuild/linux/autobuild
new file mode 100755
index 0000000..3a1ba5f
--- /dev/null
+++ b/conf.d/autobuild/linux/autobuild
@@ -0,0 +1,67 @@
+#!/usr/bin/make -f
+# Copyright (C) 2015, 2016 "IoT.bzh"
+# Author "Romain Forlot" <romain.forlot@iot.bzh>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+THISFILE := $(lastword $(MAKEFILE_LIST))
+BUILD_DIR := $(abspath $(dir $(THISFILE)/../../../../..)/build)
+DEST := ${BUILD_DIR}/target
+
+.PHONY: all clean distclean configure build package help update
+
+all: help
+
+help:
+ @echo "List of targets available:"
+ @echo ""
+ @echo "- all"
+ @echo "- clean"
+ @echo "- distclean"
+ @echo "- configure"
+ @echo "- build: compilation, link and prepare files for package into a widget"
+ @echo "- package: output a widget file '*.wgt'"
+ @echo "- install: install in your ${CMAKE_INSTALL_DIR} directory"
+ @echo ""
+ @echo "Usage: ./conf.d/autobuild/agl/autobuild package DEST=${HOME}/opt"
+ @echo "Don't use your build dir as DEST as wgt file is generated at this location"
+
+update: configure
+ @cmake --build ${BUILD_DIR} --target autobuild
+
+clean:
+ @([ -d ${BUILD_DIR} ] && make -C ${BUILD_DIR} clean) || echo Nothing to clean
+
+distclean:
+ @rm -rf ${BUILD_DIR}
+
+configure: ${BUILD_DIR}/Makefile
+
+build: configure
+ @cmake --build ${BUILD_DIR} ${BUILD_ARGS} --target all
+
+package: build
+ @mkdir -p ${BUILD_DIR}/$@/bin
+ @mkdir -p ${BUILD_DIR}/$@/etc
+ @mkdir -p ${BUILD_DIR}/$@/lib
+ @mkdir -p ${BUILD_DIR}/$@/htdocs
+ @mkdir -p ${BUILD_DIR}/$@/data
+ @cmake --build ${BUILD_DIR} --target widget
+ @mkdir -p ${DEST} && cp ${BUILD_DIR}/*wgt ${DEST}
+
+install: build
+ @cmake --build ${BUILD_DIR} --target install
+
+${BUILD_DIR}/Makefile:
+ @[ -d ${BUILD_DIR} ] || mkdir -p ${BUILD_DIR}
+ @[ -f ${BUILD_DIR}/Makefile ] || (cd ${BUILD_DIR} && cmake ${CONFIGURE_ARGS} ..)
diff --git a/conf.d/cmake/config.cmake b/conf.d/cmake/config.cmake
new file mode 100644
index 0000000..03bf212
--- /dev/null
+++ b/conf.d/cmake/config.cmake
@@ -0,0 +1,201 @@
+###########################################################################
+# Copyright 2018 IoT.bzh
+#
+# author: Loïc Collignon <loic.collignon@iot.bzh>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+###########################################################################
+
+# Project Info
+# ------------------
+set(PROJECT_NAME mixer)
+set(PROJECT_PRETTY_NAME "Mixer")
+set(PROJECT_DESCRIPTION "AGL Default Mixer")
+set(PROJECT_URL "https://gerrit.automotivelinux.org/gerrit/apps/mixer")
+set(PROJECT_ICON "icon.svg")
+set(PROJECT_AUTHOR "Collignon, Loïc")
+set(PROJECT_AUTHOR_MAIL "loic.collignon@iot.bzh")
+set(PROJECT_LICENSE "APL2.0")
+set(PROJECT_LANGUAGES "C")
+
+# Where are stored default templates files from submodule or subtree app-templates in your project tree
+# relative to the root project directory
+set(PROJECT_APP_TEMPLATES_DIR "conf.d/app-templates")
+
+# Where are stored your external libraries for your project. This is 3rd party library that you don't maintain
+# but used and must be built and linked.
+# set(PROJECT_LIBDIR "libs")
+
+# Which directories inspect to find CMakeLists.txt target files
+# set(PROJECT_SRC_DIR_PATTERN "*")
+
+# Compilation Mode (DEBUG, RELEASE)
+# ----------------------------------
+#set(CMAKE_BUILD_TYPE "DEBUG")
+set(USE_EFENCE 1)
+
+# Kernel selection if needed. You can choose between a
+# mandatory version to impose a minimal version.
+# Or check Kernel minimal version and just print a Warning
+# about missing features and define a preprocessor variable
+# to be used as preprocessor condition in code to disable
+# incompatibles features. Preprocessor define is named
+# KERNEL_MINIMAL_VERSION_OK.
+#
+# NOTE*** FOR NOW IT CHECKS KERNEL Yocto environment and
+# Yocto SDK Kernel version.
+# -----------------------------------------------
+#set (kernel_mandatory_version 4.8)
+#set (kernel_minimal_version 4.8)
+
+# Compiler selection if needed. Impose a minimal version.
+# -----------------------------------------------
+set (gcc_minimal_version 4.9)
+
+# PKG_CONFIG required packages
+# -----------------------------
+set (PKG_REQUIRED_LIST
+ json-c
+ libsystemd>=222
+ afb-daemon
+ #libhomescreen
+ # qlibwindowmanager
+)
+
+# Prefix path where will be installed the files
+# Default: /usr/local (need root permission to write in)
+# ------------------------------------------------------
+#set(CMAKE_INSTALL_PREFIX $ENV{HOME}/opt)
+
+# Customize link option
+# -----------------------------
+#list(APPEND link_libraries -an-option)
+
+# Compilation options definition
+# Use CMake generator expressions to specify only for a specific language
+# Values are prefilled with default options that is currently used.
+# Either separate options with ";", or each options must be quoted separately
+# DO NOT PUT ALL OPTION QUOTED AT ONCE , COMPILATION COULD FAILED !
+# ----------------------------------------------------------------------------
+#set(COMPILE_OPTIONS
+# -Wall
+# -Wextra
+# -Wconversion
+# -Wno-unused-parameter
+# -Wno-sign-compare
+# -Wno-sign-conversion
+# -Werror=maybe-uninitialized
+# -Werror=implicit-function-declaration
+# -ffunction-sections
+# -fdata-sections
+# -fPIC
+# CACHE STRING "Compilation flags")
+#set(C_COMPILE_OPTIONS "" CACHE STRING "Compilation flags for C language.")
+#set(CXX_COMPILE_OPTIONS "" CACHE STRING "Compilation flags for C++ language.")
+#set(PROFILING_COMPILE_OPTIONS
+# -g
+# -O0
+# -pg
+# -Wp,-U_FORTIFY_SOURCE
+# CACHE STRING "Compilation flags for PROFILING build type.")
+#set(DEBUG_COMPILE_OPTIONS
+# -g
+# -ggdb
+# -Wp,-U_FORTIFY_SOURCE
+# CACHE STRING "Compilation flags for DEBUG build type.")
+#set(CCOV_COMPILE_OPTIONS
+# -g
+# -O2
+# --coverage
+# CACHE STRING "Compilation flags for CCOV build type.")
+#set(RELEASE_COMPILE_OPTIONS
+# -g
+# -O2
+# CACHE STRING "Compilation flags for RELEASE build type.")
+
+# (BUG!!!) as PKG_CONFIG_PATH does not work [should be an env variable]
+# ---------------------------------------------------------------------
+set(CMAKE_PREFIX_PATH ${CMAKE_INSTALL_PREFIX}/lib64/pkgconfig ${CMAKE_INSTALL_PREFIX}/lib/pkgconfig)
+set(LD_LIBRARY_PATH ${CMAKE_INSTALL_PREFIX}/lib64 ${CMAKE_INSTALL_PREFIX}/lib)
+
+# Optional location for config.xml.in
+# -----------------------------------
+#set(WIDGET_ICON "\"conf.d/wgt/${PROJECT_ICON}\"" CACHE PATH "Path to the widget icon")
+set(WIDGET_CONFIG_TEMPLATE "${CMAKE_CURRENT_SOURCE_DIR}/conf.d/wgt/config.xml.in" CACHE PATH "Path to widget config file template (config.xml.in)")
+
+# Mandatory widget Mimetype specification of the main unit
+# --------------------------------------------------------------------------
+# Choose between :
+#- text/html : HTML application,
+# content.src designates the home page of the application
+#
+#- application/vnd.agl.native : AGL compatible native,
+# content.src designates the relative path of the binary.
+#
+# - application/vnd.agl.service: AGL service, content.src is not used.
+#
+#- ***application/x-executable***: Native application,
+# content.src designates the relative path of the binary.
+# For such application, only security setup is made.
+#
+set(WIDGET_TYPE application/vnd.agl.native)
+
+# Mandatory Widget entry point file of the main unit
+# --------------------------------------------------------------
+# This is the file that will be executed, loaded,
+# at launch time by the application framework.
+#
+set(WIDGET_ENTRY_POINT mixer)
+
+# Optional dependencies order
+# ---------------------------
+#set(EXTRA_DEPENDENCIES_ORDER)
+
+# Optional Extra global include path
+# -----------------------------------
+#set(EXTRA_INCLUDE_DIRS)
+
+# Optional extra libraries
+# -------------------------
+#set(EXTRA_LINK_LIBRARIES)
+
+# Optional force binding Linking flag
+# ------------------------------------
+# set(BINDINGS_LINK_FLAG LinkOptions )
+
+# Optional force package prefix generation, like widget
+# -----------------------------------------------------
+# set(PKG_PREFIX DestinationPath)
+
+# Optional Application Framework security token
+# and port use for remote debugging.
+#------------------------------------------------------------
+set(AFB_TOKEN "" CACHE PATH "Default binder security token")
+set(AFB_REMPORT "1234" CACHE PATH "Default binder listening port")
+
+# Print a helper message when every thing is finished
+# ----------------------------------------------------
+set(CLOSING_MESSAGE "Typical binding launch: afb-daemon --port=${AFB_REMPORT} --workdir=${CMAKE_BINARY_DIR}/package --ldpaths=lib --roothttp=htdocs --token=\"${AFB_TOKEN}\" --tracereq=common --verbose")
+set(PACKAGE_MESSAGE "Install widget file using in the target : afm-util install ${PROJECT_NAME}.wgt")
+
+# Optional schema validator about now only XML, LUA and JSON
+# are supported
+#------------------------------------------------------------
+#set(LUA_CHECKER "luac" "-p" CACHE STRING "LUA compiler")
+#set(XML_CHECKER "xmllint" CACHE STRING "XML linter")
+#set(JSON_CHECKER "json_verify" CACHE STRING "JSON linter")
+
+# This include is mandatory and MUST happens at the end
+# of this file, else you expose you to unexpected behavior
+# -----------------------------------------------------------
+include(${PROJECT_APP_TEMPLATES_DIR}/cmake/common.cmake)
diff --git a/conf.d/wgt/config.xml.in b/conf.d/wgt/config.xml.in
new file mode 100644
index 0000000..597f19d
--- /dev/null
+++ b/conf.d/wgt/config.xml.in
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<widget xmlns="http://www.w3.org/ns/widgets" id="@PROJECT_NAME@" version="@PROJECT_VERSION@">
+ <name>@PROJECT_NAME@</name>
+ <icon src="@PROJECT_ICON@"/>
+ <content src="@WIDGET_ENTRY_POINT@" type="@WIDGET_TYPE@"/>
+ <description>@PROJECT_DESCRIPTION@</description>
+ <author>
+ <author href="https://www.automotivelinux.org/" email = "info@automotivelinux.org">
+ Loïc Collignon &lt;loic.collignon@iot.bzh&gt;
+ Matt Porter &lt;mporter@konsulko.com&gt;
+ </author>
+ <license>@PROJECT_LICENSE@</license>
+ <feature name="urn:AGL:widget:required-api">
+ <param name="windowmanager" value="ws" />
+ <param name="homescreen" value="ws" />
+ </feature>
+ <feature name="urn:AGL:widget:required-permission">
+ <param name="urn:AGL:permission::public:no-htdocs" value="required" />
+ <param name="urn:AGL:permission::public:4a-audio-mixer" value="required" />
+ </feature>
+</widget>
diff --git a/package/icon.svg b/conf.d/wgt/icon.svg
index 85f7384..85f7384 100644
--- a/package/icon.svg
+++ b/conf.d/wgt/icon.svg
diff --git a/mixer.pro b/mixer.pro
deleted file mode 100644
index 579a952..0000000
--- a/mixer.pro
+++ /dev/null
@@ -1,3 +0,0 @@
-TEMPLATE = subdirs
-SUBDIRS = app package
-package.depends += app
diff --git a/package/config.xml b/package/config.xml
deleted file mode 100644
index bee25a0..0000000
--- a/package/config.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<widget xmlns="http://www.w3.org/ns/widgets" id="mixer" version="0.1">
- <name>Mixer</name>
- <icon src="icon.svg"/>
- <content src="bin/mixer" type="application/vnd.agl.native"/>
- <description>Simple PulseAudio mixer app</description>
- <author>Matt Porter &lt;mporter@konsulko.com&gt;</author>
- <license>APL 2.0</license>
- <feature name="urn:AGL:widget:required-api">
- <param name="windowmanager" value="ws" />
- <param name="homescreen" value="ws" />
- </feature>
- <feature name="urn:AGL:widget:required-permission">
- <param name="urn:AGL:permission::public:no-htdocs" value="required" />
- </feature>
-</widget>
-
-
diff --git a/package/package.pro b/package/package.pro
deleted file mode 100644
index 3d37bd7..0000000
--- a/package/package.pro
+++ /dev/null
@@ -1,19 +0,0 @@
-
-DISTFILES = icon.svg config.xml
-
-copy_icon.target = $$OUT_PWD/root/icon.svg
-copy_icon.depends = $$_PRO_FILE_PWD_/icon.svg
-copy_icon.commands = $(COPY_FILE) \"$$replace(copy_icon.depends, /, $$QMAKE_DIR_SEP)\" \"$$replace(copy_icon.target, /, $$QMAKE_DIR_SEP)\"
-QMAKE_EXTRA_TARGETS += copy_icon
-PRE_TARGETDEPS += $$copy_icon.target
-
-copy_config.target = $$OUT_PWD/root/config.xml
-copy_config.depends = $$_PRO_FILE_PWD_/config.xml
-copy_config.commands = $(COPY_FILE) \"$$replace(copy_config.depends, /, $$QMAKE_DIR_SEP)\" \"$$replace(copy_config.target, /, $$QMAKE_DIR_SEP)\"
-QMAKE_EXTRA_TARGETS += copy_config
-PRE_TARGETDEPS += $$copy_config.target
-
-wgt.target = package
-wgt.commands = wgtpkg-pack -f -o mixer.wgt root
-
-QMAKE_EXTRA_TARGETS += wgt