-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmain.go
More file actions
255 lines (216 loc) · 7.38 KB
/
Copy pathmain.go
File metadata and controls
255 lines (216 loc) · 7.38 KB
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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
// Package main is the main starting point of the program. It parses
// the command line arguments and initializes the mysql connection pool.
package main
import (
"encoding/json"
"flag"
"fmt"
"log"
"os"
"os/signal"
"path"
"strings"
"syscall"
"errors"
"github.com/MeesCode/mmjs/audioplayer"
"github.com/MeesCode/mmjs/database"
"github.com/MeesCode/mmjs/globals"
"github.com/MeesCode/mmjs/plugins"
"github.com/MeesCode/mmjs/tui"
)
var (
modes = []string{"filesystem", "database", "index"}
help bool
configFile string
)
func init() {
var (
defaultMode = "filesystem"
defaultHelp = false
defaultQuiet = false
defaultWebserver = false
defaultSerial = false
defaultSerialPort = "/dev/ttyUSB0"
defaultWebinterface = false
defaultLogging = false
defaultWebinterfacePort = 3307
defaultDatabasePort = 8081
defaultWebserverPort = 8080
defaultDatabaseHost = "localhost"
defaultDatabaseUser = ""
defaultDatabasePassword = ""
defaultDatabase = ""
defaultConfig = ""
defaultDisableSound = false
defaultHighlight = "cb2821"
modeUsage = "specifies what mode to run. [" + strings.Join(modes, ", ") + "]"
webserverUsage = "a boolean to specify whether to run the webserver. (only in database mode)"
webinterfaceUsage = "a boolean to specify whether to run the web interface"
serialUsage = "a boolean to specify whether listen to serial input, if received skip track"
serialPortUsage = "the serial port to use"
quietUsage = "quiet mode disables the text user interface"
loggingUsage = "enable error logging in stdout, will interfere with tui"
helpUsage = "print this help message"
webserverPortUsage = "set the port to be used by the webserver plugin"
webinterfacePortUsage = "set the port to be used by the webinterface plugin"
databasePortUsage = "set the port to be used by the database"
databaseHostUsage = "set the host for the database connection"
databaseUserUsage = "set the database user"
databasePasswordUsage = "set the database password"
databaseUsage = "The database to use"
disableSoundUsage = "disables initialization of the sound card (for server use)"
configUsage = "specify a config file to use (overrides command line arguments)"
highlightUsage = "hex code indicating the highlight color of the text user interface"
)
flag.BoolVar(&help, "help", defaultHelp, helpUsage)
flag.StringVar(&configFile, "c", defaultConfig, configUsage)
flag.StringVar(&globals.Config.Mode, "m", defaultMode, modeUsage)
flag.StringVar(&globals.Config.Highlight, "hl", defaultHighlight, highlightUsage)
flag.BoolVar(&globals.Config.Quiet, "q", defaultQuiet, quietUsage)
flag.BoolVar(&globals.Config.Logging, "x", defaultLogging, loggingUsage)
flag.BoolVar(&globals.Config.Webserver.Enable, "w", defaultWebserver, webserverUsage)
flag.BoolVar(&globals.Config.Serial.Enable, "s", defaultSerial, serialUsage)
flag.StringVar(&globals.Config.Serial.Port, "sp", defaultSerialPort, serialPortUsage)
flag.IntVar(&globals.Config.Webserver.Port, "wp", defaultWebserverPort, webserverPortUsage)
flag.BoolVar(&globals.Config.Webinterface.Enable, "i", defaultWebinterface, webinterfaceUsage)
flag.IntVar(&globals.Config.Webinterface.Port, "ip", defaultWebinterfacePort, webinterfacePortUsage)
flag.IntVar(&globals.Config.Database.Port, "dp", defaultDatabasePort, databasePortUsage)
flag.StringVar(&globals.Config.Database.Host, "h", defaultDatabaseHost, databaseHostUsage)
flag.StringVar(&globals.Config.Database.User, "u", defaultDatabaseUser, databaseUserUsage)
flag.StringVar(&globals.Config.Database.Password, "p", defaultDatabasePassword, databasePasswordUsage)
flag.StringVar(&globals.Config.Database.Database, "d", defaultDatabase, databaseUsage)
flag.BoolVar(&globals.Config.DisableSound, "ds", defaultDisableSound, disableSoundUsage)
}
// load the configuration from a json file
func loadConfiguration(file string) globals.ConfigFile {
var config globals.ConfigFile
configFile, err := os.Open(file)
defer configFile.Close()
if err != nil {
log.Fatalln("could not open configuration file (config.json)", err)
}
jsonParser := json.NewDecoder(configFile)
err = jsonParser.Decode(&config)
if err != nil {
log.Fatalln("Error decoding configuration file", err)
}
return config
}
// check if mounted path corresponds to loaded database
// by testing a random track from the database
func validatePath() error {
path := database.GetRandomPath()
if _, err := os.Stat(path); errors.Is(err, os.ErrNotExist) {
return errors.New("Filesystem not mounted correctly")
log.Fatalln("filesystem error", path)
}
return nil
}
func main() {
// write log to file
f, err := os.OpenFile("debug.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
log.Fatalln("cannot open or create logfile")
}
log.SetOutput(f)
// parse command line arguments
flag.Parse()
// check for help flag
if help {
flag.PrintDefaults()
return
}
// load configuration file if one is specified
if configFile != "" {
globals.Config = loadConfiguration(configFile)
}
base, err := os.Getwd()
if err != nil {
log.Fatalln("could not get working directory", err)
}
arg := flag.Arg(0)
// check that a path has been given
if arg == "" {
fmt.Println("please specify a path")
return
}
// make absolute if not already
if path.IsAbs(arg) {
globals.Root = path.Clean(arg)
} else {
globals.Root = path.Clean(path.Join(base, arg))
}
// check if mode is correct
if !globals.Contains(modes, globals.Config.Mode) {
fmt.Println("please use one of the available modes")
flag.PrintDefaults()
return
}
// check if path exists
if _, err := os.Stat(globals.Root); os.IsNotExist(err) {
fmt.Println("chosen path: " + globals.Root)
fmt.Println("specified path does not exist")
flag.PrintDefaults()
return
}
// disabe logging output. discard instead
if globals.Config.Logging {
log.SetOutput(os.Stdout)
}
// index filesystem at specified path
if globals.Config.Mode == "index" {
db, err := database.Warmup()
if err != nil {
log.Fatalln("could not connect to the database")
return
}
defer db.Close()
database.Index()
return
}
// start the database connection pool
if globals.Config.Mode != "filesystem" {
db, err := database.Warmup()
if err != nil {
tui.DisplayError(err)
return
}
err = validatePath()
if err != nil {
tui.DisplayError(err)
return
}
defer db.Close()
}
// initialize audio player
if !globals.Config.DisableSound {
go audioplayer.Initialize()
}
////////////////////////////////
// Start plugins here //
////////////////////////////////
if globals.Config.Webserver.Enable {
go plugins.Webserver()
}
if globals.Config.Webinterface.Enable {
go plugins.Webinterface()
}
if globals.Config.Serial.Enable {
go plugins.Coinslot()
}
///////////////////////////////
// Begin main program loop //
///////////////////////////////
if !globals.Config.Quiet {
// start user interface
// on current thread as to not immediately exit
tui.Start()
} else {
// idle until sigterm is caught
fmt.Println("started in quiet mode")
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
<-sigs
audioplayer.Close()
}
}