Reworking command line select. Starting on others.
This commit is contained in:
parent
5245291aff
commit
5f5bdab238
@ -52,9 +52,13 @@ Configuration:
|
|||||||
|
|
||||||
private static Logger logger =
|
private static Logger logger =
|
||||||
LoggerFactory.getLogger(CommandLineInterface)
|
LoggerFactory.getLogger(CommandLineInterface)
|
||||||
|
|
||||||
|
private static UPPERCASE_PATTERN = Pattern.compile(/(.)(\p{javaUpperCase})/)
|
||||||
|
|
||||||
private Properties cliConfig
|
private Properties cliConfig
|
||||||
private MediaLibrary library
|
private MediaLibrary library
|
||||||
|
|
||||||
|
/// IO Management
|
||||||
private InputStream inStream
|
private InputStream inStream
|
||||||
private OutputStream outStream
|
private OutputStream outStream
|
||||||
|
|
||||||
@ -64,6 +68,7 @@ Configuration:
|
|||||||
Collections.synchronizedList(new ArrayList<String>())
|
Collections.synchronizedList(new ArrayList<String>())
|
||||||
private synchronized boolean running
|
private synchronized boolean running
|
||||||
|
|
||||||
|
/// Console output data
|
||||||
private String titleStyle, normalStyle, statusStyle, promptStyle,
|
private String titleStyle, normalStyle, statusStyle, promptStyle,
|
||||||
artistStyle, albumStyle, fileStyle, errorStyle, playlistStyle
|
artistStyle, albumStyle, fileStyle, errorStyle, playlistStyle
|
||||||
private String clearLine = new ANSI().eraseLine(Erase.All).toString()
|
private String clearLine = new ANSI().eraseLine(Erase.All).toString()
|
||||||
@ -86,9 +91,12 @@ Configuration:
|
|||||||
private Date dismissMsgDate = new Date()
|
private Date dismissMsgDate = new Date()
|
||||||
private SimpleDateFormat sdf = new SimpleDateFormat('EEE-HH-SSS')
|
private SimpleDateFormat sdf = new SimpleDateFormat('EEE-HH-SSS')
|
||||||
|
|
||||||
|
/// Current play queue and selection data
|
||||||
def selection = [:]
|
def selection = [:]
|
||||||
def currentPlaylist = library.save(new Playlist(
|
Playlist playQueue = library.save(new Playlist(
|
||||||
"CLI Queue ${sdf.format(new Date())}"))
|
"CLI Queue ${sdf.format(new Date())}"))
|
||||||
|
Bookmark playBookmark
|
||||||
|
MediaFile curMediaFile
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
|
||||||
@ -236,23 +244,24 @@ Configuration:
|
|||||||
String command = line.poll()
|
String command = line.poll()
|
||||||
logger.debug("command: $command")
|
logger.debug("command: $command")
|
||||||
switch(command?.toLowerCase()) {
|
switch(command?.toLowerCase()) {
|
||||||
case 'album': return selectAlbum(line)
|
|
||||||
case 'artist': return selectArtist(line)
|
|
||||||
case 'playlist': return selectPlaylist(line)
|
|
||||||
case 'current': return selectCurrent(line)
|
|
||||||
case 'scan': return scanMediaLibrary()
|
case 'scan': return scanMediaLibrary()
|
||||||
case 'new': return processNew(line)
|
case 'select': return processSelect(line)
|
||||||
|
case 'list': return processList(line)
|
||||||
case 'add': return processAdd(line)
|
case 'add': return processAdd(line)
|
||||||
case 'tag': return tagMediaFiles(line)
|
case 'enque': return processEnque(line)
|
||||||
case 'split': return processSplit(line)
|
case 'tag': return processTag(line)
|
||||||
|
case 'clear': return processClear(line)
|
||||||
case 'list':
|
case 'play': return line.size() == 0 ?
|
||||||
String nextArg = line.poll()
|
transport.play() :
|
||||||
if (nextArg.toLowerCase() == 'all')
|
processPlay(line)
|
||||||
return processList(line, true)
|
case 'pause': return transport.pause()
|
||||||
else {
|
case 'stop': return transport.stop()
|
||||||
if (nextArg) line.addFirst(nextArg)
|
case 'next': return processNext(line)
|
||||||
return processList(line, false) }
|
case 'prev': return processPrev(line)
|
||||||
|
case 'ff':
|
||||||
|
case 'fastforward': return processFastForward(line)
|
||||||
|
case 'rwd':
|
||||||
|
case 'rewind': return processRewind(line)
|
||||||
|
|
||||||
case 'debug':
|
case 'debug':
|
||||||
outStream.println(
|
outStream.println(
|
||||||
@ -268,10 +277,6 @@ Configuration:
|
|||||||
consoleReaderThread.interrupt()
|
consoleReaderThread.interrupt()
|
||||||
return
|
return
|
||||||
|
|
||||||
selection.album = null
|
|
||||||
resetStatus()
|
|
||||||
break
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
status.text = errorStyle +
|
status.text = errorStyle +
|
||||||
"Unrecognized command: '$line'${normalStyle}"
|
"Unrecognized command: '$line'${normalStyle}"
|
||||||
@ -280,7 +285,58 @@ Configuration:
|
|||||||
Thread.sleep(250)
|
Thread.sleep(250)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public MediaLibrary scanMediaLibrary() {
|
||||||
|
status.text = "Scanning media library..."
|
||||||
|
library.rescanLibrary()
|
||||||
|
status.text = "Scanned ? files."
|
||||||
|
dismissMsgDate = new Date(new Date().time + msgTimeout)
|
||||||
|
return library }
|
||||||
|
|
||||||
|
private def processSelect(LinkedList line) {
|
||||||
|
String option = line.poll()
|
||||||
|
boolean current = option == "current"
|
||||||
|
def items
|
||||||
|
if (current) {
|
||||||
|
if (!curMediaFile) {
|
||||||
|
setErr "No media is currently selected."
|
||||||
|
return null }
|
||||||
|
|
||||||
|
option = line.poll()
|
||||||
|
switch (option) {
|
||||||
|
case 'album':
|
||||||
|
return select(Album, library.getAlbumsWhere({
|
||||||
|
mediaFileId: curMediaFile.id}))
|
||||||
|
case 'artist':
|
||||||
|
return select(Artist, library.getArtistsWhere({
|
||||||
|
mediaFileId: curMediaFile.id}))
|
||||||
|
case 'playlist':
|
||||||
|
return select(Playlist, playQueue)
|
||||||
|
case 'file':
|
||||||
|
return select(MediaFile, curMediaFile)
|
||||||
|
case 'tags':
|
||||||
|
return select(Tag, library.getTagsWhere({
|
||||||
|
mediaFileId: curMediaFile.id})
|
||||||
|
default:
|
||||||
|
setErr("Unrecognized option to ${promptStyle}select " +
|
||||||
|
"current${errStyle}.")
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (option) {
|
||||||
|
case 'album': return select(Album, library.getByIdOrName(line.join(' ')))
|
||||||
|
case 'artist': return select(Artist, library.getByIdOrName(line.join(' ')))
|
||||||
|
case 'playlist': return select(Playlist, library.getByIdOrName(line.join(' ')))
|
||||||
|
case 'current': return select(Current, library.getByIdOrName(line.join(' ')))
|
||||||
|
case 'file': return select(MediaFile, library.getByIdOrName(line.join(' ')))
|
||||||
|
case 'tags': return select(Tag, library.getByIdOrName(line.join(' ')))
|
||||||
|
|
||||||
|
default:
|
||||||
|
setErr("Unrecognized option to ${promptStyle}select${errStyle}")
|
||||||
|
return null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private def processNew(LinkedList line) {
|
private def processNew(LinkedList line) {
|
||||||
@ -310,9 +366,12 @@ Configuration:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private def processList(LinkedList options, boolean all) {
|
private def processList(LinkedList options) {
|
||||||
logger.debug("Listing albums. Options: $options")
|
logger.debug("Listing things. Options: $options")
|
||||||
def option = options.poll()
|
def option = options.poll()
|
||||||
|
boolean all = option == 'all'
|
||||||
|
if (all) option = options.poll()
|
||||||
|
|
||||||
logger.debug("Option: $option")
|
logger.debug("Option: $option")
|
||||||
|
|
||||||
def list
|
def list
|
||||||
@ -406,64 +465,23 @@ Configuration:
|
|||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
public Album selectAlbum(LinkedList input) {
|
public def unselect(Class modelClass) {
|
||||||
String criteria = input.join(" ")
|
String key = uncapitalize(modelClass.simpleName)
|
||||||
|
this.selection[key] = null }
|
||||||
|
|
||||||
if (!criteria) { selection.album = null; resetStatus(); return null }
|
public def select(Class modelClass, def matches) {
|
||||||
|
String englishName = ${toEnglish(modelClass.simpleName}
|
||||||
def match = library.getByIdOrName(Album, criteria)
|
if (!matches) {
|
||||||
|
setErr("No $englishName matches.");
|
||||||
if (!match) { setErr("No album matches '$input'."); return null }
|
return null }
|
||||||
else if (match.size() > 1) {
|
else if (match.size() > 1) {
|
||||||
setErr("Multiple albums match '$input': " +
|
setErr("Multiple ${englishName}s match: " +
|
||||||
match.collect { "${it.id}: ${it.name}" }.join(", "))
|
matches.collect { "${it.id}: ${it.name}" }.join(', '))
|
||||||
return null }
|
return null }
|
||||||
|
|
||||||
selection.album = match[0]
|
selection[uncapitalize(modelClass.simpleName)] = matches[0]
|
||||||
resetStatus()
|
resetStatus
|
||||||
return match[0] }
|
return matches[0] }
|
||||||
|
|
||||||
public Artist selectArtist(LinkedList input) {
|
|
||||||
String criteria = input.join(" ")
|
|
||||||
|
|
||||||
if (!criteria) { selection.artist = null; resetStatus(); return null }
|
|
||||||
|
|
||||||
def match = library.getByIdOrName(Artist, criteria)
|
|
||||||
|
|
||||||
if (!match) { setErr("No artist matches '$input'."); return null }
|
|
||||||
else if (match.size() > 1) {
|
|
||||||
setErr("Multiple artists match '$input': " +
|
|
||||||
match.collect { "${it.id}: ${it.name}" }.join(", "))
|
|
||||||
return null }
|
|
||||||
|
|
||||||
selection.artist = match[0]
|
|
||||||
resetStatus()
|
|
||||||
return match[0] }
|
|
||||||
|
|
||||||
public Playlist selectPlaylist(LinkedList input) {
|
|
||||||
String criteria = input.join(" ")
|
|
||||||
|
|
||||||
if (!criteria) { selection.playlist = null; resetStatus(); return null }
|
|
||||||
// currentPlaylist = library.save(
|
|
||||||
// new Playlist(name: "CLI Queue ${sdf.format(new Date())}")) }
|
|
||||||
|
|
||||||
def match = library.getByIdOrName(Playlist, criteria)
|
|
||||||
|
|
||||||
if (!match) { setErr("No playlist matches: '$input'."); return null }
|
|
||||||
else if (match.size() > 1) {
|
|
||||||
setErr("Multiple playlists match '$input': " +
|
|
||||||
match.collect { "${it.id}: ${it.name}" }.join(", "))
|
|
||||||
return null }
|
|
||||||
selection.playlist = match[0]
|
|
||||||
resetStatus()
|
|
||||||
return match[0] }
|
|
||||||
|
|
||||||
public MediaLibrary scanMediaLibrary() {
|
|
||||||
status.text = "Scanning media library..."
|
|
||||||
library.rescanLibrary()
|
|
||||||
status.text = "Scanned ? files."
|
|
||||||
dismissMsgDate = new Date(new Date().time + msgTimeout)
|
|
||||||
return library }
|
|
||||||
|
|
||||||
private void drawLeader(afterOutput = false) {
|
private void drawLeader(afterOutput = false) {
|
||||||
|
|
||||||
@ -559,11 +577,26 @@ Configuration:
|
|||||||
artistId: selection?.artist?.id,
|
artistId: selection?.artist?.id,
|
||||||
albumId: selection?.album?.id) }
|
albumId: selection?.album?.id) }
|
||||||
|
|
||||||
|
private String setSelection(Map s) {
|
||||||
|
['artist', 'album', 'playlist', 'file', 'tags'].each {
|
||||||
|
this.selection[it] = s[it] }
|
||||||
|
resetStatus()
|
||||||
|
}
|
||||||
|
|
||||||
private String resetStatus() {
|
private String resetStatus() {
|
||||||
String s = describeSelection()
|
String s = describeSelection()
|
||||||
|
|
||||||
if (s.size() == 0) status.text = "No current media selections."
|
if (s.size() == 0) status.text = "No current media selections."
|
||||||
else status.text = s
|
else status.text = s
|
||||||
|
|
||||||
return status.text}
|
return status.text }
|
||||||
|
|
||||||
|
private static String uncapitalize(String s) {
|
||||||
|
if (s == null) return null;
|
||||||
|
if (s.lengh() < 2) return s.toLowerCase();
|
||||||
|
return s[0].toLowerCase() + s[1..-1] }
|
||||||
|
|
||||||
|
private static String toEnglish(String modelName) {
|
||||||
|
return UPPERCASE_PATTERN.matcher(name).
|
||||||
|
replaceAll(/$1 $2/).toLowerCase() }
|
||||||
}
|
}
|
||||||
|
@ -210,6 +210,6 @@ public class MediaLibrary {
|
|||||||
|
|
||||||
public static Integer safeToInteger(def val) {
|
public static Integer safeToInteger(def val) {
|
||||||
if (val == null) return null
|
if (val == null) return null
|
||||||
try { return val as Integer }
|
try { return val.trim() as Integer }
|
||||||
catch (NumberFormatException nfe) { return null } }
|
catch (NumberFormatException nfe) { return null } }
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user