1 |
|
|
2 |
|
|
3 |
|
|
4 |
|
|
5 |
|
|
6 |
|
|
7 |
|
|
8 |
|
|
9 |
|
|
10 |
|
|
11 |
|
|
12 |
|
|
13 |
|
|
14 |
|
|
15 |
|
|
16 |
|
|
17 |
|
|
18 |
|
|
19 |
|
package net.sourceforge.subsonic.androidapp.util; |
20 |
|
|
21 |
|
import android.content.Context; |
22 |
|
import android.os.Handler; |
23 |
|
import android.util.Log; |
24 |
|
import android.view.LayoutInflater; |
25 |
|
import android.view.View; |
26 |
|
import android.widget.Checkable; |
27 |
|
import android.widget.CheckedTextView; |
28 |
|
import android.widget.LinearLayout; |
29 |
|
import android.widget.TextView; |
30 |
|
import net.sourceforge.subsonic.androidapp.R; |
31 |
|
import net.sourceforge.subsonic.androidapp.domain.MusicDirectory; |
32 |
|
import net.sourceforge.subsonic.androidapp.service.DownloadService; |
33 |
|
import net.sourceforge.subsonic.androidapp.service.DownloadServiceImpl; |
34 |
|
import net.sourceforge.subsonic.androidapp.service.DownloadFile; |
35 |
|
|
36 |
|
import java.io.File; |
37 |
|
import java.util.WeakHashMap; |
38 |
|
|
39 |
|
|
40 |
|
|
41 |
|
|
42 |
|
@author |
43 |
|
|
|
|
| 87,2% |
Uncovered Elements: 12 (94) |
Complexity: 26 |
Complexity Density: 0,43 |
|
44 |
|
public class SongView extends LinearLayout implements Checkable { |
45 |
|
|
46 |
|
private static final String TAG = SongView.class.getSimpleName(); |
47 |
|
private static final WeakHashMap<SongView, ?> INSTANCES = new WeakHashMap<SongView, Object>(); |
48 |
|
private static Handler handler; |
49 |
|
|
50 |
|
private CheckedTextView checkedTextView; |
51 |
|
private TextView titleTextView; |
52 |
|
private TextView artistTextView; |
53 |
|
private TextView durationTextView; |
54 |
|
private TextView statusTextView; |
55 |
|
private MusicDirectory.Entry song; |
56 |
|
|
|
|
| 85,7% |
Uncovered Elements: 2 (14) |
Complexity: 2 |
Complexity Density: 0,17 |
|
57 |
120
|
public SongView(Context context) {... |
58 |
120
|
super(context); |
59 |
120
|
LayoutInflater.from(context).inflate(R.layout.song_list_item, this, true); |
60 |
|
|
61 |
120
|
checkedTextView = (CheckedTextView) findViewById(R.id.song_check); |
62 |
120
|
titleTextView = (TextView) findViewById(R.id.song_title); |
63 |
120
|
artistTextView = (TextView) findViewById(R.id.song_artist); |
64 |
120
|
durationTextView = (TextView) findViewById(R.id.song_duration); |
65 |
120
|
statusTextView = (TextView) findViewById(R.id.song_status); |
66 |
|
|
67 |
120
|
INSTANCES.put(this, null); |
68 |
120
|
int instanceCount = INSTANCES.size(); |
69 |
120
|
if (instanceCount > 50) { |
70 |
0
|
Log.w(TAG, instanceCount + " live SongView instances"); |
71 |
|
} |
72 |
120
|
startUpdater(); |
73 |
|
} |
74 |
|
|
|
|
| 91,3% |
Uncovered Elements: 2 (23) |
Complexity: 7 |
Complexity Density: 0,47 |
|
75 |
233
|
public void setSong(MusicDirectory.Entry song, boolean checkable) {... |
76 |
233
|
this.song = song; |
77 |
233
|
StringBuilder artist = new StringBuilder(40); |
78 |
|
|
79 |
233
|
String bitRate = null; |
80 |
233
|
if (song.getBitRate() != null) { |
81 |
193
|
bitRate = String.format(getContext().getString(R.string.song_details_kbps), song.getBitRate()); |
82 |
|
} |
83 |
|
|
84 |
233
|
String fileFormat = null; |
85 |
233
|
if (song.getTranscodedSuffix() != null && !song.getTranscodedSuffix().equals(song.getSuffix())) { |
86 |
0
|
fileFormat = String.format("%s > %s", song.getSuffix(), song.getTranscodedSuffix()); |
87 |
|
} else { |
88 |
233
|
fileFormat = song.getSuffix(); |
89 |
|
} |
90 |
|
|
91 |
233
|
artist.append(song.getArtist()).append(" (") |
92 |
233
|
.append(String.format(getContext().getString(R.string.song_details_all), bitRate == null ? "" : bitRate, fileFormat)) |
93 |
|
.append(")"); |
94 |
|
|
95 |
233
|
titleTextView.setText(song.getTitle()); |
96 |
233
|
artistTextView.setText(artist); |
97 |
233
|
durationTextView.setText(Util.formatDuration(song.getDuration())); |
98 |
233
|
checkedTextView.setVisibility(checkable && !song.isVideo() ? View.VISIBLE : View.GONE); |
99 |
|
|
100 |
233
|
update(); |
101 |
|
} |
102 |
|
|
|
|
| 89,7% |
Uncovered Elements: 3 (29) |
Complexity: 8 |
Complexity Density: 0,42 |
|
103 |
1032
|
private void update() {... |
104 |
1032
|
DownloadService downloadService = DownloadServiceImpl.getInstance(); |
105 |
1032
|
if (downloadService == null) { |
106 |
0
|
return; |
107 |
|
} |
108 |
|
|
109 |
1032
|
DownloadFile downloadFile = downloadService.forSong(song); |
110 |
1032
|
File completeFile = downloadFile.getCompleteFile(); |
111 |
1032
|
File partialFile = downloadFile.getPartialFile(); |
112 |
|
|
113 |
1032
|
int leftImage = 0; |
114 |
1032
|
int rightImage = 0; |
115 |
|
|
116 |
1032
|
if (completeFile.exists()) { |
117 |
273
|
leftImage = downloadFile.isSaved() ? R.drawable.ic_stat_saved : R.drawable.ic_stat_downloaded; |
118 |
|
} |
119 |
|
|
120 |
1032
|
if (downloadFile.isDownloading() && !downloadFile.isDownloadCancelled() && partialFile.exists()) { |
121 |
51
|
statusTextView.setText(Util.formatLocalizedBytes(partialFile.length(), getContext())); |
122 |
51
|
rightImage = R.drawable.ic_stat_downloading; |
123 |
|
} else { |
124 |
981
|
statusTextView.setText(null); |
125 |
|
} |
126 |
1032
|
statusTextView.setCompoundDrawablesWithIntrinsicBounds(leftImage, 0, rightImage, 0); |
127 |
|
|
128 |
1032
|
boolean playing = downloadService.getCurrentPlaying() == downloadFile; |
129 |
1032
|
if (playing) { |
130 |
98
|
titleTextView.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_stat_play, 0, 0, 0); |
131 |
|
} else { |
132 |
934
|
titleTextView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); |
133 |
|
} |
134 |
|
} |
135 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (7) |
Complexity: 2 |
Complexity Density: 0,4 |
|
136 |
120
|
private static synchronized void startUpdater() {... |
137 |
120
|
if (handler != null) { |
138 |
119
|
return; |
139 |
|
} |
140 |
|
|
141 |
1
|
handler = new Handler(); |
142 |
1
|
Runnable runnable = new Runnable() { |
|
|
| 100% |
Uncovered Elements: 0 (2) |
Complexity: 1 |
Complexity Density: 0,5 |
|
143 |
446
|
@Override... |
144 |
|
public void run() { |
145 |
446
|
updateAll(); |
146 |
446
|
handler.postDelayed(this, 1000L); |
147 |
|
} |
148 |
|
}; |
149 |
1
|
handler.postDelayed(runnable, 1000L); |
150 |
|
} |
151 |
|
|
|
|
| 85,7% |
Uncovered Elements: 1 (7) |
Complexity: 3 |
Complexity Density: 0,6 |
|
152 |
446
|
private static void updateAll() {... |
153 |
446
|
try { |
154 |
446
|
for (SongView view : INSTANCES.keySet()) { |
155 |
7614
|
if (view.isShown()) { |
156 |
799
|
view.update(); |
157 |
|
} |
158 |
|
} |
159 |
|
} catch (Throwable x) { |
160 |
0
|
Log.w(TAG, "Error when updating song views.", x); |
161 |
|
} |
162 |
|
} |
163 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
164 |
923
|
@Override... |
165 |
|
public void setChecked(boolean b) { |
166 |
923
|
checkedTextView.setChecked(b); |
167 |
|
} |
168 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
169 |
0
|
@Override... |
170 |
|
public boolean isChecked() { |
171 |
0
|
return checkedTextView.isChecked(); |
172 |
|
} |
173 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
174 |
0
|
@Override... |
175 |
|
public void toggle() { |
176 |
0
|
checkedTextView.toggle(); |
177 |
|
} |
178 |
|
} |