DCL 4.0
Loading...
Searching...
No Matches
TagCounter.cpp
Go to the documentation of this file.
1#include <dcl/Config.h>
2
3#include <string.h>
4
5#if __DCL_WINDOWS
6#include <windows.h>
7#endif
8
9#include <dcl/String.h>
10#include <dcl/Charset.h>
11#include <dcl/File.h>
12#include <dcl/Dir.h>
13#include <dcl/Writer.h>
14
15#include "APEv2.h"
16
17#include "main.h"
18#include "TagCounter.h"
19
20#define __TRACE_THIS 0
21#if __TRACE_THIS
22#define __DCL_TRACE1_N __DCL_TRACE1
23#define __DCL_TRACE2_N __DCL_TRACE2
24#define __DCL_TRACE3_N __DCL_TRACE3
25#else
26#define __DCL_TRACE1_N(fmt, arg)
27#define __DCL_TRACE2_N(fmt, arg1, arg2)
28#define __DCL_TRACE3_N(fmt, arg1, arg2, arg3)
29#endif
30
31__DCL_BEGIN_NAMESPACE
32
33#if __DCL_DEBUG
34#undef __THIS_FILE__
35static const char_t __THIS_FILE__[] = __T("media/TagCounter.cpp");
36#endif
37
38void TagCounter::read(const String& _filename, TagCounter& _counter)
39{
40 File file(_filename);
41 char buf[160]; // 128 + 32
42
43 int idv2 = 0;
44 int ape = 0;
45 int idv1 = 0;
46
47 // 파일의 시작에서 ID3v2와 APEv2를 검사한다.
48 // "ID3" "APETAGEX"
49 size_t n = file.read(buf, 32);
50 if (n == 32) {
51 if (memcmp(buf, "ID3", 3) == 0) {
52 idv2 = buf[3];
53 }
54 else if (memcmp(buf, "APETAGEX", 8) == 0) {
55 ape = APEv2::word(&buf[8]) / 1000;
56 }
57 }
58
59 // 파일의 끝에서 APEv2와 ID3v1을 검사한다.
60 file.seek(-160, File::END);
61 n = file.read(buf, 160);
62 if (n == 160) {
63 if (ape == 0) {
64 if (memcmp(buf, "APETAGEX", 8) == 0) {
65 ape = APEv2::word(&buf[8]) / 1000;
66 }
67 else if (memcmp(&buf[128], "APETAGEX", 8) == 0) {
68 ape = APEv2::word(&buf[128 + 8]) / 1000;
69 }
70 }
71
72 if (memcmp(&buf[32], "TAG", 3) == 0) {
73 idv1 = 1;
74 }
75 }
76
77 switch (idv2) {
78 case 2:
79 _counter.ID3v22++;
80 break;
81 case 3 :
82 _counter.ID3v23++;
83 break;
84 case 4 :
85 _counter.ID3v24++;
86 }
87
88 switch (ape) {
89 case 1:
90 _counter.APEv1++;
91 break;
92 case 2:
93 _counter.APEv2++;
94 }
95
96 if (idv1 == 1) {
97 _counter.ID3v1++;
98 }
99}
100
101void TagCounter::readDir(const String& _path, TagCounter& _counter,
102 const MainArguments& _args)
103{
104 Dir dir(_path);
105 Dir::Entry entry;
106
107 while (dir.read(entry)) {
108 String name = entry.name();
109 if (entry.isDir()) {
110 if (name.compare(L"..", name.length()) != 0) {
111 String path = dir.path() + name;
112 TagCounter counter;
113 TagCounter::readDir(path, counter, _args);
114 _counter += counter;
115 if (_args.verbose()) {
116 _args.output() << L"[" << path << L"] " << counter.toString() << endl;
117 }
118 }
119 }
120 else {
121 if (name.toLowerCase().endsWith(L".mp3")) {
122 try {
123 TagCounter counter;
124 TagCounter::read(dir.path() + name, counter);
125 _counter += counter;
126 if (_args.verbose()) {
127 _args.output() << L"[ " << name << L"] " << counter.toString() << endl;
128 }
129 }
130 catch (Exception* e) {
131 _counter.error++;
132 _args.errout() << e->toStringAll() << endl;
133 e->destroy();
134 }
135 }
136 }
137 }
138}
139
140__DCL_END_NAMESPACE
#define __THIS_FILE__
Definition _trace.h:14
wchar_t char_t
Definition Config.h:275
#define __T(str)
Definition Object.h:44
#define endl
ByteBuffer * buf
void CharsetConvertException *size_t n
Definition SQLField.cpp:253
Definition Dir.h:38
virtual void destroy()
Definition Exception.cpp:74
String toStringAll() const
Definition Exception.cpp:45
Definition File.h:38
@ END
Definition File.h:207
off_t seek(off_t _offset, int _whence) __DCL_THROWS1(IOException *)
Definition File.cpp:590
virtual size_t read(void *_buf, size_t _n) __DCL_THROWS1(IOException *)
Definition File.cpp:476
bool verbose() const
static void read(const String &_filename, TagCounter &_counter)
String toString() const
Definition TagCounter.h:28
static void readDir(const String &_path, TagCounter &_counter, const MainArguments &_args)