├── .gitignore ├── Graphics ├── add.png ├── icon.ico ├── icon.xcf ├── icon_grey.ico ├── icon_grey.xcf ├── logo.png └── save.png ├── LICENSE ├── Let's Tag.sln ├── Let's Tag ├── Common │ ├── AbstractHttpRequest.cs │ ├── Field.cs │ ├── HttpGetRequest.cs │ ├── HttpPostRequest.cs │ ├── Preset.cs │ ├── PresetManager.cs │ ├── PresetReader.cs │ └── PresetWriter.cs ├── ConsoleProgram.cs ├── ConsoleResource.Designer.cs ├── ConsoleResource.resx ├── DataTypes.cs ├── DragAndDrop │ ├── DragAndDropDelegate.cs │ ├── FileDataObject.cs │ ├── ImageFileDataObject.cs │ └── ShellClipboardFormats.cs ├── Exporter.cs ├── Forms │ ├── AboutForm.Designer.cs │ ├── AboutForm.cs │ ├── AboutForm.resx │ ├── AddPresetForm.Designer.cs │ ├── AddPresetForm.cs │ ├── AddPresetForm.resx │ ├── AlbumGrabForm.Designer.cs │ ├── AlbumGrabForm.cs │ ├── AlbumGrabForm.resx │ ├── AlbumProgressForm.Designer.cs │ ├── AlbumProgressForm.cs │ ├── AlbumProgressForm.resx │ ├── CustomStringFieldForm.Designer.cs │ ├── CustomStringFieldForm.cs │ ├── CustomStringFieldForm.resx │ ├── ExportForm.Designer.cs │ ├── ExportForm.cs │ ├── ExportForm.resx │ ├── MainForm.Designer.cs │ ├── MainForm.cs │ ├── MainForm.resx │ ├── Mp3tagFormatStringForm.Designer.cs │ ├── Mp3tagFormatStringForm.cs │ ├── Mp3tagFormatStringForm.resx │ ├── ResultSelectorForm.Designer.cs │ ├── ResultSelectorForm.cs │ ├── ResultSelectorForm.resx │ ├── SearchForm.Designer.cs │ ├── SearchForm.cs │ ├── SearchForm.resx │ ├── SearchProgressForm.Designer.cs │ ├── SearchProgressForm.cs │ └── SearchProgressForm.resx ├── Let's Tag Console.csproj ├── Let's Tag.csproj ├── LetsTagException.cs ├── Parsers │ ├── AlbumParser.cs │ └── TracklistParser.cs ├── Presets │ ├── Default.xml │ └── Track Data Only.xml ├── Program.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── Resources │ ├── TitleStrings.Designer.cs │ └── TitleStrings.resx ├── icon.ico └── icon_grey.ico ├── README.md └── Screenshot.png /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # MSTest test Results 33 | [Tt]est[Rr]esult*/ 34 | [Bb]uild[Ll]og.* 35 | 36 | # NUNIT 37 | *.VisualState.xml 38 | TestResult.xml 39 | 40 | # Build Results of an ATL Project 41 | [Dd]ebugPS/ 42 | [Rr]eleasePS/ 43 | dlldata.c 44 | 45 | # Benchmark Results 46 | BenchmarkDotNet.Artifacts/ 47 | 48 | # .NET Core 49 | project.lock.json 50 | project.fragment.lock.json 51 | artifacts/ 52 | **/Properties/launchSettings.json 53 | 54 | *_i.c 55 | *_p.c 56 | *_i.h 57 | *.ilk 58 | *.meta 59 | *.obj 60 | *.pch 61 | *.pdb 62 | *.pgc 63 | *.pgd 64 | *.rsp 65 | *.sbr 66 | *.tlb 67 | *.tli 68 | *.tlh 69 | *.tmp 70 | *.tmp_proj 71 | *.log 72 | *.vspscc 73 | *.vssscc 74 | .builds 75 | *.pidb 76 | *.svclog 77 | *.scc 78 | 79 | # Chutzpah Test files 80 | _Chutzpah* 81 | 82 | # Visual C++ cache files 83 | ipch/ 84 | *.aps 85 | *.ncb 86 | *.opendb 87 | *.opensdf 88 | *.sdf 89 | *.cachefile 90 | *.VC.db 91 | *.VC.VC.opendb 92 | 93 | # Visual Studio profiler 94 | *.psess 95 | *.vsp 96 | *.vspx 97 | *.sap 98 | 99 | # TFS 2012 Local Workspace 100 | $tf/ 101 | 102 | # Guidance Automation Toolkit 103 | *.gpState 104 | 105 | # ReSharper is a .NET coding add-in 106 | _ReSharper*/ 107 | *.[Rr]e[Ss]harper 108 | *.DotSettings.user 109 | 110 | # JustCode is a .NET coding add-in 111 | .JustCode 112 | 113 | # TeamCity is a build add-in 114 | _TeamCity* 115 | 116 | # DotCover is a Code Coverage Tool 117 | *.dotCover 118 | 119 | # Visual Studio code coverage results 120 | *.coverage 121 | *.coveragexml 122 | 123 | # NCrunch 124 | _NCrunch_* 125 | .*crunch*.local.xml 126 | nCrunchTemp_* 127 | 128 | # MightyMoose 129 | *.mm.* 130 | AutoTest.Net/ 131 | 132 | # Web workbench (sass) 133 | .sass-cache/ 134 | 135 | # Installshield output folder 136 | [Ee]xpress/ 137 | 138 | # DocProject is a documentation generator add-in 139 | DocProject/buildhelp/ 140 | DocProject/Help/*.HxT 141 | DocProject/Help/*.HxC 142 | DocProject/Help/*.hhc 143 | DocProject/Help/*.hhk 144 | DocProject/Help/*.hhp 145 | DocProject/Help/Html2 146 | DocProject/Help/html 147 | 148 | # Click-Once directory 149 | publish/ 150 | 151 | # Publish Web Output 152 | *.[Pp]ublish.xml 153 | *.azurePubxml 154 | # TODO: Comment the next line if you want to checkin your web deploy settings 155 | # but database connection strings (with potential passwords) will be unencrypted 156 | *.pubxml 157 | *.publishproj 158 | 159 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 160 | # checkin your Azure Web App publish settings, but sensitive information contained 161 | # in these scripts will be unencrypted 162 | PublishScripts/ 163 | 164 | # NuGet Packages 165 | *.nupkg 166 | # The packages folder can be ignored because of Package Restore 167 | **/packages/* 168 | # except build/, which is used as an MSBuild target. 169 | !**/packages/build/ 170 | # Uncomment if necessary however generally it will be regenerated when needed 171 | #!**/packages/repositories.config 172 | # NuGet v3's project.json files produces more ignorable files 173 | *.nuget.props 174 | *.nuget.targets 175 | 176 | # Microsoft Azure Build Output 177 | csx/ 178 | *.build.csdef 179 | 180 | # Microsoft Azure Emulator 181 | ecf/ 182 | rcf/ 183 | 184 | # Windows Store app package directories and files 185 | AppPackages/ 186 | BundleArtifacts/ 187 | Package.StoreAssociation.xml 188 | _pkginfo.txt 189 | *.appx 190 | 191 | # Visual Studio cache files 192 | # files ending in .cache can be ignored 193 | *.[Cc]ache 194 | # but keep track of directories ending in .cache 195 | !*.[Cc]ache/ 196 | 197 | # Others 198 | ClientBin/ 199 | ~$* 200 | *~ 201 | *.dbmdl 202 | *.dbproj.schemaview 203 | *.jfm 204 | *.pfx 205 | *.publishsettings 206 | orleans.codegen.cs 207 | 208 | # Since there are multiple workflows, uncomment next line to ignore bower_components 209 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 210 | #bower_components/ 211 | 212 | # RIA/Silverlight projects 213 | Generated_Code/ 214 | 215 | # Backup & report files from converting an old project file 216 | # to a newer Visual Studio version. Backup files are not needed, 217 | # because we have git ;-) 218 | _UpgradeReport_Files/ 219 | Backup*/ 220 | UpgradeLog*.XML 221 | UpgradeLog*.htm 222 | 223 | # SQL Server files 224 | *.mdf 225 | *.ldf 226 | *.ndf 227 | 228 | # Business Intelligence projects 229 | *.rdl.data 230 | *.bim.layout 231 | *.bim_*.settings 232 | 233 | # Microsoft Fakes 234 | FakesAssemblies/ 235 | 236 | # GhostDoc plugin setting file 237 | *.GhostDoc.xml 238 | 239 | # Node.js Tools for Visual Studio 240 | .ntvs_analysis.dat 241 | node_modules/ 242 | 243 | # Typescript v1 declaration files 244 | typings/ 245 | 246 | # Visual Studio 6 build log 247 | *.plg 248 | 249 | # Visual Studio 6 workspace options file 250 | *.opt 251 | 252 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 253 | *.vbw 254 | 255 | # Visual Studio LightSwitch build output 256 | **/*.HTMLClient/GeneratedArtifacts 257 | **/*.DesktopClient/GeneratedArtifacts 258 | **/*.DesktopClient/ModelManifest.xml 259 | **/*.Server/GeneratedArtifacts 260 | **/*.Server/ModelManifest.xml 261 | _Pvt_Extensions 262 | 263 | # Paket dependency manager 264 | .paket/paket.exe 265 | paket-files/ 266 | 267 | # FAKE - F# Make 268 | .fake/ 269 | 270 | # JetBrains Rider 271 | .idea/ 272 | *.sln.iml 273 | 274 | # CodeRush 275 | .cr/ 276 | 277 | # Python Tools for Visual Studio (PTVS) 278 | __pycache__/ 279 | *.pyc 280 | 281 | # Cake - Uncomment if you are using it 282 | # tools/** 283 | # !tools/packages.config 284 | 285 | # Tabs Studio 286 | *.tss 287 | 288 | # Telerik's JustMock configuration file 289 | *.jmconfig 290 | 291 | # BizTalk build output 292 | *.btp.cs 293 | *.btm.cs 294 | *.odx.cs 295 | *.xsd.cs 296 | -------------------------------------------------------------------------------- /Graphics/add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomvoros/lets-tag/5894ece174a06c7ce1dcd09c6cb3a8a3a0d81527/Graphics/add.png -------------------------------------------------------------------------------- /Graphics/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomvoros/lets-tag/5894ece174a06c7ce1dcd09c6cb3a8a3a0d81527/Graphics/icon.ico -------------------------------------------------------------------------------- /Graphics/icon.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomvoros/lets-tag/5894ece174a06c7ce1dcd09c6cb3a8a3a0d81527/Graphics/icon.xcf -------------------------------------------------------------------------------- /Graphics/icon_grey.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomvoros/lets-tag/5894ece174a06c7ce1dcd09c6cb3a8a3a0d81527/Graphics/icon_grey.ico -------------------------------------------------------------------------------- /Graphics/icon_grey.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomvoros/lets-tag/5894ece174a06c7ce1dcd09c6cb3a8a3a0d81527/Graphics/icon_grey.xcf -------------------------------------------------------------------------------- /Graphics/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomvoros/lets-tag/5894ece174a06c7ce1dcd09c6cb3a8a3a0d81527/Graphics/logo.png -------------------------------------------------------------------------------- /Graphics/save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomvoros/lets-tag/5894ece174a06c7ce1dcd09c6cb3a8a3a0d81527/Graphics/save.png -------------------------------------------------------------------------------- /Let's Tag.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Let's Tag", "Let's Tag\Let's Tag.csproj", "{33E63699-BFB6-4719-9D9A-BBFA6AF7A8AE}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Let's Tag Console", "Let's Tag\Let's Tag Console.csproj", "{4E480DE6-1F7A-4BEF-BCCB-F027E1ADFE9B}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {33E63699-BFB6-4719-9D9A-BBFA6AF7A8AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {33E63699-BFB6-4719-9D9A-BBFA6AF7A8AE}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {33E63699-BFB6-4719-9D9A-BBFA6AF7A8AE}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {33E63699-BFB6-4719-9D9A-BBFA6AF7A8AE}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {4E480DE6-1F7A-4BEF-BCCB-F027E1ADFE9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {4E480DE6-1F7A-4BEF-BCCB-F027E1ADFE9B}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {4E480DE6-1F7A-4BEF-BCCB-F027E1ADFE9B}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {4E480DE6-1F7A-4BEF-BCCB-F027E1ADFE9B}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(SubversionScc) = preSolution 29 | Svn-Managed = True 30 | Manager = AnkhSVN - Subversion Support for Visual Studio 31 | EndGlobalSection 32 | EndGlobal 33 | -------------------------------------------------------------------------------- /Let's Tag/Common/AbstractHttpRequest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Net; 4 | 5 | namespace LetsTag.Common 6 | { 7 | public enum HttpRequestStatus { Initializing, Connecting, Downloading, Done, Aborted, Error } 8 | 9 | public delegate void HttpRequestHandler(AbstractHttpRequest request, HttpRequestStatus status); 10 | 11 | public abstract class AbstractHttpRequest 12 | { 13 | const int BUFFER_SIZE = 8192; 14 | 15 | protected WebRequest request; 16 | HttpRequestHandler handler; 17 | protected HttpRequestStatus status; 18 | byte[] responseBuffer; 19 | byte[] responseCompleteBuffer = new byte[0]; 20 | string error; 21 | 22 | public byte[] Response 23 | { 24 | get { return responseCompleteBuffer; } 25 | } 26 | 27 | public string Error 28 | { 29 | get { return error; } 30 | } 31 | 32 | public HttpRequestStatus Status 33 | { 34 | get { return status; } 35 | } 36 | 37 | public AbstractHttpRequest(string uri) 38 | : this(uri, null) { } 39 | 40 | public AbstractHttpRequest(string uri, HttpRequestHandler handler) 41 | { 42 | request = WebRequest.Create(uri); 43 | this.handler = handler; 44 | UpdateStatus(HttpRequestStatus.Initializing); 45 | } 46 | 47 | public void Abort() 48 | { 49 | UpdateStatus(HttpRequestStatus.Aborted); 50 | request.Abort(); 51 | } 52 | 53 | public virtual void Execute() 54 | { 55 | if (status == HttpRequestStatus.Aborted) 56 | return; 57 | 58 | UpdateStatus(HttpRequestStatus.Connecting); 59 | request.BeginGetResponse(new AsyncCallback(OnGetResponse), null); 60 | } 61 | 62 | void OnGetResponse(IAsyncResult result) 63 | { 64 | try 65 | { 66 | if (status == HttpRequestStatus.Aborted) 67 | return; 68 | 69 | UpdateStatus(HttpRequestStatus.Downloading); 70 | 71 | WebResponse response = request.EndGetResponse(result); 72 | 73 | Stream responseStream = response.GetResponseStream(); 74 | BufferedStream responseBufferedStream = new BufferedStream(responseStream, BUFFER_SIZE); 75 | 76 | responseBuffer = new byte[BUFFER_SIZE]; 77 | 78 | responseBufferedStream.BeginRead(responseBuffer, 0, BUFFER_SIZE, new AsyncCallback(OnRead), responseBufferedStream); 79 | } 80 | catch (Exception ex) 81 | { 82 | UpdateError(ex.Message); 83 | } 84 | } 85 | 86 | void OnRead(IAsyncResult result) 87 | { 88 | try 89 | { 90 | if (status == HttpRequestStatus.Aborted) 91 | return; 92 | 93 | BufferedStream responseBufferedStream = (BufferedStream)result.AsyncState; 94 | int length = responseBufferedStream.EndRead(result); 95 | 96 | byte[] newBuffer = new byte[responseCompleteBuffer.Length + length]; 97 | Array.Copy(responseCompleteBuffer, newBuffer, responseCompleteBuffer.Length); 98 | Array.Copy(responseBuffer, 0, newBuffer, responseCompleteBuffer.Length, length); 99 | responseCompleteBuffer = newBuffer; 100 | 101 | // Update status since responseCompleteBuffer size has changed 102 | UpdateStatus(HttpRequestStatus.Downloading); 103 | 104 | if (length > 0) 105 | { 106 | responseBufferedStream.BeginRead(responseBuffer, 0, BUFFER_SIZE, new AsyncCallback(OnRead), responseBufferedStream); 107 | } 108 | else 109 | { 110 | responseBufferedStream.Close(); 111 | UpdateStatus(HttpRequestStatus.Done); 112 | } 113 | } 114 | catch (Exception ex) 115 | { 116 | UpdateError(ex.Message); 117 | } 118 | } 119 | 120 | protected void UpdateStatus(HttpRequestStatus status) 121 | { 122 | this.status = status; 123 | 124 | if(handler != null) 125 | handler(this, status); 126 | } 127 | 128 | protected void UpdateError(string error) 129 | { 130 | this.error = error; 131 | UpdateStatus(HttpRequestStatus.Error); 132 | } 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /Let's Tag/Common/Field.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Xml; 3 | 4 | namespace LetsTag.Common 5 | { 6 | public interface IField 7 | { 8 | string GetName(); 9 | string GetMp3tagFormat(); 10 | string GetValue(Album album, Disc disc, Track track); 11 | void WriteXml(XmlWriter writer); 12 | } 13 | 14 | public abstract class BaseField : IField 15 | { 16 | public abstract string GetName(); 17 | public abstract string GetMp3tagFormat(); 18 | public abstract string GetValue(Album album, Disc disc, Track track); 19 | public abstract void WriteXml(XmlWriter writer); 20 | 21 | protected void WriteXmlStartField(XmlWriter writer) 22 | { 23 | writer.WriteStartElement("field"); 24 | writer.WriteStartAttribute("mp3tagFormat"); 25 | writer.WriteString(GetMp3tagFormat()); 26 | writer.WriteEndAttribute(); 27 | } 28 | 29 | protected void WriteXmlEndField(XmlWriter writer) 30 | { 31 | writer.WriteEndElement(); 32 | } 33 | } 34 | 35 | public class SimpleField : BaseField 36 | { 37 | IFieldValue fieldValue; 38 | string mp3tagFormat; 39 | 40 | public SimpleField(IFieldValue fieldValue) 41 | : this(fieldValue, "%dummy%") { } 42 | 43 | public SimpleField(IFieldValue fieldValue, string mp3tagFormat) 44 | { 45 | this.fieldValue = fieldValue; 46 | this.mp3tagFormat = mp3tagFormat; 47 | } 48 | 49 | public override string GetName() 50 | { 51 | return fieldValue.GetName(); 52 | } 53 | 54 | public override string GetMp3tagFormat() 55 | { 56 | return mp3tagFormat; 57 | } 58 | 59 | public override string GetValue(Album album, Disc disc, Track track) 60 | { 61 | return fieldValue.GetValue(album, disc, track); 62 | } 63 | 64 | public override void WriteXml(XmlWriter writer) 65 | { 66 | WriteXmlStartField(writer); 67 | fieldValue.WriteXml(writer); 68 | WriteXmlEndField(writer); 69 | } 70 | } 71 | 72 | public class CompositeField : BaseField 73 | { 74 | IList fieldValues = new List(); 75 | string mp3tagFormat; 76 | 77 | public IList FieldValues 78 | { 79 | get { return fieldValues; } 80 | } 81 | 82 | public CompositeField() 83 | : this("%dummy%") { } 84 | 85 | public CompositeField(string mp3tagFormat) 86 | { 87 | this.mp3tagFormat = mp3tagFormat; 88 | } 89 | 90 | public override string GetName() 91 | { 92 | string name = ""; 93 | foreach (IFieldValue fieldValue in fieldValues) 94 | name += fieldValue.GetName(); 95 | return name; 96 | } 97 | 98 | public override string GetMp3tagFormat() 99 | { 100 | return mp3tagFormat; 101 | } 102 | 103 | public override string GetValue(Album album, Disc disc, Track track) 104 | { 105 | string value = ""; 106 | foreach (IFieldValue fieldValue in fieldValues) 107 | value += fieldValue.GetValue(album, disc, track); 108 | return value; 109 | } 110 | 111 | public override void WriteXml(XmlWriter writer) 112 | { 113 | WriteXmlStartField(writer); 114 | foreach (IFieldValue fieldValue in fieldValues) 115 | fieldValue.WriteXml(writer); 116 | WriteXmlEndField(writer); 117 | } 118 | } 119 | 120 | public interface IFieldValue 121 | { 122 | string GetName(); 123 | string GetValue(Album album, Disc disc, Track track); 124 | void WriteXml(XmlWriter writer); 125 | } 126 | 127 | public class AlbumFieldValue : IFieldValue 128 | { 129 | string fieldName; 130 | 131 | public AlbumFieldValue(string fieldName) 132 | { 133 | this.fieldName = fieldName; 134 | } 135 | 136 | public string GetName() 137 | { 138 | return string.Format("", fieldName); 139 | } 140 | 141 | public string GetValue(Album album, Disc disc, Track track) 142 | { 143 | return album.Details[fieldName]; 144 | } 145 | 146 | public void WriteXml(XmlWriter writer) 147 | { 148 | writer.WriteStartElement("albumfield"); 149 | writer.WriteStartAttribute("name"); 150 | writer.WriteString(fieldName); 151 | writer.WriteEndAttribute(); 152 | writer.WriteEndElement(); 153 | } 154 | } 155 | 156 | public class DiscNumberValue : IFieldValue 157 | { 158 | public DiscNumberValue() { } 159 | 160 | public string GetName() 161 | { 162 | return ""; 163 | } 164 | 165 | public string GetValue(Album album, Disc disc, Track track) 166 | { 167 | return disc.Number; 168 | } 169 | 170 | public void WriteXml(XmlWriter writer) 171 | { 172 | writer.WriteStartElement("discnumber"); 173 | writer.WriteEndElement(); 174 | } 175 | } 176 | 177 | public class TrackNumberValue : IFieldValue 178 | { 179 | public TrackNumberValue() { } 180 | 181 | public string GetName() 182 | { 183 | return ""; 184 | } 185 | 186 | public string GetValue(Album album, Disc disc, Track track) 187 | { 188 | return track.Number; 189 | } 190 | 191 | public void WriteXml(XmlWriter writer) 192 | { 193 | writer.WriteStartElement("tracknumber"); 194 | writer.WriteEndElement(); 195 | } 196 | } 197 | 198 | public class TrackNameValue : IFieldValue 199 | { 200 | public TrackNameValue() { } 201 | 202 | public string GetName() 203 | { 204 | return ""; 205 | } 206 | 207 | public string GetValue(Album album, Disc disc, Track track) 208 | { 209 | return track.Name; 210 | } 211 | 212 | public void WriteXml(XmlWriter writer) 213 | { 214 | writer.WriteStartElement("trackname"); 215 | writer.WriteEndElement(); 216 | } 217 | } 218 | 219 | public class StringValue : IFieldValue 220 | { 221 | string value; 222 | 223 | public StringValue(string value) 224 | { 225 | this.value = value; 226 | } 227 | 228 | public string GetName() 229 | { 230 | return value; 231 | } 232 | 233 | public string GetValue(Album album, Disc disc, Track track) 234 | { 235 | return value; 236 | } 237 | 238 | public void WriteXml(XmlWriter writer) 239 | { 240 | writer.WriteString(value); 241 | } 242 | } 243 | } 244 | -------------------------------------------------------------------------------- /Let's Tag/Common/HttpGetRequest.cs: -------------------------------------------------------------------------------- 1 | namespace LetsTag.Common 2 | { 3 | public class HttpGetRequest : AbstractHttpRequest 4 | { 5 | public HttpGetRequest(string uri) 6 | : base(uri) { } 7 | 8 | public HttpGetRequest(string uri, HttpRequestHandler handler) 9 | : base(uri, handler) { } 10 | 11 | public override void Execute() 12 | { 13 | request.Method = "GET"; 14 | base.Execute(); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Let's Tag/Common/HttpPostRequest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text; 5 | 6 | namespace LetsTag.Common 7 | { 8 | public class HttpPostRequest : AbstractHttpRequest 9 | { 10 | IDictionary postData; 11 | 12 | public IDictionary PostData 13 | { 14 | get { return postData; } 15 | set { postData = value; } 16 | } 17 | 18 | public HttpPostRequest(string uri) 19 | : this(uri, new Dictionary(), null) { } 20 | 21 | public HttpPostRequest(string uri, HttpRequestHandler handler) 22 | : this(uri, new Dictionary(), handler) { } 23 | 24 | public HttpPostRequest(string uri, IDictionary postData) 25 | : this(uri, postData, null) { } 26 | 27 | public HttpPostRequest(string uri, IDictionary postData, HttpRequestHandler handler) 28 | : base(uri, handler) 29 | { 30 | this.postData = postData; 31 | } 32 | 33 | public override void Execute() 34 | { 35 | request.Method = "POST"; 36 | request.ContentType = "application/x-www-form-urlencoded"; 37 | request.BeginGetRequestStream(new AsyncCallback(OnGetRequestStream), null); 38 | } 39 | 40 | void OnGetRequestStream(IAsyncResult result) 41 | { 42 | try 43 | { 44 | if (status == HttpRequestStatus.Aborted) 45 | return; 46 | 47 | Stream requestStream = request.EndGetRequestStream(result); 48 | StreamWriter requestStreamWriter = new StreamWriter(requestStream); 49 | requestStreamWriter.Write(BuildPostDataString()); 50 | requestStreamWriter.Close(); 51 | 52 | base.Execute(); 53 | } 54 | catch (Exception ex) 55 | { 56 | UpdateError(ex.Message); 57 | } 58 | } 59 | 60 | string BuildPostDataString() 61 | { 62 | StringBuilder postDataBuilder = new StringBuilder(); 63 | foreach (KeyValuePair pair in postData) 64 | postDataBuilder.AppendFormat("{0}={1}&", pair.Key, Uri.EscapeDataString(pair.Value.ToString())); 65 | return postDataBuilder.ToString(); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Let's Tag/Common/Preset.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace LetsTag.Common 4 | { 5 | public class Preset 6 | { 7 | string name; 8 | IList fields; 9 | string delimiter; 10 | 11 | public string Name 12 | { 13 | get { return name; } 14 | set { name = value; } 15 | } 16 | 17 | public IList Fields 18 | { 19 | get { return fields; } 20 | } 21 | 22 | public string Delimiter 23 | { 24 | get { return delimiter; } 25 | set { delimiter = value; } 26 | } 27 | 28 | public Preset(string name) 29 | : this(name, new List(), "//") { } 30 | 31 | public Preset(string name, string delimiter) 32 | : this(name, new List(), delimiter) { } 33 | 34 | public Preset(string name, IList fields) 35 | : this(name, new List(fields), "//") { } 36 | 37 | public Preset(string name, IList fields, string delimiter) 38 | { 39 | this.name = name; 40 | this.fields = new List(fields); 41 | this.delimiter = delimiter; 42 | } 43 | 44 | public Preset Clone() 45 | { 46 | return new Preset(name, fields, delimiter); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Let's Tag/Common/PresetManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Reflection; 4 | 5 | namespace LetsTag.Common 6 | { 7 | public class PresetManager 8 | { 9 | static readonly string APPLICATION_PATH = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); 10 | static readonly string PRESETS_PATH = APPLICATION_PATH + @"\Presets"; 11 | 12 | public static Stream OpenPresetFile(string path, FileMode mode, FileAccess access) 13 | { 14 | string currentDirectory = Directory.GetCurrentDirectory(); 15 | try 16 | { 17 | Directory.SetCurrentDirectory(PRESETS_PATH); 18 | return File.Open(path, mode, access); 19 | } 20 | catch (Exception ex) 21 | { 22 | throw new LetsTagException("Could not access presets directory", ex); 23 | } 24 | finally 25 | { 26 | Directory.SetCurrentDirectory(currentDirectory); 27 | } 28 | } 29 | 30 | public static bool PresetFileExists(string path) 31 | { 32 | string currentDirectory = Directory.GetCurrentDirectory(); 33 | try 34 | { 35 | Directory.SetCurrentDirectory(PRESETS_PATH); 36 | return File.Exists(path); 37 | } 38 | catch (Exception ex) 39 | { 40 | throw new LetsTagException("Could not access presets directory", ex); 41 | } 42 | finally 43 | { 44 | Directory.SetCurrentDirectory(currentDirectory); 45 | } 46 | } 47 | 48 | public static void DeletePresetFile(string path) 49 | { 50 | string currentDirectory = Directory.GetCurrentDirectory(); 51 | try 52 | { 53 | Directory.SetCurrentDirectory(PRESETS_PATH); 54 | File.Delete(path); 55 | } 56 | catch (Exception ex) 57 | { 58 | throw new LetsTagException("Could not access presets directory", ex); 59 | } 60 | finally 61 | { 62 | Directory.SetCurrentDirectory(currentDirectory); 63 | } 64 | } 65 | 66 | public static string[] GetPresetFiles() 67 | { 68 | string[] presetFiles = Directory.GetFiles(PRESETS_PATH, "*.xml", SearchOption.TopDirectoryOnly); 69 | for (int i = 0; i < presetFiles.Length; i++) 70 | presetFiles[i] = Path.GetFileName(presetFiles[i]); 71 | return presetFiles; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Let's Tag/Common/PresetReader.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Xml; 3 | 4 | namespace LetsTag.Common 5 | { 6 | public class PresetReader 7 | { 8 | public static Preset LoadPreset(string path) 9 | { 10 | Stream stream = PresetManager.OpenPresetFile(path, FileMode.Open, FileAccess.Read); 11 | XmlReader reader = new XmlTextReader(stream); 12 | Preset preset = new Preset(Path.GetFileNameWithoutExtension(path)); 13 | ReadPreset(reader, preset); 14 | reader.Close(); 15 | return preset; 16 | } 17 | 18 | private static void ReadPreset(XmlReader reader, Preset preset) 19 | { 20 | while (reader.Read()) 21 | { 22 | if (reader.NodeType == XmlNodeType.Element && reader.Name.ToLower() == "preset") 23 | { 24 | string delimiter = reader.GetAttribute("delimiter"); 25 | if (!string.IsNullOrEmpty(delimiter)) 26 | preset.Delimiter = delimiter; 27 | 28 | ReadPresetFields(reader.ReadSubtree(), preset); 29 | 30 | return; 31 | } 32 | } 33 | 34 | throw new LetsTagException("Could not find element"); 35 | } 36 | 37 | private static void ReadPresetFields(XmlReader reader, Preset preset) 38 | { 39 | while (reader.Read()) 40 | { 41 | if (reader.NodeType == XmlNodeType.Element && reader.Name.ToLower() == "field") 42 | preset.Fields.Add(ReadPresetField(reader.ReadSubtree())); 43 | } 44 | } 45 | 46 | private static IField ReadPresetField(XmlReader reader) 47 | { 48 | CompositeField field; 49 | 50 | reader.Read(); 51 | 52 | if(string.IsNullOrEmpty(reader.GetAttribute("mp3tagFormat"))) 53 | field = new CompositeField(); 54 | else 55 | field = new CompositeField(reader.GetAttribute("mp3tagFormat")); 56 | 57 | while (reader.Read()) 58 | { 59 | switch (reader.NodeType) 60 | { 61 | case XmlNodeType.Text: 62 | field.FieldValues.Add(new StringValue(reader.Value)); 63 | break; 64 | 65 | case XmlNodeType.Element: 66 | switch (reader.Name.ToLower()) 67 | { 68 | case "discnumber": 69 | field.FieldValues.Add(new DiscNumberValue()); 70 | break; 71 | 72 | case "tracknumber": 73 | field.FieldValues.Add(new TrackNumberValue()); 74 | break; 75 | 76 | case "trackname": 77 | field.FieldValues.Add(new TrackNameValue()); 78 | break; 79 | 80 | case "albumfield": 81 | field.FieldValues.Add(ReadPresetAlbumFieldValue(reader.ReadSubtree())); 82 | break; 83 | 84 | case "field": 85 | throw new LetsTagException("Missing closing element"); 86 | 87 | default: 88 | throw new LetsTagException(string.Format("Unrecognized element <{0}>", reader.Name)); 89 | } 90 | break; 91 | 92 | case XmlNodeType.EndElement: 93 | if(reader.Name.ToLower() == "field") 94 | return field; 95 | break; 96 | } 97 | } 98 | 99 | throw new LetsTagException("Missing closing element"); 100 | } 101 | 102 | private static AlbumFieldValue ReadPresetAlbumFieldValue(XmlReader reader) 103 | { 104 | reader.Read(); 105 | 106 | string name = reader.GetAttribute("name"); 107 | 108 | if(string.IsNullOrEmpty(name)) 109 | throw new LetsTagException(" element missing name attribute"); 110 | 111 | return new AlbumFieldValue(name); 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /Let's Tag/Common/PresetWriter.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Text; 3 | using System.Xml; 4 | 5 | namespace LetsTag.Common 6 | { 7 | public class PresetWriter 8 | { 9 | public static void SavePreset(Preset preset) 10 | { 11 | string path = string.Format("{0}.xml", preset.Name); 12 | Stream stream = PresetManager.OpenPresetFile(path, FileMode.Create, FileAccess.ReadWrite); 13 | XmlWriter writer = new XmlTextWriter(stream, UTF8Encoding.UTF8); 14 | WritePreset(writer, preset); 15 | writer.Flush(); 16 | writer.Close(); 17 | } 18 | 19 | private static void WritePreset(XmlWriter writer, Preset preset) 20 | { 21 | writer.WriteStartDocument(); 22 | writer.WriteWhitespace("\r\n"); 23 | writer.WriteStartElement("preset"); 24 | writer.WriteStartAttribute("delimiter"); 25 | writer.WriteString(preset.Delimiter); 26 | writer.WriteEndAttribute(); 27 | writer.WriteWhitespace("\r\n"); 28 | 29 | WritePresetFields(writer, preset); 30 | 31 | writer.WriteEndElement(); 32 | writer.WriteEndDocument(); 33 | } 34 | 35 | private static void WritePresetFields(XmlWriter writer, Preset preset) 36 | { 37 | foreach (IField field in preset.Fields) 38 | { 39 | writer.WriteWhitespace("\t"); 40 | field.WriteXml(writer); 41 | writer.WriteWhitespace("\r\n"); 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Let's Tag/ConsoleProgram.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Reflection; 5 | using System.Resources; 6 | using System.Text; 7 | using System.Threading; 8 | using LetsTag.Common; 9 | 10 | namespace LetsTag 11 | { 12 | class ConsoleProgram 13 | { 14 | public static int Main(string[] args) 15 | { 16 | try 17 | { 18 | if (args.Length == 0) 19 | { 20 | PrintUsage(); 21 | return 0; 22 | } 23 | 24 | IDictionary options = new Dictionary(); 25 | 26 | for (int i = 0; i < args.Length; i++) 27 | { 28 | string arg = args[i]; 29 | 30 | if (arg == "--help") 31 | { 32 | PrintUsage(); 33 | return 0; 34 | } 35 | else if (arg.StartsWith("--album=")) 36 | { 37 | options.Add("album", arg.Substring(8)); 38 | } 39 | else if (arg.StartsWith("-a=")) 40 | { 41 | options.Add("album", arg.Substring(3)); 42 | } 43 | else if (arg.StartsWith("--preset=")) 44 | { 45 | options.Add("preset", arg.Substring(9)); 46 | } 47 | else if (arg.StartsWith("-p=")) 48 | { 49 | options.Add("preset", arg.Substring(3)); 50 | } 51 | else if (i == args.Length - 1) 52 | { 53 | options.Add("output", arg); 54 | } 55 | } 56 | 57 | if (!options.ContainsKey("output")) 58 | options.Add("output", "-"); 59 | 60 | Validate(options); 61 | Execute(options); 62 | } 63 | catch (LetsTagException ex) 64 | { 65 | Console.WriteLine(ex.ToString()); 66 | return 1; 67 | } 68 | catch (Exception ex) 69 | { 70 | Console.WriteLine("Let's Tag encountered an unhandled exception:"); 71 | Console.WriteLine(ex.ToString()); 72 | return 2; 73 | } 74 | 75 | return 0; 76 | } 77 | 78 | static void PrintUsage() 79 | { 80 | ResourceManager resourceManager = new ResourceManager("LetsTag.ConsoleResource", Assembly.GetExecutingAssembly()); 81 | Console.WriteLine(resourceManager.GetString("UsageString")); 82 | } 83 | 84 | static void Validate(IDictionary options) 85 | { 86 | string output = options["output"]; 87 | if (output != "-") 88 | { 89 | try 90 | { 91 | Path.GetFullPath(output); 92 | } 93 | catch (Exception ex) 94 | { 95 | throw new LetsTagException("Invalid output file: " + output, ex); 96 | } 97 | } 98 | 99 | if (!options.ContainsKey("album")) 100 | throw new LetsTagException("No album specified"); 101 | } 102 | 103 | static void Execute(IDictionary options) 104 | { 105 | Preset preset = GetPreset(options); 106 | Album album = GetAlbum(options["album"]); 107 | StreamWriter output = OpenOutput(options["output"]); 108 | Exporter.Export(album, preset, output); 109 | output.Close(); 110 | } 111 | 112 | static StreamWriter OpenOutput(string output) 113 | { 114 | if (output == "-") 115 | { 116 | return new StreamWriter(Console.OpenStandardOutput(), new UTF8Encoding(false)); 117 | } 118 | else 119 | { 120 | try 121 | { 122 | return new StreamWriter(output, false, new UTF8Encoding(true)); 123 | } 124 | catch (Exception ex) 125 | { 126 | throw new LetsTagException("Could not open output file: " + output, ex); 127 | } 128 | } 129 | } 130 | 131 | static Album GetAlbum(string albumId) 132 | { 133 | string albumData = GetAlbumData(albumId); 134 | 135 | Album album = new Album(); 136 | 137 | // Split data string where the tracklist starts 138 | int tracklistIndex = albumData.IndexOf(">Tracklist options) 174 | { 175 | try 176 | { 177 | string presetName = "Default.xml"; 178 | if (options.ContainsKey("preset")) 179 | { 180 | presetName = options["preset"]; 181 | if (string.IsNullOrEmpty(Path.GetExtension(presetName))) 182 | presetName = string.Format("{0}.xml", presetName); 183 | } 184 | return PresetReader.LoadPreset(presetName); 185 | } 186 | catch (Exception ex) 187 | { 188 | throw new LetsTagException("Could not load preset", ex); 189 | } 190 | } 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /Let's Tag/ConsoleResource.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace LetsTag { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class ConsoleResource { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal ConsoleResource() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("LetsTag.ConsoleResource", typeof(ConsoleResource).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized string similar to Usage: letstagc [OPTION] [FILE] 65 | ///Download album data from vgmdb.net and output formatted data to FILE. 66 | /// 67 | ///Options: 68 | /// -a, --album=NUMBER album NUMBER of album to download 69 | /// -p, --preset=NAME use preset NAME to format output 70 | /// 71 | ///When FILE is not specified, write to standard output.. 72 | /// 73 | internal static string UsageString { 74 | get { 75 | return ResourceManager.GetString("UsageString", resourceCulture); 76 | } 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Let's Tag/ConsoleResource.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | Usage: letstagc [OPTION] [FILE] 122 | Download album data from vgmdb.net and output formatted data to FILE. 123 | 124 | Options: 125 | -a, --album=NUMBER album NUMBER of album to download 126 | -p, --preset=NAME use preset NAME to format output 127 | 128 | When FILE is not specified, write to standard output. 129 | 130 | -------------------------------------------------------------------------------- /Let's Tag/DataTypes.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Drawing; 3 | 4 | namespace LetsTag 5 | { 6 | public class Album 7 | { 8 | public IDictionary Details = new Dictionary(); 9 | public IList Discs = new List(); 10 | public Image Cover = null; 11 | } 12 | 13 | public class Disc 14 | { 15 | public string Number; 16 | public IList Tracks = new List(); 17 | } 18 | 19 | public class Track 20 | { 21 | public string Number; 22 | public string Name; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Let's Tag/DragAndDrop/DragAndDropDelegate.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * This file is based on sample code found on the internet. 4 | * Original author unknown. 5 | * 6 | * Source: 7 | * http://riqueliam.blog.51cto.com/466137/107612 8 | * 9 | *****************************************************************************/ 10 | 11 | using System.Windows.Forms; 12 | 13 | namespace LetsTag.DragAndDrop 14 | { 15 | public class DragAndDropDelegate 16 | { 17 | Control dragSourceControl; 18 | DataObject dataObject; 19 | 20 | QueryContinueDragEventHandler queryContinueDragEventHandler; 21 | 22 | public DragAndDropDelegate(Control dragSourceControl, DataObject dataObject, DragDropEffects allowedEffects) 23 | { 24 | this.dragSourceControl = dragSourceControl; 25 | this.dataObject = dataObject; 26 | 27 | queryContinueDragEventHandler = new QueryContinueDragEventHandler(HandleQueryContinueDrag); 28 | dragSourceControl.QueryContinueDrag += queryContinueDragEventHandler; 29 | dragSourceControl.DoDragDrop(dataObject, allowedEffects); 30 | } 31 | 32 | private void HandleQueryContinueDrag(object sender, QueryContinueDragEventArgs e) 33 | { 34 | bool endDrag = false; 35 | 36 | if (e.EscapePressed) 37 | { 38 | // ESC pressed 39 | e.Action = DragAction.Cancel; 40 | endDrag = true; 41 | } 42 | else if (e.KeyState == 0) 43 | { 44 | // Drop 45 | dataObject.SetData(ShellClipboardFormats.CFSTR_INDRAGLOOP, 0); 46 | e.Action = DragAction.Drop; 47 | endDrag = true; 48 | } 49 | 50 | if (endDrag) 51 | { 52 | dragSourceControl.QueryContinueDrag -= queryContinueDragEventHandler; 53 | return; 54 | } 55 | 56 | e.Action = DragAction.Continue; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Let's Tag/DragAndDrop/FileDataObject.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * This file is based on sample code found on the internet. 4 | * Original author unknown. 5 | * 6 | * Source: 7 | * http://riqueliam.blog.51cto.com/466137/107612 8 | * 9 | *****************************************************************************/ 10 | 11 | using System.IO; 12 | using System.Windows.Forms; 13 | 14 | namespace LetsTag.DragAndDrop 15 | { 16 | public abstract class FileDataObject : DataObject 17 | { 18 | // This flag is used to prevent multiple callings to "GetData" when dropping in Explorer 19 | bool fileCreated = false; 20 | 21 | string tempFilename; 22 | 23 | public FileDataObject(string filename) 24 | { 25 | // Build a path for the temporary file 26 | tempFilename = Path.Combine(Path.GetTempPath(), filename); 27 | 28 | // Create the temporary file to make sure it exists 29 | FileStream fileStream = File.Create(tempFilename); 30 | fileStream.Close(); 31 | 32 | // Add the file to the data object 33 | SetData(DataFormats.FileDrop, new string[] { tempFilename }); 34 | 35 | // Set the preferred drop effect 36 | SetData(ShellClipboardFormats.CFSTR_PREFERREDDROPEFFECT, DragDropEffects.Copy); 37 | 38 | // Indicate that we are in a drag loop 39 | SetData(ShellClipboardFormats.CFSTR_INDRAGLOOP, 1); 40 | } 41 | 42 | public override object GetData(string format) 43 | { 44 | object obj = base.GetData(format); 45 | 46 | if (!fileCreated && format == DataFormats.FileDrop && !InDragLoop()) 47 | { 48 | CreateFile(tempFilename); 49 | fileCreated = true; 50 | } 51 | 52 | return obj; 53 | } 54 | 55 | private bool InDragLoop() 56 | { 57 | return ((int)GetData(ShellClipboardFormats.CFSTR_INDRAGLOOP) != 0); 58 | } 59 | 60 | // Create the temporary file and its data 61 | protected abstract void CreateFile(string tempFilename); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Let's Tag/DragAndDrop/ImageFileDataObject.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using System.Drawing.Imaging; 3 | 4 | namespace LetsTag.DragAndDrop 5 | { 6 | public class ImageFileDataObject : FileDataObject 7 | { 8 | Image image; 9 | ImageCodecInfo imageEncoder; 10 | EncoderParameters imageEncoderParams; 11 | 12 | public ImageFileDataObject(string filename, Image image) 13 | : this(filename, image, null) { } 14 | 15 | public ImageFileDataObject(string filename, Image image, ImageCodecInfo imageEncoder) 16 | : this(filename, image, imageEncoder, null) { } 17 | 18 | public ImageFileDataObject(string filename, Image image, ImageCodecInfo imageEncoder, EncoderParameters imageEncoderParams) 19 | : base(filename) 20 | { 21 | this.image = image; 22 | this.imageEncoder = imageEncoder; 23 | this.imageEncoderParams = imageEncoderParams; 24 | } 25 | 26 | protected override void CreateFile(string tempFilename) 27 | { 28 | if (imageEncoder == null) 29 | image.Save(tempFilename); 30 | else 31 | image.Save(tempFilename, imageEncoder, imageEncoderParams); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Let's Tag/DragAndDrop/ShellClipboardFormats.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * This file is based on sample code found on the internet. 4 | * Original author unknown. 5 | * 6 | * Source: 7 | * http://riqueliam.blog.51cto.com/466137/107612 8 | * 9 | *****************************************************************************/ 10 | 11 | namespace LetsTag.DragAndDrop 12 | { 13 | // Constant declarations. Please refer to "shlobj.h". 14 | public static class ShellClipboardFormats 15 | { 16 | public const string CFSTR_SHELLIDLIST = "Shell IDList Array"; 17 | public const string CFSTR_SHELLIDLISTOFFSET = "Shell Object Offsets"; 18 | public const string CFSTR_NETRESOURCES = "Net Resource"; 19 | public const string CFSTR_FILEDESCRIPTORA = "FileGroupDescriptor"; 20 | public const string CFSTR_FILEDESCRIPTORW = "FileGroupDescriptorW"; 21 | public const string CFSTR_FILECONTENTS = "FileContents"; 22 | public const string CFSTR_FILENAMEA = "FileName"; 23 | public const string CFSTR_FILENAMEW = "FileNameW"; 24 | public const string CFSTR_PRINTERGROUP = "PrinterFreindlyName"; 25 | public const string CFSTR_FILENAMEMAPA = "FileNameMap"; 26 | public const string CFSTR_FILENAMEMAPW = "FileNameMapW"; 27 | public const string CFSTR_SHELLURL = "UniformResourceLocator"; 28 | public const string CFSTR_INETURLA = CFSTR_SHELLURL; 29 | public const string CFSTR_INETURLW = "UniformResourceLocatorW"; 30 | public const string CFSTR_PREFERREDDROPEFFECT = "Preferred DropEffect"; 31 | public const string CFSTR_PERFORMEDDROPEFFECT = "Performed DropEffect"; 32 | public const string CFSTR_PASTESUCCEEDED = "Paste Succeeded"; 33 | public const string CFSTR_INDRAGLOOP = "InShellDragLoop"; 34 | public const string CFSTR_DRAGCONTEXT = "DragContext"; 35 | public const string CFSTR_MOUNTEDVOLUME = "MountedVolume"; 36 | public const string CFSTR_PERSISTEDDATAOBJECT = "PersistedDataObject"; 37 | public const string CFSTR_TARGETCLSID = "TargetCLSID"; 38 | public const string CFSTR_LOGICALPERFORMEDDROPEFFECT = "Logical Performed DropEffect"; 39 | public const string CFSTR_AUTOPLAY_SHELLIDLISTS = "Autoplay Enumerated IDList Array"; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Let's Tag/Exporter.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using LetsTag.Common; 3 | 4 | namespace LetsTag 5 | { 6 | public static class Exporter 7 | { 8 | public static void Export(Album album, Preset preset, StreamWriter streamWriter) 9 | { 10 | foreach (Disc disc in album.Discs) 11 | { 12 | foreach (Track track in disc.Tracks) 13 | { 14 | bool isFirstField = true; 15 | foreach(IField field in preset.Fields) 16 | { 17 | if (isFirstField) 18 | isFirstField = false; 19 | else 20 | streamWriter.Write(preset.Delimiter); 21 | 22 | streamWriter.Write(field.GetValue(album, disc, track)); 23 | } 24 | 25 | streamWriter.WriteLine(); 26 | } 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Let's Tag/Forms/AboutForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Reflection; 4 | using System.Windows.Forms; 5 | 6 | namespace LetsTag 7 | { 8 | partial class AboutForm : Form 9 | { 10 | public AboutForm() 11 | { 12 | InitializeComponent(); 13 | this.Text = String.Format("About {0}", AssemblyTitle); 14 | this.labelProductName.Text = AssemblyProduct; 15 | this.labelVersion.Text = String.Format("Version {0}", AssemblyVersion); 16 | this.labelCopyright.Text = AssemblyCopyright; 17 | this.textBoxDescription.Text = AssemblyDescription; 18 | } 19 | 20 | #region Assembly Attribute Accessors 21 | 22 | public string AssemblyTitle 23 | { 24 | get 25 | { 26 | object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false); 27 | if (attributes.Length > 0) 28 | { 29 | AssemblyTitleAttribute titleAttribute = (AssemblyTitleAttribute)attributes[0]; 30 | if (titleAttribute.Title != "") 31 | { 32 | return titleAttribute.Title; 33 | } 34 | } 35 | return System.IO.Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase); 36 | } 37 | } 38 | 39 | public string AssemblyVersion 40 | { 41 | get 42 | { 43 | return Assembly.GetExecutingAssembly().GetName().Version.ToString(); 44 | } 45 | } 46 | 47 | public string AssemblyDescription 48 | { 49 | get 50 | { 51 | object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false); 52 | if (attributes.Length == 0) 53 | { 54 | return ""; 55 | } 56 | return ((AssemblyDescriptionAttribute)attributes[0]).Description; 57 | } 58 | } 59 | 60 | public string AssemblyProduct 61 | { 62 | get 63 | { 64 | object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false); 65 | if (attributes.Length == 0) 66 | { 67 | return ""; 68 | } 69 | return ((AssemblyProductAttribute)attributes[0]).Product; 70 | } 71 | } 72 | 73 | public string AssemblyCopyright 74 | { 75 | get 76 | { 77 | object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false); 78 | if (attributes.Length == 0) 79 | { 80 | return ""; 81 | } 82 | return ((AssemblyCopyrightAttribute)attributes[0]).Copyright; 83 | } 84 | } 85 | 86 | public string AssemblyCompany 87 | { 88 | get 89 | { 90 | object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCompanyAttribute), false); 91 | if (attributes.Length == 0) 92 | { 93 | return ""; 94 | } 95 | return ((AssemblyCompanyAttribute)attributes[0]).Company; 96 | } 97 | } 98 | #endregion 99 | 100 | private void okButton_Click(object sender, EventArgs e) 101 | { 102 | Close(); 103 | } 104 | 105 | private void brinkoftimeLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) 106 | { 107 | Process.Start(brinkoftimeLinkLabel.Text); 108 | } 109 | 110 | private void vgmdbLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) 111 | { 112 | Process.Start(vgmdbLinkLabel.Text); 113 | } 114 | 115 | private void mp3tagLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) 116 | { 117 | Process.Start(mp3tagLinkLabel.Text); 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /Let's Tag/Forms/AddPresetForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace LetsTag 2 | { 3 | partial class AddPresetForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.presetNameTextBox = new System.Windows.Forms.TextBox(); 32 | this.cancelButton = new System.Windows.Forms.Button(); 33 | this.addButton = new System.Windows.Forms.Button(); 34 | this.label1 = new System.Windows.Forms.Label(); 35 | this.SuspendLayout(); 36 | // 37 | // presetNameTextBox 38 | // 39 | this.presetNameTextBox.Location = new System.Drawing.Point(13, 29); 40 | this.presetNameTextBox.Name = "presetNameTextBox"; 41 | this.presetNameTextBox.Size = new System.Drawing.Size(324, 20); 42 | this.presetNameTextBox.TabIndex = 0; 43 | // 44 | // cancelButton 45 | // 46 | this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; 47 | this.cancelButton.Location = new System.Drawing.Point(262, 55); 48 | this.cancelButton.Name = "cancelButton"; 49 | this.cancelButton.Size = new System.Drawing.Size(75, 23); 50 | this.cancelButton.TabIndex = 2; 51 | this.cancelButton.Text = "&Cancel"; 52 | this.cancelButton.UseVisualStyleBackColor = true; 53 | this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); 54 | // 55 | // addButton 56 | // 57 | this.addButton.Location = new System.Drawing.Point(181, 55); 58 | this.addButton.Name = "addButton"; 59 | this.addButton.Size = new System.Drawing.Size(75, 23); 60 | this.addButton.TabIndex = 1; 61 | this.addButton.Text = "&Add"; 62 | this.addButton.UseVisualStyleBackColor = true; 63 | this.addButton.Click += new System.EventHandler(this.addButton_Click); 64 | // 65 | // label1 66 | // 67 | this.label1.AutoSize = true; 68 | this.label1.Location = new System.Drawing.Point(13, 13); 69 | this.label1.Name = "label1"; 70 | this.label1.Size = new System.Drawing.Size(138, 13); 71 | this.label1.TabIndex = 6; 72 | this.label1.Text = "Enter a name for the preset:"; 73 | // 74 | // AddPresetForm 75 | // 76 | this.AcceptButton = this.addButton; 77 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 78 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 79 | this.CancelButton = this.cancelButton; 80 | this.ClientSize = new System.Drawing.Size(348, 89); 81 | this.Controls.Add(this.label1); 82 | this.Controls.Add(this.presetNameTextBox); 83 | this.Controls.Add(this.cancelButton); 84 | this.Controls.Add(this.addButton); 85 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; 86 | this.MaximizeBox = false; 87 | this.MinimizeBox = false; 88 | this.Name = "AddPresetForm"; 89 | this.ShowIcon = false; 90 | this.ShowInTaskbar = false; 91 | this.Text = "Add Preset"; 92 | this.ResumeLayout(false); 93 | this.PerformLayout(); 94 | 95 | } 96 | 97 | #endregion 98 | 99 | private System.Windows.Forms.TextBox presetNameTextBox; 100 | private System.Windows.Forms.Button cancelButton; 101 | private System.Windows.Forms.Button addButton; 102 | private System.Windows.Forms.Label label1; 103 | } 104 | } -------------------------------------------------------------------------------- /Let's Tag/Forms/AddPresetForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | using LetsTag.Common; 4 | 5 | namespace LetsTag 6 | { 7 | public partial class AddPresetForm : Form 8 | { 9 | string presetName; 10 | 11 | public string PresetName 12 | { 13 | get { return presetName; } 14 | } 15 | 16 | public AddPresetForm(string presetName) 17 | { 18 | InitializeComponent(); 19 | presetNameTextBox.Text = presetName; 20 | presetNameTextBox.SelectAll(); 21 | } 22 | 23 | private void cancelButton_Click(object sender, EventArgs e) 24 | { 25 | Close(); 26 | } 27 | 28 | private void addButton_Click(object sender, EventArgs e) 29 | { 30 | presetName = presetNameTextBox.Text.Trim(); 31 | if (presetName.Length == 0) 32 | { 33 | MessageBox.Show("Please enter a preset name.", null, MessageBoxButtons.OK, MessageBoxIcon.Warning); 34 | presetNameTextBox.Focus(); 35 | return; 36 | } 37 | 38 | if (PresetManager.PresetFileExists(string.Format("{0}.xml", presetName))) 39 | { 40 | if (MessageBox.Show(string.Format("Preset {0} already exists. Overwrite?", presetName), Text, MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.Cancel) 41 | { 42 | presetNameTextBox.Focus(); 43 | return; 44 | } 45 | } 46 | 47 | DialogResult = DialogResult.OK; 48 | Close(); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Let's Tag/Forms/AddPresetForm.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /Let's Tag/Forms/AlbumGrabForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace LetsTag 2 | { 3 | partial class AlbumGrabForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.urlTextBox = new System.Windows.Forms.TextBox(); 32 | this.cancelButton = new System.Windows.Forms.Button(); 33 | this.grabButton = new System.Windows.Forms.Button(); 34 | this.label1 = new System.Windows.Forms.Label(); 35 | this.SuspendLayout(); 36 | // 37 | // urlTextBox 38 | // 39 | this.urlTextBox.Location = new System.Drawing.Point(12, 60); 40 | this.urlTextBox.Name = "urlTextBox"; 41 | this.urlTextBox.Size = new System.Drawing.Size(324, 20); 42 | this.urlTextBox.TabIndex = 0; 43 | // 44 | // cancelButton 45 | // 46 | this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; 47 | this.cancelButton.Location = new System.Drawing.Point(261, 86); 48 | this.cancelButton.Name = "cancelButton"; 49 | this.cancelButton.Size = new System.Drawing.Size(75, 23); 50 | this.cancelButton.TabIndex = 2; 51 | this.cancelButton.Text = "&Cancel"; 52 | this.cancelButton.UseVisualStyleBackColor = true; 53 | this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); 54 | // 55 | // grabButton 56 | // 57 | this.grabButton.Location = new System.Drawing.Point(180, 86); 58 | this.grabButton.Name = "grabButton"; 59 | this.grabButton.Size = new System.Drawing.Size(75, 23); 60 | this.grabButton.TabIndex = 1; 61 | this.grabButton.Text = "&Download"; 62 | this.grabButton.UseVisualStyleBackColor = true; 63 | this.grabButton.Click += new System.EventHandler(this.grabButton_Click); 64 | // 65 | // label1 66 | // 67 | this.label1.Location = new System.Drawing.Point(12, 9); 68 | this.label1.Name = "label1"; 69 | this.label1.Size = new System.Drawing.Size(324, 48); 70 | this.label1.TabIndex = 6; 71 | this.label1.Text = "Download album data directly by entering the album\'s URL below.\r\n\r\nExample: http:" + 72 | "//vgmdb.net/album/5411"; 73 | // 74 | // AlbumGrabForm 75 | // 76 | this.AcceptButton = this.grabButton; 77 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 78 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 79 | this.CancelButton = this.cancelButton; 80 | this.ClientSize = new System.Drawing.Size(348, 122); 81 | this.Controls.Add(this.label1); 82 | this.Controls.Add(this.urlTextBox); 83 | this.Controls.Add(this.cancelButton); 84 | this.Controls.Add(this.grabButton); 85 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; 86 | this.MaximizeBox = false; 87 | this.MinimizeBox = false; 88 | this.Name = "AlbumGrabForm"; 89 | this.ShowIcon = false; 90 | this.ShowInTaskbar = false; 91 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; 92 | this.Text = "Album"; 93 | this.ResumeLayout(false); 94 | this.PerformLayout(); 95 | 96 | } 97 | 98 | #endregion 99 | 100 | private System.Windows.Forms.TextBox urlTextBox; 101 | private System.Windows.Forms.Button cancelButton; 102 | private System.Windows.Forms.Button grabButton; 103 | private System.Windows.Forms.Label label1; 104 | } 105 | } -------------------------------------------------------------------------------- /Let's Tag/Forms/AlbumGrabForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | namespace LetsTag 5 | { 6 | public partial class AlbumGrabForm : Form 7 | { 8 | public AlbumGrabForm() 9 | { 10 | InitializeComponent(); 11 | } 12 | 13 | private void cancelButton_Click(object sender, EventArgs e) 14 | { 15 | Close(); 16 | } 17 | 18 | private void grabButton_Click(object sender, EventArgs e) 19 | { 20 | Form form = null; 21 | try 22 | { 23 | form = new AlbumProgressForm(urlTextBox.Text); 24 | form.ShowDialog(); 25 | form.Dispose(); 26 | Close(); 27 | } 28 | catch (Exception ex) 29 | { 30 | MessageBox.Show(ex.Message, null, MessageBoxButtons.OK, MessageBoxIcon.Error); 31 | if(form != null) 32 | form.Dispose(); 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Let's Tag/Forms/AlbumGrabForm.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /Let's Tag/Forms/AlbumProgressForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace LetsTag 2 | { 3 | partial class AlbumProgressForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.cancelButton = new System.Windows.Forms.Button(); 32 | this.SuspendLayout(); 33 | // 34 | // cancelButton 35 | // 36 | this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; 37 | this.cancelButton.Location = new System.Drawing.Point(116, 11); 38 | this.cancelButton.Name = "cancelButton"; 39 | this.cancelButton.Size = new System.Drawing.Size(75, 23); 40 | this.cancelButton.TabIndex = 0; 41 | this.cancelButton.Text = "&Cancel"; 42 | this.cancelButton.UseVisualStyleBackColor = true; 43 | this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); 44 | // 45 | // AlbumProgressForm 46 | // 47 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 48 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 49 | this.CancelButton = this.cancelButton; 50 | this.ClientSize = new System.Drawing.Size(307, 45); 51 | this.ControlBox = false; 52 | this.Controls.Add(this.cancelButton); 53 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; 54 | this.MaximizeBox = false; 55 | this.MinimizeBox = false; 56 | this.Name = "AlbumProgressForm"; 57 | this.ShowIcon = false; 58 | this.ShowInTaskbar = false; 59 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; 60 | this.Text = "Connecting..."; 61 | this.Load += new System.EventHandler(this.AlbumProgressForm_Load); 62 | this.ResumeLayout(false); 63 | 64 | } 65 | 66 | #endregion 67 | 68 | private System.Windows.Forms.Button cancelButton; 69 | 70 | } 71 | } -------------------------------------------------------------------------------- /Let's Tag/Forms/AlbumProgressForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using System.Windows.Forms; 4 | using LetsTag.Common; 5 | 6 | namespace LetsTag 7 | { 8 | public partial class AlbumProgressForm : Form 9 | { 10 | delegate void ShowAlbumHandler(); 11 | delegate void SetTextHandler(string text); 12 | delegate void CloseHandler(); 13 | 14 | public static event AlbumSelectedHandler AlbumSelected; 15 | 16 | HttpGetRequest request; 17 | 18 | public AlbumProgressForm(string url) 19 | { 20 | InitializeComponent(); 21 | request = new HttpGetRequest(url, new HttpRequestHandler(OnRequestStatusChange)); 22 | } 23 | 24 | private void AlbumProgressForm_Load(object sender, EventArgs e) 25 | { 26 | request.Execute(); 27 | } 28 | 29 | private void cancelButton_Click(object sender, EventArgs e) 30 | { 31 | request.Abort(); 32 | Close(); 33 | } 34 | 35 | void OnRequestStatusChange(AbstractHttpRequest request, HttpRequestStatus status) 36 | { 37 | switch (status) 38 | { 39 | case HttpRequestStatus.Downloading: 40 | Invoke(new SetTextHandler(SetText), string.Format("Downloading... ({0} bytes)", request.Response.Length)); 41 | break; 42 | 43 | case HttpRequestStatus.Error: 44 | MessageBox.Show(request.Error, null, MessageBoxButtons.OK, MessageBoxIcon.Error); 45 | Invoke(new CloseHandler(Close)); 46 | break; 47 | 48 | case HttpRequestStatus.Done: 49 | Invoke(new ShowAlbumHandler(ShowAlbum)); 50 | break; 51 | } 52 | } 53 | 54 | void SetText(string text) 55 | { 56 | Text = text; 57 | } 58 | 59 | void ShowAlbum() 60 | { 61 | AlbumSelected(UTF8Encoding.UTF8.GetString(request.Response)); 62 | Close(); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Let's Tag/Forms/AlbumProgressForm.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /Let's Tag/Forms/CustomStringFieldForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace LetsTag 2 | { 3 | partial class CustomStringFieldForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.cancelButton = new System.Windows.Forms.Button(); 32 | this.okButton = new System.Windows.Forms.Button(); 33 | this.label1 = new System.Windows.Forms.Label(); 34 | this.label2 = new System.Windows.Forms.Label(); 35 | this.valueTextBox = new System.Windows.Forms.TextBox(); 36 | this.mp3tagFormatTextBox = new System.Windows.Forms.TextBox(); 37 | this.SuspendLayout(); 38 | // 39 | // cancelButton 40 | // 41 | this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); 42 | this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; 43 | this.cancelButton.Location = new System.Drawing.Point(198, 113); 44 | this.cancelButton.Name = "cancelButton"; 45 | this.cancelButton.Size = new System.Drawing.Size(75, 23); 46 | this.cancelButton.TabIndex = 3; 47 | this.cancelButton.Text = "&Cancel"; 48 | this.cancelButton.UseVisualStyleBackColor = true; 49 | this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); 50 | // 51 | // okButton 52 | // 53 | this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); 54 | this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK; 55 | this.okButton.Location = new System.Drawing.Point(117, 113); 56 | this.okButton.Name = "okButton"; 57 | this.okButton.Size = new System.Drawing.Size(75, 23); 58 | this.okButton.TabIndex = 2; 59 | this.okButton.Text = "&OK"; 60 | this.okButton.UseVisualStyleBackColor = true; 61 | this.okButton.Click += new System.EventHandler(this.okButton_Click); 62 | // 63 | // label1 64 | // 65 | this.label1.AutoSize = true; 66 | this.label1.Location = new System.Drawing.Point(9, 15); 67 | this.label1.Name = "label1"; 68 | this.label1.Size = new System.Drawing.Size(37, 13); 69 | this.label1.TabIndex = 2; 70 | this.label1.Text = "Value:"; 71 | // 72 | // label2 73 | // 74 | this.label2.AutoSize = true; 75 | this.label2.Location = new System.Drawing.Point(9, 64); 76 | this.label2.Name = "label2"; 77 | this.label2.Size = new System.Drawing.Size(111, 13); 78 | this.label2.TabIndex = 3; 79 | this.label2.Text = "Mp3tag Format String:"; 80 | // 81 | // valueTextBox 82 | // 83 | this.valueTextBox.Location = new System.Drawing.Point(12, 31); 84 | this.valueTextBox.Name = "valueTextBox"; 85 | this.valueTextBox.Size = new System.Drawing.Size(261, 20); 86 | this.valueTextBox.TabIndex = 0; 87 | // 88 | // mp3tagFormatTextBox 89 | // 90 | this.mp3tagFormatTextBox.Location = new System.Drawing.Point(12, 80); 91 | this.mp3tagFormatTextBox.Name = "mp3tagFormatTextBox"; 92 | this.mp3tagFormatTextBox.Size = new System.Drawing.Size(261, 20); 93 | this.mp3tagFormatTextBox.TabIndex = 1; 94 | this.mp3tagFormatTextBox.Text = "%dummy%"; 95 | // 96 | // CustomStringFieldForm 97 | // 98 | this.AcceptButton = this.okButton; 99 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 100 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 101 | this.CancelButton = this.cancelButton; 102 | this.ClientSize = new System.Drawing.Size(285, 148); 103 | this.Controls.Add(this.mp3tagFormatTextBox); 104 | this.Controls.Add(this.valueTextBox); 105 | this.Controls.Add(this.label2); 106 | this.Controls.Add(this.label1); 107 | this.Controls.Add(this.okButton); 108 | this.Controls.Add(this.cancelButton); 109 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; 110 | this.MaximizeBox = false; 111 | this.MinimizeBox = false; 112 | this.Name = "CustomStringFieldForm"; 113 | this.ShowIcon = false; 114 | this.ShowInTaskbar = false; 115 | this.Text = "Custom String Field"; 116 | this.ResumeLayout(false); 117 | this.PerformLayout(); 118 | 119 | } 120 | 121 | #endregion 122 | 123 | private System.Windows.Forms.Button cancelButton; 124 | private System.Windows.Forms.Button okButton; 125 | private System.Windows.Forms.Label label1; 126 | private System.Windows.Forms.Label label2; 127 | private System.Windows.Forms.TextBox valueTextBox; 128 | private System.Windows.Forms.TextBox mp3tagFormatTextBox; 129 | } 130 | } -------------------------------------------------------------------------------- /Let's Tag/Forms/CustomStringFieldForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | namespace LetsTag 5 | { 6 | public partial class CustomStringFieldForm : Form 7 | { 8 | public string Value 9 | { 10 | get { return valueTextBox.Text; } 11 | } 12 | 13 | public string Mp3tagFormat 14 | { 15 | get { return mp3tagFormatTextBox.Text; } 16 | } 17 | 18 | public CustomStringFieldForm() 19 | { 20 | InitializeComponent(); 21 | } 22 | 23 | private void okButton_Click(object sender, EventArgs e) 24 | { 25 | Close(); 26 | } 27 | 28 | private void cancelButton_Click(object sender, EventArgs e) 29 | { 30 | Close(); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Let's Tag/Forms/CustomStringFieldForm.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /Let's Tag/Forms/ExportForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Windows.Forms; 6 | using LetsTag.Common; 7 | 8 | namespace LetsTag 9 | { 10 | public partial class ExportForm : Form 11 | { 12 | Album album; 13 | Preset currentPreset; 14 | Preset blankPreset; 15 | 16 | public ExportForm(Album album) 17 | { 18 | this.album = album; 19 | InitializeComponent(); 20 | 21 | blankPreset = new Preset("Blank"); 22 | presetComboBox.DisplayMember = "Name"; 23 | ReloadPresets(); 24 | 25 | foreach (string key in album.Details.Keys.Reverse()) 26 | { 27 | ToolStripMenuItem menuItem = new ToolStripMenuItem(key); 28 | menuItem.Click += new EventHandler(albumFieldMenuItem_Click); 29 | toolStripDropDownButton1.DropDownItems.Insert(0, menuItem); 30 | } 31 | } 32 | 33 | private void presetComboBox_SelectedIndexChanged(object sender, EventArgs e) 34 | { 35 | currentPreset = ((Preset)presetComboBox.SelectedItem).Clone(); 36 | Populate(); 37 | } 38 | 39 | private void addPresetToolStripButton_Click(object sender, EventArgs e) 40 | { 41 | string presetName = presetComboBox.Text; 42 | if (presetComboBox.SelectedItem == blankPreset) 43 | presetName = "New Preset"; 44 | 45 | AddPresetForm addPresetForm = new AddPresetForm(presetName); 46 | if (addPresetForm.ShowDialog() == DialogResult.OK) 47 | { 48 | currentPreset.Name = addPresetForm.PresetName; 49 | 50 | try 51 | { 52 | PresetWriter.SavePreset(currentPreset); 53 | ReloadPresets(currentPreset.Name); 54 | } 55 | catch (Exception ex) 56 | { 57 | MessageBox.Show(ex.Message, null, MessageBoxButtons.OK, MessageBoxIcon.Error); 58 | } 59 | } 60 | addPresetForm.Dispose(); 61 | } 62 | 63 | private void removePresetToolStripButton_Click(object sender, EventArgs e) 64 | { 65 | if (presetComboBox.SelectedItem != blankPreset) 66 | { 67 | if (MessageBox.Show(string.Format("Delete preset {0}?", currentPreset.Name), "Delete Preset", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK) 68 | { 69 | try 70 | { 71 | PresetManager.DeletePresetFile(string.Format("{0}.xml", currentPreset.Name)); 72 | ReloadPresets(); 73 | } 74 | catch (Exception ex) 75 | { 76 | MessageBox.Show(ex.Message, null, MessageBoxButtons.OK, MessageBoxIcon.Error); 77 | } 78 | } 79 | } 80 | } 81 | 82 | void albumFieldMenuItem_Click(object sender, EventArgs e) 83 | { 84 | ToolStripMenuItem menuItem = (ToolStripMenuItem)sender; 85 | 86 | string mp3tagFormat; 87 | switch (menuItem.Text.ToLower()) 88 | { 89 | case "album name": 90 | mp3tagFormat = "%album%"; 91 | break; 92 | case "catalog number": 93 | mp3tagFormat = "%comment%"; 94 | break; 95 | case "published by": 96 | mp3tagFormat = "%copyright%"; 97 | break; 98 | case "composed by": 99 | mp3tagFormat = "%artist%"; 100 | break; 101 | default: 102 | mp3tagFormat = "%dummy%"; 103 | break; 104 | } 105 | 106 | AddField(new SimpleField(new AlbumFieldValue(menuItem.Text), mp3tagFormat)); 107 | } 108 | 109 | private void discNumberToolStripMenuItem_Click(object sender, EventArgs e) 110 | { 111 | AddField(new SimpleField(new DiscNumberValue(), "%discnumber%")); 112 | } 113 | 114 | private void trackNumberToolStripMenuItem_Click(object sender, EventArgs e) 115 | { 116 | AddField(new SimpleField(new TrackNumberValue(), "%track%")); 117 | } 118 | 119 | private void trackNameToolStripMenuItem_Click(object sender, EventArgs e) 120 | { 121 | AddField(new SimpleField(new TrackNameValue(), "%title%")); 122 | } 123 | 124 | private void customStringToolStripMenuItem_Click(object sender, EventArgs e) 125 | { 126 | CustomStringFieldForm form = new CustomStringFieldForm(); 127 | if (form.ShowDialog() == DialogResult.OK) 128 | AddField(new SimpleField(new StringValue(form.Value), form.Mp3tagFormat)); 129 | form.Dispose(); 130 | } 131 | 132 | private void deleteToolStripButton_Click(object sender, EventArgs e) 133 | { 134 | if (fieldsListBox.SelectedIndex != -1) 135 | RemoveField(fieldsListBox.SelectedIndex); 136 | } 137 | 138 | private void moveUpToolStripButton_Click(object sender, EventArgs e) 139 | { 140 | if (fieldsListBox.SelectedIndex > 0) 141 | MoveUp(fieldsListBox.SelectedIndex); 142 | } 143 | 144 | private void moveDownToolStripButton_Click(object sender, EventArgs e) 145 | { 146 | if (fieldsListBox.SelectedIndex != -1 && fieldsListBox.SelectedIndex < fieldsListBox.Items.Count - 1) 147 | MoveDown(fieldsListBox.SelectedIndex); 148 | } 149 | 150 | private void delimiterTextBox_TextChanged(object sender, EventArgs e) 151 | { 152 | currentPreset.Delimiter = delimiterTextBox.Text; 153 | } 154 | 155 | private void mp3tagFormatStringLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) 156 | { 157 | Form form = new Mp3tagFormatStringForm(currentPreset); 158 | form.ShowDialog(); 159 | form.Dispose(); 160 | } 161 | 162 | private void exportButton_Click(object sender, EventArgs e) 163 | { 164 | try 165 | { 166 | if (exportSaveFileDialog.ShowDialog() == DialogResult.OK) 167 | { 168 | Stream stream = exportSaveFileDialog.OpenFile(); 169 | StreamWriter streamWriter = new StreamWriter(stream, new UTF8Encoding(true)); 170 | Exporter.Export(album, currentPreset, streamWriter); 171 | streamWriter.Close(); 172 | Close(); 173 | } 174 | } 175 | catch (Exception ex) 176 | { 177 | MessageBox.Show(ex.Message, null, MessageBoxButtons.OK, MessageBoxIcon.Error); 178 | } 179 | } 180 | 181 | private void cancelButton_Click(object sender, EventArgs e) 182 | { 183 | Close(); 184 | } 185 | 186 | void ReloadPresets() 187 | { 188 | ReloadPresets("Default"); 189 | } 190 | 191 | void ReloadPresets(string defaultPresetName) 192 | { 193 | presetComboBox.Items.Clear(); 194 | presetComboBox.Items.Add(blankPreset); 195 | 196 | Preset defaultPreset = blankPreset; 197 | 198 | defaultPresetName = defaultPresetName.ToLower(); 199 | string[] presetFiles = PresetManager.GetPresetFiles(); 200 | foreach (string presetFile in presetFiles) 201 | { 202 | try 203 | { 204 | Preset preset = PresetReader.LoadPreset(presetFile); 205 | presetComboBox.Items.Add(preset); 206 | 207 | if (preset.Name.ToLower() == defaultPresetName) 208 | defaultPreset = preset; 209 | } 210 | catch (Exception ex) 211 | { 212 | MessageBox.Show(string.Format("{0} is not a valid preset file:\n{1}", presetFile, ex.Message), null, MessageBoxButtons.OK, MessageBoxIcon.Warning); 213 | } 214 | } 215 | 216 | presetComboBox.SelectedItem = defaultPreset; 217 | } 218 | 219 | void Populate() 220 | { 221 | fieldsListBox.Items.Clear(); 222 | foreach (IField field in currentPreset.Fields) 223 | fieldsListBox.Items.Add(field.GetName()); 224 | delimiterTextBox.Text = currentPreset.Delimiter; 225 | } 226 | 227 | void AddField(IField field) 228 | { 229 | currentPreset.Fields.Add(field); 230 | fieldsListBox.Items.Add(field.GetName()); 231 | } 232 | 233 | void RemoveField(int index) 234 | { 235 | currentPreset.Fields.RemoveAt(index); 236 | fieldsListBox.Items.RemoveAt(index); 237 | if(fieldsListBox.Items.Count > 0) 238 | fieldsListBox.SelectedIndex = (index < fieldsListBox.Items.Count ? index : fieldsListBox.Items.Count - 1); 239 | } 240 | 241 | void MoveUp(int index) 242 | { 243 | IField field = currentPreset.Fields[index]; 244 | currentPreset.Fields.RemoveAt(index); 245 | currentPreset.Fields.Insert(index - 1, field); 246 | 247 | object item = fieldsListBox.Items[index]; 248 | fieldsListBox.Items.RemoveAt(index); 249 | fieldsListBox.Items.Insert(index - 1, item); 250 | fieldsListBox.SelectedIndex = index - 1; 251 | } 252 | 253 | void MoveDown(int index) 254 | { 255 | IField field = currentPreset.Fields[index]; 256 | currentPreset.Fields.RemoveAt(index); 257 | currentPreset.Fields.Insert(index + 1, field); 258 | 259 | object item = fieldsListBox.Items[index]; 260 | fieldsListBox.Items.RemoveAt(index); 261 | fieldsListBox.Items.Insert(index + 1, item); 262 | fieldsListBox.SelectedIndex = index + 1; 263 | } 264 | } 265 | } 266 | -------------------------------------------------------------------------------- /Let's Tag/Forms/ExportForm.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 17, 17 122 | 123 | 124 | 125 | 126 | iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 127 | YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAEhJREFUOE9jYKAh 128 | +A80GxmTbNX//3MYwBhq0HA3AD3AwHy0MMCmBh4ucMUwTYRo9ICl3AC0OCfZC9jieKSlA6xhQGlmIirz 129 | AACRpaZFz30eJAAAAABJRU5ErkJggg== 130 | 131 | 132 | 133 | 134 | iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 135 | YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAGNJREFUOE9jYKAS 136 | +A80B4YJGYlV7f//cxjAGGoQLkNwqoNL4DGEoBp8CghqhjkZm0KiNWM1BBY2RIQPSrih2EqqZpBJFBmA 137 | oZnIKAZ7gaJApCgaiYkqvGooT8qUZiZCORCnPABOM9pNoZ4S+wAAAABJRU5ErkJggg== 138 | 139 | 140 | 141 | 142 | iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 143 | YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAE9JREFUOE9jYKAx 144 | +A80H4TJAv//z2EAY3IMgWsmxxAMzaQYglMzMYYQ1IzPEKI14zIEFtJwGqYQTQO6OpzRS1EsgEwdNQCS 145 | gbBhsjIVXk0AoMLTjT3ETH4AAAAASUVORK5CYII= 146 | 147 | 148 | 149 | 150 | iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 151 | YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAFZJREFUOE9jYKAR 152 | +A80Fxsm2rr//+cwoGCogaMG4AkBjBDHEYjo6uBGYoQ6ugHExArRhuCLUoKGEJMecBpCjGZYoFCcEkEG 153 | wQ0hxWb0mIZFG9F5gGSFALMU0421s7ahAAAAAElFTkSuQmCC 154 | 155 | 156 | 157 | 298, 17 158 | 159 | 160 | 161 | iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 162 | YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAEhJREFUOE9jYKAh 163 | +A80GxmTbNX//3MYwBhq0HA3AD3AwHy0MMCmBh4ucMUwTYRo9ICl3AC0OCfZC9jieKSlA6xhQGlmIirz 164 | AACRpaZFz30eJAAAAABJRU5ErkJggg== 165 | 166 | 167 | 168 | 169 | iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 170 | YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAGNJREFUOE9jYKAS 171 | +A80B4YJGYlV7f//cxjAGGoQLkNwqoNL4DGEoBp8CghqhjkZm0KiNWM1BBY2RIQPSrih2EqqZpBJFBmA 172 | oZnIKAZ7gaJApCgaiYkqvGooT8qUZiZCORCnPABOM9pNoZ4S+wAAAABJRU5ErkJggg== 173 | 174 | 175 | 176 | 141, 17 177 | 178 | -------------------------------------------------------------------------------- /Let's Tag/Forms/MainForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Drawing.Imaging; 5 | using System.Globalization; 6 | using System.IO; 7 | using System.Reflection; 8 | using System.Resources; 9 | using System.Windows.Forms; 10 | using LetsTag.DragAndDrop; 11 | 12 | namespace LetsTag 13 | { 14 | public delegate void AlbumSelectedHandler(string albumDetailsString); 15 | 16 | public partial class MainForm : Form 17 | { 18 | Album album = new Album(); 19 | 20 | bool coverDrag = false; 21 | int coverMouseDownX; 22 | int coverMouseDownY; 23 | 24 | ImageCodecInfo[] imageEncoders = ImageCodecInfo.GetImageEncoders(); 25 | ImageCodecInfo dragAndDropImageEncoder; 26 | EncoderParameters imageEncoderParams = new EncoderParameters(1); 27 | 28 | public MainForm() 29 | { 30 | AlbumProgressForm.AlbumSelected += new AlbumSelectedHandler(OnAlbumSelected); 31 | SearchProgressForm.AlbumSelected += new AlbumSelectedHandler(OnAlbumSelected); 32 | 33 | InitializeComponent(); 34 | 35 | // Load title strings 36 | ResourceManager resourceManager = new ResourceManager("LetsTag.Resources.TitleStrings", Assembly.GetExecutingAssembly()); 37 | IList titleStrings = new List(); 38 | foreach (DictionaryEntry resource in resourceManager.GetResourceSet(CultureInfo.InvariantCulture, true, true)) 39 | titleStrings.Add((string)resource.Value); 40 | 41 | // Choose one at random and append it to the title 42 | Random random = new Random(); 43 | Text += string.Format(" - {0}", titleStrings[random.Next(titleStrings.Count)]); 44 | 45 | // Initialize imageEncoderParams 46 | imageEncoderParams.Param[0] = new EncoderParameter(Encoder.Quality, 100L); 47 | 48 | // Initialize dragAndDropImageEncoder 49 | foreach (ImageCodecInfo encoder in imageEncoders) 50 | { 51 | if (encoder.FormatID == ImageFormat.Jpeg.Guid) 52 | { 53 | dragAndDropImageEncoder = encoder; 54 | break; 55 | } 56 | } 57 | } 58 | 59 | private void exitToolStripMenuItem_Click(object sender, EventArgs e) 60 | { 61 | Application.Exit(); 62 | } 63 | 64 | private void searchToolStripMenuItem_Click(object sender, EventArgs e) 65 | { 66 | Form form = new SearchForm(); 67 | form.ShowDialog(); 68 | form.Dispose(); 69 | } 70 | 71 | private void grabAlbumToolStripMenuItem_Click(object sender, EventArgs e) 72 | { 73 | Form form = new AlbumGrabForm(); 74 | form.ShowDialog(); 75 | form.Dispose(); 76 | } 77 | 78 | private void exportToolStripMenuItem_Click(object sender, EventArgs e) 79 | { 80 | Form form = new ExportForm(album); 81 | form.ShowDialog(); 82 | form.Dispose(); 83 | } 84 | 85 | private void aboutVGMdbDataGrabberToolStripMenuItem_Click(object sender, EventArgs e) 86 | { 87 | Form form = new AboutForm(); 88 | form.ShowDialog(); 89 | form.Dispose(); 90 | } 91 | 92 | private void albumCoverPanel_MouseClick(object sender, MouseEventArgs e) 93 | { 94 | if (!coverDrag) 95 | { 96 | bool enabled = (this.album.Cover != null); 97 | copyCoverToolStripMenuItem.Enabled = enabled; 98 | saveCoverAsToolStripMenuItem.Enabled = enabled; 99 | albumCoverContextMenuStrip.Show(albumCoverPanel.PointToScreen(e.Location)); 100 | } 101 | } 102 | 103 | private void albumCoverPanel_MouseDown(object sender, MouseEventArgs e) 104 | { 105 | if (this.album.Cover != null) 106 | { 107 | coverDrag = false; 108 | coverMouseDownX = e.X; 109 | coverMouseDownY = e.Y; 110 | } 111 | } 112 | 113 | private void albumCoverPanel_MouseMove(object sender, MouseEventArgs e) 114 | { 115 | // Start a drag if: 116 | // - album cover is not null 117 | // - a drag is not already started 118 | // - user pressed left or right mouse buttons 119 | // - mouse moved from starting position 120 | if (this.album.Cover != null && !coverDrag && (e.Button == MouseButtons.Left || e.Button == MouseButtons.Right) && (e.X != coverMouseDownX || e.Y != coverMouseDownY)) 121 | { 122 | coverDrag = true; 123 | ImageFileDataObject dataObject = new ImageFileDataObject("folder.jpg", this.album.Cover, dragAndDropImageEncoder, imageEncoderParams); 124 | new DragAndDropDelegate(albumCoverPanel, dataObject, DragDropEffects.Copy); 125 | } 126 | } 127 | 128 | private void copyCoverToolStripMenuItem_Click(object sender, EventArgs e) 129 | { 130 | Clipboard.SetImage(this.album.Cover); 131 | } 132 | 133 | private void saveCoverAsToolStripMenuItem_Click(object sender, EventArgs e) 134 | { 135 | try 136 | { 137 | if (coverSaveFileDialog.ShowDialog() == DialogResult.OK) 138 | { 139 | string filename = coverSaveFileDialog.FileName; 140 | string extension = Path.GetExtension(filename).ToLower(); 141 | 142 | // Look for a matching encoder to save with 143 | foreach (ImageCodecInfo encoder in imageEncoders) 144 | { 145 | if (encoder.FilenameExtension.ToLower().Contains(extension)) 146 | { 147 | album.Cover.Save(filename, encoder, imageEncoderParams); 148 | return; 149 | } 150 | } 151 | 152 | // No codec was found -- save in native format 153 | album.Cover.Save(filename); 154 | } 155 | } 156 | catch (Exception ex) 157 | { 158 | MessageBox.Show(ex.Message, null, MessageBoxButtons.OK, MessageBoxIcon.Error); 159 | } 160 | } 161 | 162 | void OnAlbumSelected(string albumDetailsString) 163 | { 164 | try 165 | { 166 | Album album = new Album(); 167 | 168 | // Split data string where the tracklist starts 169 | int tracklistIndex = albumDetailsString.IndexOf(">Tracklist detail in album.Details) 205 | detailsListView.Items.Add(new ListViewItem(new string[] {detail.Key, detail.Value})); 206 | 207 | tracksListView.Items.Clear(); 208 | tracksListView.Groups.Clear(); 209 | foreach (Disc disc in album.Discs) 210 | { 211 | tracksListView.Groups.Add(disc.Number, string.Format("Disc {0}", disc.Number)); 212 | foreach (Track track in disc.Tracks) 213 | tracksListView.Items.Add(new ListViewItem(new string[] {track.Number, track.Name}, tracksListView.Groups[disc.Number])); 214 | } 215 | } 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /Let's Tag/Forms/Mp3tagFormatStringForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace LetsTag 2 | { 3 | partial class Mp3tagFormatStringForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.label1 = new System.Windows.Forms.Label(); 32 | this.okButton = new System.Windows.Forms.Button(); 33 | this.copyButton = new System.Windows.Forms.Button(); 34 | this.formatStringTextBox = new System.Windows.Forms.TextBox(); 35 | this.SuspendLayout(); 36 | // 37 | // label1 38 | // 39 | this.label1.Location = new System.Drawing.Point(12, 9); 40 | this.label1.Name = "label1"; 41 | this.label1.Size = new System.Drawing.Size(602, 18); 42 | this.label1.TabIndex = 0; 43 | this.label1.Text = "Use the format string below to import the exported album data into Mp3tag."; 44 | // 45 | // okButton 46 | // 47 | this.okButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; 48 | this.okButton.Location = new System.Drawing.Point(540, 57); 49 | this.okButton.Name = "okButton"; 50 | this.okButton.Size = new System.Drawing.Size(75, 23); 51 | this.okButton.TabIndex = 2; 52 | this.okButton.Text = "&OK"; 53 | this.okButton.UseVisualStyleBackColor = true; 54 | this.okButton.Click += new System.EventHandler(this.okButton_Click); 55 | // 56 | // copyButton 57 | // 58 | this.copyButton.Location = new System.Drawing.Point(459, 57); 59 | this.copyButton.Name = "copyButton"; 60 | this.copyButton.Size = new System.Drawing.Size(75, 23); 61 | this.copyButton.TabIndex = 1; 62 | this.copyButton.Text = "&Copy"; 63 | this.copyButton.UseVisualStyleBackColor = true; 64 | this.copyButton.Click += new System.EventHandler(this.copyButton_Click); 65 | // 66 | // formatStringTextBox 67 | // 68 | this.formatStringTextBox.Location = new System.Drawing.Point(13, 31); 69 | this.formatStringTextBox.Name = "formatStringTextBox"; 70 | this.formatStringTextBox.ReadOnly = true; 71 | this.formatStringTextBox.Size = new System.Drawing.Size(601, 20); 72 | this.formatStringTextBox.TabIndex = 0; 73 | // 74 | // Mp3tagFormatStringForm 75 | // 76 | this.AcceptButton = this.okButton; 77 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 78 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 79 | this.CancelButton = this.okButton; 80 | this.ClientSize = new System.Drawing.Size(627, 92); 81 | this.Controls.Add(this.formatStringTextBox); 82 | this.Controls.Add(this.copyButton); 83 | this.Controls.Add(this.okButton); 84 | this.Controls.Add(this.label1); 85 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; 86 | this.MaximizeBox = false; 87 | this.MinimizeBox = false; 88 | this.Name = "Mp3tagFormatStringForm"; 89 | this.ShowIcon = false; 90 | this.ShowInTaskbar = false; 91 | this.Text = "Mp3tag Format String"; 92 | this.ResumeLayout(false); 93 | this.PerformLayout(); 94 | 95 | } 96 | 97 | #endregion 98 | 99 | private System.Windows.Forms.Label label1; 100 | private System.Windows.Forms.Button okButton; 101 | private System.Windows.Forms.Button copyButton; 102 | private System.Windows.Forms.TextBox formatStringTextBox; 103 | } 104 | } -------------------------------------------------------------------------------- /Let's Tag/Forms/Mp3tagFormatStringForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | using LetsTag.Common; 4 | 5 | namespace LetsTag 6 | { 7 | public partial class Mp3tagFormatStringForm : Form 8 | { 9 | public Mp3tagFormatStringForm(Preset preset) 10 | { 11 | InitializeComponent(); 12 | 13 | string formatString = ""; 14 | bool isFirstField = true; 15 | foreach(IField field in preset.Fields) 16 | { 17 | if (isFirstField) 18 | isFirstField = false; 19 | else 20 | formatString += preset.Delimiter; 21 | 22 | formatString += field.GetMp3tagFormat(); 23 | } 24 | formatStringTextBox.Text = formatString; 25 | } 26 | 27 | private void copyButton_Click(object sender, EventArgs e) 28 | { 29 | Clipboard.SetText(formatStringTextBox.Text); 30 | } 31 | 32 | private void okButton_Click(object sender, EventArgs e) 33 | { 34 | Close(); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Let's Tag/Forms/Mp3tagFormatStringForm.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /Let's Tag/Forms/ResultSelectorForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace LetsTag 2 | { 3 | partial class ResultSelectorForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ResultSelectorForm)); 32 | this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); 33 | this.resultsListView = new System.Windows.Forms.ListView(); 34 | this.columnHeader1 = new System.Windows.Forms.ColumnHeader(); 35 | this.columnHeader2 = new System.Windows.Forms.ColumnHeader(); 36 | this.columnHeader3 = new System.Windows.Forms.ColumnHeader(); 37 | this.panel1 = new System.Windows.Forms.Panel(); 38 | this.selectButton = new System.Windows.Forms.Button(); 39 | this.cancelButton = new System.Windows.Forms.Button(); 40 | this.tableLayoutPanel1.SuspendLayout(); 41 | this.panel1.SuspendLayout(); 42 | this.SuspendLayout(); 43 | // 44 | // tableLayoutPanel1 45 | // 46 | this.tableLayoutPanel1.ColumnCount = 1; 47 | this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); 48 | this.tableLayoutPanel1.Controls.Add(this.resultsListView, 0, 0); 49 | this.tableLayoutPanel1.Controls.Add(this.panel1, 0, 1); 50 | this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; 51 | this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); 52 | this.tableLayoutPanel1.Name = "tableLayoutPanel1"; 53 | this.tableLayoutPanel1.RowCount = 2; 54 | this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); 55 | this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 37F)); 56 | this.tableLayoutPanel1.Size = new System.Drawing.Size(779, 475); 57 | this.tableLayoutPanel1.TabIndex = 3; 58 | // 59 | // resultsListView 60 | // 61 | this.resultsListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { 62 | this.columnHeader1, 63 | this.columnHeader2, 64 | this.columnHeader3}); 65 | this.resultsListView.Dock = System.Windows.Forms.DockStyle.Fill; 66 | this.resultsListView.FullRowSelect = true; 67 | this.resultsListView.Location = new System.Drawing.Point(3, 3); 68 | this.resultsListView.MultiSelect = false; 69 | this.resultsListView.Name = "resultsListView"; 70 | this.resultsListView.Size = new System.Drawing.Size(773, 432); 71 | this.resultsListView.TabIndex = 2; 72 | this.resultsListView.UseCompatibleStateImageBehavior = false; 73 | this.resultsListView.View = System.Windows.Forms.View.Details; 74 | this.resultsListView.DoubleClick += new System.EventHandler(this.resultsListView_DoubleClick); 75 | // 76 | // columnHeader1 77 | // 78 | this.columnHeader1.Text = "Catalog Number"; 79 | this.columnHeader1.Width = 150; 80 | // 81 | // columnHeader2 82 | // 83 | this.columnHeader2.Text = "Album Title"; 84 | this.columnHeader2.Width = 400; 85 | // 86 | // columnHeader3 87 | // 88 | this.columnHeader3.Text = "Extra Info"; 89 | this.columnHeader3.Width = 200; 90 | // 91 | // panel1 92 | // 93 | this.panel1.Controls.Add(this.selectButton); 94 | this.panel1.Controls.Add(this.cancelButton); 95 | this.panel1.Dock = System.Windows.Forms.DockStyle.Fill; 96 | this.panel1.Location = new System.Drawing.Point(3, 441); 97 | this.panel1.Name = "panel1"; 98 | this.panel1.Size = new System.Drawing.Size(773, 31); 99 | this.panel1.TabIndex = 3; 100 | // 101 | // selectButton 102 | // 103 | this.selectButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); 104 | this.selectButton.Location = new System.Drawing.Point(614, 3); 105 | this.selectButton.Name = "selectButton"; 106 | this.selectButton.Size = new System.Drawing.Size(75, 23); 107 | this.selectButton.TabIndex = 1; 108 | this.selectButton.Text = "&Select"; 109 | this.selectButton.UseVisualStyleBackColor = true; 110 | this.selectButton.Click += new System.EventHandler(this.selectButton_Click); 111 | // 112 | // cancelButton 113 | // 114 | this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); 115 | this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; 116 | this.cancelButton.Location = new System.Drawing.Point(695, 3); 117 | this.cancelButton.Name = "cancelButton"; 118 | this.cancelButton.Size = new System.Drawing.Size(75, 23); 119 | this.cancelButton.TabIndex = 0; 120 | this.cancelButton.Text = "&Cancel"; 121 | this.cancelButton.UseVisualStyleBackColor = true; 122 | this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); 123 | // 124 | // ResultSelectorForm 125 | // 126 | this.AcceptButton = this.selectButton; 127 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 128 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 129 | this.CancelButton = this.cancelButton; 130 | this.ClientSize = new System.Drawing.Size(779, 475); 131 | this.Controls.Add(this.tableLayoutPanel1); 132 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 133 | this.MaximizeBox = false; 134 | this.MinimizeBox = false; 135 | this.Name = "ResultSelectorForm"; 136 | this.ShowIcon = false; 137 | this.ShowInTaskbar = false; 138 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; 139 | this.Text = "Search Results"; 140 | this.Load += new System.EventHandler(this.ResultSelectorForm_Load); 141 | this.tableLayoutPanel1.ResumeLayout(false); 142 | this.panel1.ResumeLayout(false); 143 | this.ResumeLayout(false); 144 | 145 | } 146 | 147 | #endregion 148 | 149 | private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; 150 | private System.Windows.Forms.ListView resultsListView; 151 | private System.Windows.Forms.ColumnHeader columnHeader1; 152 | private System.Windows.Forms.ColumnHeader columnHeader2; 153 | private System.Windows.Forms.ColumnHeader columnHeader3; 154 | private System.Windows.Forms.Panel panel1; 155 | private System.Windows.Forms.Button selectButton; 156 | private System.Windows.Forms.Button cancelButton; 157 | 158 | } 159 | } -------------------------------------------------------------------------------- /Let's Tag/Forms/ResultSelectorForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text.RegularExpressions; 4 | using System.Web; 5 | using System.Windows.Forms; 6 | 7 | namespace LetsTag 8 | { 9 | public partial class ResultSelectorForm : Form 10 | { 11 | readonly static Regex regex = new Regex( 12 | @"(.*?)" + // Catalog number 13 | @"(.*?(.*?)", // Album title 16 | RegexOptions.IgnoreCase); 17 | 18 | string resultsString; 19 | IList albumsList = new List(); 20 | 21 | public ResultSelectorForm(string resultsString) 22 | { 23 | this.resultsString = resultsString; 24 | InitializeComponent(); 25 | } 26 | 27 | private void ResultSelectorForm_Load(object sender, EventArgs e) 28 | { 29 | Match match = regex.Match(resultsString); 30 | while (match.Success) 31 | { 32 | AlbumData albumData = new AlbumData(); 33 | albumData.CatalogNumber = HttpUtility.HtmlDecode(match.Groups[1].Value); 34 | albumData.ExtraInfo = HttpUtility.HtmlDecode(match.Groups[3].Value); 35 | albumData.AlbumNumber = HttpUtility.HtmlDecode(match.Groups[4].Value); 36 | albumData.AlbumTitle = HttpUtility.HtmlDecode(match.Groups[5].Value); 37 | albumsList.Add(albumData); 38 | 39 | match = match.NextMatch(); 40 | } 41 | Populate(); 42 | } 43 | 44 | private void Populate() 45 | { 46 | foreach (AlbumData album in albumsList) 47 | { 48 | resultsListView.Items.Add(new ListViewItem(new string[] { album.CatalogNumber, album.AlbumTitle, album.ExtraInfo })); 49 | } 50 | } 51 | 52 | private void ShowAlbum() 53 | { 54 | string url = string.Format("http://vgmdb.net/album/{0}", albumsList[resultsListView.SelectedIndices[0]].AlbumNumber); 55 | Form form = new AlbumProgressForm(url); 56 | form.ShowDialog(); 57 | form.Dispose(); 58 | Close(); 59 | } 60 | 61 | private void cancelButton_Click(object sender, EventArgs e) 62 | { 63 | Close(); 64 | } 65 | 66 | private void resultsListView_DoubleClick(object sender, EventArgs e) 67 | { 68 | ShowAlbum(); 69 | } 70 | 71 | private void selectButton_Click(object sender, EventArgs e) 72 | { 73 | ShowAlbum(); 74 | } 75 | } 76 | 77 | public class AlbumData 78 | { 79 | public string CatalogNumber; 80 | public string ExtraInfo; 81 | public string AlbumNumber; 82 | public string AlbumTitle; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /Let's Tag/Forms/SearchForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace LetsTag 2 | { 3 | partial class SearchForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.searchButton = new System.Windows.Forms.Button(); 32 | this.cancelButton = new System.Windows.Forms.Button(); 33 | this.searchTextBox = new System.Windows.Forms.TextBox(); 34 | this.SuspendLayout(); 35 | // 36 | // searchButton 37 | // 38 | this.searchButton.Location = new System.Drawing.Point(180, 38); 39 | this.searchButton.Name = "searchButton"; 40 | this.searchButton.Size = new System.Drawing.Size(75, 23); 41 | this.searchButton.TabIndex = 1; 42 | this.searchButton.Text = "&Search"; 43 | this.searchButton.UseVisualStyleBackColor = true; 44 | this.searchButton.Click += new System.EventHandler(this.searchButton_Click); 45 | // 46 | // cancelButton 47 | // 48 | this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; 49 | this.cancelButton.Location = new System.Drawing.Point(261, 38); 50 | this.cancelButton.Name = "cancelButton"; 51 | this.cancelButton.Size = new System.Drawing.Size(75, 23); 52 | this.cancelButton.TabIndex = 2; 53 | this.cancelButton.Text = "&Cancel"; 54 | this.cancelButton.UseVisualStyleBackColor = true; 55 | this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); 56 | // 57 | // searchTextBox 58 | // 59 | this.searchTextBox.Location = new System.Drawing.Point(12, 12); 60 | this.searchTextBox.Name = "searchTextBox"; 61 | this.searchTextBox.Size = new System.Drawing.Size(324, 20); 62 | this.searchTextBox.TabIndex = 0; 63 | // 64 | // SearchForm 65 | // 66 | this.AcceptButton = this.searchButton; 67 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 68 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 69 | this.CancelButton = this.cancelButton; 70 | this.ClientSize = new System.Drawing.Size(348, 72); 71 | this.Controls.Add(this.searchTextBox); 72 | this.Controls.Add(this.cancelButton); 73 | this.Controls.Add(this.searchButton); 74 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; 75 | this.MaximizeBox = false; 76 | this.MinimizeBox = false; 77 | this.Name = "SearchForm"; 78 | this.ShowIcon = false; 79 | this.ShowInTaskbar = false; 80 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; 81 | this.Text = "Search for Albums"; 82 | this.ResumeLayout(false); 83 | this.PerformLayout(); 84 | 85 | } 86 | 87 | #endregion 88 | 89 | private System.Windows.Forms.Button searchButton; 90 | private System.Windows.Forms.Button cancelButton; 91 | private System.Windows.Forms.TextBox searchTextBox; 92 | } 93 | } -------------------------------------------------------------------------------- /Let's Tag/Forms/SearchForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | namespace LetsTag 5 | { 6 | public partial class SearchForm : Form 7 | { 8 | public SearchForm() 9 | { 10 | InitializeComponent(); 11 | } 12 | 13 | private void cancelButton_Click(object sender, EventArgs e) 14 | { 15 | Close(); 16 | } 17 | 18 | private void searchButton_Click(object sender, EventArgs e) 19 | { 20 | if (searchTextBox.Text.Length < 3) 21 | { 22 | MessageBox.Show("Please enter at least 3 characters.", null, MessageBoxButtons.OK, MessageBoxIcon.Warning); 23 | searchTextBox.Focus(); 24 | return; 25 | } 26 | 27 | Form form = new SearchProgressForm(searchTextBox.Text); 28 | form.ShowDialog(); 29 | form.Dispose(); 30 | Close(); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Let's Tag/Forms/SearchForm.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /Let's Tag/Forms/SearchProgressForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace LetsTag 2 | { 3 | partial class SearchProgressForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.cancelButton = new System.Windows.Forms.Button(); 32 | this.SuspendLayout(); 33 | // 34 | // cancelButton 35 | // 36 | this.cancelButton.Location = new System.Drawing.Point(116, 12); 37 | this.cancelButton.Name = "cancelButton"; 38 | this.cancelButton.Size = new System.Drawing.Size(75, 23); 39 | this.cancelButton.TabIndex = 1; 40 | this.cancelButton.Text = "&Cancel"; 41 | this.cancelButton.UseVisualStyleBackColor = true; 42 | this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); 43 | // 44 | // SearchProgressForm 45 | // 46 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 47 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 48 | this.ClientSize = new System.Drawing.Size(307, 45); 49 | this.ControlBox = false; 50 | this.Controls.Add(this.cancelButton); 51 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; 52 | this.MaximizeBox = false; 53 | this.MinimizeBox = false; 54 | this.Name = "SearchProgressForm"; 55 | this.ShowIcon = false; 56 | this.ShowInTaskbar = false; 57 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; 58 | this.Text = "Connecting..."; 59 | this.Load += new System.EventHandler(this.SearchProgressForm_Load); 60 | this.ResumeLayout(false); 61 | 62 | } 63 | 64 | #endregion 65 | 66 | private System.Windows.Forms.Button cancelButton; 67 | } 68 | } -------------------------------------------------------------------------------- /Let's Tag/Forms/SearchProgressForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using System.Text.RegularExpressions; 4 | using System.Windows.Forms; 5 | using LetsTag.Common; 6 | 7 | namespace LetsTag 8 | { 9 | public partial class SearchProgressForm : Form 10 | { 11 | delegate void ShowResultsHandler(); 12 | delegate void SetTextHandler(string text); 13 | delegate void CloseHandler(); 14 | 15 | public static event AlbumSelectedHandler AlbumSelected; 16 | 17 | readonly static Regex isAlbumRegex = new Regex(@"\>\s*Album\s+Stats\s*\<"); 18 | readonly static Regex isNoResultsRegex = new Regex(@"\>\s*No\s+results\s+found\s*\.\s*\<"); 19 | 20 | HttpPostRequest request; 21 | 22 | public SearchProgressForm(string searchText) 23 | { 24 | InitializeComponent(); 25 | request = new HttpPostRequest("http://vgmdb.net/db/albums-search.php?do=results", new HttpRequestHandler(OnRequestStatusChange)); 26 | request.PostData.Add("action", "simplesearch"); 27 | request.PostData.Add("formalbumtitle", searchText); 28 | } 29 | 30 | private void SearchProgressForm_Load(object sender, EventArgs e) 31 | { 32 | request.Execute(); 33 | } 34 | 35 | private void cancelButton_Click(object sender, EventArgs e) 36 | { 37 | request.Abort(); 38 | Close(); 39 | } 40 | 41 | void OnRequestStatusChange(AbstractHttpRequest request, HttpRequestStatus status) 42 | { 43 | switch (status) 44 | { 45 | case HttpRequestStatus.Downloading: 46 | Invoke(new SetTextHandler(SetText), string.Format("Downloading... ({0} bytes)", request.Response.Length)); 47 | break; 48 | 49 | case HttpRequestStatus.Error: 50 | MessageBox.Show(request.Error, null, MessageBoxButtons.OK, MessageBoxIcon.Error); 51 | Invoke(new CloseHandler(Close)); 52 | break; 53 | 54 | case HttpRequestStatus.Done: 55 | Invoke(new ShowResultsHandler(ShowResults)); 56 | break; 57 | } 58 | } 59 | 60 | void SetText(string text) 61 | { 62 | Text = text; 63 | } 64 | 65 | void ShowResults() 66 | { 67 | string responseString = UTF8Encoding.UTF8.GetString(request.Response); 68 | 69 | if (isAlbumRegex.IsMatch(responseString)) 70 | { 71 | // There was a single result -- web service returned album 72 | AlbumSelected(responseString); 73 | } 74 | else if (isNoResultsRegex.IsMatch(responseString)) 75 | { 76 | // There are no results 77 | MessageBox.Show("No results found.", null, MessageBoxButtons.OK, MessageBoxIcon.Information); 78 | } 79 | else 80 | { 81 | // There are multiple results 82 | Form form = new ResultSelectorForm(responseString); 83 | form.ShowDialog(); 84 | form.Dispose(); 85 | } 86 | 87 | Close(); 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Let's Tag/Forms/SearchProgressForm.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /Let's Tag/Let's Tag Console.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.21022 7 | 2.0 8 | {4E480DE6-1F7A-4BEF-BCCB-F027E1ADFE9B} 9 | Exe 10 | Properties 11 | LetsTag 12 | letstagc 13 | v3.5 14 | 512 15 | icon_grey.ico 16 | 17 | 18 | 19 | 20 | 3.5 21 | 22 | 23 | true 24 | full 25 | false 26 | bin\Debug\ 27 | DEBUG;TRACE 28 | prompt 29 | 4 30 | 31 | 32 | pdbonly 33 | true 34 | bin\Release\ 35 | TRACE 36 | prompt 37 | 4 38 | 39 | 40 | 41 | 42 | 3.5 43 | 44 | 45 | 46 | 47 | 3.5 48 | 49 | 50 | 3.5 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | True 67 | True 68 | ConsoleResource.resx 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | Always 81 | 82 | 83 | 84 | Always 85 | 86 | 87 | 88 | 89 | ResXFileCodeGenerator 90 | ConsoleResource.Designer.cs 91 | Designer 92 | 93 | 94 | 95 | 102 | -------------------------------------------------------------------------------- /Let's Tag/LetsTagException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace LetsTag 4 | { 5 | public class LetsTagException : Exception 6 | { 7 | string message; 8 | Exception nestedException; 9 | 10 | public LetsTagException(string message) 11 | : this(message, null) { } 12 | 13 | public LetsTagException(string message, Exception nestedException) 14 | { 15 | this.message = message; 16 | this.nestedException = nestedException; 17 | } 18 | 19 | public override string ToString() 20 | { 21 | return message + (nestedException == null ? "" : "\r\n" + nestedException.ToString()); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Let's Tag/Parsers/AlbumParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Net; 4 | using System.Text.RegularExpressions; 5 | using System.Web; 6 | 7 | namespace LetsTag 8 | { 9 | public static class AlbumParser 10 | { 11 | readonly static Regex albumNameRegex = new Regex( 12 | @"(.*?)", 13 | RegexOptions.Singleline | RegexOptions.IgnoreCase); 14 | 15 | readonly static Regex coverRegex = new Regex( 16 | @"]*background-image:\s*url\('(.*?)'\)", 17 | RegexOptions.Singleline | RegexOptions.IgnoreCase); 18 | 19 | readonly static Regex detailRegex = new Regex( 20 | @".*?.*?\s*(.*?)\s*.*?.*?(.*?).*?", 21 | RegexOptions.Singleline | RegexOptions.IgnoreCase); 22 | 23 | readonly static Regex detailCatalogNumberRegex = new Regex( 24 | @"(.*?)", 25 | RegexOptions.Singleline | RegexOptions.IgnoreCase); 26 | 27 | readonly static Regex detailMultilingualValueRegex = new Regex( 28 | @"(.*?)", 29 | RegexOptions.Singleline | RegexOptions.IgnoreCase); 30 | 31 | readonly static Regex detailValueCleanupRegex = new Regex( 32 | @"<.*?>", 33 | RegexOptions.Singleline | RegexOptions.IgnoreCase); 34 | 35 | public static void Parse(Album album, string data) 36 | { 37 | // Extract album name 38 | 39 | Match match = albumNameRegex.Match(data); 40 | 41 | if (!match.Success) 42 | throw new Exception("There was a problem parsing the album data."); 43 | 44 | album.Details.Add("Album Name", HttpUtility.HtmlDecode(match.Groups[1].Value).Trim()); 45 | 46 | // Extract cover 47 | 48 | match = coverRegex.Match(data); 49 | 50 | if (match.Success) 51 | album.Cover = GetImage(match.Groups[1].Value); 52 | 53 | // Extract other details 54 | 55 | match = detailRegex.Match(data); 56 | while (match.Success) 57 | { 58 | string key = HttpUtility.HtmlDecode(match.Groups[1].Value).Trim(); 59 | string value = match.Groups[2].Value; 60 | 61 | if (key.ToLower().Contains("catalog")) 62 | { 63 | Match subMatch = detailCatalogNumberRegex.Match(value); 64 | if (subMatch.Success) 65 | value = subMatch.Groups[1].Value; 66 | } 67 | else 68 | { 69 | value = detailMultilingualValueRegex.Replace(value, new MatchEvaluator(DetailMultilingualEvaluator)); 70 | } 71 | 72 | value = HttpUtility.HtmlDecode(detailValueCleanupRegex.Replace(value, "")).Trim(); 73 | 74 | album.Details.Add(key, value); 75 | 76 | match = match.NextMatch(); 77 | } 78 | } 79 | 80 | static Image GetImage(string url) 81 | { 82 | WebRequest request = WebRequest.Create(url); 83 | request.Method = "GET"; 84 | WebResponse response = request.GetResponse(); 85 | Image image = Image.FromStream(response.GetResponseStream()); 86 | response.Close(); 87 | return image; 88 | } 89 | 90 | static string DetailMultilingualEvaluator(Match match) 91 | { 92 | if (match.Groups[1].Value.ToLower() == "en") 93 | return match.Groups[2].Value; 94 | else 95 | return ""; 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Let's Tag/Parsers/TracklistParser.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using System.Text.RegularExpressions; 4 | using System.Web; 5 | 6 | namespace LetsTag 7 | { 8 | public static class TracklistParser 9 | { 10 | readonly static Regex discRegex = new Regex( 11 | @"\s*Disc\s+(\d+)\s*.*?(.*?)", 12 | RegexOptions.Singleline | RegexOptions.IgnoreCase); 13 | 14 | readonly static Regex trackRegex = new Regex( 15 | @"(.*?)" + // Track number 16 | @".*?(.*?)", // Track name 17 | RegexOptions.Singleline | RegexOptions.IgnoreCase); 18 | 19 | public static void Parse(Album album, string data) 20 | { 21 | IList discNumbers = new List(); 22 | 23 | Match match = discRegex.Match(data); 24 | while (match.Success) 25 | { 26 | Disc disc = new Disc(); 27 | disc.Number = HttpUtility.HtmlDecode(match.Groups[1].Value).Trim(); 28 | 29 | if (!discNumbers.Contains(disc.Number)) 30 | { 31 | discNumbers.Add(disc.Number); 32 | 33 | Match subMatch = trackRegex.Match(match.Groups[2].Value); 34 | while (subMatch.Success) 35 | { 36 | Track track = new Track(); 37 | track.Number = HttpUtility.HtmlDecode(subMatch.Groups[1].Value); 38 | track.Name = HttpUtility.HtmlDecode(subMatch.Groups[2].Value); 39 | 40 | disc.Tracks.Add(track); 41 | 42 | subMatch = subMatch.NextMatch(); 43 | } 44 | 45 | album.Discs.Add(disc); 46 | } 47 | 48 | match = match.NextMatch(); 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Let's Tag/Presets/Default.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Game 11 | -------------------------------------------------------------------------------- /Let's Tag/Presets/Track Data Only.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Let's Tag/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | namespace LetsTag 5 | { 6 | static class Program 7 | { 8 | /// 9 | /// The main entry point for the application. 10 | /// 11 | [STAThread] 12 | static void Main() 13 | { 14 | Application.EnableVisualStyles(); 15 | Application.SetCompatibleTextRenderingDefault(false); 16 | Application.Run(new MainForm()); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Let's Tag/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Let's Tag")] 9 | [assembly: AssemblyDescription("Let's Tag assists in tagging game music albums. It connects to vgmdb.net to download album data and exports it in a format that can be imported into Mp3tag.")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Tom Voros")] 12 | [assembly: AssemblyProduct("Let's Tag")] 13 | [assembly: AssemblyCopyright("")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("437fe066-8a06-4362-818c-209ad6bb18d9")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("0.2.2.*")] 36 | [assembly: AssemblyFileVersion("0.2.2.0")] 37 | -------------------------------------------------------------------------------- /Let's Tag/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace LetsTag.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("LetsTag.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Let's Tag/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /Let's Tag/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace LetsTag.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Let's Tag/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Let's Tag/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomvoros/lets-tag/5894ece174a06c7ce1dcd09c6cb3a8a3a0d81527/Let's Tag/icon.ico -------------------------------------------------------------------------------- /Let's Tag/icon_grey.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomvoros/lets-tag/5894ece174a06c7ce1dcd09c6cb3a8a3a0d81527/Let's Tag/icon_grey.ico -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Let's Tag 2 | 3 | Let's Tag assists in tagging game music albums. It connects to vgmdb.net to download album data and exports it in a format that can be imported into Mp3tag. 4 | 5 | **I stopped maintaining Let's Tag a long time ago because the alternative solutions available (see below) are much better.** 6 | 7 | ![Screenshot](Screenshot.png) 8 | 9 | ## Download 10 | 11 | ### Let's Tag v0.2.2 12 | https://github.com/tomvoros/lets-tag/releases/tag/v0.2.2 13 | 14 | ## How to Use 15 | 16 | Here's a slideshow demonstrating how to use Let's Tag with Mp3tag: 17 | https://docs.google.com/presentation/d/1VVsxFKsUv7I_9lPwckUHx_1J1F59uvIitz7l8ls7q5U/embed 18 | 19 | ## Alternatively... 20 | 21 | Other ways to get VGMdb tag data that may be more convenient than using Let's Tag: 22 | * VGMdb's official CDDB/freedb support (by Zorbfish): 23 | http://vgmdb.net/forums/showthread.php?t=2618 24 | * VGMdb data source for Mp3tag (by dano): 25 | https://forums.mp3tag.de/index.php?showtopic=10991 26 | * Another VGMdb data source for Mp3tag (by PBXg33k): 27 | https://gist.github.com/PBXg33k/7b80a86d53b922f0873a 28 | 29 | ## Links 30 | 31 | VGMdb: 32 | http://vgmdb.net 33 | 34 | Let's Tag discussion thread on VGMdb Forums: 35 | http://vgmdb.net/forums/showthread.php?t=1902 36 | 37 | Mp3tag: 38 | http://www.mp3tag.de/en/ 39 | 40 | ## Release History 41 | 42 | ### Version 0.2.2 (July 23, 2017) 43 | * Published Let's Tag to GitHub 44 | * Updated Let's Tag to support the current version of vgmdb.net 45 | * Updated the link in the About window to point to GitHub 46 | 47 | ### Version 0.2.1 (May 23, 2009) 48 | * Added drag and drop for album cover. When the album cover is dropped on an Explorer window, it is saved as folder.jpg. 49 | * Added additional image formats for saving album cover. 50 | 51 | ### Version 0.2 (May 11, 2009) 52 | * Cover art is downloaded and displayed. It can be copied to the clipboard (for pasting into Mp3tag) or saved to a file. 53 | * Added a command line app, letstagc.exe, for those who want to use Let's Tag in scripts or batch files. (Functionality is fairly limited at the moment.) 54 | * Export presets can be saved. They are saved as XML files in Let's Tag's Presets folder. 55 | * Editing the export preset XML files by hand allows you to make more advanced presets. For example, it is possible to put multiple album fields into a single MP3 tag field. 56 | * Code was refactored quite a bit, though it still needs some work. 57 | 58 | ### Version 0.1.1 (April 19, 2009) 59 | * Fixed search results parser to accomodate a minor change in the HTML. 60 | 61 | ### Version 0.1 (February 17, 2009) 62 | * Initial release. 63 | -------------------------------------------------------------------------------- /Screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomvoros/lets-tag/5894ece174a06c7ce1dcd09c6cb3a8a3a0d81527/Screenshot.png --------------------------------------------------------------------------------