Reworking command line select. Starting on others.

This commit is contained in:
Jonathan Bernard 2016-02-22 22:14:49 -06:00
parent 5245291aff
commit 5f5bdab238
2 changed files with 111 additions and 78 deletions

View File

@ -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,6 +577,12 @@ 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()
@ -566,4 +590,13 @@ Configuration:
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() }
} }

View File

@ -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 } }
} }