forked from jleight/omxplayer
-
Notifications
You must be signed in to change notification settings - Fork 1
/
omxplayer.go
165 lines (140 loc) · 4.44 KB
/
omxplayer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
// Package omxplayer is a simple library for controlling the omxplayer
// application on your Raspberry Pi from Go.
package omxplayer
import (
"os"
"os/exec"
"strings"
dbus "github.com/guelfey/go.dbus"
log "github.com/sirupsen/logrus"
)
const (
envDisplay = "DISPLAY"
envDbusAddress = "DBUS_SESSION_BUS_ADDRESS"
envDbusPid = "DBUS_SESSION_BUS_PID"
prefixOmxDbusFiles = "/tmp/omxplayerdbus."
suffixOmxDbusPid = ".pid"
pathMpris = "/org/mpris/MediaPlayer2"
ifaceMpris = "org.mpris.MediaPlayer2"
ifaceOmx = ifaceMpris + ".omxplayer"
exeOxmPlayer = "omxplayer"
keyPause = "p"
)
var (
user string
home string
fileOmxDbusPath string
fileOmxDbusPid string
)
func init() {
SetUser(os.Getenv("USER"), os.Getenv("HOME"))
}
// SetUser sets the username (u) and home directory (h) of the user that new
// omxplayer processes will be running as. This does not change which user the
// processes will be spawned as, it is just used to find the correct D-Bus
// configuration file after a new process has been started.
func SetUser(u, h string) {
user = u
home = h
fileOmxDbusPath = prefixOmxDbusFiles + user
fileOmxDbusPid = prefixOmxDbusFiles + user + suffixOmxDbusPid
}
// New returns a new Player instance that can be used to control an OMXPlayer
// instance that is playing the video located at the specified URL.
func New(url string, args ...string) (player *Player, err error) {
removeDbusFiles()
cmd, err := execOmxplayer(url, args...)
if err != nil {
return
}
err = setupDbusEnvironment()
if err != nil {
return
}
conn, err := getDbusConnection()
if err != nil {
return
}
player = &Player{
command: cmd,
connection: conn,
bus: conn.Object(ifaceOmx, pathMpris),
}
return
}
// removeDbusFiles removes the files that OMXPlayer creates containing the D-Bus
// path and PID. This ensures that when the path and PID are read in, the new
// files are read instead of the old ones.
func removeDbusFiles() {
removeFile(fileOmxDbusPath)
removeFile(fileOmxDbusPid)
}
// getDbusPath reads the D-Bus path from the file OMXPlayer writes it's path to.
// If the file cannot be read, it returns an error, otherwise it returns the
// path as a string.
func getDbusPath() (string, error) {
if err := waitForFile(fileOmxDbusPath); err != nil {
return "", err
}
return readFile(fileOmxDbusPath)
}
// getDbusPath reads the D-Bus PID from the file OMXPlayer writes it's PID to.
// If the file cannot be read, it returns an error, otherwise it returns the
// PID as a string.
func getDbusPid() (string, error) {
if err := waitForFile(fileOmxDbusPid); err != nil {
return "", err
}
return readFile(fileOmxDbusPid)
}
// getDbusConnection establishes and returns a D-Bus connection. The connection
// is made to the D-Bus service that has been set via the two `DBUS_*`
// environment variables. Since the connection's `Auth` method attempts to use
// Go's `os/user` package to get the current user's name and home directory, and
// `os/user` is not implemented for Linux-ARM, the `authMethods` parameter is
// specified explicitly rather than passing `nil`.
func getDbusConnection() (conn *dbus.Conn, err error) {
authMethods := []dbus.Auth{
dbus.AuthExternal(user),
dbus.AuthCookieSha1(user, home),
}
log.Debug("omxplayer: opening dbus session")
if conn, err = dbus.SessionBusPrivate(); err != nil {
return
}
log.Debug("omxplayer: authenticating dbus session")
if err = conn.Auth(authMethods); err != nil {
return
}
log.Debug("omxplayer: initializing dbus session")
err = conn.Hello()
return
}
// setupDbusEnvironment sets the environment variables that are necessary to
// establish a D-Bus connection. If the connection's path or PID cannot be read,
// the associated error is returned.
func setupDbusEnvironment() (err error) {
log.Debug("omxplayer: setting up dbus environment")
path, err := getDbusPath()
if err != nil {
return
}
pid, err := getDbusPid()
if err != nil {
return
}
setEnv(envDisplay, ":0")
setEnv(envDbusAddress, path)
setEnv(envDbusPid, pid)
return
}
// execOmxplayer starts a new OMXPlayer process and tells it to pause the video
// by passing a "p" on standard input.
func execOmxplayer(url string, args ...string) (cmd *exec.Cmd, err error) {
log.Debug("omxplayer: starting omxplayer process")
args = append(args, url)
cmd = exec.Command(exeOxmPlayer, args...)
cmd.Stdin = strings.NewReader(keyPause)
err = cmd.Start()
return
}