Added the relevant source files.
This commit is contained in:
310
capture.c
Normal file
310
capture.c
Normal file
@@ -0,0 +1,310 @@
|
|||||||
|
#include <linux/input.h>
|
||||||
|
#include <linux/input-event-codes.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
int callSound(char* path)
|
||||||
|
{
|
||||||
|
int child = fork();
|
||||||
|
if (child == 0)
|
||||||
|
{
|
||||||
|
char finalPath[60];
|
||||||
|
strcpy(finalPath, getenv("HOME"));
|
||||||
|
strcat(finalPath, "/.local/share/sounds/");
|
||||||
|
strcat(finalPath, path);
|
||||||
|
|
||||||
|
execlp("ffmpeg", "ffmpeg", "-loglevel", "error", "-i", finalPath, "-f", "alsa", "default", NULL);
|
||||||
|
}
|
||||||
|
else if (child < 0)
|
||||||
|
{
|
||||||
|
printf("Could not generate sound %s\n", path);
|
||||||
|
exit(5);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void callErrorSound(int code)
|
||||||
|
{
|
||||||
|
int returnCode = callSound("error.wav");
|
||||||
|
wait(NULL);
|
||||||
|
for (int i = 0; i < code; i++)
|
||||||
|
{
|
||||||
|
returnCode = callSound("bit.wav");
|
||||||
|
wait(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
const int NUM_KEYS = 249;
|
||||||
|
const int ARG_LENGTH = 20;
|
||||||
|
const int MAX_ARGS = 20;
|
||||||
|
char validChars[NUM_KEYS][2];
|
||||||
|
for (int i = 0; i < NUM_KEYS; i++)
|
||||||
|
{
|
||||||
|
switch (i)
|
||||||
|
{
|
||||||
|
case KEY_0:
|
||||||
|
validChars[i][0] = '0';
|
||||||
|
validChars[i][1] = '0';
|
||||||
|
break;
|
||||||
|
case KEY_1:
|
||||||
|
validChars[i][0] = '1';
|
||||||
|
validChars[i][1] = '1';
|
||||||
|
break;
|
||||||
|
case KEY_2:
|
||||||
|
validChars[i][0] = '2';
|
||||||
|
validChars[i][1] = '2';
|
||||||
|
break;
|
||||||
|
case KEY_3:
|
||||||
|
validChars[i][0] = '3';
|
||||||
|
validChars[i][1] = '3';
|
||||||
|
break;
|
||||||
|
case KEY_4:
|
||||||
|
validChars[i][0] = '4';
|
||||||
|
validChars[i][1] = '4';
|
||||||
|
break;
|
||||||
|
case KEY_5:
|
||||||
|
validChars[i][0] = '5';
|
||||||
|
validChars[i][1] = '5';
|
||||||
|
break;
|
||||||
|
case KEY_6:
|
||||||
|
validChars[i][0] = '6';
|
||||||
|
validChars[i][1] = '6';
|
||||||
|
break;
|
||||||
|
case KEY_7:
|
||||||
|
validChars[i][0] = '7';
|
||||||
|
validChars[i][1] = '7';
|
||||||
|
break;
|
||||||
|
case KEY_8:
|
||||||
|
validChars[i][0] = '8';
|
||||||
|
validChars[i][1] = '8';
|
||||||
|
break;
|
||||||
|
case KEY_9:
|
||||||
|
validChars[i][0] = '9';
|
||||||
|
validChars[i][1] = '9';
|
||||||
|
break;
|
||||||
|
case KEY_A:
|
||||||
|
validChars[i][0] = 'A';
|
||||||
|
validChars[i][1] = 'a';
|
||||||
|
break;
|
||||||
|
case KEY_B:
|
||||||
|
validChars[i][0] = 'B';
|
||||||
|
validChars[i][1] = 'b';
|
||||||
|
break;
|
||||||
|
case KEY_C:
|
||||||
|
validChars[i][0] = 'C';
|
||||||
|
validChars[i][1] = 'c';
|
||||||
|
break;
|
||||||
|
case KEY_D:
|
||||||
|
validChars[i][0] = 'D';
|
||||||
|
validChars[i][1] = 'd';
|
||||||
|
break;
|
||||||
|
case KEY_E:
|
||||||
|
validChars[i][0] = 'E';
|
||||||
|
validChars[i][1] = 'e';
|
||||||
|
break;
|
||||||
|
case KEY_F:
|
||||||
|
validChars[i][0] = 'F';
|
||||||
|
validChars[i][1] = 'f';
|
||||||
|
break;
|
||||||
|
case KEY_G:
|
||||||
|
validChars[i][0] = 'G';
|
||||||
|
validChars[i][1] = 'g';
|
||||||
|
break;
|
||||||
|
case KEY_H:
|
||||||
|
validChars[i][0] = 'H';
|
||||||
|
validChars[i][1] = 'h';
|
||||||
|
break;
|
||||||
|
case KEY_I:
|
||||||
|
validChars[i][0] = 'I';
|
||||||
|
validChars[i][1] = 'i';
|
||||||
|
break;
|
||||||
|
case KEY_J:
|
||||||
|
validChars[i][0] = 'J';
|
||||||
|
validChars[i][1] = 'j';
|
||||||
|
break;
|
||||||
|
case KEY_K:
|
||||||
|
validChars[i][0] = 'K';
|
||||||
|
validChars[i][1] = 'k';
|
||||||
|
break;
|
||||||
|
case KEY_L:
|
||||||
|
validChars[i][0] = 'L';
|
||||||
|
validChars[i][1] = 'l';
|
||||||
|
break;
|
||||||
|
case KEY_M:
|
||||||
|
validChars[i][0] = 'M';
|
||||||
|
validChars[i][1] = 'm';
|
||||||
|
break;
|
||||||
|
case KEY_N:
|
||||||
|
validChars[i][0] = 'N';
|
||||||
|
validChars[i][1] = 'n';
|
||||||
|
break;
|
||||||
|
case KEY_O:
|
||||||
|
validChars[i][0] = 'O';
|
||||||
|
validChars[i][1] = 'o';
|
||||||
|
break;
|
||||||
|
case KEY_P:
|
||||||
|
validChars[i][0] = 'P';
|
||||||
|
validChars[i][1] = 'p';
|
||||||
|
break;
|
||||||
|
case KEY_Q:
|
||||||
|
validChars[i][0] = 'Q';
|
||||||
|
validChars[i][1] = 'q';
|
||||||
|
break;
|
||||||
|
case KEY_R:
|
||||||
|
validChars[i][0] = 'R';
|
||||||
|
validChars[i][1] = 'r';
|
||||||
|
break;
|
||||||
|
case KEY_S:
|
||||||
|
validChars[i][0] = 'S';
|
||||||
|
validChars[i][1] = 's';
|
||||||
|
break;
|
||||||
|
case KEY_T:
|
||||||
|
validChars[i][0] = 'T';
|
||||||
|
validChars[i][1] = 't';
|
||||||
|
break;
|
||||||
|
case KEY_U:
|
||||||
|
validChars[i][0] = 'U';
|
||||||
|
validChars[i][1] = 'u';
|
||||||
|
break;
|
||||||
|
case KEY_V:
|
||||||
|
validChars[i][0] = 'V';
|
||||||
|
validChars[i][1] = 'v';
|
||||||
|
break;
|
||||||
|
case KEY_W:
|
||||||
|
validChars[i][0] = 'W';
|
||||||
|
validChars[i][1] = 'w';
|
||||||
|
break;
|
||||||
|
case KEY_X:
|
||||||
|
validChars[i][0] = 'X';
|
||||||
|
validChars[i][1] = 'x';
|
||||||
|
break;
|
||||||
|
case KEY_Y:
|
||||||
|
validChars[i][0] = 'Y';
|
||||||
|
validChars[i][1] = 'y';
|
||||||
|
break;
|
||||||
|
case KEY_Z:
|
||||||
|
validChars[i][0] = 'Z';
|
||||||
|
validChars[i][1] = 'z';
|
||||||
|
break;
|
||||||
|
case KEY_MINUS:
|
||||||
|
validChars[i][0] = '_';
|
||||||
|
validChars[i][1] = '-';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
validChars[i][0] = 0;
|
||||||
|
validChars[i][1] = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need this command for when we trigger the app from the command line,
|
||||||
|
* because otherwise the upstroke on the enter key will kill the app.
|
||||||
|
*/
|
||||||
|
int waitEnter = 0;
|
||||||
|
char* ARGS[MAX_ARGS];
|
||||||
|
int numArgs = 0;
|
||||||
|
ARGS[numArgs++] = "play";
|
||||||
|
//ARGS[numArgs++] = "--directory=/home/markil3/.local/share/lollypop";
|
||||||
|
char* BUFFER = (char*) calloc(ARG_LENGTH, sizeof(char));
|
||||||
|
int index = 0;
|
||||||
|
BUFFER[index] = '\0';
|
||||||
|
int fd;
|
||||||
|
int len;
|
||||||
|
if(argc < 2) {
|
||||||
|
printf("usage: %s <device>\n", argv[0]);
|
||||||
|
callErrorSound(1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = open(argv[1], O_RDONLY);
|
||||||
|
|
||||||
|
if (fd < 0)
|
||||||
|
{
|
||||||
|
callErrorSound(2);
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
struct input_event ev;
|
||||||
|
|
||||||
|
callSound("triggerActivate.wav");
|
||||||
|
|
||||||
|
while (len >= 0 && ev.value != 0 || waitEnter == 0 || (ev.code != KEY_ENTER && ev.code != KEY_ESC))
|
||||||
|
{
|
||||||
|
len = read(fd, &ev, sizeof(struct input_event));
|
||||||
|
|
||||||
|
if (len < 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ev.code == KEY_ENTER || ev.code == KEY_ESC) && ev.value == 1)
|
||||||
|
{
|
||||||
|
waitEnter = 1;
|
||||||
|
}
|
||||||
|
if (ev.type == 1 && ev.value == 1)
|
||||||
|
{
|
||||||
|
//printf("Keycode: %i, status %i\n", ev.code, ev.value);
|
||||||
|
if ((ev.code == KEY_SPACE || ev.code == KEY_ENTER) && index > 0)
|
||||||
|
{
|
||||||
|
if (ev.code == KEY_SPACE)
|
||||||
|
{
|
||||||
|
callSound("bit.wav");
|
||||||
|
}
|
||||||
|
BUFFER[index] = '\0';
|
||||||
|
ARGS[numArgs++] = BUFFER;
|
||||||
|
BUFFER = (char*) calloc(ARG_LENGTH, sizeof(char));
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
else if (ev.code < NUM_KEYS && validChars[ev.code][1] != 0)
|
||||||
|
{
|
||||||
|
if (index < ARG_LENGTH)
|
||||||
|
{
|
||||||
|
BUFFER[index++] = validChars[ev.code][1];
|
||||||
|
BUFFER[index] = '\0';
|
||||||
|
callSound("bit.wav");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
ARGS[numArgs] = NULL;
|
||||||
|
|
||||||
|
if (len < 0)
|
||||||
|
{
|
||||||
|
callErrorSound(3);
|
||||||
|
exit(3);
|
||||||
|
}
|
||||||
|
if (index > 0)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* If index was not reset, then we canceled.
|
||||||
|
*/
|
||||||
|
callSound("end.wav");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
callSound("triggerDeactivate.wav");
|
||||||
|
|
||||||
|
printf("Running args: ");
|
||||||
|
for (int i = 0; i <= numArgs; i++)
|
||||||
|
{
|
||||||
|
printf("'%s' ", ARGS[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
execvp(ARGS[0], ARGS);
|
||||||
|
}
|
||||||
272
play
Normal file
272
play
Normal file
@@ -0,0 +1,272 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
import pathlib
|
||||||
|
from pathlib import Path
|
||||||
|
from urllib import parse
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import random
|
||||||
|
from os.path import exists
|
||||||
|
import sqlite3
|
||||||
|
|
||||||
|
'''
|
||||||
|
A sorting method for songs. It works by pushing file names with more matches up higher.
|
||||||
|
'''
|
||||||
|
def getValueFunction(terms):
|
||||||
|
def valOfResult(song):
|
||||||
|
val = 0
|
||||||
|
for arg in terms:
|
||||||
|
for part in song[2:]:
|
||||||
|
if arg in part.lower():
|
||||||
|
val -= 1
|
||||||
|
# Double every point received by a playlist
|
||||||
|
if song[0] == True:
|
||||||
|
val -= 1
|
||||||
|
#print("%s got %d hits" % (song, val))
|
||||||
|
return val
|
||||||
|
return valOfResult
|
||||||
|
|
||||||
|
'''
|
||||||
|
Merges certain words into one. This is helpful for voice commands
|
||||||
|
'''
|
||||||
|
def mergeWords(argList):
|
||||||
|
i = 0
|
||||||
|
quoting = False
|
||||||
|
while i < len(argList):
|
||||||
|
# Merge underscore for handling later
|
||||||
|
if quoting:
|
||||||
|
if argList[i] != "unquote":
|
||||||
|
argList[i - 1] = argList[i - 1] + " " + argList[i]
|
||||||
|
else:
|
||||||
|
quoting = False
|
||||||
|
del argList[i]
|
||||||
|
i -= 1
|
||||||
|
elif argList[i] == "quote":
|
||||||
|
quoting = True
|
||||||
|
del argList[i]
|
||||||
|
elif i < len(argList) - 1 and argList[i] == "under" and argList[i + 1] == "score":
|
||||||
|
argList[i] = "underscore"
|
||||||
|
del argList[i + 1]
|
||||||
|
elif i < len(argList) - 1 and argList[i] == "play" and argList[i + 1] == "list":
|
||||||
|
argList[i] = "playlist"
|
||||||
|
del argList[i + 1]
|
||||||
|
if argList[i] == "dot":
|
||||||
|
argList[i - 1] = argList[i - 1] + "."
|
||||||
|
del argList[i]
|
||||||
|
i -= 1
|
||||||
|
elif argList[i] == "underscore":
|
||||||
|
argList[i - 1] = argList[i - 1] + "_"
|
||||||
|
del argList[i]
|
||||||
|
i -= 1
|
||||||
|
elif i < len(argList) - 1 and argList[i] == "dash":
|
||||||
|
argList[i] = "-" + argList[i + 1]
|
||||||
|
del argList[i + 1]
|
||||||
|
elif argList[i - 1].endswith(".") or argList[i - 1].endswith("_"):
|
||||||
|
argList[i - 1] = argList[i - 1] + argList[i]
|
||||||
|
del argList[i]
|
||||||
|
i -= 1
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
return argList
|
||||||
|
|
||||||
|
def extractOptions(args):
|
||||||
|
options = {}
|
||||||
|
i = 0
|
||||||
|
while i < len(args):
|
||||||
|
# Some dashed fields have special meanings.
|
||||||
|
if args[i].startswith("-") and args[i] != "-or" and args[i] != "-and" and args[i] != "--or" and args[i] != "--and":
|
||||||
|
if args[i].startswith("--"):
|
||||||
|
if "=" in args[i]:
|
||||||
|
options[args[i][2:args[i].index("=")]] = args[i][args[i].index("=") + 1:]
|
||||||
|
else:
|
||||||
|
options[args[i][2:]] = True
|
||||||
|
# These two have special meanings
|
||||||
|
else:
|
||||||
|
for char in args[i][1:]:
|
||||||
|
options[char] = True
|
||||||
|
del args[i]
|
||||||
|
elif args[i] == "playlist" or args[i] == "m3u":
|
||||||
|
options["playlist"] = True
|
||||||
|
del args[i]
|
||||||
|
elif args[i].endswith(".m3u"):
|
||||||
|
options["playlist"] = True
|
||||||
|
args[i] = args[i][0:args[i].rindex(".m3u")]
|
||||||
|
i += 1
|
||||||
|
else:
|
||||||
|
i += 1
|
||||||
|
return options
|
||||||
|
|
||||||
|
def searchFiles(terms, options):
|
||||||
|
musicHome = Path(Path.home(), "Music")
|
||||||
|
if not musicHome.is_dir():
|
||||||
|
# We are probably on Windows
|
||||||
|
musicHome = Path(Path.home(), "My Music")
|
||||||
|
|
||||||
|
findArgs = ["find", str(musicHome)]
|
||||||
|
terms = appendSearchArguments(findArgs, sys.argv[1:], options)
|
||||||
|
print(" ".join(findArgs))
|
||||||
|
print()
|
||||||
|
process = subprocess.Popen(findArgs, stdout=subprocess.PIPE)
|
||||||
|
output, error = process.communicate()
|
||||||
|
files = output.decode().split("\n")
|
||||||
|
# Remove any empty things
|
||||||
|
while "" in files:
|
||||||
|
files.remove("")
|
||||||
|
return files
|
||||||
|
|
||||||
|
'''
|
||||||
|
Compiles all arguments in the argument list into a SQLite search term
|
||||||
|
|
||||||
|
@return A set of search terms provided, stripped of all extra arguments.
|
||||||
|
'''
|
||||||
|
def appendDatabaseArguments(argList, args, options, playlist):
|
||||||
|
notArgs = []
|
||||||
|
terms = set()
|
||||||
|
if len(args) > 0:
|
||||||
|
for arg in args:
|
||||||
|
if arg.startswith("!"):
|
||||||
|
notArgs.append(arg[1:])
|
||||||
|
elif arg == "AND" or arg == "and" or arg == "-and" or arg =="--and" or arg == "&&":
|
||||||
|
# Override whatever AND/OR we had before
|
||||||
|
argList.pop()
|
||||||
|
argList.append("AND")
|
||||||
|
elif arg == "OR" or arg == "or" or arg == "-or" or arg =="--or" or arg == "||":
|
||||||
|
# Override whatever AND/OR we had before
|
||||||
|
argList.pop()
|
||||||
|
argList.append("OR")
|
||||||
|
else:
|
||||||
|
argList.append("(")
|
||||||
|
if playlist:
|
||||||
|
argList.append("playlists.name")
|
||||||
|
argList.append("LIKE")
|
||||||
|
argList.append("'%" + arg + "%'")
|
||||||
|
else:
|
||||||
|
argList.append("tracks.name")
|
||||||
|
argList.append("LIKE")
|
||||||
|
argList.append("'%" + arg + "%'")
|
||||||
|
argList.append("OR")
|
||||||
|
argList.append("albums.name")
|
||||||
|
argList.append("LIKE")
|
||||||
|
argList.append("'%" + arg + "%'")
|
||||||
|
argList.append("OR")
|
||||||
|
argList.append("artists.name")
|
||||||
|
argList.append("LIKE")
|
||||||
|
argList.append("'%" + arg + "%'")
|
||||||
|
argList.append(")")
|
||||||
|
terms.add(arg)
|
||||||
|
if "a" in options:
|
||||||
|
argList.append("AND")
|
||||||
|
else:
|
||||||
|
argList.append("OR")
|
||||||
|
if argList[len(argList) - 1] == "AND" or argList[len(argList) - 1] == "OR":
|
||||||
|
argList.pop()
|
||||||
|
if len(notArgs) > 0:
|
||||||
|
argList.append("AND")
|
||||||
|
for arg in notArgs:
|
||||||
|
argList.append("tracks.name")
|
||||||
|
argList.append("NOT")
|
||||||
|
argList.append("LIKE")
|
||||||
|
argList.append("'%" + arg + "%'")
|
||||||
|
argList.append("AND")
|
||||||
|
argList.pop()
|
||||||
|
return terms
|
||||||
|
|
||||||
|
def searchDatabase(options):
|
||||||
|
files = []
|
||||||
|
|
||||||
|
if "directory" in options:
|
||||||
|
dbDir = Path(options["directory"])
|
||||||
|
else:
|
||||||
|
dbDir = Path(Path.home(), ".local/share/lollypop")
|
||||||
|
|
||||||
|
if "playlist" in options:
|
||||||
|
db = sqlite3.connect(str(Path(dbDir, "playlists.db")))
|
||||||
|
findArgs = "SELECT tracks.uri, playlists.name FROM tracks INNER JOIN playlists ON tracks.playlist_id = playlists.id WHERE".split(" ")
|
||||||
|
terms = appendDatabaseArguments(findArgs, sys.argv[1:], options, True)
|
||||||
|
findArgs = " ".join(findArgs) + ";"
|
||||||
|
results = db.execute(findArgs);
|
||||||
|
for row in results:
|
||||||
|
files.append((True,) + row)
|
||||||
|
db.close()
|
||||||
|
db = sqlite3.connect(str(Path(dbDir, "lollypop.db")))
|
||||||
|
findArgs = "SELECT tracks.uri, tracks.name, albums.name, artists.name FROM tracks INNER JOIN albums ON tracks.album_id = albums.id INNER JOIN track_artists ON tracks.id = track_artists.track_id INNER JOIN artists ON track_artists.artist_id = artists.id WHERE".split(" ")
|
||||||
|
terms = appendDatabaseArguments(findArgs, sys.argv[1:], options, False)
|
||||||
|
findArgs = " ".join(findArgs) + ";"
|
||||||
|
results = db.execute(findArgs);
|
||||||
|
for row in results:
|
||||||
|
files.append((False,) + row)
|
||||||
|
db.close()
|
||||||
|
|
||||||
|
return (files, terms)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# Checks if VLC is installed
|
||||||
|
missing = subprocess.call("command -v vlc >> /dev/null", shell=True)
|
||||||
|
if missing:
|
||||||
|
print("VLC Media Player is not installed", file=sys.stderr)
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
print(sys.argv)
|
||||||
|
mergeWords(sys.argv)
|
||||||
|
options = extractOptions(sys.argv)
|
||||||
|
if "h" in options or "help" in options:
|
||||||
|
print("""Usage: %s [OPTIONS]... [TERM]...
|
||||||
|
Searches for a song within the music collection
|
||||||
|
|
||||||
|
OPTIONS:
|
||||||
|
--directory=[dir] Define the database directory.
|
||||||
|
-a The search must match every single term
|
||||||
|
-v Displays the media player
|
||||||
|
-l Loops through the found files until a new command is entered.
|
||||||
|
-s Only the first option will play.
|
||||||
|
-h, --help Shows this message
|
||||||
|
|
||||||
|
TERMS:
|
||||||
|
For the most part, you can just enter a single-word term, and it will be added
|
||||||
|
to the possible substrings included in the file name search. However, there are
|
||||||
|
a few additional ways to refine your search.
|
||||||
|
|
||||||
|
-and, --and, AND, and Any of these keywords will cause the previous and next
|
||||||
|
terms to be linked together, so that they MUST appear
|
||||||
|
for the file to qualify.
|
||||||
|
-or, --or, OR, or Any of these keywords will cause the previous and next
|
||||||
|
terms to be linked together, so that only one or the
|
||||||
|
other needs to appear for the file to qualify.
|
||||||
|
Overrides the -a option for those two terms.
|
||||||
|
! Add this to the beginning of a term to ensure that the
|
||||||
|
keyword does NOT appear in any matching file paths.
|
||||||
|
m3u, playlist Normally, playlists are ignored during the file search.
|
||||||
|
However, this term will not only allow for their
|
||||||
|
search, but will also give them higher precedence.""" % (sys.argv[0]))
|
||||||
|
exit(0)
|
||||||
|
|
||||||
|
files, terms = searchDatabase(options)
|
||||||
|
|
||||||
|
if len(files) == 0:
|
||||||
|
print("No files found", file=sys.stderr)
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
random.shuffle(files)
|
||||||
|
files.sort(key=getValueFunction(terms))
|
||||||
|
for i in range(len(files)):
|
||||||
|
files[i] = files[i][1]
|
||||||
|
if "s" in options:
|
||||||
|
files = [files[0]]
|
||||||
|
for song in files:
|
||||||
|
print(song)
|
||||||
|
|
||||||
|
if "v" in options:
|
||||||
|
vlcArgs = ["vlc"]
|
||||||
|
else:
|
||||||
|
vlcArgs = ["cvlc"]
|
||||||
|
if "l" in options:
|
||||||
|
vlcArgs.append("--loop")
|
||||||
|
else:
|
||||||
|
files.append("vlc://quit")
|
||||||
|
vlcArgs += files
|
||||||
|
#print(" ".join(vlcArgs))
|
||||||
|
print("Launching VLC: %s" % (vlcArgs))
|
||||||
|
process = subprocess.Popen(vlcArgs, stdout=sys.stdout, stderr=sys.stderr)
|
||||||
|
if not "l" in options:
|
||||||
|
exit(process.wait())
|
||||||
|
else:
|
||||||
|
exit(0)
|
||||||
Reference in New Issue
Block a user