Subject: [PATCH v5] home: services: Add readymedia.

From: Sughosha <[email-masked]>
Date: Sat, 10 May 2025 20:04:58 +0530

* gnu/home/services/upnp.scm: New file.
* gnu/local.mk: Register it.
* gnu/services/upnp.scm: Export readymedia-activation and
readymedia-shepherd-service.
(<readymedia-configuration>)[home-service?]: New field.
[cache-directory]: Adjust value depending on 'for-home?'.
[log-directory]: Ditto.
(readymedia-shepherd-service): Adjust 'requirement' and 'start' according to
'home-service?'.
(readymedia-activation): Adjust creating 'media-directories' with permissions
according to 'home-service?'.
* gnu/tests/upnp.scm (%readymedia-configuration-test): Configure port with
%readymedia-default-port.
* doc/guix.texi (Miscellaneous Home Services): Document Readymedia Service.
(Miscellaneous Services): Add cross-reference.

Change-Id: I5c48595d84a815d98e03c7f68a716f048903720c
---
 doc/guix.texi              | 45 +++++++++++++++++++++++++++++++
 gnu/home/services/upnp.scm | 55 ++++++++++++++++++++++++++++++++++++++
 gnu/local.mk               |  1 +
 gnu/services/upnp.scm      | 50 ++++++++++++++++++++++++----------
 gnu/tests/upnp.scm         |  1 +
 5 files changed, 138 insertions(+), 14 deletions(-)
 create mode 100644 gnu/home/services/upnp.scm

diff --git a/doc/guix.texi b/doc/guix.texi
index 7f796c5fc94..bb48b1ae8ec 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -44872,6 +44872,12 @@ Miscellaneous Services
 field is mandatory.  All other fields (such as network ports and the
 server name) come with a predefined default and can be omitted.
 
+@quotation Note
+This service is also available for Guix Home, where it runs directly
+with your user privileges (@pxref{Miscellaneous Home Services,
+@code{home-readymedia-service-type}}).
+@end quotation
+
 @c %start of fragment
 
 @deftp {Data Type} readymedia-configuration
@@ -51149,6 +51155,8 @@ Networking Home Services
 This section lists services somewhat networking-related that you may use
 with Guix Home.
 
+@subheading Syncthing Service
+
 @cindex Syncthing, file synchronization service
 @cindex backup service, Syncthing
 The @code{(gnu home services syncthing)} module provides a service to
@@ -51251,6 +51259,43 @@ Miscellaneous Home Services
           (dicod-configuration @dots{})))
 @end lisp
 
+@subheading ReadyMedia Service
+
+@cindex ReadyMedia, DLNA/UPnP Service
+The @code{(gnu home services upnp)} module provides a service to set up
+the @uref{https://minidlna.sourceforge.net/, ReadyMedia} @acronym{DLNA,
+Digital Living Network Alliance} @acronym{UPnP, Universal Plug and Play}
+media server.
+
+@defvar home-readymedia-service-type
+This is the service type for the @command{minidlnad} daemon; it is the
+Home counterpart of the @code{readymedia-service-type} system service
+(@pxref{Miscellaneous Services, @code{readymedia-service-type}}).  The value
+for this service type is a @code{readymedia-configuration}.
+@end defvar
+
+The service can be used with a @code{readymedia-configuration} wrapped in
+@code{for-home} like this:
+
+@lisp
+(service home-readymedia-service-type
+         (for-home
+          (readymedia-configuration
+            (media-directories
+             (list (readymedia-directory
+                     (path "/path/to/media/audio")
+                     (types '(A)))
+                   (readymedia-directory
+                     (path "/path/to/media/video")
+                     (types '(V)))
+                   (readymedia-directory
+                     (path "/path/to/media/misc")))))))
+@end lisp
+
+For details about @code{readymedia-configuration}, check out the
+documentation of the system service (@pxref{Miscellaneous Services,
+@code{readymedia-service-type}}).
+
 @node Invoking guix home
 @section Invoking @command{guix home}
 
diff --git a/gnu/home/services/upnp.scm b/gnu/home/services/upnp.scm
new file mode 100644
index 00000000000..869c8e0c4a7
--- /dev/null
+++ b/gnu/home/services/upnp.scm
@@ -0,0 +1,55 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2025 Sughosha <[email-masked]>
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix is free software; you can redistribute it and/or modify it
+;;; under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation; either version 3 of the License, or (at
+;;; your option) any later version.
+;;;
+;;; GNU Guix is distributed in the hope that it will be useful, but
+;;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (gnu home services upnp)
+  #:use-module ((gnu build linux-container) #:select (%namespaces))
+  #:use-module (gnu services)
+  #:use-module (gnu home services)
+  ;; For the 'home-shepherd-service-type' mapping.
+  #:use-module (gnu home services shepherd)
+  #:use-module (gnu services upnp)
+  #:use-module (guix records)
+  #:export (home-readymedia-service-type)
+  #:re-export (readymedia-configuration
+               readymedia-configuration?
+               readymedia-configuration-readymedia
+               readymedia-configuration-port
+               readymedia-configuration-cache-directory
+               readymedia-configuration-extra-config
+               readymedia-configuration-friendly-name
+               readymedia-configuration-log-directory
+               readymedia-configuration-media-directories
+               readymedia-media-directory
+               readymedia-media-directory?
+               readymedia-media-directory-path
+               readymedia-media-directory-types))
+
+(define home-readymedia-service-type
+  (service-type
+   (inherit (system->home-service-type readymedia-service-type))
+   ;; system->home-service-type does not convert special-files-service-type to
+   ;; home-files-service-type, so redefine extensios
+   (extensions
+    (list (service-extension home-shepherd-service-type
+                             (compose list readymedia-shepherd-service))
+          (service-extension home-activation-service-type
+                             readymedia-activation)))
+   (default-value
+    (for-home
+     (readymedia-configuration
+       (media-directories '()))))))
diff --git a/gnu/local.mk b/gnu/local.mk
index e25fcc115be..673d2636c24 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -122,6 +122,7 @@ GNU_SYSTEM_MODULES =				\
   %D%/home/services/sway.scm			\
   %D%/home/services/syncthing.scm		\
   %D%/home/services/mcron.scm			\
+  %D%/home/services/upnp.scm			\
   %D%/home/services/utils.scm			\
   %D%/home/services/xdg.scm			\
   %D%/image.scm					\
diff --git a/gnu/services/upnp.scm b/gnu/services/upnp.scm
index 47c32f0a1ef..363da005f1e 100644
--- a/gnu/services/upnp.scm
+++ b/gnu/services/upnp.scm
@@ -33,7 +33,6 @@ (define-module (gnu services upnp)
   #:use-module (ice-9 match)
   #:export (%readymedia-default-cache-directory
             %readymedia-default-log-directory
-            %readymedia-default-port
             %readymedia-log-file
             %readymedia-user-account
             %readymedia-user-group
@@ -50,7 +49,9 @@ (define-module (gnu services upnp)
             readymedia-media-directory-path
             readymedia-media-directory-types
             readymedia-media-directory?
-            readymedia-service-type))
+            readymedia-service-type
+            readymedia-activation
+            readymedia-shepherd-service))
 
 ;;; Commentary:
 ;;;
@@ -72,14 +73,27 @@ (define-record-type* <readymedia-configuration>
   (port readymedia-configuration-port
         (default #f))
   (cache-directory readymedia-configuration-cache-directory
-                   (default %readymedia-default-cache-directory))
+                   (default (if for-home?
+                                (string-append (or (getenv "XDG_CACHE_HOME")
+                                                   (string-append
+                                                    (getenv "HOME") "/.cache"))
+                                               "/readymedia")
+                              %readymedia-default-cache-directory)))
   (log-directory readymedia-configuration-log-directory
-                 (default %readymedia-default-log-directory))
+                 (default (if for-home?
+                              (string-append (or (getenv "XDG_STATE_HOME")
+                                                 (string-append
+                                                  (getenv "HOME")
+                                                  "/.local/state"))
+                                             "/readymedia")
+                            %readymedia-default-log-directory)))
   (friendly-name readymedia-configuration-friendly-name
                  (default #f))
   (media-directories readymedia-configuration-media-directories)
   (extra-config readymedia-configuration-extra-config
-                (default '())))
+                (default '()))
+  (home-service? syncthing-configuration-home-service?
+                 (default for-home?) (innate)))
 
 ;; READYMEDIA-MEDIA-DIR is a record that indicates the path of a media folder
 ;; and the types of media included within it. Allowed individual types are the
@@ -96,9 +110,13 @@ (define-record-type* <readymedia-media-directory>
 (define (readymedia-configuration->config-file config)
   "Return the ReadyMedia/MiniDLNA configuration file corresponding to CONFIG."
   (match-record config <readymedia-configuration>
-    (port friendly-name cache-directory log-directory media-directories extra-config)
+    (port friendly-name cache-directory log-directory media-directories
+     extra-config home-service?)
     (apply mixed-text-file
            "minidlna.conf"
+           (if home-service?
+               (string-append "user=" (number->string (getuid)) "\n")
+               "")
            "db_dir=" cache-directory "\n"
            "log_dir=" log-directory "\n"
            (if friendly-name
@@ -125,12 +143,12 @@ (define (readymedia-configuration->config-file config)
 (define (readymedia-shepherd-service config)
   "Return a least-authority ReadyMedia/MiniDLNA Shepherd service."
   (match-record config <readymedia-configuration>
-    (cache-directory log-directory media-directories)
+    (cache-directory log-directory media-directories home-service?)
     (let ((minidlna-conf (readymedia-configuration->config-file config)))
       (shepherd-service
        (documentation "Run the ReadyMedia/MiniDLNA daemon.")
        (provision '(readymedia))
-       (requirement '(networking user-processes))
+       (requirement (if home-service? '() '(networking user-processes)))
        (start
         #~(make-forkexec-constructor
            (list #$(least-authority-wrapper
@@ -159,8 +177,8 @@ (define (readymedia-shepherd-service config)
                  #$minidlna-conf
                  "-S")
            #:log-file #$(string-append log-directory "/" %readymedia-log-file)
-           #:user #$%readymedia-user-account
-           #:group #$%readymedia-user-group))
+           #:user #$(if home-service? #f %readymedia-user-account)
+           #:group #$(if home-service? #f %readymedia-user-group)))
        (stop #~(make-kill-destructor))))))
 
 (define readymedia-accounts
@@ -178,7 +196,7 @@ (define readymedia-accounts
 (define (readymedia-activation config)
   "Set up directories for ReadyMedia/MiniDLNA."
   (match-record config <readymedia-configuration>
-    (cache-directory log-directory media-directories)
+    (cache-directory log-directory media-directories home-service?)
     (with-imported-modules (source-module-closure '((gnu build activation)))
       #~(begin
           (use-modules (gnu build activation))
@@ -186,14 +204,18 @@ (define (readymedia-activation config)
           (for-each (lambda (directory)
                       (unless (file-exists? directory)
                         (mkdir-p/perms directory
-                                       (getpw #$%readymedia-user-account)
-                                       #o775)))
+                                       (getpw #$(if home-service?
+                                                    #~(getuid)
+                                                    %readymedia-user-account))
+                                       #$(if home-service? #o755 #o775))))
                     (list #$@(map readymedia-media-directory-path
                                   media-directories)))
           (for-each (lambda (directory)
                       (unless (file-exists? directory)
                         (mkdir-p/perms directory
-                                       (getpw #$%readymedia-user-account)
+                                       (getpw #$(if home-service?
+                                                    #~(getuid)
+                                                    %readymedia-user-account))
                                        #o755)))
                     (list #$cache-directory #$log-directory))))))
 
diff --git a/gnu/tests/upnp.scm b/gnu/tests/upnp.scm
index e4bce30d89d..0224557f401 100644
--- a/gnu/tests/upnp.scm
+++ b/gnu/tests/upnp.scm
@@ -38,6 +38,7 @@ (define %readymedia-default-port 8200)
 (define %readymedia-media-directory "/media")
 (define %readymedia-configuration-test
   (readymedia-configuration
+   (port %readymedia-default-port)
    (media-directories
     (list (readymedia-media-directory (path %readymedia-media-directory)
                                       (types '(A V)))))))

base-commit: cea6eedfcea2defa526bc58d4fb2085cc8c0cb36
-- 
2.49.0