summaryrefslogtreecommitdiffstats
path: root/meta-pipewire/conf
AgeCommit message (Collapse)AuthorFilesLines
2022-03-29Declare layer compatibility with kirkstoneScott Murray1-1/+1
For tracking upstream, we need to update the layer compatibility. Bug-AGL: SPEC-3819 Change-Id: Ic1bc22653e59b2891d77d44cdd409a805e5cc332 Signed-off-by: Scott Murray <scott.murray@konsulko.com> Signed-off-by: Jan-Simon Moeller <jsmoeller@linuxfoundation.org>
2021-11-04Prepare master for new framework integrationJan-Simon Moeller1-5/+0
During the last workshop the transition to the new framework was presented. This change essentially deprecates the SMACK-based application framework. To prepare the integration of it, we remove the deprecated components: - meta-agl-core: remove Smack kernel patches - meta-app-framework - meta-pipewire/dynamic-layers/meta-app-framework/ v2: rebased Bug-AGL: SPEC-4121 Signed-off-by: Jan-Simon Moeller <jsmoeller@linuxfoundation.org> Change-Id: Icdaeadfb5d2193f3a4c535168c88da6073423e67 Reviewed-on: https://gerrit.automotivelinux.org/gerrit/c/AGL/meta-agl/+/26752
2021-08-23Convert to new override syntaxScott Murray1-1/+1
This is mostly the result of running a slightly customized version of the convert-overrides.py script from poky with additional overrides added. A few minor fixups were done by hand afterwards during a review of the changes. The intent of these changes is to minimize the effort to keep the "next" branch that builds against poky master up to date and tested in preparation for the switch to the next Yocto LTS release in early 2022. Bug-AGL: SPEC-4052 Signed-off-by: Scott Murray <scott.murray@konsulko.com> Change-Id: Ia3bf63b7cb1aa1d95ada373d1a3ab56def0a125d Reviewed-on: https://gerrit.automotivelinux.org/gerrit/c/AGL/meta-agl/+/26564 Tested-by: Jenkins Job builder account ci-image-build: Jenkins Job builder account ci-image-boot-test: Jenkins Job builder account Reviewed-by: Jan-Simon Moeller <jsmoeller@linuxfoundation.org>
2021-06-21pipewire: update to pw 0.3.30 and wp 0.4.0George Kiagiadakis1-0/+3
* The pipewire recipe has been synced with the upstream yocto one * WirePlumber configuration now has volume ducking enabled for navigation messages. This means that music will now duck when a navigation message plays instead of being corked. * PipeWire's default configuration now lives in /usr/share/pipewire, with the possibility to override it in /etc/pipewire. This allows resetting to upstream defaults by removing /etc/pipewire v2: add licenses to the layer to match the upstream recipe, adapt licenses of sub-packages v3: mark each package with the desired license instead of the mix v4: simplify the license output of the sub-packages Bug-AGL: SPEC-3844 Change-Id: I7a15ddb503d5b064f244c8a42a1aafb4caa1d46a Signed-off-by: George Kiagiadakis <george.kiagiadakis@collabora.com> Signed-off-by: Jan-Simon Moeller <jsmoeller@linuxfoundation.org> Reviewed-on: https://gerrit.automotivelinux.org/gerrit/c/AGL/meta-agl/+/26426 Tested-by: Jenkins Job builder account ci-image-build: Jenkins Job builder account ci-image-boot-test: Jenkins Job builder account
2021-05-12meta-pipewire: add meta-oe dependencyScott Murray1-0/+1
Add LAYERDEPENDS definition to meta-pipewire's layer.conf, meta-oe is now a dependency due to Wireplumber's use of lua. Bug-AGL: SPEC-3909 Signed-off-by: Scott Murray <scott.murray@konsulko.com> Change-Id: Ia57de5b43cca86a5b5260a06494ef43dec6ae675 Reviewed-on: https://gerrit.automotivelinux.org/gerrit/c/AGL/meta-agl/+/26343 Tested-by: Jenkins Job builder account ci-image-build: Jenkins Job builder account ci-image-boot-test: Jenkins Job builder account Reviewed-by: Jan-Simon Moeller <jsmoeller@linuxfoundation.org>
2021-04-26meta-pipewire: update to pipewire 0.3.25 and wireplumber masterGeorge Kiagiadakis1-2/+1
Bug-AGL: SPEC-3844 Change-Id: Ie32bfa43bf078c7d218d3150dc616501b8848bd0 Signed-off-by: George Kiagiadakis <george.kiagiadakis@collabora.com> Reviewed-on: https://gerrit.automotivelinux.org/gerrit/c/AGL/meta-agl/+/26094 Reviewed-by: Jan-Simon Moeller <jsmoeller@linuxfoundation.org> Tested-by: Jan-Simon Moeller <jsmoeller@linuxfoundation.org>
2020-12-17SPEC-3723: restructure meta-aglJan-Simon Moeller1-0/+5
Goal is to reach a minimal meta-agl-core as base for IVI and IC work at the same time. Trim dependencies and move most 'demo' related recipes to meta-agl-demo. v2: changed to bbapend + .inc , added description v3: testbuild of all images v4: restore -test packagegroup and -qa images, compare manifests and adapt packagegroups. v5: rebased v6: merged meta-agl-distro into meta-agl-core, due to dependency on meta-oe, moved -test packagegroup and -qa images to own layer meta-agl-core-test v7: Fixed comments from Paul Barker v8: Update the markdown files v9: restore wayland/weston/agl-compositor recipes/appends, reworked to move app f/w specific changes to bbappends in meta-app-framework and only demo specific weston-init changes to meta-agl-demo v10: fix s/agldemo/aglcore/ missed in weston-init.bbappend Description: This patch is part 1 out of 2 large patches that implement the layer rework discussed during the previous workshop. Essentially meta-agl-core is the small but versatile new core layer of AGL serving as basis for the work done by the IC and IVI EGs. All demo related work is moved to meta-agl-demo in the 2nd patchset. This should be applied together as atomic change. The resulting meta-agl/* follows these guidelines: - only bsp adaptations in meta-agl-bsp - remove the agl-profile-* layers for simplicity -- the packagegroup-agl(-profile)-graphical and so on have been kept in meta-agl-demo - meta-agl-profile-core is now meta-agl-core - meta-agl-core does pass yocto-check-layer -- therefore use the bbappend + conditional + .inc file construct found in meta-virtualization - meta-agl/meta-security has been merged into meta-agl/meta-app-framework - meta-netboot does pass yocto-check-layer - meta-pipewire does pass yocto-check-layer Migration: All packagegroups are preserved but they're now enabled by 'agl-demo'. Bug-AGL: SPEC-3723 Signed-off-by: Jan-Simon Moeller <jsmoeller@linuxfoundation.org> Signed-off-by: Scott Murray <scott.murray@konsulko.com> Change-Id: Ia6c6e5e6ce2b4ffa69ea94959cdc57c310ba7c53 Reviewed-on: https://gerrit.automotivelinux.org/gerrit/c/AGL/meta-agl/+/25769
2020-06-26Move meta-agl-profile-graphical-html5 and meta-pipewire into the main layerJan-Simon Möller2-0/+15
Reasoning: - the profile-graphical-html5 belongs in the main layer - meta-pipewire is enabled by default For reference - the original location is: https://gerrit.automotivelinux.org/gerrit/gitweb?p=AGL%2Fmeta-agl-devel.git;a=commit;h=8479cd0c37e5e5e207a16f21c8646
package model

import (
	"encoding/xml"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/Sirupsen/logrus"
	common "github.com/iotbzh/xds-common/golib"
	"github.com/iotbzh/xds-server/lib/folder"
	"github.com/iotbzh/xds-server/lib/syncthing"
	"github.com/iotbzh/xds-server/lib/xdsconfig"
	"github.com/syncthing/syncthing/lib/sync"
)

// Folders Represent a an XDS folders
type Folders struct {
	fileOnDisk string
	Conf       *xdsconfig.Config
	Log        *logrus.Logger
	SThg       *st.SyncThing
	folders    map[string]*folder.IFOLDER
	registerCB []RegisteredCB
}

type RegisteredCB struct {
	cb   *folder.EventCB
	data *folder.EventCBData
}

// Mutex to make add/delete atomic
var fcMutex = sync.NewMutex()
var ffMutex = sync.NewMutex()

// FoldersNew Create a new instance of Model Folders
func FoldersNew(cfg *xdsconfig.Config, st *st.SyncThing) *Folders {
	file, _ := xdsconfig.FoldersConfigFilenameGet()
	return &Folders{
		fileOnDisk: file,
		Conf:       cfg,
		Log:        cfg.Log,
		SThg:       st,
		folders:    make(map[string]*folder.IFOLDER),
		registerCB: []RegisteredCB{},
	}
}

// LoadConfig Load folders configuration from disk
func (f *Folders) LoadConfig() error {
	var flds []folder.FolderConfig
	var stFlds []folder.FolderConfig

	// load from disk
	if f.Conf.Options.NoFolderConfig {
		f.Log.Infof("Don't read folder config file (-no-folderconfig option is set)")
	} else if f.fileOnDisk != "" {
		f.Log.Infof("Use folder config file: %s", f.fileOnDisk)
		err := foldersConfigRead(f.fileOnDisk, &flds)
		if err != nil {
			if strings.HasPrefix(err.Error(), "No folder config") {
				f.Log.Warnf(err.Error())
			} else {
				return err
			}
		}
	} else {
		f.Log.Warnf("Folders config filename not set")
	}

	// Retrieve initial Syncthing config (just append don't overwrite existing ones)
	if f.SThg != nil {
		f.Log.Infof("Retrieve syncthing folder config")
		if err := f.SThg.FolderLoadFromStConfig(&stFlds); err != nil {
			// Don't exit on such error, just log it
			f.Log.Errorf(err.Error())
		}
	}

	// Merge syncthing folders into XDS folders
	for _, stf := range stFlds {
		found := false
		for i, xf := range flds {
			if xf.ID == stf.ID {
				found = true
				// sanity check
				if xf.Type != folder.TypeCloudSync {
					flds[i].Status = folder.StatusErrorConfig
				}
				break
			}
		}
		// add it
		if !found {
			flds = append(flds, stf)
		}
	}

	// Detect ghost project
	// (IOW existing in xds file config and not in syncthing database)
	for i, xf := range flds {
		// only for syncthing project
		if xf.Type != folder.TypeCloudSync {
			continue
		}
		found := false
		for _, stf := range stFlds {
			if stf.ID == xf.ID {
				found = true
				break
			}
		}
		if !found {
			flds[i].Status = folder.StatusErrorConfig
		}
	}

	// Update folders
	f.Log.Infof("Loading initial folders config: %d folders found", len(flds))
	for _, fc := range flds {
		if _, err := f.createUpdate(fc, false, true); err != nil {
			return err
		}
	}

	// Save config on disk
	err := f.SaveConfig()

	return err
}

// SaveConfig Save folders configuration to disk
func (f *Folders) SaveConfig() error {
	if f.fileOnDisk == "" {
		return fmt.Errorf("Folders config filename not set")
	}

	// FIXME: buffered save or avoid to write on disk each time
	return foldersConfigWrite(f.fileOnDisk, f.getConfigArrUnsafe())
}

// Get returns the folder config or nil if not existing
func (f *Folders) Get(id string) *folder.IFOLDER {
	if id == "" {
		return nil
	}
	fc, exist := f.folders[id]
	if !exist {
		return nil
	}
	return fc
}

// GetConfigArr returns the config of all folders as an array
func (f *Folders) GetConfigArr() []folder.FolderConfig {
	fcMutex.Lock()
	defer fcMutex.Unlock()

	return f.getConfigArrUnsafe()
}

// getConfigArrUnsafe Same as GetConfigArr without mutex protection
func (f *Folders) getConfigArrUnsafe() []folder.FolderConfig {
	var conf []folder.FolderConfig

	for _, v := range f.folders {
		conf = append(conf, (*v).GetConfig())
	}
	return conf
}

// Add adds a new folder
func (f *Folders) Add(newF folder.FolderConfig) (*folder.FolderConfig, error) {
	return f.createUpdate(newF, true, false)
}

// CreateUpdate creates or update a folder
func (f *Folders) createUpdate(newF folder.FolderConfig, create bool, initial bool) (*folder.FolderConfig, error) {

	fcMutex.Lock()
	defer fcMutex.Unlock()

	// Sanity check
	if _, exist := f.folders[newF.ID]; create && exist {
		return nil, fmt.Errorf("ID already exists")
	}
	if newF.ClientPath == "" {
		return nil, fmt.Errorf("ClientPath must be set")
	}

	// Create a new folder object
	var fld folder.IFOLDER
	switch newF.Type {
	// SYNCTHING
	case folder.TypeCloudSync:
		if f.SThg == nil {
			return nil, fmt.Errorf("ClownSync type not supported (syncthing not initialized)")
		}
		fld = f.SThg.NewFolderST(f.Conf)
	// PATH MAP
	case folder.TypePathMap:
		fld = folder.NewFolderPathMap(f.Conf)
	default:
		return nil, fmt.Errorf("Unsupported folder type")
	}

	// Set default value if needed
	if newF.Status == "" {
		newF.Status = folder.StatusDisable
	}
	if newF.Label == "" {
		newF.Label = filepath.Base(newF.ClientPath) + "_" + newF.ID[0:8]
	}

	// Allocate a new UUID
	if create {
		i := len(newF.Label)
		if i > 20 {
			i = 20
		}
		newF.ID = fld.NewUID(newF.Label[:i])
	}
	if !create && newF.ID == "" {
		return nil, fmt.Errorf("Cannot update folder with null ID")
	}

	// Normalize path (needed for Windows path including bashlashes)
	newF.ClientPath = common.PathNormalize(newF.ClientPath)

	// Add new folder
	newFolder, err := fld.Add(newF)
	if err != nil {
		newF.Status = folder.StatusErrorConfig
		log.Printf("ERROR Adding folder: %v\n", err)
		return newFolder, err
	}

	// Add to folders list
	f.folders[newF.ID] = &fld

	// Save config on disk
	if !initial {
		if err := f.SaveConfig(); err != nil {
			return newFolder, err
		}
	}

	// Register event change callback
	for _, rcb := range f.registerCB {
		if err := fld.RegisterEventChange(rcb.cb, rcb.data); err != nil {
			return newFolder, err
		}
	}

	// Force sync after creation
	// (need to defer to be sure that WS events will arrive after HTTP creation reply)
	go func() {
		time.Sleep(time.Millisecond * 500)
		fld.Sync()
	}()

	return newFolder, nil
}

// Delete deletes a specific folder
func (f *Folders) Delete(id string) (folder.FolderConfig, error) {
	var err error

	fcMutex.Lock()
	defer fcMutex.Unlock()

	fld := folder.FolderConfig{}
	fc, exist := f.folders[id]
	if !exist {
		return fld, fmt.Errorf("unknown id")
	}

	fld = (*fc).GetConfig()

	if err = (*fc).Remove(); err != nil {
		return fld, err
	}

	delete(f.folders, id)

	// Save config on disk
	err = f.SaveConfig()

	return fld, err
}

// RegisterEventChange requests registration for folder event change
func (f *Folders) RegisterEventChange(id string, cb *folder.EventCB, data *folder.EventCBData) error {

	flds := make(map[string]*folder.IFOLDER)
	if id != "" {
		// Register to a specific folder
		flds[id] = f.Get(id)
	} else {
		// Register to all folders
		flds = f.folders
		f.registerCB = append(f.registerCB, RegisteredCB{cb: cb, data: data})
	}

	for _, fld := range flds {
		err := (*fld).RegisterEventChange(cb, data)
		if err != nil {
			return err
		}
	}

	return nil
}

// ForceSync Force the synchronization of a folder
func (f *Folders) ForceSync(id string) error {
	fc := f.Get(id)
	if fc == nil {
		return fmt.Errorf("Unknown id")
	}
	return (*fc).Sync()
}

// IsFolderInSync Returns true when folder is in sync
func (f *Folders) IsFolderInSync(id string) (bool, error) {
	fc := f.Get(id)
	if fc == nil {
		return false, fmt.Errorf("Unknown id")
	}
	return (*fc).IsInSync()
}

//*** Private functions ***

// Use XML format and not json to be able to save/load all fields including
// ones that are masked in json (IOW defined with `json:"-"`)
type xmlFolders struct {
	XMLName xml.Name              `xml:"folders"`
	Version string                `xml:"version,attr"`
	Folders []folder.FolderConfig `xml:"folders"`
}

// foldersConfigRead reads folders config from disk
func foldersConfigRead(file string, folders *[]folder.FolderConfig) error {
	if !common.Exists(file) {
		return fmt.Errorf("No folder config file found (%s)", file)
	}

	ffMutex.Lock()
	defer ffMutex.Unlock()

	fd, err := os.Open(file)
	defer fd.Close()
	if err != nil {
		return err
	}

	data := xmlFolders{}
	err = xml.NewDecoder(fd).Decode(&data)
	if err == nil {
		*folders = data.Folders
	}
	return err
}

// foldersConfigWrite writes folders config on disk
func foldersConfigWrite(file string, folders []folder.FolderConfig) error {
	ffMutex.Lock()
	defer ffMutex.Unlock()

	fd, err := os.OpenFile(file, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
	defer fd.Close()
	if err != nil {
		return err
	}

	data := &xmlFolders{
		Version: "1",
		Folders: folders,
	}

	enc := xml.NewEncoder(fd)
	enc.Indent("", "  ")
	return enc.Encode(data)
}