From 9fc7355d05996983ef4e4c753e30d5167c86d732 Mon Sep 17 00:00:00 2001 From: Christian Meffert Date: Thu, 3 Oct 2024 07:56:32 +0200 Subject: [PATCH] [dev] Add devcontainers and vscode config templates --- .clang-format | 245 +++++++++ .dev/Makefile | 7 + .../.scripts/init-devcontainer-cli.sh | 20 + .../.scripts/install-devcontainer-tools.sh | 26 + .../data/devcontainer-owntone.conf | 479 ++++++++++++++++++ .dev/devcontainer/devcontainer.env | 11 + .dev/devcontainer/ubuntu/Dockerfile | 74 +++ .dev/devcontainer/ubuntu/devcontainer.json | 55 ++ .dev/vscode/c_cpp_properties.json | 17 + .dev/vscode/launch.json | 28 + .dev/vscode/settings.json | 12 + .dev/vscode/tasks.json | 106 ++++ .gitignore | 6 +- web-src/package.json | 2 +- 14 files changed, 1086 insertions(+), 2 deletions(-) create mode 100644 .clang-format create mode 100644 .dev/Makefile create mode 100755 .dev/devcontainer/.scripts/init-devcontainer-cli.sh create mode 100755 .dev/devcontainer/.scripts/install-devcontainer-tools.sh create mode 100644 .dev/devcontainer/data/devcontainer-owntone.conf create mode 100644 .dev/devcontainer/devcontainer.env create mode 100644 .dev/devcontainer/ubuntu/Dockerfile create mode 100644 .dev/devcontainer/ubuntu/devcontainer.json create mode 100644 .dev/vscode/c_cpp_properties.json create mode 100644 .dev/vscode/launch.json create mode 100644 .dev/vscode/settings.json create mode 100644 .dev/vscode/tasks.json diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000000..6675e72bd5 --- /dev/null +++ b/.clang-format @@ -0,0 +1,245 @@ +--- +Language: Cpp +AccessModifierOffset: -2 +AlignAfterOpenBracket: DontAlign +AlignArrayOfStructures: Left +AlignConsecutiveAssignments: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionPointers: false + PadOperators: true +AlignConsecutiveBitFields: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveDeclarations: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveMacros: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveShortCaseStatements: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCaseColons: false +AlignEscapedNewlines: Right +AlignOperands: Align +AlignTrailingComments: + Kind: Always + OverEmptyLines: 0 +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowBreakBeforeNoexceptSpecifier: Never +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortCompoundRequirementOnASingleLine: true +AllowShortEnumsOnASingleLine: true +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: All +AlwaysBreakAfterReturnType: All +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: MultiLine +AttributeMacros: + - __capability +BinPackArguments: true +BinPackParameters: true +BitFieldColonSpacing: Both +BraceWrapping: + AfterCaseLabel: true + AfterClass: true + AfterControlStatement: Always + AfterEnum: false + AfterExternBlock: true + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: true + AfterStruct: false + AfterUnion: true + BeforeCatch: true + BeforeElse: true + BeforeLambdaBody: false + BeforeWhile: true + IndentBraces: true + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakAdjacentStringLiterals: true +BreakAfterAttributes: Leave +BreakAfterJavaFieldAnnotations: false +BreakArrays: true +BreakBeforeBinaryOperators: All +BreakBeforeConceptDeclarations: Always +BreakBeforeBraces: Custom +BreakBeforeInlineASMColon: OnlyMultiline +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeColon +BreakInheritanceList: BeforeColon +BreakStringLiterals: true +ColumnLimit: 120 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: false +DerivePointerAlignment: false +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: false +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 1 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' +IndentAccessModifiers: false +IndentCaseBlocks: false +IndentCaseLabels: false +IndentExternBlock: AfterExternBlock +IndentGotoLabels: true +IndentPPDirectives: None +IndentRequiresClause: true +IndentWidth: 2 +IndentWrappedFunctionNames: false +InsertBraces: false +InsertNewlineAtEOF: false +InsertTrailingCommas: None +IntegerLiteralSeparator: + Binary: 0 + BinaryMinDigits: 0 + Decimal: 0 + DecimalMinDigits: 0 + Hex: 0 + HexMinDigits: 0 +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +KeepEmptyLinesAtEOF: false +LambdaBodyIndentation: Signature +LineEnding: DeriveLF +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PackConstructorInitializers: BinPack +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakScopeResolution: 500 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyIndentedWhitespace: 0 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Right +PPIndentWidth: -1 +QualifierAlignment: Leave +ReferenceAlignment: Pointer +ReflowComments: true +RemoveBracesLLVM: false +RemoveParentheses: Leave +RemoveSemicolon: false +RequiresClausePosition: OwnLine +RequiresExpressionIndentation: OuterScope +SeparateDefinitionBlocks: Leave +ShortNamespaceLines: 1 +SkipMacroDefinitionBody: false +SortIncludes: CaseSensitive +SortJavaStaticImport: Before +SortUsingDeclarations: LexicographicNumeric +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceAroundPointerQualifiers: Default +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeJsonColon: false +SpaceBeforeParens: ControlStatements +SpaceBeforeParensOptions: + AfterControlStatements: false + AfterForeachMacros: false + AfterFunctionDefinitionName: false + AfterFunctionDeclarationName: false + AfterIfMacros: false + AfterOverloadedOperator: false + AfterPlacementOperator: true + AfterRequiresInClause: false + AfterRequiresInExpression: false + BeforeNonEmptyParentheses: false +SpaceBeforeRangeBasedForLoopColon: true +SpaceBeforeSquareBrackets: false +SpaceInEmptyBlock: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: Never +SpacesInContainerLiterals: true +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParens: Never +SpacesInParensOptions: + InCStyleCasts: false + InConditionalStatements: false + InEmptyParentheses: false + Other: false +SpacesInSquareBrackets: false +Standard: c++03 +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 8 +UseTab: ForIndentation +VerilogBreakBetweenInstancePorts: true +WhitespaceSensitiveMacros: + - BOOST_PP_STRINGIZE + - CF_SWIFT_NAME + - NS_SWIFT_NAME + - PP_STRINGIZE + - STRINGIZE +... + diff --git a/.dev/Makefile b/.dev/Makefile new file mode 100644 index 0000000000..050c7c823d --- /dev/null +++ b/.dev/Makefile @@ -0,0 +1,7 @@ +.PHONY: vscode + +vscode: + mkdir -p ../.vscode + cp -rT ./vscode ../.vscode + mkdir -p ../.devcontainer + cp -rT ./devcontainer ../.devcontainer diff --git a/.dev/devcontainer/.scripts/init-devcontainer-cli.sh b/.dev/devcontainer/.scripts/init-devcontainer-cli.sh new file mode 100755 index 0000000000..0e17335b05 --- /dev/null +++ b/.dev/devcontainer/.scripts/init-devcontainer-cli.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env sh + +# cd aliases +alias ..='cd ..' +alias ...='cd ../..' +alias -- -='cd -' + +# bat aliases +alias bat='batcat' + +if [ "$ENABLE_ESA" = "1" ]; then + if [ "$(command -v eza)" ]; then + alias l='eza -la --icons=auto --group-directories-first' + alias la='eza -la --icons=auto --group-directories-first' + alias ll='eza -l --icons=auto --group-directories-first' + alias l.='eza -d .*' + alias ls='eza' + alias l1='eza -1' + fi +fi diff --git a/.dev/devcontainer/.scripts/install-devcontainer-tools.sh b/.dev/devcontainer/.scripts/install-devcontainer-tools.sh new file mode 100755 index 0000000000..38486e8f7b --- /dev/null +++ b/.dev/devcontainer/.scripts/install-devcontainer-tools.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +# Install mkdocs with mkdocs-material theme +#pipx install --include-deps mkdocs-material +#pipx inject mkdocs-material mkdocs-minify-plugin + +# Starfish (https://starship.rs/) - shell prompt +if [ "$ENABLE_STARSHIP" = "1" ] +then + curl -sS https://starship.rs/install.sh | sh -s -- -y + echo 'eval "$(starship init bash)"' >> ~/.bashrc +fi + +# Atuin (https://atuin.sh/) - shell history +if [ "$ENABLE_ATUIN" = "1" ] +then + curl --proto '=https' --tlsv1.2 -LsSf https://setup.atuin.sh | sh + curl https://raw.githubusercontent.com/rcaloras/bash-preexec/master/bash-preexec.sh -o ~/.bash-preexec.sh +fi + +# zoxide (https://github.com/ajeetdsouza/zoxide) - replacement for cd +if [ "$ENABLE_ZOXIDE" = "1" ] +then + curl -sSfL https://raw.githubusercontent.com/ajeetdsouza/zoxide/main/install.sh | sh + echo 'eval "$(zoxide init bash)"' >> ~/.bashrc +fi diff --git a/.dev/devcontainer/data/devcontainer-owntone.conf b/.dev/devcontainer/data/devcontainer-owntone.conf new file mode 100644 index 0000000000..14ba96c057 --- /dev/null +++ b/.dev/devcontainer/data/devcontainer-owntone.conf @@ -0,0 +1,479 @@ +# A quick guide to configuring OwnTone: +# +# For regular use, the most important setting to configure is "directories", +# which should be the location of your media. Whatever user you have set as +# "uid" must have read access to this location. If the location is a network +# mount, please see the README. +# +# In all likelihood, that's all you need to do! + +general { + # Username + # Make sure the user has read access to the library directories you set + # below, and full access to the databases, log and local audio + uid = "vscode" + + # Database location + db_path = "/data/cache/songs3.db" + + # Database backup location + # Uncomment and specify a full path to enable abilty to use REST endpoint + # to initiate backup of songs3.db +# db_backup_path = "/usr/local/var/cache/owntone/songs3.bak" + + # Log file and level + # Available levels: fatal, log, warning, info, debug, spam + logfile = "/data/logs/owntone.log" + loglevel = debug + + # Admin password for the web interface + # Note that access to the web interface from computers in + # "trusted_network" (see below) does not require password +# admin_password = "" + + # Websocket port for the web interface. + websocket_port = 0 + + # Websocket interface to bind listener to (e.g. "eth0"). Default is + # disabled, which means listen on all interfaces. +# websocket_interface = "" + + # Sets who is allowed to connect without authorisation. This applies to + # client types like Remotes, DAAP clients (iTunes) and to the web + # interface. Options are "any", "localhost" or the prefix to one or + # more ipv4/6 networks. The default is { "localhost", "192.168", "fd" } +# trusted_networks = { "localhost", "192.168", "fd" } + + # Enable/disable IPv6 +# ipv6 = no + + # Set this if you want the server to bind to a specific IP address. Can + # be ipv6 or ipv4. Default (commented out or "::") is to listen on all + # IP addresses. +# bind_address = "::" + + # Location of cache database + cache_path = "/data/cache/cache.db" + + # DAAP requests that take longer than this threshold (in msec) get their + # replies cached for next time. Set to 0 to disable caching. +# cache_daap_threshold = 1000 + + # When starting playback, autoselect speaker (if none of the previously + # selected speakers/outputs are available) +# speaker_autoselect = no + + # Most modern systems have a high-resolution clock, but if you are on an + # unusual platform and experience audio drop-outs, you can try changing + # this option +# high_resolution_clock = yes +} + +# Library configuration +library { + # Name of the library as displayed by the clients (%h: hostname). If you + # change the name after pairing with Remote you may have to re-pair. + name = "My Music on %h" + + # TCP port to listen on. Default port is 3689 (daap) + port = 3689 + + # Password for the library. Optional. +# password = "" + + # Directories to index + directories = { "/data/music" } + + # Follow symlinks. Default: true. +# follow_symlinks = true + + # Directories containing podcasts + # For each directory that is indexed the path is matched against these + # names. If there is a match all items in the directory are marked as + # podcasts. Eg. if you index /srv/music, and your podcasts are in + # /srv/music/Podcasts, you can set this to "/Podcasts". + # (changing this setting only takes effect after rescan, see the README) + podcasts = { "/Podcasts" } + + # Directories containing audiobooks + # For each directory that is indexed the path is matched against these + # names. If there is a match all items in the directory are marked as + # audiobooks. + # (changing this setting only takes effect after rescan, see the README) + audiobooks = { "/Audiobooks" } + + # Directories containing compilations (eg soundtracks) + # For each directory that is indexed the path is matched against these + # names. If there is a match all items in the directory are marked as + # compilations. + # (changing this setting only takes effect after rescan, see the README) + compilations = { "/Compilations" } + + # Compilations usually have many artists, and sometimes no album artist. + # If you don't want every artist to be listed in artist views, you can + # set a single name which will be used for all compilation tracks + # without an album artist, and for all tracks in the compilation + # directories. + # (changing this setting only takes effect after rescan, see the README) + compilation_artist = "Various Artists" + + # If your album and artist lists are cluttered, you can choose to hide + # albums and artists with only one track. The tracks will still be + # visible in other lists, e.g. songs and playlists. This setting + # currently only works in some remotes. +# hide_singles = false + + # Internet streams in your playlists will by default be shown in the + # "Radio" library, like iTunes does. However, some clients (like + # TunesRemote+) won't show the "Radio" library. If you would also like + # to have them shown like normal playlists, you can enable this option. +# radio_playlists = false + + # These are the default playlists. If you want them to have other names, + # you can set it here. +# name_library = "Library" +# name_music = "Music" +# name_movies = "Movies" +# name_tvshows = "TV Shows" +# name_podcasts = "Podcasts" +# name_audiobooks = "Audiobooks" +# name_radio = "Radio" + + # Artwork file names (without file type extension) + # OwnTone will look for jpg and png files with these base names +# artwork_basenames = { "artwork", "cover", "Folder" } + + # Enable searching for artwork corresponding to each individual media + # file instead of only looking for album artwork. This is disabled by + # default to reduce cache size. +# artwork_individual = false + + # File types the scanner should ignore + # Non-audio files will never be added to the database, but here you + # can prevent the scanner from even probing them. This might improve + # scan time. By default .db, .ini, .db-journal, .pdf and .metadata are + # ignored. +# filetypes_ignore = { ".db", ".ini", ".db-journal", ".pdf", ".metadata" } + + # File paths the scanner should ignore + # If you want to exclude files on a more advanced basis you can enter + # one or more POSIX regular expressions, and any file with a matching + # path will be ignored. +# filepath_ignore = { "myregex" } + + # Disable startup file scanning + # When OwnTone starts it will do an initial file scan of your + # library (and then watch it for changes). If you are sure your library + # never changes while OwnTone is not running, you can disable the + # initial file scan and save some system ressources. Disabling this scan + # may lead to OwnTone's database coming out of sync with the + # library. If that happens read the instructions in the README on how + # to trigger a rescan. +# filescan_disable = false + + # Only use the first genre found in metadata + # Some tracks have multiple genres semicolon-separated in the same tag, + # e.g. 'Pop;Rock'. If you don't want them listed like this, you can + # enable this option and only the first genre will be used (i.e. 'Pop'). +# only_first_genre = false + + # Should metadata from m3u playlists, e.g. artist and title in EXTINF, + # override the metadata we get from radio streams? +# m3u_overrides = false + + # Should iTunes metadata override ours? +# itunes_overrides = false + + # Should we import the content of iTunes smart playlists? +# itunes_smartpl = false + + # Decoding options for DAAP and RSP clients + # Since iTunes has native support for mpeg, mp4a, mp4v, alac and wav, + # such files will be sent as they are. Any other formats will be decoded + # to raw wav. If OwnTone detects a non-iTunes DAAP client, it is + # assumed to only support mpeg and wav, other formats will be decoded. + # Here you can change when to decode. Note that these settings only + # affect serving media to DAAP and RSP clients, they have no effect on + # direct AirPlay, Chromecast and local audio playback. + # Formats: mp4a, mp4v, mpeg, alac, flac, mpc, ogg, wma, wmal, wmav, aif, wav + # Formats that should never be decoded +# no_decode = { "format", "format" } + # Formats that should always be decoded +# force_decode = { "format", "format" } + + # Set ffmpeg filters (similar to 'ffmpeg -af xxx') that you want the + # server to use when decoding files from your library. Examples: + # { 'volume=replaygain=track' } -> use REPLAYGAIN_TRACK_GAIN metadata + # { 'loudnorm=I=-16:LRA=11:TP=-1.5' } -> normalize volume +# decode_audio_filters = { } + + # Watch named pipes in the library for data and autostart playback when + # there is data to be read. To exclude specific pipes from watching, + # consider using the above _ignore options. +# pipe_autostart = true + + # Enable automatic rating updates + # If enabled, rating is automatically updated after a song has either been + # played or skipped (only skipping to the next song is taken into account). + # The calculation is taken from the beets plugin "mpdstats" (see + # https://beets.readthedocs.io/en/latest/plugins/mpdstats.html). + # It consist of calculating a stable rating based only on the play- and + # skipcount and a rolling rating based on the current rating and the action + # (played or skipped). Both results are combined with a mix-factor of 0.75: + # new rating = 0.75 * stable rating + 0.25 * rolling rating) +# rating_updates = false + + # By default, ratings are only saved in the server's database. Enable + # the below to make the server also read ratings from file metadata and + # write on update (requires write access). To avoid excessive writing to + # the library, automatic rating updates are not written, even with the + # write_rating option enabled. +# read_rating = false +# write_rating = false + # The scale used when reading/writing ratings to files +# max_rating = 100 + + # Allows creating, deleting and modifying m3u playlists in the library directories. + # Only supported by the player web interface and some mpd clients + # Defaults to being disabled. +# allow_modifying_stored_playlists = false + + # A directory in one of the library directories that will be used as the default + # playlist directory. OwnTone creates new playlists in this directory if only + # a playlist name is provided (requires "allow_modify_stored_playlists" set to true). +# default_playlist_directory = "" + + # By default OwnTone will - like iTunes - clear the playqueue if + # playback stops. Setting clear_queue_on_stop_disable to true will keep + # the playlist like MPD does. Note that some dacp clients do not show + # the playqueue if playback is stopped. +# clear_queue_on_stop_disable = false +} + +# Local audio output +audio { + # Name - used in the speaker list in Remote + nickname = "Computer" + + # Type of the output (alsa, pulseaudio, dummy or disabled) +# type = "alsa" + + # For pulseaudio output, an optional server hostname or IP can be + # specified (e.g. "localhost"). If not set, connection is made via local + # socket. +# server = "" + + # Audio PCM device name for local audio output - ALSA only +# card = "default" + + # Mixer channel to use for volume control - ALSA only + # If not set, PCM will be used if available, otherwise Master. +# mixer = "" + + # Mixer device to use for volume control - ALSA only + # If not set, the value for "card" will be used. +# mixer_device = "" + + # Enable or disable audio resampling to keep local audio in sync with + # e.g. Airplay. This feature relies on accurate ALSA measurements of + # delay, and some devices don't provide that. If that is the case you + # are better off disabling the feature. +# sync_disable = false + + # Here you can adjust when local audio is started relative to other + # speakers, e.g. Airplay. Negative values correspond to moving local + # audio ahead, positive correspond to delaying it. The unit is + # milliseconds. The offset must be between -1000 and 1000 (+/- 1 sec). +# offset_ms = 0 + + # To calculate what and if resampling is required, local audio delay is + # measured each second. After a period the collected measurements are + # used to estimate drift and latency, which determines if corrections + # are required. This setting sets the length of that period in seconds. +# adjust_period_seconds = 100 +} + +# ALSA device settings +# If you have multiple ALSA devices you can configure them individually via +# sections like the below. Make sure to set the "card name" correctly. See the +# README about ALSA for details. Note that these settings will override the ALSA +# settings in the "audio" section above. +#alsa "card name" { + # Name used in the speaker list. If not set, the card name will be used. +# nickname = "Computer" + + # Mixer channel to use for volume control + # If not set, PCM will be used if available, otherwise Master +# mixer = "" + + # Mixer device to use for volume control + # If not set, the card name will be used +# mixer_device = "" +#} + +# Pipe output +# Allows OwnTone to output audio data to a named pipe +#fifo { +# nickname = "fifo" +# path = "/path/to/fifo" +#} + +# AirPlay settings common to all devices +#airplay_shared { + # UDP ports used when airplay devices make connections back to + # OwnTone (choosing specific ports may be helpful when running + # OwnTone behind a firewall) +# control_port = 0 +# timing_port = 0 + + # Switch Airplay 1 streams to uncompressed ALAC (as opposed to regular, + # compressed ALAC). Reduces CPU use at the cost of network bandwidth. +# uncompressed_alac = false +#} + +# AirPlay per device settings +# (make sure you get the capitalization of the device name right) +#airplay "My AirPlay device" { + # OwnTone's volume goes to 11! If that's more than you can handle + # you can set a lower value here +# max_volume = 11 + + # Enable this option to exclude a particular AirPlay device from the + # speaker list +# exclude = false + + # Enable this option to keep a particular AirPlay device in the speaker + # list and thus ignore mdns notifications about it no longer being + # present. The speaker will remain until restart of OwnTone. +# permanent = false + + # Some devices spuriously disconnect during playback, and based on the + # device type OwnTone may attempt to reconnect. Setting this option + # overrides this so reconnecting is either always enabled or disabled. +# reconnect = false + + # AirPlay password +# password = "s1kr3t" + + # Disable AirPlay 1 (RAOP) +# raop_disable = false + + # Name used in the speaker list, overrides name from the device +# nickname = "My speaker name" +#} + +# Chromecast settings +# (make sure you get the capitalization of the device name right) +#chromecast "My Chromecast device" { + # OwnTone's volume goes to 11! If that's more than you can handle + # you can set a lower value here +# max_volume = 11 + + # Enable this option to exclude a particular device from the speaker + # list +# exclude = false + + # Name used in the speaker list, overrides name from the device +# nickname = "My speaker name" +#} + +# Spotify settings (only have effect if Spotify enabled - see README/INSTALL) +spotify { + # Set preferred bitrate for music streaming + # 0: No preference (default), 1: 96kbps, 2: 160kbps, 3: 320kbps +# bitrate = 0 + + # Your Spotify playlists will by default be put in a "Spotify" playlist + # folder. If you would rather have them together with your other + # playlists you can set this option to true. +# base_playlist_disable = false + + # Spotify playlists usually have many artist, and if you don't want + # every artist to be listed when artist browsing in Remote, you can set + # the artist_override flag to true. This will use the compilation_artist + # as album artist for Spotify items. +# artist_override = false + + # Similar to the different artists in Spotify playlists, the playlist + # items belong to different albums, and if you do not want every album + # to be listed when browsing in Remote, you can set the album_override + # flag to true. This will use the playlist name as album name for + # Spotify items. Notice that if an item is in more than one playlist, + # it will only appear in one album when browsing (in which album is + # random). +# album_override = false +} + +# RCP/Roku Soundbridge output settings +# (make sure you get the capitalization of the device name right) +#rcp "My SoundBridge device" { + # Enable this option to exclude a particular device from the speaker + # list +# exclude = false + + # A Roku/SoundBridge can power up in 2 modes: (default) reconnect to the + # previously used library (ie OwnTone) or in a 'cleared library' mode. + # The Roku power up behaviour is affected by how OwnTone disconnects + # from the Roku device. + # + # Set to false to maintain default Roku power on behaviour +# clear_on_close = false +#} + + +# MPD configuration (only have effect if MPD enabled - see README/INSTALL) +mpd { + # TCP port to listen on for MPD client requests. + # Default port is 6600, set to 0 to disable MPD support. +# port = 6600 + + # HTTP port to listen for artwork requests (only supported by some MPD + # clients and will need additional configuration in the MPD client to + # work). Set to 0 to disable serving artwork over http. +# http_port = 0 +} + +# SQLite configuration (allows to modify the operation of the SQLite databases) +# Make sure to read the SQLite documentation for the corresponding PRAGMA +# statements as changing them from the defaults may increase the possibility of +# database corruptions! By default the SQLite default values are used. +sqlite { + # Cache size in number of db pages for the library database + # (SQLite default page size is 1024 bytes and cache size is 2000 pages) +# pragma_cache_size_library = 2000 + + # Cache size in number of db pages for the daap cache database + # (SQLite default page size is 1024 bytes and cache size is 2000 pages) +# pragma_cache_size_cache = 2000 + + # Sets the journal mode for the database + # DELETE (default), TRUNCATE, PERSIST, MEMORY, WAL, OFF +# pragma_journal_mode = DELETE + + # Change the setting of the "synchronous" flag + # 0: OFF, 1: NORMAL, 2: FULL (default) +# pragma_synchronous = 2 + + # Number of bytes set aside for memory-mapped I/O for the library database + # (requires sqlite 3.7.17 or later) + # 0: disables mmap (default), any other value > 0: number of bytes for mmap +# pragma_mmap_size_library = 0 + + # Number of bytes set aside for memory-mapped I/O for the cache database + # (requires sqlite 3.7.17 or later) + # 0: disables mmap (default), any other value > 0: number of bytes for mmap +# pragma_mmap_size_cache = 0 + + # Should the database be vacuumed on startup? (increases startup time, + # but may reduce database size). Default is yes. +# vacuum = yes +} + +# Streaming audio settings for remote connections (ie stream.mp3) +streaming { + # Sample rate, typically 44100 or 48000 +# sample_rate = 44100 + + # Set the MP3 streaming bit rate (in kbps), valid options: 64 / 96 / 128 / 192 / 320 +# bit_rate = 192 +} diff --git a/.dev/devcontainer/devcontainer.env b/.dev/devcontainer/devcontainer.env new file mode 100644 index 0000000000..715c87b9d5 --- /dev/null +++ b/.dev/devcontainer/devcontainer.env @@ -0,0 +1,11 @@ +# Starfish (https://starship.rs/) - shell prompt +ENABLE_STARSHIP=1 + +# Atuin (https://atuin.sh/) - shell history +ENABLE_ATUIN=1 + +# zoxide (https://github.com/ajeetdsouza/zoxide) - replacement for cd +ENABLE_ZOXIDE=1 + +# eza (https://eza.rocks/) - replacement for ls +ENABLE_ESA=1 diff --git a/.dev/devcontainer/ubuntu/Dockerfile b/.dev/devcontainer/ubuntu/Dockerfile new file mode 100644 index 0000000000..e65ea5bbad --- /dev/null +++ b/.dev/devcontainer/ubuntu/Dockerfile @@ -0,0 +1,74 @@ +FROM mcr.microsoft.com/devcontainers/base:ubuntu-24.04 + +ARG USERNAME=vscode + +# Workaround for bug: https://github.com/devcontainers/images/issues/1056 +RUN userdel -r ubuntu; usermod -u 1000 $USERNAME; groupmod -g 1000 $USERNAME + +RUN apt-get -y update \ + && apt-get install -y \ + # Build tools and dependencies for OwnTone + autoconf \ + automake \ + autotools-dev \ + bison \ + build-essential \ + flex \ + gawk \ + gettext \ + git \ + gperf \ + libasound2-dev \ + libavahi-client-dev \ + libavcodec-dev \ + libavfilter-dev \ + libavformat-dev \ + libavutil-dev \ + libconfuse-dev \ + libcurl4-openssl-dev \ + libevent-dev \ + libgcrypt20-dev \ + libjson-c-dev \ + libmxml-dev \ + libplist-dev \ + libprotobuf-c-dev \ + libsodium-dev \ + libsqlite3-dev \ + libswscale-dev \ + libtool \ + libunistring-dev \ + libwebsockets-dev \ + libxml2-dev \ + zlib1g-dev \ + # Build tools for mmkdocs (OwnTone documentation) + python3-pip \ + # Additional runtime dependencies for dev container + avahi-daemon \ + # Additional debug and devtools for dev container + clang \ + clang-format \ + clang-tools \ + gdb \ + valgrind \ + # Additional terminal utility applications + # bat - replacement for cat + bat \ + # eza (https://eza.rocks/) - replacement for ls + eza \ + # fuzzy search + fzf \ + # Build tools for mmkdocs (OwnTone documentation) + && pip3 install --break-system-packages mkdocs-material mkdocs-minify-plugin \ + # Create folders and set ownership for folders that might be mounted as volumes + && mkdir -p /home/$USERNAME/.local/share \ + && chown -R $USERNAME /home/$USERNAME/.local \ + && mkdir /commandhistory \ + && touch /commandhistory/.bash_history \ + && chown -R $USERNAME /commandhistory \ + && echo "export PROMPT_COMMAND='history -a' && export HISTFILE=/commandhistory/.bash_history" >> "/home/$USERNAME/.bashrc" \ + && echo '[[ -f /scripts/init-devcontainer-cli.sh ]] && source /scripts/init-devcontainer-cli.sh' >> "/home/$USERNAME/.bashrc" \ + # Create folders for owntone-server data + && mkdir -p /data/logs /data/music /data/cache /data/conf \ + && chown -R $USERNAME /data \ + # Clean up + && apt-get clean -y && rm -rf /var/lib/apt/lists/* diff --git a/.dev/devcontainer/ubuntu/devcontainer.json b/.dev/devcontainer/ubuntu/devcontainer.json new file mode 100644 index 0000000000..6f5c6babf6 --- /dev/null +++ b/.dev/devcontainer/ubuntu/devcontainer.json @@ -0,0 +1,55 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/ubuntu +{ + "name": "Ubuntu", + // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile + // "image": "mcr.microsoft.com/devcontainers/base:jammy" + "build": { + "dockerfile": "Dockerfile" + }, + + "runArgs": [ + // Use host network to be able to connect to remote speakers + "--network=host", + "--env-file", ".devcontainer/devcontainer.env" + ], + + // Configure tool-specific properties. + "customizations": { + "vscode": { + "extensions": [ + "Vue.volar", + "ms-vscode.cpptools-extension-pack", + "ms-azuretools.vscode-docker", + "lokalise.i18n-ally", + "esbenp.prettier-vscode" + ] + } + }, + + // Features to add to the dev container. More info: https://containers.dev/features. + "features": { + "ghcr.io/devcontainers/features/node:1": {} + }, + + // Mounts volumes to keep files / state between container rebuilds + "mounts": [ + // Map script folder to install and init additional tools (see "postCreateCommand" and Dockerfile / .bashrc) + "source=${localWorkspaceFolder}/.devcontainer/.scripts,target=/scripts,type=bind,consistency=cached", + // Persist ~/.bash_history + "source=owntone-bashhistory,target=/commandhistory,type=volume", + // Persist ~/.local/share to persist state of additionally installed tools (e. g. atuin, zoxide) + "source=owntone-localshare,target=/home/vscode/.local/share,type=volume", + // Bind mounts for owntone config file and logs, cache, music directories + //"source=,target=/data/logs,type=bind,consistency=cached", + //"source=,target=/data/cache,type=bind,consistency=cached", + //"source=,target=/data/music,type=bind,consistency=cached", + "source=${localWorkspaceFolder}/.devcontainer/data/devcontainer-owntone.conf,target=/data/conf/owntone.conf,type=bind,consistency=cached" + ], + + // Use 'postCreateCommand' to run commands after the container is created. + "postCreateCommand": "bash /scripts/install-devcontainer-tools.sh", + + // Start dbus and avahi, required when running owntone-server + "postStartCommand": "sudo service dbus start ; sudo avahi-daemon -D" +} diff --git a/.dev/vscode/c_cpp_properties.json b/.dev/vscode/c_cpp_properties.json new file mode 100644 index 0000000000..8c4dc691fe --- /dev/null +++ b/.dev/vscode/c_cpp_properties.json @@ -0,0 +1,17 @@ +{ + "configurations": [ + { + "name": "Linux", + "includePath": [ + "${workspaceFolder}/**", + "/usr/include/json-c" + ], + "defines": [], + "compilerPath": "/usr/bin/clang", + "cStandard": "c17", + "cppStandard": "c++17", + "intelliSenseMode": "linux-clang-x64" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.dev/vscode/launch.json b/.dev/vscode/launch.json new file mode 100644 index 0000000000..16d728c187 --- /dev/null +++ b/.dev/vscode/launch.json @@ -0,0 +1,28 @@ +{ + "configurations": [ + { + "name": "OwnTone", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/src/owntone", + "args": ["-f", "-c", "/data/conf/owntone.conf", "-w", "${workspaceFolder}/htdocs", "-s", "${workspaceFolder}/sqlext/.libs/owntone-sqlext.so"], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + }, + { + "description": "Set Disassembly Flavor to Intel", + "text": "-gdb-set disassembly-flavor intel", + "ignoreFailures": true + } + ] + } + ], + "version": "2.0.0" +} \ No newline at end of file diff --git a/.dev/vscode/settings.json b/.dev/vscode/settings.json new file mode 100644 index 0000000000..0510f4c388 --- /dev/null +++ b/.dev/vscode/settings.json @@ -0,0 +1,12 @@ +{ + "C_Cpp.default.forcedInclude": [ + "${workspaceFolder}/config.h" + ], + "[vue]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[c]": { + "editor.detectIndentation": false, + "editor.tabSize": 8 + } +} \ No newline at end of file diff --git a/.dev/vscode/tasks.json b/.dev/vscode/tasks.json new file mode 100644 index 0000000000..ca436ddcc2 --- /dev/null +++ b/.dev/vscode/tasks.json @@ -0,0 +1,106 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "[owntone-server] autoreconf", + "type": "shell", + "command": "autoreconf -i", + "group": { + "kind": "build", + "isDefault": false + } + }, + { + "label": "[owntone-server] configure", + "type": "shell", + "command": "./configure", + "group": { + "kind": "build", + "isDefault": false + } + }, + { + "label": "[owntone-server] make", + "type": "shell", + "command": "make", + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "label": "[owntone-server] scan-build", + "type": "shell", + "command": "make clean && scan-build --status-bugs -disable-checker deadcode.DeadStores --exclude src/parsers make", + "group": { + "kind": "build", + "isDefault": false + } + }, + { + "label": "[owntone-server] clean", + "type": "shell", + "command": "make clean", + "group": { + "kind": "build", + "isDefault": false + } + }, + { + "label": "[owntone-web] install", + "type": "npm", + "script": "install", + "options": { + "cwd": "${workspaceFolder}/web-src" + }, + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "label": "[owntone-web] build", + "type": "npm", + "script": "build", + "options": { + "cwd": "${workspaceFolder}/web-src" + }, + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "label": "[owntone-web] serve", + "type": "npm", + "script": "serve", + "options": { + "cwd": "${workspaceFolder}/web-src" + }, + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "label": "[owntone-docs] serve", + "type": "shell", + "command": "mkdocs serve", + "group": { + "kind": "build", + "isDefault": false + } + }, + { + "label": "[owntone-docs] build", + "type": "shell", + "command": "mkdocs build", + "group": { + "kind": "build", + "isDefault": true + } + } + ] +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 432c91bd65..d4ddb4c71e 100644 --- a/.gitignore +++ b/.gitignore @@ -39,7 +39,11 @@ owntone@.service /.cproject /.project /.autotools -/.vscode # ignore MkDocs generated documentation /site/ +/test/ + +/.vscode/ +/.devcontainer/ +!/.dev/Makefile diff --git a/web-src/package.json b/web-src/package.json index 6563f3f216..08fe4983dd 100644 --- a/web-src/package.json +++ b/web-src/package.json @@ -3,7 +3,7 @@ "version": "2.0.1", "type": "module", "scripts": { - "serve": "vite --port 3000", + "serve": "vite --port 3000 --host", "build": "vite build --base='./'", "lint": "eslint", "dev": "vite",