From 88c9b7050ce03a4a9bd37f0238dff56fb5c514f4 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Sat, 20 Sep 2014 08:03:52 -0700 Subject: Add tags lib from adrian-bl/vanilla --- src/github/daneren2005/dsub/util/tags/Bastp.java | 85 ++++++++++++ .../daneren2005/dsub/util/tags/BastpUtil.java | 78 +++++++++++ src/github/daneren2005/dsub/util/tags/Common.java | 111 ++++++++++++++++ .../daneren2005/dsub/util/tags/FlacFile.java | 85 ++++++++++++ .../daneren2005/dsub/util/tags/ID3v2File.java | 148 +++++++++++++++++++++ .../daneren2005/dsub/util/tags/LameHeader.java | 70 ++++++++++ src/github/daneren2005/dsub/util/tags/OggFile.java | 114 ++++++++++++++++ 7 files changed, 691 insertions(+) create mode 100644 src/github/daneren2005/dsub/util/tags/Bastp.java create mode 100644 src/github/daneren2005/dsub/util/tags/BastpUtil.java create mode 100644 src/github/daneren2005/dsub/util/tags/Common.java create mode 100644 src/github/daneren2005/dsub/util/tags/FlacFile.java create mode 100644 src/github/daneren2005/dsub/util/tags/ID3v2File.java create mode 100644 src/github/daneren2005/dsub/util/tags/LameHeader.java create mode 100644 src/github/daneren2005/dsub/util/tags/OggFile.java (limited to 'src/github') diff --git a/src/github/daneren2005/dsub/util/tags/Bastp.java b/src/github/daneren2005/dsub/util/tags/Bastp.java new file mode 100644 index 00000000..aa0a2e25 --- /dev/null +++ b/src/github/daneren2005/dsub/util/tags/Bastp.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2013 Adrian Ulrich + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +package github.daneren2005.dsub.util.tags; + +import java.io.RandomAccessFile; +import java.io.IOException; +import java.util.HashMap; + + +public class Bastp { + + public Bastp() { + } + + public HashMap getTags(String fname) { + HashMap tags = new HashMap(); + try { + RandomAccessFile ra = new RandomAccessFile(fname, "r"); + tags = getTags(ra); + ra.close(); + } + catch(Exception e) { + /* we dont' care much: SOMETHING went wrong. d'oh! */ + } + + return tags; + } + + public HashMap getTags(RandomAccessFile s) { + HashMap tags = new HashMap(); + byte[] file_ff = new byte[4]; + + try { + s.read(file_ff); + String magic = new String(file_ff); + if(magic.equals("fLaC")) { + tags = (new FlacFile()).getTags(s); + } + else if(magic.equals("OggS")) { + tags = (new OggFile()).getTags(s); + } + else if(file_ff[0] == -1 && file_ff[1] == -5) { /* aka 0xfffb in real languages */ + tags = (new LameHeader()).getTags(s); + } + else if(magic.substring(0,3).equals("ID3")) { + tags = (new ID3v2File()).getTags(s); + if(tags.containsKey("_hdrlen")) { + Long hlen = Long.parseLong( tags.get("_hdrlen").toString(), 10 ); + HashMap lameInfo = (new LameHeader()).parseLameHeader(s, hlen); + /* add gain tags if not already present */ + inheritTag("REPLAYGAIN_TRACK_GAIN", lameInfo, tags); + inheritTag("REPLAYGAIN_ALBUM_GAIN", lameInfo, tags); + } + } + tags.put("_magic", magic); + } + catch (IOException e) { + } + return tags; + } + + private void inheritTag(String key, HashMap from, HashMap to) { + if(!to.containsKey(key) && from.containsKey(key)) { + to.put(key, from.get(key)); + } + } + +} + diff --git a/src/github/daneren2005/dsub/util/tags/BastpUtil.java b/src/github/daneren2005/dsub/util/tags/BastpUtil.java new file mode 100644 index 00000000..99279f62 --- /dev/null +++ b/src/github/daneren2005/dsub/util/tags/BastpUtil.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2013 Adrian Ulrich + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package github.daneren2005.dsub.util.tags; + +import android.util.LruCache; +import java.util.HashMap; +import java.util.Vector; + +public class BastpUtil { + private RGLruCache rgCache; + + public BastpUtil() { + rgCache = new RGLruCache(16); /* Cache up to 16 entries */ + } + + + /** Returns the ReplayGain values of 'path' as + */ + public float[] getReplayGainValues(String path) { + float[] cached = rgCache.get(path); + + if(cached == null) { + cached = getReplayGainValuesFromFile(path); + rgCache.put(path, cached); + } + return cached; + } + + + + /** Parse given file and return track,album replay gain values + */ + private float[] getReplayGainValuesFromFile(String path) { + String[] keys = { "REPLAYGAIN_TRACK_GAIN", "REPLAYGAIN_ALBUM_GAIN" }; + float[] adjust= { 0f , 0f }; + HashMap tags = (new Bastp()).getTags(path); + + for (int i=0; i { + public RGLruCache(int size) { + super(size); + } + } + +} + diff --git a/src/github/daneren2005/dsub/util/tags/Common.java b/src/github/daneren2005/dsub/util/tags/Common.java new file mode 100644 index 00000000..51344d90 --- /dev/null +++ b/src/github/daneren2005/dsub/util/tags/Common.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2013 Adrian Ulrich + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +package github.daneren2005.dsub.util.tags; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.HashMap; +import java.util.Vector; + +public class Common { + private static final long MAX_PKT_SIZE = 524288; + + public void xdie(String reason) throws IOException { + throw new IOException(reason); + } + + /* + ** Returns a 32bit int from given byte offset in LE + */ + public int b2le32(byte[] b, int off) { + int r = 0; + for(int i=0; i<4; i++) { + r |= ( b2u(b[off+i]) << (8*i) ); + } + return r; + } + + public int b2be32(byte[] b, int off) { + return swap32(b2le32(b, off)); + } + + public int swap32(int i) { + return((i&0xff)<<24)+((i&0xff00)<<8)+((i&0xff0000)>>8)+((i>>24)&0xff); + } + + /* + ** convert 'byte' value into unsigned int + */ + public int b2u(byte x) { + return (x & 0xFF); + } + + /* + ** Printout debug message to STDOUT + */ + public void debug(String s) { + System.out.println("DBUG "+s); + } + + public HashMap parse_vorbis_comment(RandomAccessFile s, long offset, long payload_len) throws IOException { + HashMap tags = new HashMap(); + int comments = 0; // number of found comments + int xoff = 0; // offset within 'scratch' + int can_read = (int)(payload_len > MAX_PKT_SIZE ? MAX_PKT_SIZE : payload_len); + byte[] scratch = new byte[can_read]; + + // seek to given position and slurp in the payload + s.seek(offset); + s.read(scratch); + + // skip vendor string in format: [LEN][VENDOR_STRING] + xoff += 4 + b2le32(scratch, xoff); // 4 = LEN = 32bit int + comments = b2le32(scratch, xoff); + xoff += 4; + + // debug("comments count = "+comments); + for(int i=0; i scratch.length) + xdie("string out of bounds"); + + String tag_raw = new String(scratch, xoff-clen, clen); + String[] tag_vec = tag_raw.split("=",2); + String tag_key = tag_vec[0].toUpperCase(); + + addTagEntry(tags, tag_key, tag_vec[1]); + } + return tags; + } + + public void addTagEntry(HashMap tags, String key, String value) { + if(tags.containsKey(key)) { + ((Vector)tags.get(key)).add(value); // just add to existing vector + } + else { + Vector vx = new Vector(); + vx.add(value); + tags.put(key, vx); + } + } + +} diff --git a/src/github/daneren2005/dsub/util/tags/FlacFile.java b/src/github/daneren2005/dsub/util/tags/FlacFile.java new file mode 100644 index 00000000..de3584d1 --- /dev/null +++ b/src/github/daneren2005/dsub/util/tags/FlacFile.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2013 Adrian Ulrich + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package github.daneren2005.dsub.util.tags; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.HashMap; +import java.util.Enumeration; + + +public class FlacFile extends Common { + private static final int FLAC_TYPE_COMMENT = 4; // ID of 'VorbisComment's + + public FlacFile() { + } + + public HashMap getTags(RandomAccessFile s) throws IOException { + int xoff = 4; // skip file magic + int retry = 64; + int r[]; + HashMap tags = new HashMap(); + + for(; retry > 0; retry--) { + r = parse_metadata_block(s, xoff); + + if(r[2] == FLAC_TYPE_COMMENT) { + tags = parse_vorbis_comment(s, xoff+r[0], r[1]); + break; + } + + if(r[3] != 0) + break; // eof reached + + // else: calculate next offset + xoff += r[0] + r[1]; + } + return tags; + } + + /* Parses the metadata block at 'offset' and returns + ** [header_size, payload_size, type, stop_after] + */ + private int[] parse_metadata_block(RandomAccessFile s, long offset) throws IOException { + int[] result = new int[4]; + byte[] mb_head = new byte[4]; + int stop_after = 0; + int block_type = 0; + int block_size = 0; + + s.seek(offset); + + if( s.read(mb_head) != 4 ) + xdie("failed to read metadata block header"); + + block_size = b2be32(mb_head,0); // read whole header as 32 big endian + block_type = (block_size >> 24) & 127; // BIT 1-7 are the type + stop_after = (((block_size >> 24) & 128) > 0 ? 1 : 0 ); // BIT 0 indicates the last-block flag + block_size = (block_size & 0x00FFFFFF); // byte 1-7 are the size + + // debug("size="+block_size+", type="+block_type+", is_last="+stop_after); + + result[0] = 4; // hardcoded - only returned to be consistent with OGG parser + result[1] = block_size; + result[2] = block_type; + result[3] = stop_after; + + return result; + } + +} diff --git a/src/github/daneren2005/dsub/util/tags/ID3v2File.java b/src/github/daneren2005/dsub/util/tags/ID3v2File.java new file mode 100644 index 00000000..7710654e --- /dev/null +++ b/src/github/daneren2005/dsub/util/tags/ID3v2File.java @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2013 Adrian Ulrich + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package github.daneren2005.dsub.util.tags; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.HashMap; +import java.util.Enumeration; + + + +public class ID3v2File extends Common { + private static int ID3_ENC_LATIN = 0x00; + private static int ID3_ENC_UTF16LE = 0x01; + private static int ID3_ENC_UTF16BE = 0x02; + private static int ID3_ENC_UTF8 = 0x03; + + public ID3v2File() { + } + + public HashMap getTags(RandomAccessFile s) throws IOException { + HashMap tags = new HashMap(); + + final int v2hdr_len = 10; + byte[] v2hdr = new byte[v2hdr_len]; + + // read the whole 10 byte header into memory + s.seek(0); + s.read(v2hdr); + + int id3v = ((b2be32(v2hdr,0))) & 0xFF; // swapped ID3\04 -> ver. ist the first byte + int v3len = ((b2be32(v2hdr,6))); // total size EXCLUDING the this 10 byte header + v3len = ((v3len & 0x7f000000) >> 3) | // for some funky reason, this is encoded as 7*4 bits + ((v3len & 0x007f0000) >> 2) | + ((v3len & 0x00007f00) >> 1) | + ((v3len & 0x0000007f) >> 0) ; + + // debug(">> tag version ID3v2."+id3v); + // debug(">> LEN= "+v3len+" // "+v3len); + + // we should already be at the first frame + // so we can start the parsing right now + tags = parse_v3_frames(s, v3len); + tags.put("_hdrlen", v3len+v2hdr_len); + return tags; + } + + /* Parses all ID3v2 frames at the current position up until payload_len + ** bytes were read + */ + public HashMap parse_v3_frames(RandomAccessFile s, long payload_len) throws IOException { + HashMap tags = new HashMap(); + byte[] frame = new byte[10]; // a frame header is always 10 bytes + long bread = 0; // total amount of read bytes + + while(bread < payload_len) { + bread += s.read(frame); + String framename = new String(frame, 0, 4); + int slen = b2be32(frame, 4); + + /* Abort on silly sizes */ + if(slen < 1 || slen > 524288) + break; + + byte[] xpl = new byte[slen]; + bread += s.read(xpl); + + if(framename.substring(0,1).equals("T")) { + String[] nmzInfo = normalizeTaginfo(framename, xpl); + String oggKey = nmzInfo[0]; + String decPld = nmzInfo[1]; + + if(oggKey.length() > 0 && !tags.containsKey(oggKey)) { + addTagEntry(tags, oggKey, decPld); + } + } + else if(framename.equals("RVA2")) { + // + } + + } + return tags; + } + + /* Converts ID3v2 sillyframes to OggNames */ + private String[] normalizeTaginfo(String k, byte[] v) { + String[] rv = new String[] {"",""}; + HashMap lu = new HashMap(); + lu.put("TIT2", "TITLE"); + lu.put("TALB", "ALBUM"); + lu.put("TPE1", "ARTIST"); + + if(lu.containsKey(k)) { + /* A normal, known key: translate into Ogg-Frame name */ + rv[0] = (String)lu.get(k); + rv[1] = getDecodedString(v); + } + else if(k.equals("TXXX")) { + /* A freestyle field, ieks! */ + String txData[] = getDecodedString(v).split(Character.toString('\0'), 2); + /* Check if we got replaygain info in key\0value style */ + if(txData.length == 2 && txData[0].matches("^(?i)REPLAYGAIN_(ALBUM|TRACK)_GAIN$")) { + rv[0] = txData[0].toUpperCase(); /* some tagwriters use lowercase for this */ + rv[1] = txData[1]; + } + } + + return rv; + } + + /* Converts a raw byte-stream text into a java String */ + private String getDecodedString(byte[] raw) { + int encid = raw[0] & 0xFF; + int len = raw.length; + String v = ""; + try { + if(encid == ID3_ENC_LATIN) { + v = new String(raw, 1, len-1, "ISO-8859-1"); + } + else if (encid == ID3_ENC_UTF8) { + v = new String(raw, 1, len-1, "UTF-8"); + } + else if (encid == ID3_ENC_UTF16LE) { + v = new String(raw, 3, len-3, "UTF-16LE"); + } + else if (encid == ID3_ENC_UTF16BE) { + v = new String(raw, 3, len-3, "UTF-16BE"); + } + } catch(Exception e) {} + return v; + } + +} diff --git a/src/github/daneren2005/dsub/util/tags/LameHeader.java b/src/github/daneren2005/dsub/util/tags/LameHeader.java new file mode 100644 index 00000000..720ee87f --- /dev/null +++ b/src/github/daneren2005/dsub/util/tags/LameHeader.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2013 Adrian Ulrich + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package github.daneren2005.dsub.util.tags; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.HashMap; +import java.util.Enumeration; + + +public class LameHeader extends Common { + + public LameHeader() { + } + + public HashMap getTags(RandomAccessFile s) throws IOException { + return parseLameHeader(s, 0); + } + + public HashMap parseLameHeader(RandomAccessFile s, long offset) throws IOException { + HashMap tags = new HashMap(); + byte[] chunk = new byte[4]; + + s.seek(offset + 0x24); + s.read(chunk); + + String lameMark = new String(chunk, 0, chunk.length, "ISO-8859-1"); + + if(lameMark.equals("Info") || lameMark.equals("Xing")) { + s.seek(offset+0xAB); + s.read(chunk); + + int raw = b2be32(chunk, 0); + int gtrk_raw = raw >> 16; /* first 16 bits are the raw track gain value */ + int galb_raw = raw & 0xFFFF; /* the rest is for the album gain value */ + + float gtrk_val = (float)(gtrk_raw & 0x01FF)/10; + float galb_val = (float)(galb_raw & 0x01FF)/10; + + gtrk_val = ((gtrk_raw&0x0200)!=0 ? -1*gtrk_val : gtrk_val); + galb_val = ((galb_raw&0x0200)!=0 ? -1*galb_val : galb_val); + + if( (gtrk_raw&0xE000) == 0x2000 ) { + addTagEntry(tags, "REPLAYGAIN_TRACK_GAIN", gtrk_val+" dB"); + } + if( (gtrk_raw&0xE000) == 0x4000 ) { + addTagEntry(tags, "REPLAYGAIN_ALBUM_GAIN", galb_val+" dB"); + } + + } + + return tags; + } + +} diff --git a/src/github/daneren2005/dsub/util/tags/OggFile.java b/src/github/daneren2005/dsub/util/tags/OggFile.java new file mode 100644 index 00000000..d0b31671 --- /dev/null +++ b/src/github/daneren2005/dsub/util/tags/OggFile.java @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2013 Adrian Ulrich + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package github.daneren2005.dsub.util.tags; + + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.HashMap; + + +public class OggFile extends Common { + + private static final int OGG_PAGE_SIZE = 27; // Static size of an OGG Page + private static final int OGG_TYPE_COMMENT = 3; // ID of 'VorbisComment's + + public OggFile() { + } + + public HashMap getTags(RandomAccessFile s) throws IOException { + long offset = 0; + int retry = 64; + HashMap tags = new HashMap(); + + for( ; retry > 0 ; retry-- ) { + long res[] = parse_ogg_page(s, offset); + if(res[2] == OGG_TYPE_COMMENT) { + tags = parse_ogg_vorbis_comment(s, offset+res[0], res[1]); + break; + } + offset += res[0] + res[1]; + } + return tags; + } + + + /* Parses the ogg page at offset 'offset' and returns + ** [header_size, payload_size, type] + */ + private long[] parse_ogg_page(RandomAccessFile s, long offset) throws IOException { + long[] result = new long[3]; // [header_size, payload_size] + byte[] p_header = new byte[OGG_PAGE_SIZE]; // buffer for the page header + byte[] scratch; + int bread = 0; // number of bytes read + int psize = 0; // payload-size + int nsegs = 0; // Number of segments + + s.seek(offset); + bread = s.read(p_header); + if(bread != OGG_PAGE_SIZE) + xdie("Unable to read() OGG_PAGE_HEADER"); + if((new String(p_header, 0, 5)).equals("OggS\0") != true) + xdie("Invalid magic - not an ogg file?"); + + nsegs = b2u(p_header[26]); + // debug("> file seg: "+nsegs); + if(nsegs > 0) { + scratch = new byte[nsegs]; + bread = s.read(scratch); + if(bread != nsegs) + xdie("Failed to read segtable"); + + for(int i=0; i pre-read */ + if(psize >= 1 && s.read(p_header, 0, 1) == 1) { + result[2] = b2u(p_header[0]); + } + + return result; + } + + /* In 'vorbiscomment' field is prefixed with \3vorbis in OGG files + ** we check that this marker is present and call the generic comment + ** parset with the correct offset (+7) */ + private HashMap parse_ogg_vorbis_comment(RandomAccessFile s, long offset, long pl_len) throws IOException { + final int pfx_len = 7; + byte[] pfx = new byte[pfx_len]; + + if(pl_len < pfx_len) + xdie("ogg vorbis comment field is too short!"); + + s.seek(offset); + s.read(pfx); + + if( (new String(pfx, 0, pfx_len)).equals("\3vorbis") == false ) + xdie("Damaged packet found!"); + + return parse_vorbis_comment(s, offset+pfx_len, pl_len-pfx_len); + } + +}; -- cgit v1.2.3 From 13587d80273b19125e5bd8c7a6ccbb9dcd7e2d93 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Sun, 21 Sep 2014 16:05:54 -0700 Subject: Copy replaygain application logic from adrian-bl/vanilla --- .../daneren2005/dsub/service/DownloadService.java | 49 ++++++++++++++++++++++ .../daneren2005/dsub/util/tags/BastpUtil.java | 17 +++----- 2 files changed, 55 insertions(+), 11 deletions(-) (limited to 'src/github') diff --git a/src/github/daneren2005/dsub/service/DownloadService.java b/src/github/daneren2005/dsub/service/DownloadService.java index 127df768..c3eb3ef7 100644 --- a/src/github/daneren2005/dsub/service/DownloadService.java +++ b/src/github/daneren2005/dsub/service/DownloadService.java @@ -47,10 +47,13 @@ import github.daneren2005.dsub.util.ShufflePlayBuffer; import github.daneren2005.dsub.util.SimpleServiceBinder; import github.daneren2005.dsub.util.Util; import github.daneren2005.dsub.util.compat.RemoteControlClientHelper; +import github.daneren2005.dsub.util.tags.BastpUtil; import github.daneren2005.dsub.view.UpdateView; import github.daneren2005.serverproxy.BufferProxy; import java.io.File; +import java.io.IOError; +import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; @@ -1415,6 +1418,8 @@ public class DownloadService extends Service { } cachedPosition = position; + applyReplayGain(mediaPlayer, downloadFile); + if (start || autoPlayStart) { mediaPlayer.start(); setPlayerState(STARTED); @@ -1473,6 +1478,8 @@ public class DownloadService extends Service { mediaPlayer.setNextMediaPlayer(nextMediaPlayer); nextSetup = true; } + + applyReplayGain(nextMediaPlayer, downloadFile); } catch (Exception x) { handleErrorNext(x); } @@ -1922,6 +1929,48 @@ public class DownloadService extends Service { } } + private void applyReplayGain(MediaPlayer mediaPlayer, DownloadFile downloadFile) { + if(currentPlaying == null) { + return; + } + + try { + float[] rg = BastpUtil.getReplayGainValues(downloadFile.getFile().getCanonicalPath()); /* track, album */ + float adjust = 0f; + if (true /*mReplayGainAlbumEnabled*/) { + adjust = (rg[0] != 0 ? rg[0] : adjust); /* do we have track adjustment ? */ + adjust = (rg[1] != 0 ? rg[1] : adjust); /* ..or, even better, album adj? */ + } + if (/*mReplayGainTrackEnabled || (mReplayGainAlbumEnabled && */ adjust == 0) { + adjust = (rg[1] != 0 ? rg[1] : adjust); /* do we have album adjustment ? */ + adjust = (rg[0] != 0 ? rg[0] : adjust); /* ..or, even better, track adj? */ + } + if (adjust == 0) { + /* No RG value found: decrease volume for untagged song if requested by user */ + // adjust = (mReplayGainUntaggedDeBump - 150) / 10f; + } else { + /* This song has some replay gain info, we are now going to apply the 'bump' value + ** The preferences stores the raw value of the seekbar, that's 0-150 + ** But we want -15 <-> +15, so 75 shall be zero */ + // adjust += 2 * (mReplayGainBump - 75) / 10f; /* 2* -> we want +-15, not +-7.5 */ + } + /*if (mReplayGainAlbumEnabled == false && mReplayGainTrackEnabled == false) { + // Feature is disabled: Make sure that we are going to 100% volume + adjust = 0f; + }*/ + float rg_result = ((float) Math.pow(10, (adjust / 20)))/* * mFadeOut*/; + if (rg_result > 1.0f) { + rg_result = 1.0f; /* android would IGNORE the change if this is > 1 and we would end up with the wrong volume */ + } else if (rg_result < 0.0f) { + rg_result = 0.0f; + } + Log.d(TAG, "Applied volume of " + rg_result); + mediaPlayer.setVolume(rg_result, rg_result); + } catch(IOException e) { + Log.w(TAG, "Failed to apply replay gain values", e); + } + } + private class BufferTask extends SilentBackgroundTask { private final DownloadFile downloadFile; private final int position; diff --git a/src/github/daneren2005/dsub/util/tags/BastpUtil.java b/src/github/daneren2005/dsub/util/tags/BastpUtil.java index 99279f62..a738bbce 100644 --- a/src/github/daneren2005/dsub/util/tags/BastpUtil.java +++ b/src/github/daneren2005/dsub/util/tags/BastpUtil.java @@ -21,17 +21,12 @@ import android.util.LruCache; import java.util.HashMap; import java.util.Vector; -public class BastpUtil { - private RGLruCache rgCache; - - public BastpUtil() { - rgCache = new RGLruCache(16); /* Cache up to 16 entries */ - } - - +public final class BastpUtil { + private static final RGLruCache rgCache = new RGLruCache(16); + /** Returns the ReplayGain values of 'path' as */ - public float[] getReplayGainValues(String path) { + public static float[] getReplayGainValues(String path) { float[] cached = rgCache.get(path); if(cached == null) { @@ -45,7 +40,7 @@ public class BastpUtil { /** Parse given file and return track,album replay gain values */ - private float[] getReplayGainValuesFromFile(String path) { + private static float[] getReplayGainValuesFromFile(String path) { String[] keys = { "REPLAYGAIN_TRACK_GAIN", "REPLAYGAIN_ALBUM_GAIN" }; float[] adjust= { 0f , 0f }; HashMap tags = (new Bastp()).getTags(path); @@ -68,7 +63,7 @@ public class BastpUtil { /** LRU cache for ReplayGain values */ - private class RGLruCache extends LruCache { + private static class RGLruCache extends LruCache { public RGLruCache(int size) { super(size); } -- cgit v1.2.3 From 2b68dad21ad76cafdb51b1f8d50793735a54260a Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Mon, 22 Sep 2014 15:55:08 -0700 Subject: Keep track of volume set by setVolume, multiply replay gain value by it --- src/github/daneren2005/dsub/service/DownloadService.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/github') diff --git a/src/github/daneren2005/dsub/service/DownloadService.java b/src/github/daneren2005/dsub/service/DownloadService.java index c3eb3ef7..ab302729 100644 --- a/src/github/daneren2005/dsub/service/DownloadService.java +++ b/src/github/daneren2005/dsub/service/DownloadService.java @@ -136,6 +136,7 @@ public class DownloadService extends Service { private boolean keepScreenOn; private int cachedPosition = 0; private boolean downloadOngoing = false; + private float volume = 1.0f; private AudioEffectsController effectsController; private RemoteControlState remoteState = RemoteControlState.LOCAL; @@ -1599,7 +1600,8 @@ public class DownloadService extends Service { public void setVolume(float volume) { if(mediaPlayer != null && (playerState == STARTED || playerState == PAUSED || playerState == STOPPED)) { try { - mediaPlayer.setVolume(volume, volume); + this.volume = volume; + applyReplayGain(mediaPlayer, currentPlaying); } catch(Exception e) { Log.w(TAG, "Failed to set volume"); } @@ -1958,7 +1960,7 @@ public class DownloadService extends Service { // Feature is disabled: Make sure that we are going to 100% volume adjust = 0f; }*/ - float rg_result = ((float) Math.pow(10, (adjust / 20)))/* * mFadeOut*/; + float rg_result = ((float) Math.pow(10, (adjust / 20))) * volume; if (rg_result > 1.0f) { rg_result = 1.0f; /* android would IGNORE the change if this is > 1 and we would end up with the wrong volume */ } else if (rg_result < 0.0f) { -- cgit v1.2.3 From 091bba2a329f236251d69697f892b923796a5e5c Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Mon, 22 Sep 2014 16:10:51 -0700 Subject: Add start of smart replaygain logic, make it optional --- .../daneren2005/dsub/service/DownloadService.java | 23 +++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'src/github') diff --git a/src/github/daneren2005/dsub/service/DownloadService.java b/src/github/daneren2005/dsub/service/DownloadService.java index ab302729..1e32bd2a 100644 --- a/src/github/daneren2005/dsub/service/DownloadService.java +++ b/src/github/daneren2005/dsub/service/DownloadService.java @@ -137,6 +137,7 @@ public class DownloadService extends Service { private int cachedPosition = 0; private boolean downloadOngoing = false; private float volume = 1.0f; + private boolean singleAlbum = false; private AudioEffectsController effectsController; private RemoteControlState remoteState = RemoteControlState.LOCAL; @@ -1939,14 +1940,17 @@ public class DownloadService extends Service { try { float[] rg = BastpUtil.getReplayGainValues(downloadFile.getFile().getCanonicalPath()); /* track, album */ float adjust = 0f; - if (true /*mReplayGainAlbumEnabled*/) { - adjust = (rg[0] != 0 ? rg[0] : adjust); /* do we have track adjustment ? */ - adjust = (rg[1] != 0 ? rg[1] : adjust); /* ..or, even better, album adj? */ - } - if (/*mReplayGainTrackEnabled || (mReplayGainAlbumEnabled && */ adjust == 0) { - adjust = (rg[1] != 0 ? rg[1] : adjust); /* do we have album adjustment ? */ - adjust = (rg[0] != 0 ? rg[0] : adjust); /* ..or, even better, track adj? */ + if (Util.getPreferences(this).getBoolean(Constants.PREFERENCES_KEY_REPLAY_GAIN, true)) { + // If playing a single album or no track gain, use album gain + if((singleAlbum || rg[0] == 0) && rg[1] != 0) { + adjust = rg[1]; + } else { + // Otherwise, give priority to track gain + adjust = rg[0]; + } } + + // TODO: Figure out if I want any of this logic if (adjust == 0) { /* No RG value found: decrease volume for untagged song if requested by user */ // adjust = (mReplayGainUntaggedDeBump - 150) / 10f; @@ -1956,10 +1960,7 @@ public class DownloadService extends Service { ** But we want -15 <-> +15, so 75 shall be zero */ // adjust += 2 * (mReplayGainBump - 75) / 10f; /* 2* -> we want +-15, not +-7.5 */ } - /*if (mReplayGainAlbumEnabled == false && mReplayGainTrackEnabled == false) { - // Feature is disabled: Make sure that we are going to 100% volume - adjust = 0f; - }*/ + float rg_result = ((float) Math.pow(10, (adjust / 20))) * volume; if (rg_result > 1.0f) { rg_result = 1.0f; /* android would IGNORE the change if this is > 1 and we would end up with the wrong volume */ -- cgit v1.2.3 From 0e54ba2dc6f3c548e954669df94f57d46a34a84c Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Mon, 22 Sep 2014 21:07:28 -0700 Subject: Make replay gain optional --- res/values/strings.xml | 2 ++ res/xml/settings.xml | 6 ++++++ src/github/daneren2005/dsub/service/DownloadService.java | 2 +- src/github/daneren2005/dsub/util/Constants.java | 1 + 4 files changed, 10 insertions(+), 1 deletion(-) (limited to 'src/github') diff --git a/res/values/strings.xml b/res/values/strings.xml index 009e369b..64237ac0 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -429,6 +429,8 @@ Display albums with large album art instead of in a list Admin Enabled Whether or not to display the admin listing in the pull out drawer + Replay Gain + Whether or not to scale playback volume by track and album replay gain tags Shuffle By Start Year: diff --git a/res/xml/settings.xml b/res/xml/settings.xml index bafb5f6c..bc2fd9e3 100644 --- a/res/xml/settings.xml +++ b/res/xml/settings.xml @@ -369,6 +369,12 @@ android:key="mediaButtons" android:defaultValue="true"/> + + Date: Mon, 22 Sep 2014 21:13:31 -0700 Subject: Improve log message --- src/github/daneren2005/dsub/service/DownloadService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/github') diff --git a/src/github/daneren2005/dsub/service/DownloadService.java b/src/github/daneren2005/dsub/service/DownloadService.java index 9c2e2ce5..d008035c 100644 --- a/src/github/daneren2005/dsub/service/DownloadService.java +++ b/src/github/daneren2005/dsub/service/DownloadService.java @@ -1962,12 +1962,12 @@ public class DownloadService extends Service { } float rg_result = ((float) Math.pow(10, (adjust / 20))) * volume; + Log.d(TAG, "Applied volume of " + rg_result + " +- " + adjust); if (rg_result > 1.0f) { rg_result = 1.0f; /* android would IGNORE the change if this is > 1 and we would end up with the wrong volume */ } else if (rg_result < 0.0f) { rg_result = 0.0f; } - Log.d(TAG, "Applied volume of " + rg_result); mediaPlayer.setVolume(rg_result, rg_result); } catch(IOException e) { Log.w(TAG, "Failed to apply replay gain values", e); -- cgit v1.2.3 From afb593f2be23339ec52fb96d8498739c40480f04 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Tue, 23 Sep 2014 15:03:37 -0700 Subject: #43 Keep track of whether or not we are playing a single album for replay gain purposes --- .../daneren2005/dsub/service/DownloadService.java | 29 ++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) (limited to 'src/github') diff --git a/src/github/daneren2005/dsub/service/DownloadService.java b/src/github/daneren2005/dsub/service/DownloadService.java index d008035c..7f822c58 100644 --- a/src/github/daneren2005/dsub/service/DownloadService.java +++ b/src/github/daneren2005/dsub/service/DownloadService.java @@ -138,6 +138,7 @@ public class DownloadService extends Service { private boolean downloadOngoing = false; private float volume = 1.0f; private boolean singleAlbum = false; + private String singleAlbumName; private AudioEffectsController effectsController; private RemoteControlState remoteState = RemoteControlState.LOCAL; @@ -316,7 +317,7 @@ public class DownloadService extends Service { for (MusicDirectory.Entry song : songs) { if(song != null) { DownloadFile downloadFile = new DownloadFile(this, song, save); - downloadList.add(getCurrentPlayingIndex() + offset, downloadFile); + addToDownloadList(downloadFile, getCurrentPlayingIndex() + offset); offset++; } } @@ -327,7 +328,7 @@ public class DownloadService extends Service { int index = getCurrentPlayingIndex(); for (MusicDirectory.Entry song : songs) { DownloadFile downloadFile = new DownloadFile(this, song, save); - downloadList.add(downloadFile); + addToDownloadList(downloadFile, -1); } if(!autoplay && (size - 1) == index) { setNextPlaying(); @@ -354,6 +355,27 @@ public class DownloadService extends Service { } lifecycleSupport.serializeDownloadQueue(); } + private void addToDownloadList(DownloadFile file, int offset) { + if(offset == -1) { + downloadList.add(downloadList); + } else { + downloadList.add(offset, file); + } + + // Check if we are still dealing with a single album + // Don't bother with check if it is already false + if(singleAlbum) { + // If first download, set album to it + if(singleAlbumName == null) { + singleAlbumName = file.getSong().getAlbum(); + } else { + // Otherwise, check again previous album name + if(!singleAlbumName.equals(file.getSong().getAlbum())) { + singleAlbum = false; + } + } + } + } public synchronized void downloadBackground(List songs, boolean save) { for (MusicDirectory.Entry song : songs) { DownloadFile downloadFile = new DownloadFile(this, song, save); @@ -616,6 +638,8 @@ public class DownloadService extends Service { suggestedPlaylistName = null; suggestedPlaylistId = null; + singleAlbum = true; + singleAlbumName = null; } public synchronized void remove(int which) { @@ -1792,6 +1816,7 @@ public class DownloadService extends Service { } } currentPlayingIndex = downloadList.indexOf(currentPlaying); + singleAlbum = false; if (revisionBefore != revision) { updateJukeboxPlaylist(); -- cgit v1.2.3 From 78263d8e5a9a303956ab28b3545e57dbb8345d12 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Tue, 23 Sep 2014 20:53:49 -0700 Subject: Add better log message --- src/github/daneren2005/dsub/service/DownloadService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/github') diff --git a/src/github/daneren2005/dsub/service/DownloadService.java b/src/github/daneren2005/dsub/service/DownloadService.java index 7f822c58..702a2b2f 100644 --- a/src/github/daneren2005/dsub/service/DownloadService.java +++ b/src/github/daneren2005/dsub/service/DownloadService.java @@ -357,7 +357,7 @@ public class DownloadService extends Service { } private void addToDownloadList(DownloadFile file, int offset) { if(offset == -1) { - downloadList.add(downloadList); + downloadList.add(file); } else { downloadList.add(offset, file); } @@ -1987,7 +1987,7 @@ public class DownloadService extends Service { } float rg_result = ((float) Math.pow(10, (adjust / 20))) * volume; - Log.d(TAG, "Applied volume of " + rg_result + " +- " + adjust); + Log.d(TAG, "Applied volume of " + rg_result + " +- " + adjust + " (" + singleAlbum + ")"); if (rg_result > 1.0f) { rg_result = 1.0f; /* android would IGNORE the change if this is > 1 and we would end up with the wrong volume */ } else if (rg_result < 0.0f) { -- cgit v1.2.3 From 1789036c1b3bed2afcf5074cd9cd0e91b4c5a6a2 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Wed, 24 Sep 2014 05:22:16 -0700 Subject: Instantly update volume when toggling replay gain --- src/github/daneren2005/dsub/activity/SettingsActivity.java | 5 +++++ src/github/daneren2005/dsub/service/DownloadService.java | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'src/github') diff --git a/src/github/daneren2005/dsub/activity/SettingsActivity.java b/src/github/daneren2005/dsub/activity/SettingsActivity.java index e40a62d2..710d7385 100644 --- a/src/github/daneren2005/dsub/activity/SettingsActivity.java +++ b/src/github/daneren2005/dsub/activity/SettingsActivity.java @@ -267,6 +267,11 @@ public class SettingsActivity extends PreferenceActivity implements SharedPrefer } else if(Constants.PREFERENCES_KEY_SYNC_MOST_RECENT.equals(key)) { SyncUtil.removeMostRecentSyncFiles(this); + } else if(Constants.PREFERENCES_KEY_REPLAY_GAIN.equals(key)) { + DownloadService downloadService = DownloadService.getInstance(); + if(downloadService != null) { + downloadService.reapplyVolume(); + } } scheduleBackup(); diff --git a/src/github/daneren2005/dsub/service/DownloadService.java b/src/github/daneren2005/dsub/service/DownloadService.java index 702a2b2f..a67418a8 100644 --- a/src/github/daneren2005/dsub/service/DownloadService.java +++ b/src/github/daneren2005/dsub/service/DownloadService.java @@ -1626,12 +1626,15 @@ public class DownloadService extends Service { if(mediaPlayer != null && (playerState == STARTED || playerState == PAUSED || playerState == STOPPED)) { try { this.volume = volume; - applyReplayGain(mediaPlayer, currentPlaying); + reapplyVolume(); } catch(Exception e) { Log.w(TAG, "Failed to set volume"); } } } + public void reapplyVolume() { + applyReplayGain(mediaPlayer, currentPlaying); + } public synchronized void swap(boolean mainList, int from, int to) { List list = mainList ? downloadList : backgroundDownloadList; -- cgit v1.2.3 From 669be10aaf5b6fc04de6b88cd41ce8595b9dd1b7 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Thu, 25 Sep 2014 16:26:40 -0700 Subject: #43 Add bump values to replay gain application logic --- .../daneren2005/dsub/service/DownloadService.java | 24 ++++++++++++---------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'src/github') diff --git a/src/github/daneren2005/dsub/service/DownloadService.java b/src/github/daneren2005/dsub/service/DownloadService.java index a67418a8..21de600d 100644 --- a/src/github/daneren2005/dsub/service/DownloadService.java +++ b/src/github/daneren2005/dsub/service/DownloadService.java @@ -1965,10 +1965,11 @@ public class DownloadService extends Service { return; } + SharedPreferences prefs = Util.getPeferences(this); try { float[] rg = BastpUtil.getReplayGainValues(downloadFile.getFile().getCanonicalPath()); /* track, album */ float adjust = 0f; - if (Util.getPreferences(this).getBoolean(Constants.PREFERENCES_KEY_REPLAY_GAIN, false)) { + if (prefs.getBoolean(Constants.PREFERENCES_KEY_REPLAY_GAIN, false)) { // If playing a single album or no track gain, use album gain if((singleAlbum || rg[0] == 0) && rg[1] != 0) { adjust = rg[1]; @@ -1976,17 +1977,18 @@ public class DownloadService extends Service { // Otherwise, give priority to track gain adjust = rg[0]; } - } - // TODO: Figure out if I want any of this logic - if (adjust == 0) { - /* No RG value found: decrease volume for untagged song if requested by user */ - // adjust = (mReplayGainUntaggedDeBump - 150) / 10f; - } else { - /* This song has some replay gain info, we are now going to apply the 'bump' value - ** The preferences stores the raw value of the seekbar, that's 0-150 - ** But we want -15 <-> +15, so 75 shall be zero */ - // adjust += 2 * (mReplayGainBump - 75) / 10f; /* 2* -> we want +-15, not +-7.5 */ + if (adjust == 0) { + /* No RG value found: decrease volume for untagged song if requested by user */ + int untagged = prefs.getInt(Constants.PREFERENCES_KEY_REPLAY_GAIN_UNTAGGED, 0); + adjust = (untagged - 150) / 10f; + } else { + /* This song has some replay gain info, we are now going to apply the 'bump' value + ** The preferences stores the raw value of the seekbar, that's 0-150 + ** But we want -15 <-> +15, so 75 shall be zero */ + int bump = prefs.getInt(Constants.PREFERENCES_KEY_REPLAY_GAIN_BUMP, 0); + adjust += 2 * (bump - 75) / 10f; + } } float rg_result = ((float) Math.pow(10, (adjust / 20))) * volume; -- cgit v1.2.3 From 9d6e8004c7bea55160f7a9a631b452083aea421f Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Thu, 25 Sep 2014 19:52:43 -0700 Subject: #43 Add remaining parts for settings --- res/layout/seekbar_preference.xml | 18 +++ res/values/strings.xml | 2 + res/xml/settings.xml | 24 ++++ .../dsub/activity/SettingsActivity.java | 16 ++- .../daneren2005/dsub/service/DownloadService.java | 6 +- src/github/daneren2005/dsub/util/Constants.java | 2 + .../daneren2005/dsub/view/SeekBarPreference.java | 137 +++++++++++++++++++++ 7 files changed, 201 insertions(+), 4 deletions(-) create mode 100644 res/layout/seekbar_preference.xml create mode 100644 src/github/daneren2005/dsub/view/SeekBarPreference.java (limited to 'src/github') diff --git a/res/layout/seekbar_preference.xml b/res/layout/seekbar_preference.xml new file mode 100644 index 00000000..4d3bc877 --- /dev/null +++ b/res/layout/seekbar_preference.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/res/values/strings.xml b/res/values/strings.xml index 64237ac0..b00f66bc 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -431,6 +431,8 @@ Whether or not to display the admin listing in the pull out drawer Replay Gain Whether or not to scale playback volume by track and album replay gain tags + Replay Gain Pre-amp + Songs without Replay Gain Shuffle By Start Year: diff --git a/res/xml/settings.xml b/res/xml/settings.xml index bc2fd9e3..553fe710 100644 --- a/res/xml/settings.xml +++ b/res/xml/settings.xml @@ -354,6 +354,30 @@ android:entries="@array/videoPlayerNames"/> + + + + + + + + + diff --git a/src/github/daneren2005/dsub/activity/SettingsActivity.java b/src/github/daneren2005/dsub/activity/SettingsActivity.java index 710d7385..5ca30f62 100644 --- a/src/github/daneren2005/dsub/activity/SettingsActivity.java +++ b/src/github/daneren2005/dsub/activity/SettingsActivity.java @@ -86,6 +86,9 @@ public class SettingsActivity extends PreferenceActivity implements SharedPrefer private CheckBoxPreference syncNotification; private CheckBoxPreference syncStarred; private CheckBoxPreference syncMostRecent; + private CheckBoxPreference replayGain; + private Preference replayGainBump; + private Preference replayGainUntagged; private String internalSSID; private int serverCount = 3; @@ -127,6 +130,9 @@ public class SettingsActivity extends PreferenceActivity implements SharedPrefer syncNotification = (CheckBoxPreference) findPreference(Constants.PREFERENCES_KEY_SYNC_NOTIFICATION); syncStarred = (CheckBoxPreference) findPreference(Constants.PREFERENCES_KEY_SYNC_STARRED); syncMostRecent = (CheckBoxPreference) findPreference(Constants.PREFERENCES_KEY_SYNC_MOST_RECENT); + replayGain = (CheckBoxPreference) findPreference(Constants.PREFERENCES_KEY_REPLAY_GAIN); + replayGainBump = (Preference) findPreference(Constants.PREFERENCES_KEY_REPLAY_GAIN_BUMP); + replayGainUntagged = (Preference) findPreference(Constants.PREFERENCES_KEY_REPLAY_GAIN_UNTAGGED); settings = Util.getPreferences(this); serverCount = settings.getInt(Constants.PREFERENCES_KEY_SERVER_COUNT, 1); @@ -267,7 +273,7 @@ public class SettingsActivity extends PreferenceActivity implements SharedPrefer } else if(Constants.PREFERENCES_KEY_SYNC_MOST_RECENT.equals(key)) { SyncUtil.removeMostRecentSyncFiles(this); - } else if(Constants.PREFERENCES_KEY_REPLAY_GAIN.equals(key)) { + } else if(Constants.PREFERENCES_KEY_REPLAY_GAIN.equals(key) || Constants.PREFERENCES_KEY_REPLAY_GAIN_BUMP.equals(key) || Constants.PREFERENCES_KEY_REPLAY_GAIN_UNTAGGED.equals(key)) { DownloadService downloadService = DownloadService.getInstance(); if(downloadService != null) { downloadService.reapplyVolume(); @@ -331,6 +337,14 @@ public class SettingsActivity extends PreferenceActivity implements SharedPrefer syncMostRecent.setEnabled(false); } } + if(replayGain.isChecked()) { + replayGainBump.setEnabled(true); + replayGainUntagged.setEnabled(true); + } else { + replayGainBump.setEnabled(false); + replayGainUntagged.setEnabled(false); + } + for (ServerSettings ss : serverSettings.values()) { ss.update(); } diff --git a/src/github/daneren2005/dsub/service/DownloadService.java b/src/github/daneren2005/dsub/service/DownloadService.java index 21de600d..d813ddc0 100644 --- a/src/github/daneren2005/dsub/service/DownloadService.java +++ b/src/github/daneren2005/dsub/service/DownloadService.java @@ -1965,7 +1965,7 @@ public class DownloadService extends Service { return; } - SharedPreferences prefs = Util.getPeferences(this); + SharedPreferences prefs = Util.getPreferences(this); try { float[] rg = BastpUtil.getReplayGainValues(downloadFile.getFile().getCanonicalPath()); /* track, album */ float adjust = 0f; @@ -1980,13 +1980,13 @@ public class DownloadService extends Service { if (adjust == 0) { /* No RG value found: decrease volume for untagged song if requested by user */ - int untagged = prefs.getInt(Constants.PREFERENCES_KEY_REPLAY_GAIN_UNTAGGED, 0); + int untagged = Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_REPLAY_GAIN_UNTAGGED, "0")); adjust = (untagged - 150) / 10f; } else { /* This song has some replay gain info, we are now going to apply the 'bump' value ** The preferences stores the raw value of the seekbar, that's 0-150 ** But we want -15 <-> +15, so 75 shall be zero */ - int bump = prefs.getInt(Constants.PREFERENCES_KEY_REPLAY_GAIN_BUMP, 0); + int bump = Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_REPLAY_GAIN_BUMP, "0")); adjust += 2 * (bump - 75) / 10f; } } diff --git a/src/github/daneren2005/dsub/util/Constants.java b/src/github/daneren2005/dsub/util/Constants.java index 88dfa086..30dc33b4 100644 --- a/src/github/daneren2005/dsub/util/Constants.java +++ b/src/github/daneren2005/dsub/util/Constants.java @@ -145,6 +145,8 @@ public final class Constants { public static final String PREFERENCES_KEY_RECENT_COUNT = "mostRecentCount"; public static final String PREFERENCES_KEY_MENU_RATING = "showRating"; public static final String PREFERENCES_KEY_REPLAY_GAIN = "replayGain"; + public static final String PREFERENCES_KEY_REPLAY_GAIN_BUMP = "replayGainBump2"; + public static final String PREFERENCES_KEY_REPLAY_GAIN_UNTAGGED = "replayGainUntagged2"; public static final String OFFLINE_SCROBBLE_COUNT = "scrobbleCount"; public static final String OFFLINE_SCROBBLE_ID = "scrobbleID"; diff --git a/src/github/daneren2005/dsub/view/SeekBarPreference.java b/src/github/daneren2005/dsub/view/SeekBarPreference.java new file mode 100644 index 00000000..d0127857 --- /dev/null +++ b/src/github/daneren2005/dsub/view/SeekBarPreference.java @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2012 Christopher Eby + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package github.daneren2005.dsub.view; + +import android.content.Context; +import android.content.res.TypedArray; +import android.preference.DialogPreference; +import android.util.AttributeSet; +import android.view.View; +import android.widget.SeekBar; +import android.widget.TextView; + +import github.daneren2005.dsub.R; +import github.daneren2005.dsub.util.Constants; + +/** + * SeekBar preference to set the shake force threshold. + */ +public class SeekBarPreference extends DialogPreference implements SeekBar.OnSeekBarChangeListener { + /** + * The current value. + */ + private String mValue; + + /** + * Our context (needed for getResources()) + */ + private Context mContext; + + /** + * TextView to display current threshold. + */ + private TextView mValueText; + + public SeekBarPreference(Context context, AttributeSet attrs) + { + super(context, attrs); + mContext = context; + } + + @Override + public CharSequence getSummary() + { + return getSummary(mValue); + } + + @Override + protected Object onGetDefaultValue(TypedArray a, int index) + { + return a.getString(index); + } + + @Override + protected void onSetInitialValue(boolean restoreValue, Object defaultValue) + { + mValue = restoreValue ? getPersistedString((String) defaultValue) : (String)defaultValue; + } + + /** + * Create the summary for the given value. + * + * @param value The force threshold. + * @return A string representation of the threshold. + */ + private String getSummary(String value) { + int val = Integer.parseInt(value); + if(Constants.PREFERENCES_KEY_REPLAY_GAIN_UNTAGGED.equals(getKey())) { + return String.format("%+.1f dB", (val - 150) / 10f); + } else if(Constants.PREFERENCES_KEY_REPLAY_GAIN_BUMP.equals(getKey())) { + return String.format("%+.1f dB", 2 * (val - 75) / 10f); + } else { + return String.format("%+.1f", val); + } + } + + @Override + protected View onCreateDialogView() + { + View view = super.onCreateDialogView(); + + mValueText = (TextView)view.findViewById(R.id.value); + mValueText.setText(getSummary(mValue)); + + SeekBar seekBar = (SeekBar)view.findViewById(R.id.seek_bar); + seekBar.setMax(150); + seekBar.setProgress(Integer.parseInt(mValue)); + seekBar.setOnSeekBarChangeListener(this); + + return view; + } + + @Override + protected void onDialogClosed(boolean positiveResult) + { + persistString(mValue); + notifyChanged(); + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) + { + if (fromUser) { + mValue = String.valueOf(progress); + mValueText.setText(getSummary(mValue)); + } + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) + { + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) + { + } +} -- cgit v1.2.3 From d3dd5cc574fe306e473199572dce4e86062476f9 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Sat, 27 Sep 2014 16:47:34 -0700 Subject: Remove log message --- src/github/daneren2005/dsub/service/DownloadService.java | 1 - 1 file changed, 1 deletion(-) (limited to 'src/github') diff --git a/src/github/daneren2005/dsub/service/DownloadService.java b/src/github/daneren2005/dsub/service/DownloadService.java index d813ddc0..3b211d9c 100644 --- a/src/github/daneren2005/dsub/service/DownloadService.java +++ b/src/github/daneren2005/dsub/service/DownloadService.java @@ -1992,7 +1992,6 @@ public class DownloadService extends Service { } float rg_result = ((float) Math.pow(10, (adjust / 20))) * volume; - Log.d(TAG, "Applied volume of " + rg_result + " +- " + adjust + " (" + singleAlbum + ")"); if (rg_result > 1.0f) { rg_result = 1.0f; /* android would IGNORE the change if this is > 1 and we would end up with the wrong volume */ } else if (rg_result < 0.0f) { -- cgit v1.2.3