I’m a long time Sony Vegas fan. My history with Sony goodies dates back to Acid Pro 3, when was still developed by Sonic Foundry, which had created a very intuitive interface and workflow. Sony bought Sonic Foundry and started migrating all the programs to .Net Framework crap, and quality began to suffer.
Sony Vegas was still usable up to version 12. Not exactly fast, but pretty usable. Testing out this version 13 – build 373 is the lastest at the moment I write this post –, I’m deeply disgusted to what they have done. Without any noticeable improvement, the interface has got a bit uglier, and everything, absolutely everything is slower. I dislike laptops, I have a desktop computer with quite powerful hardware components, and even though, the timeline elements became sluggish when reacting to the mouse, the video preview rendering is blurred and skipping frames, and any cross-fading is simply not viewable due to slowness. Among other oddities.
After some hours of headache, I simply removed this version and reinstalled the version 12 back. What a relief. No more Vegas 13 over here. I hope Vegas 14 can have more luck – although I doubt it.
Monday, September 22, 2014
Friday, September 19, 2014
Music Man JP comparison chart
After his solid Ibanez JPM, it seems that John Petrucci doesn’t know what he wants, so he changes the specs of his signature guitar each year. There are way too many versions so far, and no single place where you can find all the specs together, so I compiled a comprehensive chart of all John Petrucci models with Ernie Ball Music Man.
Note: this chart doesn’t include the dozens of limited series that have been released, just the standard specs.
Year | Model | Body | Neck | Fingerboard | Bridge PU | Neck PU | F radius | Frets |
---|---|---|---|---|---|---|---|---|
2000 | JP6 | Basswood | Birdseye maple | Rosewood | Custom, based on Evolution (ref) |
Custom, based on Air Norton |
15" 381mm |
High wide h .047", w .104" h 1.19, w 2.64mm |
2005 | D-Sonic | |||||||
2007 | JP6 BFR | Alder, maple top, mahogany block |
Mahogany | Rosewood or ebony | ||||
2008 | JP6 | Basswood | Birdseye maple | Rosewood | Crunch Lab | LiquiFire | ||
JP6 BFR | Alder, maple top, mahogany block |
Mahogany | Rosewood or ebony | |||||
JP6 BFR Baritone | ||||||||
2010 | JPX | Chambered alder, maple top, mahogany block |
Ebony | Jumbo h .057", w .110" h 1.45, w 2.79mm |
||||
2011 | JPXI | Alder, maple top, mahogany block |
20" 508mm |
Medium jumbo h .051", w .108" h 1.30, w 2.74mm |
||||
2012 | JP12 | Basswood, maple top, mahogany block |
||||||
2013 | JP13 | Rosewood | Illuminator | Illuminator | 17" 432mm |
|||
2014 | Majesty | Basswood, maple top |
Mahogany, neck-thru | Ebony | ||||
2015 | JP15 | African mahogany, maple top |
Roasted maple | |||||
Majesty Artisan | Honduran mahogany, neck-thru |
Ebony | ||||||
2016 | JP16 | Basswood | Roasted maple | Smokey ebony | Sonic Ecstasy | Sonic Ecstasy | ||
2017 | Majesty Monarchy | African mahogany, maple top |
Honduran mahogany, neck-thru |
Ebony | ||||
2019 | Dreamcatcher | Rainmaker | ||||||
2021 | JP 20th | Honduran mahogany, maple top |
Honduran mahogany | Crunch Lab | LiquiFire | 15" 381mm |
High wide h .047", w .104" h 1.19, w 2.64mm |
|
Majesty 20th | Honduran mahogany, neck-thru |
Dream Catcher | Rainmaker | 17" 432mm |
Medium jumbo h .051", w .108" h 1.30, w 2.74mm |
|||
Majesty 8 | Basswood | Mahogany, neck-thru |
Other changes:
- On the first model, the following are optional: piezo, matching headstock, shield fretboard inlays. A “full loaded” specimen has all three.
- Compensated nut was introduced in early 2006.
- The BFR Baritone has a 27.5" scale length.
- Stainless steel frets debuted with the JPXI in January 2011, and later became standard on all JP models ordered since January 2012.
- The rectangular tremolo base plate was introduced in August 2011.
- In 2011 the piezo saddles changed for ones with lower output; because of this, the preamp was changed for one with a higher output to compensate.
- The BFR logos (on the 12th fret) were retired from all models with the release of the JP13, in early 2013.
- The JP12 was the last model to feature a passive circuit for the magnetic pickups, which can work without a battery. The JP13 and all later models feature an active circuit for everything, including the magnetic pickups: without batteries guitar has no sound.
- Around October 2016 the logo at the back of the headstock changed, from “Made in San Luis Obispo California, USA” to “Californa heritage, since 1974” with a bear picture.
- The JP16 has a Korean-made Floyd Rose bridge, and no piezo system.
- In 2019, the Majesty eletronics layout was redesigned, with less wiring in the back cavity. The layout of the back controls is different.
- The Majesty 8 has a fixed bridge and it’s 25 to 27" multi-scale.
This chart was last updated in 2024-04-02.
Saturday, August 9, 2014
A balanced .008 gauge string set for guitar
Last month I restrung my 2004 Music Man JP6 with a .008 gauge string set, D’Addario EXL130. I started to feel very uncomfortable with the G string, because it has so much more tension than all the others. I even considered trading the JP6 for an Ibanez Jem, which I travelled about 150 km just to test for a couple minutes, and it felt good on my fingers, possibly due to my 8 years playing exclusively a 1996 UV7BK.
Then yesterday I took a different direction and it came to my mind the idea of assembling a balanced string set, thus fixing the problem with the heavy G string. I know that there are commercial balanced sets, but they just alleviate the problem, not fixing it. I found this excellent post on Jemsite, where the guy made a comprehensive chart with all D’Addario sets and tension of each string. The .008 data confirmed what my fingers already knew: the G string is much heavier than it should. Also, the A string is slightly heavier, but I really didn’t felt it that much.
What I can’t really understand is why all the string sets are so unbalanced, and why so few people complain about it.
In order to find the right gauge to balance my .008 set, I found a handy online calculator for string tension, not very intuitive, but accurate. With it, I found the gauge of .013 for the G string, instead of the .015, to balance my .008 set. The B string of an ordinary .010 set – D’Addario EXL110 – is exactly .013, so if I buy such a set I could pick the B string and use it. Also, the D string is a .026 gauge, which could replace my current A of .030, making my set more even.
After replacing these two strings, and loosening the spring claw and the truss rod a bit, my JP6 felt a lot better. Instant gratification. The heaviness of the G is finally gone, the bends are easier, and the slightly loosened A added a very smooth feel to the wound strings. And I love loose strings. Here is the tension chart comparison:
Then yesterday I took a different direction and it came to my mind the idea of assembling a balanced string set, thus fixing the problem with the heavy G string. I know that there are commercial balanced sets, but they just alleviate the problem, not fixing it. I found this excellent post on Jemsite, where the guy made a comprehensive chart with all D’Addario sets and tension of each string. The .008 data confirmed what my fingers already knew: the G string is much heavier than it should. Also, the A string is slightly heavier, but I really didn’t felt it that much.
What I can’t really understand is why all the string sets are so unbalanced, and why so few people complain about it.
In order to find the right gauge to balance my .008 set, I found a handy online calculator for string tension, not very intuitive, but accurate. With it, I found the gauge of .013 for the G string, instead of the .015, to balance my .008 set. The B string of an ordinary .010 set – D’Addario EXL110 – is exactly .013, so if I buy such a set I could pick the B string and use it. Also, the D string is a .026 gauge, which could replace my current A of .030, making my set more even.
After replacing these two strings, and loosening the spring claw and the truss rod a bit, my JP6 felt a lot better. Instant gratification. The heaviness of the G is finally gone, the bends are easier, and the slightly loosened A added a very smooth feel to the wound strings. And I love loose strings. Here is the tension chart comparison:
Ordinary (unbalanced) .008 set: E: .008" [PL] = 10.38 pounds B: .010" [PL] = 09.10 pounds G: .015" [PL] = 12.90 pounds D: .021" [NW] = 12.05 pounds A: .030" [NW] = 14.05 pounds E: .040" [NW] = 12.11 pounds Total tension = 70.59 pounds
My balanced .008 set: E: .008" [PL] = 10.38 pounds B: .010" [PL] = 09.10 pounds G: .013" [PL] = 09.68 pounds D: .021" [NW] = 12.05 pounds A: .026" [NW] = 11.23 pounds E: .040" [NW] = 12.11 pounds Total tension = 64.55 poundsAnd I’m not thinking about the Jem anymore. By now.
Saturday, June 14, 2014
Named arguments in C
When experimenting with some C99 features of C, I found a very cool trick to have named parameters, using a feature called designated initializers. The first time I read about designated initializers I must admit I found it to be pretty useless, but as I started testing it out, I ended up finding it very useful, since it can make code a lot more readable. Using it together with variadic macros, it was possible to have a very clean named parameter system.
Straight into the code, this is the technique:
Straight into the code, this is the technique:
typedef struct { int year; const wchar_t *name; } Foo_args; // parameters void Foo_func(Foo_args args) { int x = args.year + 10; // use the argument } #define Foo(...) Foo_func((Foo_args){ __VA_ARGS__ })And this is how you call the function:
Foo(.year = 2014, .name = L"Rodrigo");The function calling is clear, and its implementation doesn’t add much noise to the code: I believe the price is payable and the result is worth.
Tuesday, May 13, 2014
Fixing .htaccess in Apache with Ubuntu 12
I have an ordinary Apache installation on an Ubuntu 12 OS, where the root webserver directory is ordinarily pointing to
So, after some minor stress, here it is the quick step-by-step guide of what I did, without further explanations:
/var/www
. I have many subdirectories within it, and I’d like to have one of these subdirectories using clean URLs, specifically becaused I was testing some RESTful API stuff. However, I’ve struggled a bit to make Apache recognize my .htaccess file.So, after some minor stress, here it is the quick step-by-step guide of what I did, without further explanations:
sudo vim /etc/apache2/sites-available/defaultWithin the
Directory /var/www
directive, change AllowOverride None
by AllowOverride All
. Then run these two commands:sudo a2enmod rewrite sudo service apache2 restartAnd all of sudden it started working.
Friday, March 28, 2014
A simple alternative to C++ exceptions
I’ve been doing a lot of C++11 research and coding ultimately, and I’m still upset with the C++ exceptions. When reading the concepts, it seems to be a reasonably good alternative to simply return a boolean, but as you try to stuff it in your code, you begin to feel like manipulating a stressed hedgehog. And it’s very frustrating, since you have to stop thinking about your code – what really matters –, to think about the implications of the code you are writing upon the code itself.
Usually, my needs are really simple, I just need an extended way to report a success or a failure from a function. I never wrote something that really needed to tackle differents kinds of errors: it’s just success, or failure with a reason, which usually popped in an alert message box.
After quitting the exceptions, when trying to solve this problem, my first move was to use an extra string pointer as the last parameter to hold eventual error messages. It goes like this:
My second approach was to use a standard pair as the return type to the function. Something like this:
Then I start thinking about writing a “bool on steroids” class, specifically overloading the operator bool, so there would be no need to declare a variable just to hold the result value of the invoked function. This is the class:
The only thing which makes me uncomfortable with this class is the
Other than that, I consider it a neat approach, and that’s the best solution I could come up with so far.
Usually, my needs are really simple, I just need an extended way to report a success or a failure from a function. I never wrote something that really needed to tackle differents kinds of errors: it’s just success, or failure with a reason, which usually popped in an alert message box.
After quitting the exceptions, when trying to solve this problem, my first move was to use an extra string pointer as the last parameter to hold eventual error messages. It goes like this:
bool Func(int p1, int p2, wstring *pErr=nullptr) { if(false) { if(pErr) *pErr = L"Error message."; return false; } if(pErr) *pErr = L""; // all good return true; } bool Second(float nn, wstring *pErr=nullptr) { if(!Func(42, 1337, pErr)) { // will return error message from inner function return false; } else if(false) { if(pErr) *pErr = L"Another error."; return false; } if(pErr) *pErr = L""; // all good return true; } { wstring err; if(!Func(42, 1337, &err)) scream(err.c_str()); }There is no problem with this approach, and I used it for quite some time. It is clear, and one would have no doubts about what is going on. It is, however a bit cumbersome to write all those
pErr
checks. So at some point I started considering something else.My second approach was to use a standard pair as the return type to the function. Something like this:
pair<bool, wstring> Func() { if(false) return make_pair(false, L"Error description message."); return make_pair(true, L""); } { pair<bool, wstring> ret = Func(); if(!ret.first) scream(ret.second.c_str()); }I never really used this. It doesn’t look clear enough, and the declaration of the pair variable, just to hold the return value, doesn’t amuse me.
Then I start thinking about writing a “bool on steroids” class, specifically overloading the operator bool, so there would be no need to declare a variable just to hold the result value of the invoked function. This is the class:
#include <string> class Failed { public: Failed(bool allGood) : _hasFailed(!allGood) { } explicit Failed(std::wstring reason) : _hasFailed(true), _reason(reason) { } explicit Failed(const wchar_t *reason) : _hasFailed(true), _reason(reason) { } virtual ~Failed() { } operator bool() const { return _hasFailed; } const wchar_t* reason() const { return _reason.c_str(); } private: bool _hasFailed; std::wstring _reason; };And this is the usage:
Failed Func() { if(false) return Failed(L"This function failed."); return true; } Failed Second() { if(Failed f = Func()) { // if Func() returned false return f; // return from inner function } else if(false) { return Failed(L"Another error message."); } return true; } { if(Failed f = Second()) scream(f.reason()); }This approach looks a lot elegant to me. It’s clean, allows the chaining of error messages, and it even allows the inheriting of the
Failed
class to add more specific error data – although I never really needed this.The only thing which makes me uncomfortable with this class is the
_hasFailed
member, which holds a reversed boolean value of the object meaning: if there’s a success, it’s false
; if there’s a failure, it’s true
. I implemented it this way so that I could use a declaration of the class within an if
statement, with no need to declare a variable just to hold the result, as I did on the previous example when I returned a standard pair. Also, it explains why I chose the name “Failed” instead of something like “BigBool”: to explicit the idea of a failure being handled by the if
.Other than that, I consider it a neat approach, and that’s the best solution I could come up with so far.
Saturday, February 15, 2014
Queen 2011 remasters: horrible
As an audophile, I care a lot about my music collection. Some albums do have multiple pressings, with new remastered versions of the same old material. These remasters rarely surpass the originals, they tend to be overcompressed due to the infamous loudness wars, but I always seek to hear them, waiting for a miracle.
Right now I’m listening to the Queen 2011 remasters, which sound all really bad to my ears. I’ve read somewhere that Bob Ludwig was responsible for this work, but it’s hard to believe that such a great professional have done such a shitty job. Some songs – particularly the heavier ones – have so much compression that distortion is openly audible. The Jazz album is the worst one so far, with burnt peaks on all tracks, a mess of noise.
The Sheer Heart Attack song, from News of the World album, is a full block of deafening noise, that gave me a headache before the second minute ended, and I had to skip it. The same for the heavy parts of Brighton Rock and Stone Cold Crazy, from Sheer Heart Attack album. Basically, the songs are ruined, sounding really harsh, overcompressed on every single opportunity.
Label managers of today are not only stupid, they are deaf too. When I see things like this, I only can hope that digital music distribution kills this industry as soon as possible, as it is already happening. With the home studios and the internet, we don’t need their greed anymore.
Right now I’m listening to the Queen 2011 remasters, which sound all really bad to my ears. I’ve read somewhere that Bob Ludwig was responsible for this work, but it’s hard to believe that such a great professional have done such a shitty job. Some songs – particularly the heavier ones – have so much compression that distortion is openly audible. The Jazz album is the worst one so far, with burnt peaks on all tracks, a mess of noise.
The Sheer Heart Attack song, from News of the World album, is a full block of deafening noise, that gave me a headache before the second minute ended, and I had to skip it. The same for the heavy parts of Brighton Rock and Stone Cold Crazy, from Sheer Heart Attack album. Basically, the songs are ruined, sounding really harsh, overcompressed on every single opportunity.
Label managers of today are not only stupid, they are deaf too. When I see things like this, I only can hope that digital music distribution kills this industry as soon as possible, as it is already happening. With the home studios and the internet, we don’t need their greed anymore.
Wednesday, January 29, 2014
JavaScript anonymous closures
Today I was going to write about my fruitful experiments in JavaScript using anonymous closures, scope and namespacing in general. But I stumbled across two articles that are so good, that I just felt the need to publish the links to both, because they explain everything I was about to write in great detail:
- JavaScript Module Pattern: In-Depth, by Ben Cherry (2010); and
- Namespacing in JavaScript, by Angus Croll (2011).
Thursday, January 9, 2014
Logitech, please bring back the wired Trackman Wheel
About 2 years ago I was suffering from some wrist pain, due to countless hours of computer work with an ordinary mouse. I started searching for some device to relieve the pain, and after test several gadgets, I came across the Logitech Trackman Wheel. It’s a trackball which sphere is moved with the thumb, leaving the whole hand resting on the desk. And it’s absolutely great, precise, comfortable, I could use that thing for hours without any signs of tiring.
This week, however, the left click just started acting numb, unresponsive, and I found a video teaching a way that could possibly fix it. After three days, the problem seemed to be unfixable, so I decided to buy another unit of this wonderful thing. But to my surprise, I found out the Logitech discontinued the Trackman Wheel, in favor of a wireless version called M570, which like any laggy wireless device, relies on batteries, which require you to figure out when they start dying, so you can buy more batteries to replace the old ones, if you don’t have them dying in the middle of an online game, for example, case when you’d be screwed. Oh, and also it has an annoying switch to turn on and off, so that’s another thing you have to remember to do. The Trackman is supposed to stay fixed on the desk, so why the hell do you need a wireless version of it?
I’m not the only one who wants the wired Trackman Wheel back, there’s even a group on Facebook with people discussing this. Unfortunately, Logitech didn’t reply the user complains, and so far there’s no hope to have a wired version of our beloved Trackman Wheel.
I could not find any unit to buy, not even on eBay. By now, I’m desperately trying to find a way to fix my old and good Trackman Wheel, to use it for as long as I can. And to Logitech, for blindly joining this wireless bandwagon, I just want to leave a sincere fuck you, Logitech.
Update, Jan 11:
This morning I found a skillful electrician who managed to swap the bad left click component with the middle click one, which was working fine. Now I don’t have a middle click anymore, but at least my beloved Trackman Wheel is usable again.
This week, however, the left click just started acting numb, unresponsive, and I found a video teaching a way that could possibly fix it. After three days, the problem seemed to be unfixable, so I decided to buy another unit of this wonderful thing. But to my surprise, I found out the Logitech discontinued the Trackman Wheel, in favor of a wireless version called M570, which like any laggy wireless device, relies on batteries, which require you to figure out when they start dying, so you can buy more batteries to replace the old ones, if you don’t have them dying in the middle of an online game, for example, case when you’d be screwed. Oh, and also it has an annoying switch to turn on and off, so that’s another thing you have to remember to do. The Trackman is supposed to stay fixed on the desk, so why the hell do you need a wireless version of it?
I’m not the only one who wants the wired Trackman Wheel back, there’s even a group on Facebook with people discussing this. Unfortunately, Logitech didn’t reply the user complains, and so far there’s no hope to have a wired version of our beloved Trackman Wheel.
I could not find any unit to buy, not even on eBay. By now, I’m desperately trying to find a way to fix my old and good Trackman Wheel, to use it for as long as I can. And to Logitech, for blindly joining this wireless bandwagon, I just want to leave a sincere fuck you, Logitech.
Update, Jan 11:
This morning I found a skillful electrician who managed to swap the bad left click component with the middle click one, which was working fine. Now I don’t have a middle click anymore, but at least my beloved Trackman Wheel is usable again.
Tuesday, December 17, 2013
Creating project templates for Visual Studio 2013
There are a couple of project settings that I set for every native C++ Win32 project I want to start, basically, more aggressive optimizations for the release build.
Right now, messing around with my brand new Visual Studio 2013 – which I’m appreciating so far –, I discovered how to create a template project with all the settings I need, including subfolders and files. I found this article which explains the process for an ASP.NET MVC project, but the steps are the same for a C++ one.
The templates are exported as ordinary ZIP files, and importing existing ones is trivial, you just need to copy this ZIP file into the base directory. On my computer, this is the full path for the custom user templates:
Right now, messing around with my brand new Visual Studio 2013 – which I’m appreciating so far –, I discovered how to create a template project with all the settings I need, including subfolders and files. I found this article which explains the process for an ASP.NET MVC project, but the steps are the same for a C++ one.
The templates are exported as ordinary ZIP files, and importing existing ones is trivial, you just need to copy this ZIP file into the base directory. On my computer, this is the full path for the custom user templates:
C:\Users\Rodrigo\Documents\Visual Studio 2013\Templates\ProjectTemplatesIn addition to the project settings, I also put in the template a subdirectory called “src”, my very basic main.cpp file, which contains my wWinMain entry point. It seems that I’ll never have to write it again.
Monday, December 16, 2013
A simple C++ smart pointer class
Until I started using move semantics of C++11, I used this smart pointer class, which is template-based, heavily relies on operator overloading, and uses an instance counter:
template<typename T> class Ptr { public: Ptr() : _ptr(NULL), _counter(NULL) { } Ptr(T *ptr) : _ptr(NULL), _counter(NULL) { operator=(ptr); } Ptr(const Ptr& other) : _ptr(NULL), _counter(NULL) { operator=(other); } ~Ptr() { if(_counter && !--(*_counter)) { delete _ptr; _ptr = NULL; delete _counter; _counter = NULL; } } Ptr& operator=(T *ptr) { this->~Ptr(); if(ptr) { _ptr = ptr; // take ownership _counter = new int(1); // start counter } return *this; } Ptr& operator=(const Ptr& other) { if(this != &other) { this->~Ptr(); _ptr = other._ptr; _counter = other._counter; if(_counter) ++(*_counter); } return *this; } bool isNull() const { return _ptr == NULL; } T& operator*() { return *_ptr; } const T* operator->() const { return _ptr; } T* operator->() { return _ptr; } operator T*() const { return _ptr; } private: T *_ptr; int *_counter; };Example usage:
struct When { int month; int day; }; Ptr<When> GetLunchTime() { Ptr<When> ret = new When(); // alloc pointer to be owned ret->month = 12; ret->day = 16; return ret; } int main() { Ptr<When> lunchTime = GetLunchTime(); // ... // no need to delete lunchTime return 0; }It works fine, but with the implementation of move semantics – which is truly great –, it seems that I don’t need it anymore. So I’m publishing it here for historical reasons.
Sunday, December 15, 2013
C++11 move semantics are amazing
Right now I’m testing Visual C++ 2013, which implements some interesting innovations from C++11 specification. I started taking a look at some of them, and the move semantics instantly caught my attention because they solve a problem I was just facing. I implemented a smart pointer class so that I could return a string object from a function – my own String class, I don’t use STL –, and it was something like this:
Now, with the new C++11 move semantics, when we write the constructor and the assignment operator for a class, we write specific code to use when receiving a temporary object, which will be destroyed right after the operation completes – it means we can do whathever we want with this temporary object, no one will bother. After implementing the move semantics on my String class, and on the underneath Array class which powers it, I could rewrite the above function like this:
Right now I feel I won’t even need my smart pointer class anymore, as I’ll refactor all my classes to take advantage of the move semantics: the implications are huge. This will result in a general optimization, saving several memory allocations all around. And that’s amazing. All right, call me a C++11 guy now, it has just got me, I’ve been converted.
Ptr<String> Function() { Ptr<String> ret = new String(); return ret; }This worked perfectly fine. What bugged me was that two more allocations are needed on this approach: the internal smart pointer instance counter, and the pointer itself. These two allocations, of course, are summed up to the internal String array allocation, so I ended up with three memory allocations for a trivial string return. That sounded too much to my optimization paranoia.
Now, with the new C++11 move semantics, when we write the constructor and the assignment operator for a class, we write specific code to use when receiving a temporary object, which will be destroyed right after the operation completes – it means we can do whathever we want with this temporary object, no one will bother. After implementing the move semantics on my String class, and on the underneath Array class which powers it, I could rewrite the above function like this:
String Function() { String ret; return ret; }My return object is allocated on the stack, not heap-allocated, so we have saved one allocation. And since I’m not returning a pointer – but rather returning the object my value – we don’t need the smart pointer anymore, so we saved another allocation. In the end, we shrinked down from three to only one single allocation, the internal string array itself. With the move semantics implemented, the internal string array just flies from an object into another, without cloning the whole array.
Right now I feel I won’t even need my smart pointer class anymore, as I’ll refactor all my classes to take advantage of the move semantics: the implications are huge. This will result in a general optimization, saving several memory allocations all around. And that’s amazing. All right, call me a C++11 guy now, it has just got me, I’ve been converted.
Subscribe to:
Posts (Atom)