Skip to content

Commit

Permalink
v1.9
Browse files Browse the repository at this point in the history
- Added support for custom formatting!
  You can use the following placeholders:
        - %title
        - %artist
        - %date
        - %album
  There are multiple ways to use this feature:
        1.  using command-line arguments
                ```--top, -t``` "format string"
                ```--bottom, -b``` "format string"
        2.  using a configuration file
                Make sure it's called "cmusrp.conf", is in the same directory as the jar file and contains the following:
                ```
                TOP_FORMAT="format string goes here"
                BOTTOM_FORMAT="format string goes here"
                ```
  • Loading branch information
pascalpuffke committed Dec 22, 2020
1 parent 1c7ae3c commit ace393a
Show file tree
Hide file tree
Showing 6 changed files with 183 additions and 14 deletions.
29 changes: 26 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,33 @@ External Discord Rich Presence plugin for the C* music player. Linux only.
- ```--interval [value]``` ```-i [value]```: Changes polling interval, in ms. Default: 1000
- ```--quiet``` ```-q```: Disables console output
- ```--help``` ```-h```: Shows the help screen and then exits
- ```--top``` ```-t```: Sets the top format string. It's recommended to change this in the cmusrp.conf file. Default: "%artist - %title"
- ```--bottom``` ```-b```: Sets the bottom format string. It's recommended to change this in the cmusrp.conf file. Default: "from %album (%year)"

## Future plans
- Display current and remaining time. This is a little difficult though, as it would require coming up with a different updating method and I don't know how to realize this yet
- Easy customization options
Note that command line arguments have priority over the cmusrp.conf configuration file.

## Configuration file
This program creates a configuration file when it doesn't already exist in the same directory as the jar file.

It was made as an easier way to customize how this tool behaves and displays information. By default, it looks like this:
```
DEBUG=false
QUIET=false
INTERVAL=1000
TOP_FORMAT="%artist - %title"
BOTTOM_FORMAT="from %album (%date)"
```

The syntax should be pretty straight forward. See the Options paragraph for more information about the different values.

You can customize the top and bottom format using these placeholders:
- %artist
- %title
- %album
- %date

**Note: ** If you don't like the way this program handles its configuration file, please continue using version 1.8 and wait for 2.0 to come out, where I will put the config file in more appropriate places (or even custom ones).
As of now, this is only an admittedly janky solution to finally have this functionality implemented.

## Dependencies
- **Java 8**
Expand Down
5 changes: 5 additions & 0 deletions cmusrp.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
DEBUG=false
QUIET=false
INTERVAL=1000
TOP_FORMAT="%artist - %title"
BOTTOM_FORMAT="from %album (%date)"
29 changes: 24 additions & 5 deletions src/de/mineclashtv/Main.java
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
package de.mineclashtv;

import de.mineclashtv.utils.ArgumentHandler;
import de.mineclashtv.utils.ConfigurationFile;
import de.mineclashtv.utils.Updater;
import net.arikia.dev.drpc.DiscordRPC;

import java.io.IOException;

public class Main {

/** When set to <code>true</code>, DiscordRPC won't be initialized and verbose console output gets enabled. */
public static boolean debug = false;
public static boolean debug;
/** When set to <code>true</code>, all console output gets disabled. */
public static boolean quiet = false;
public static boolean quiet;
/** How often to update DiscordRPC in ms */
public static int interval = 1000;
public static int interval;
/** While set to <code>true</code>, the update loop will run. */
public static boolean run = false;
private static final String VER = "1.8";
private static final String VER = "1.9";
private static final String ID = "718109162923360327";
/** Text to display when user hovers over icon */
public static final String ICON_TEXT = String.format("[v%s] C* music player", VER);
public static final ConfigurationFile configurationFile = new ConfigurationFile();

public static void main(String[] args) {
// The DiscordRPC library does not currently support macOS, so display this error message instead of pretending to work
Expand All @@ -26,7 +30,22 @@ public static void main(String[] args) {
System.exit(1);
}

ArgumentHandler.parseArguments(args);
try {
configurationFile.initialize();

debug = (boolean) configurationFile.getValue("debug");
quiet = (boolean) configurationFile.getValue("quiet");
interval = (int) configurationFile.getValue("interval");
} catch(IOException exception) {
System.err.println("Could not access config file!");
exception.printStackTrace();
}

try {
ArgumentHandler.parseArguments(args);
} catch (IOException exception) {
exception.printStackTrace();
}

if(!debug) {
DiscordRPC.discordInitialize(ID, null, true);
Expand Down
24 changes: 20 additions & 4 deletions src/de/mineclashtv/utils/ArgumentHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,25 @@

import de.mineclashtv.Main;

import java.io.IOException;

import static de.mineclashtv.Main.printf;

public class ArgumentHandler {

private static final String HELP_MESSAGE =
public static final String HELP_MESSAGE =
"Usage: java -jar cmus-rich-presence-x.x.jar [OPTION...]\n\n" +
"\t--debug, -d\t\t\tDisables rich presence functionality and shows more verbose console output\n" +
"\t--interval [value], -i\t\tChanges polling interval, in ms. Default: 1000\n" +
"\t--interval, -i\t\tChanges polling interval, in ms. Default: 1000\n" +
"\t--quiet, -q\t\t\tDisables all console output\n" +
"\t--help, -h\t\t\tShows this text\n\n" +
"\t--help, -h\t\t\tShows this text\n" +
"\t--top, -t\t\t\tSets custom formatting for the top string. Default: \"%artist - %title\"\n" +
"\t--bottom, -b\t\tSets custom formatting for the bottom string. Default: \"from %album (%date)\"\n\n" +
"This program requires you to use a GNU/Linux-based operating system.\n" +
"The DiscordRPC library this program uses doesn't yet support macOS.\n"
;

public static void parseArguments(String[] args) {
public static void parseArguments(String[] args) throws IOException {
for(int i = 0; i < args.length; i++) {
switch(args[i]) {
case "-d":
Expand All @@ -38,6 +42,18 @@ public static void parseArguments(String[] args) {
case "--help":
printf(HELP_MESSAGE);
System.exit(0);
case "-t":
case "--top":
Main.configurationFile.replaceValue(
"top_format", args[i + 1].substring(1, args[i + 1].length() - 1)
);
break;
case "-b":
case "--bottom":
Main.configurationFile.replaceValue(
"bottom_format", args[i + 1].substring(1, args[i + 1].length() - 1)
);
break;
default:
break;
}
Expand Down
79 changes: 79 additions & 0 deletions src/de/mineclashtv/utils/ConfigurationFile.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package de.mineclashtv.utils;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;

public class ConfigurationFile {

/*
The procedure is as follows:
1. Check if a config file already exists
- if it does, use that;
- otherwise, create one with the default values (DEFAULT_CONFIG string).
2. Parse every line and search for supported keywords.
- These are: DEBUG, QUIET, INTERVAL, TOP_FORMAT, BOTTOM_FORMAT.
3. Put the results from step 2 into a HashMap (CONFIG_MAP)
4. Use the values from the generated HashMap elsewhere
*/

private final String DEFAULT_CONFIG =
"DEBUG=false\n" +
"QUIET=false\n" +
"INTERVAL=1000\n" +
"TOP_FORMAT=\"%artist - %title\"\n" +
"BOTTOM_FORMAT=\"from %album (%date)\"\n"
;
private final Map<String, Object> CONFIG_MAP = new HashMap<>();

private final Path WORKING_DIR = Paths.get(System.getProperty("user.dir"));
private final Path CONFIG_FILE = Paths.get(WORKING_DIR.toString() + "/cmusrp.conf");

public void initialize() throws IOException {
if(!Files.exists(CONFIG_FILE))
createDefault(CONFIG_FILE);
}

public void createDefault(Path path) throws IOException {
Files.write(path, DEFAULT_CONFIG.getBytes());
}

public Object getValue(String key) throws IOException {
if(this.CONFIG_MAP.isEmpty())
populateConfigMap(read(CONFIG_FILE));

return CONFIG_MAP.get(key);
}

public void replaceValue(String key, Object value) throws IOException {
if(this.CONFIG_MAP.isEmpty())
populateConfigMap(read(CONFIG_FILE));

this.CONFIG_MAP.replace(key, value);
}

private String read(Path path) throws IOException {
return new String(Files.readAllBytes(path));
}

private void populateConfigMap(String data) {
/* Maybe there is a better way to do this. */
for(String s : data.split("\n")) {
if(s.startsWith("DEBUG="))
CONFIG_MAP.put("debug", Boolean.parseBoolean(s.substring(6)));
else if(s.startsWith("QUIET="))
CONFIG_MAP.put("quiet", Boolean.parseBoolean(s.substring(6)));
else if(s.startsWith("INTERVAL="))
CONFIG_MAP.put("interval", Integer.parseInt(s.substring(9)));
else if(s.startsWith("TOP_FORMAT="))
CONFIG_MAP.put("top_format", s.substring(12, s.length() - 1));
else if(s.startsWith("BOTTOM_FORMAT="))
CONFIG_MAP.put("bottom_format", s.substring(15, s.length() - 1));
else
System.out.println("Unknown config '" + s + "'.");
}
}
}
31 changes: 29 additions & 2 deletions src/de/mineclashtv/utils/DiscordRichPresenceFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,24 @@
import de.mineclashtv.Main;
import net.arikia.dev.drpc.DiscordRichPresence;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class DiscordRichPresenceFactory {

public static Map<String, String> format = new HashMap<>();

static {
try {
format.put("bottom", (String) Main.configurationFile.getValue("bottom_format"));
format.put("top", (String) Main.configurationFile.getValue("top_format"));
} catch (IOException exception) {
exception.printStackTrace();
}
}

/**
* Creates a formatted <code>DiscordRichPresence</code> object with all available information.<br/>
* If the currently playing song does not have a title tag, it will use the full filename instead.
Expand All @@ -20,9 +36,20 @@ public static DiscordRichPresence getRichPresence(Parser parser, String iconText
String artist = parser.getArtist();
String title = parser.getTitle();

String top = format.get("top")
.replace("%album", album)
.replace("%date", date)
.replace("%artist", artist)
.replace("%title", title);
String bottom = format.get("bottom")
.replace("%album", album)
.replace("%date", date)
.replace("%artist", artist)
.replace("%title", title);

return new DiscordRichPresence
.Builder("from " + album + " (" + date + ")")
.setDetails(artist + " - " + title)
.Builder(bottom)
.setDetails(top)
.setBigImage("icon", iconText)
.build();
} else { // Song isn't tagged properly; show filename
Expand Down

0 comments on commit ace393a

Please sign in to comment.