Added list and select for playlists, bookmarks.

This commit is contained in:
Jonathan Bernard 2016-02-15 16:31:52 -06:00
parent 2010aa7d46
commit 5245291aff

View File

@ -10,6 +10,7 @@ import com.zaxxer.hikari.HikariConfig
import com.zaxxer.hikari.HikariDataSource import com.zaxxer.hikari.HikariDataSource
import org.docopt.Docopt import org.docopt.Docopt
import jline.console.ConsoleReader import jline.console.ConsoleReader
import java.text.SimpleDateFormat
import java.util.regex.Matcher import java.util.regex.Matcher
import org.slf4j.Logger import org.slf4j.Logger
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
@ -83,8 +84,11 @@ Configuration:
text: "No media currently playing.") text: "No media currently playing.")
private ScrollText status = new ScrollText(maxWidth: displayWidth) private ScrollText status = new ScrollText(maxWidth: displayWidth)
private Date dismissMsgDate = new Date() private Date dismissMsgDate = new Date()
private SimpleDateFormat sdf = new SimpleDateFormat('EEE-HH-SSS')
def selection = [:] def selection = [:]
def currentPlaylist = library.save(new Playlist(
"CLI Queue ${sdf.format(new Date())}"))
public static void main(String[] args) { public static void main(String[] args) {
@ -117,7 +121,8 @@ Configuration:
File libRoot = new File( File libRoot = new File(
opts["--library-root"] ?: opts["--library-root"] ?:
givenCfg[ConfigWrapper.LIBRARY_DIR_KEY] ?: givenCfg[ConfigWrapper.LIBRARY_DIR_KEY] ?:
wdiwtltDefaultConfig.libraryRootPath) wdiwtltDefaultConfig.libraryRootPath ?:
"no libRoot configured")
if (libRoot && (!libRoot.exists() || !libRoot.isDirectory())) if (libRoot && (!libRoot.exists() || !libRoot.isDirectory()))
exitErr("Library root does not exist or is not a directory: " + exitErr("Library root does not exist or is not a directory: " +
@ -181,10 +186,11 @@ Configuration:
} }
void setupTextStyles() { void setupTextStyles() {
titleStyle = new ANSI().color(Colors.GREEN, Colors.DEFAULT, false).toString() titleStyle = new ANSI().color(Colors.WHITE, Colors.DEFAULT, false).toString()
normalStyle = new ANSI().resetText().toString() normalStyle = new ANSI().resetText().toString()
promptStyle = new ANSI().color(Colors.YELLOW, Colors.DEFAULT, true).toString() promptStyle = new ANSI().color(Colors.YELLOW, Colors.DEFAULT, true).toString()
statusStyle = new ANSI().color(Colors.CYAN, Colors.DEFAULT, false).toString() statusStyle = new ANSI().color(Colors.CYAN, Colors.DEFAULT, false).toString()
playlistStyle = new ANSI().color(Colors.GREEN, Colors.DEFAULT, false).toString()
artistStyle = new ANSI().color(Colors.RED, Colors.DEFAULT, false).toString() artistStyle = new ANSI().color(Colors.RED, Colors.DEFAULT, false).toString()
albumStyle = new ANSI().color(Colors.BLUE, Colors.DEFAULT, false).toString() albumStyle = new ANSI().color(Colors.BLUE, Colors.DEFAULT, false).toString()
fileStyle = new ANSI().color(Colors.GREEN, Colors.DEFAULT, false).toString() fileStyle = new ANSI().color(Colors.GREEN, Colors.DEFAULT, false).toString()
@ -230,9 +236,15 @@ 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 'album': return selectAlbum(line)
case 'artist': return selectArtist(line) case 'artist': return selectArtist(line)
case 'scan': return scanMediaLibrary() case 'playlist': return selectPlaylist(line)
case 'current': return selectCurrent(line)
case 'scan': return scanMediaLibrary()
case 'new': return processNew(line)
case 'add': return processAdd(line)
case 'tag': return tagMediaFiles(line)
case 'split': return processSplit(line)
case 'list': case 'list':
String nextArg = line.poll() String nextArg = line.poll()
@ -271,6 +283,33 @@ Configuration:
} }
private def processNew(LinkedList line) {
def option = line.poll()
switch(option) {
case 'playlist':
case 'bookmark':
default:
printLongMessage("Unrecognized option to the ${promptStyle}" +
"new${normalStyle} command. Use ${promptStyle}help new" +
"${normalStyle} to see a list of valid options.")
return null
}
}
private def processAdd(LinkedList line) {
// Add takes the form of
def options = line.poll()
switch(option) {
case 'playlist':
case 'bookmark':
default:
printLongMessage("Unrecognized option to the ${promptStyle}" +
"add${normalStyle} command. Use ${promptStyle}help add" +
"${normalStyle} to see a list of valid options.")
return null
}
}
private def processList(LinkedList options, boolean all) { private def processList(LinkedList options, boolean all) {
logger.debug("Listing albums. Options: $options") logger.debug("Listing albums. Options: $options")
def option = options.poll() def option = options.poll()
@ -288,7 +327,8 @@ Configuration:
String albumMatch = options?.join(" ")?.trim() String albumMatch = options?.join(" ")?.trim()
if (albumMatch) list = list.findAll { it.name =~ albumMatch } if (albumMatch) list = list.findAll { it.name =~ albumMatch }
printLongMessage(makeAlbumList(list, all)) printLongMessage(makeList(Album, list, all,
{ "${it.id}: ${it}" }))
break break
case 'artists': case 'artists':
@ -301,21 +341,20 @@ Configuration:
String artistMatch = options?.join(" ")?.trim() String artistMatch = options?.join(" ")?.trim()
if (artistMatch) list = list.findAll { it.name =~ artistMatch } if (artistMatch) list = list.findAll { it.name =~ artistMatch }
printLongMessage(makeArtistList(list, all)) printLongMessage(makeList(Artist, list, all,
{ "${it.id}: ${it.name}" }))
break break
case 'files': case 'files':
case 'selection':
if (all) list = library.getMediaFiles() if (all) list = library.getMediaFiles()
else if (selection.mediaFile) list = [selection.mediaFile] else list = getSelectedMediaFiles()
else list = library.getMediaFilesWhere(
playlistId: selection.playlist?.id,
artistId: selection.artist?.id,
albumId: selection.album?.id)
String mediaFileMatch = options?.join(" ")?.trim() String mediaFileMatch = options?.join(" ")?.trim()
if (mediaFileMatch) list = list.findAll { if (mediaFileMatch) list = list.findAll {
it.name =~ mediaFileMatch } it.name =~ mediaFileMatch }
printLongMessage(makeMediaFileList(list, all)) printLongMessage(makeList(MediaFile, list, all
{ "${it.id}: ${it.trackNumber} - ${it.name}" }))
break break
case 'bookmarks': case 'bookmarks':
@ -326,12 +365,12 @@ Configuration:
String bookmarkMatch = options?.join(" ")?.trim() String bookmarkMatch = options?.join(" ")?.trim()
if (boolmarkMatch) if (boolmarkMatch)
list = list.findAll { it.name =~ bookmarkMatch } list = list.findAll { it.name =~ bookmarkMatch }
printLongMessage(makeBookmarkList(list, all)) printLongMessage(makeList(Bookmark, list, all,
{ "${it.id}: ${it.name} ${it.userCreated ? '' : ' (auto)'}" }))
break break
case 'playlists': case 'playlists':
if (all) list = library.getPlaylists() if (all) list = library.getPlaylists()
else if (selection.playlist) list = [selection.playlist]
else list = library.getPlaylistsWhere( else list = library.getPlaylistsWhere(
artistId: selection?.artist?.id, artistId: selection?.artist?.id,
albumId: selection?.album?.id, albumId: selection?.album?.id,
@ -340,7 +379,21 @@ Configuration:
String playlistMatch = options?.join(" ")?.trim() String playlistMatch = options?.join(" ")?.trim()
if (playlistMatch) if (playlistMatch)
list = list.findAll { it.name =~ playlistMatch } list = list.findAll { it.name =~ playlistMatch }
printLongMessage(makePlaylistList(list, all)) printLongMessage(makeList(Playlist, list, all,
{ "${it.id}: ${it.name} ${it.userCreated ? '' : ' (auto)'}" }))
break
case 'tags':
if (all) list = library.getTags()
else list = library.getTagsWhere(
playlistId: selection?.playlist?.id,
artistId: selection?.artist?.id,
albumId: selection?.album?.id)
String tagMatch = options?.join(" ")?.trim()
if (tagMatch) list = list.findAll { it.name =~ tagMatch }
printLongMessage(makeList(Tag, list, all,
{ "${it.id}: ${it.name}" }))
break break
default: default:
@ -382,10 +435,29 @@ Configuration:
setErr("Multiple artists match '$input': " + setErr("Multiple artists match '$input': " +
match.collect { "${it.id}: ${it.name}" }.join(", ")) match.collect { "${it.id}: ${it.name}" }.join(", "))
return null } return null }
selection.artist = match[0] selection.artist = match[0]
resetStatus() resetStatus()
return match[0] } 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() { public MediaLibrary scanMediaLibrary() {
status.text = "Scanning media library..." status.text = "Scanning media library..."
library.rescanLibrary() library.rescanLibrary()
@ -435,47 +507,21 @@ Configuration:
status.text = errorStyle + errMsg status.text = errorStyle + errMsg
dismissMsgDate = new Date(new Date().time + msgTimeout) } dismissMsgDate = new Date(new Date().time + msgTimeout) }
private String makeAlbumList(def albums, boolean listAll) { private String makeList(Class modelClass, def items,
boolean listAll = false, Closure toString = null) {
def result = new StringBuilder() def result = new StringBuilder()
.append("--------------------\nAlbums") .append("--------------------\n${modelClass.simpleName}")
if (!listAll && (selection.playlist || selection.artist || if (!listAll && (selection.playlist || selection.artist ||
selection.mediaFile)) selection.mediaFile))
result.append("\n(for selection: ") result.append("\n(for selection: ")
.append(describeSelection()) .append(describeSelection())
.append(normalStyle)
.append(")")
result.append(":\n\n") result.append(":\n\n")
result.append(albums.collect { "${it.id}: ${it}" }.join("\n")) result.append(items.collect( toString ?: { it.toString() }).join("\n"))
.append("\n")
return result.toString() }
private String makeArtistList(def artists, boolean listAll) {
def result = new StringBuilder()
.append("--------------------\nArists")
if (!listAll && (selection.playlist || selection.artist ||
selection.mediaFile))
result.append("\n(for selection: ")
.append(describeSelection())
result.append(":\n\n")
result.append(artists.collect { "${it.id}: ${it.name}" }.join("\n"))
.append("\n")
return result.toString() }
private String makeMediaFileList(def mediaFiles, boolean listAll) {
def result = new StringBuilder()
.append("--------------------\nMedia Files")
if (!listAll && (selection.playlist || selection.artist ||
selection.mediaFile))
result.append("\n(for selection: ")
.append(describeSelection())
result.append(":\n\n")
result.append(mediaFiles.collect { "${it.id}: ${it.trackNumber} - ${it.name}" }.join("\n"))
.append("\n") .append("\n")
return result.toString() } return result.toString() }
@ -505,6 +551,14 @@ Configuration:
return s.toString() return s.toString()
} }
private getSelectedMediaFiles() {
if (selection.mediaFile) return selection.mediaFile
return list = library.getMediaFilesWhere(
playlistId: selection?.playlist?.id,
artistId: selection?.artist?.id,
albumId: selection?.album?.id) }
private String resetStatus() { private String resetStatus() {
String s = describeSelection() String s = describeSelection()