Boy was I surprised when I saw this:
Looks like Munroe knows what he's doing when it comes to a-foolin'.
Well, Spring quarter has finally started up today. I'll miss the freedom of the break, but I'll be learning a lot more in class.
I'm really excited for me CSE 303 class, which is basically a "how to use Linux" class. Now I already know quite a lot about the subject (obviously), but I wish to learn a bit more. I have friends in both this course and CSE 321, so it'll likely be quite a bit of fun.
Although a fairly recent addition to my collection, 此処じゃない何処かへ (ここじゃないどこかへ, koko janai dokoka e, "Not Here, to Somewhere") has caught my interest. However, I don't like the chorus (which repeats the title), but much of the rest.
I've been riding buses regularly for years now, and I still enjoy it. When I started, I rode local routes and was interested in the express routes. However, I mainly ride express routes to UW and enjoy local routes more. It's gotten to the point that I associate certain experiences with certain songs in my collection, because I listen to music on the majority of these journeys.
My local authority, Community Transit, has many routes covering a large area of Snohomish County. Just today I rode the 270 to Gold Bar and the 280 to Granite Falls. I've found that I really like those mountain towns way out there.
Although I have been going to the Coyote Creek Cafe for years (ever since I started at Cascadia), but waited until today to post because I went today. The pizza is amazing: they use thick slices of pepperoni sliced into sectors, whole roasted garlic cloves, and the bases can be anything between red sauce, white sauce, olive oil, and pesto. Their calzones and appetizers are pretty good, too. One I really liked is a fried flatbread that comes with half a head of roasted garlic and a large slice of gorganzola.
I would really recommend trying this place out if you live in the Seattle area. I try to limit myself to once per month, since the food's a bit much to eat too often. By the way, I always go to the one in Kirkland; it's right next to the transit center.
Well, it looks like my laptop decided to stop working again. Since the last time it worked, I only put it in its case; nothing more. That thing's been extremely unreliable, with an MTBF of mere months. Because it keeps going down, I'm seriously considering buying a new one this Summer.
This would've potentially ruined my plans tomorrow, if my dad were right about the time the repair place opened. My parents weren't fazed by the potential of it ruining my plans, either.
I originally heard this song on her second singles collection. I only liked that version to an extent, and listened to it sparingly. However, this last Friday I bought an album of hers titled "10 WINGs," which has a much better version. That better version is why I've posted this.
What's sad is that this story is most likely true for the majority of us. What happened to the mystery in life?
We all know about Chuck Norris facts, but what about the facts of others, such as a few very influential minds:
I went to buy music at Kinokuniya today, and ended up getting two albums and a single (for the price of two albums, thanks to my VIP card). The single was particularly interesting, since it had something I hadn't expected: a new version of one of aiko's old songs (ひまわりになったら, himawari ni nattara, "If I become a Sunflower"). Unlike the original version, this one has flares in it as though it's more free-spirited than the original. Unfortunately, I can't find my recording of the original.
Here are some questions I'd like the answer to. By 'everyone', I mean people outside of my family and those who aren't good friends.
This was more of relieving stress, but it also checks to see if anyone actually reads my blog. I feel a bit better, at least.
I originally implemented this script in Bourne shell, but decided to do it up in Perl this time. It simply searches $PATH for any binary matching the pattern you pass to it, case-insensitively. Albeit simple, it's very useful, at least to me.
#!/usr/bin/perl -w
use strict;
use warnings;
scalar @ARGV || die "Usage: $0 match\n";
my $match = shift @ARGV;
my @PATH = split(/:/, $ENV{PATH});
foreach(@PATH) {
print "$_\n" foreach(grep(/$match/i, (/\s/ ? <"$_"/*> : <$_/*>)));
}
One of my favorite parts about Perl is that it's easy to write very efficient scripts that look confusing to many.
Here's a slightly better version that searches only the basename of each file:
#!/usr/bin/perl -w
use strict;
use warnings;
scalar @ARGV || die "Usage: $0 match\n";
my $match = shift @ARGV;
my @PATH = split(/:/, $ENV{PATH});
foreach(@PATH) {
print "$_\n" foreach(grep(/$match[^\/]*$/i, (/\s/ ? <"$_"/*> : <$_/*>)));
}
Although mentioned in the intro credits, few seem to realize that Disney's production of "The Fox and the Hound" is actually based upon a novel of the same name. The novel is darker than the movie (not surprising), and extends much further into Tod's life, including Tod fathering his kits, until both him and Copper end up shot by Copper's owner. Still, I'd like to see Disney continue with the plot, since their production seems open-ended. Yes, I do realize that Disney made a second movie, but it's more akin to some of their other productions, and in no way a continuation of the first.
I would really like a chance to read the actual book, and have put a hold on it at the local library.
Something I've noticed when I watch the movies from my youth is that my viewpoint is far different. I see things I never did when younger, and they spin interesting new perspective of the happenings in the movies.
My dreams have always interested me. Some are almost normal with parts that could never happen, and others take memories from my entire lifespan and are creative with them. I mainly enjoy sleep because of the adventures in my dreams.
It started off where I had entered a place (not sure if it was a country or not) which was run by children. In the dream, I was much older than I am now, but it seemed as though I had somehow traveled through time, as the last quarter on my UW ID surprised me. I was taken into custody for being an adult, and had to show photo ID to the officers there. Unfortunately, a long-term adult holding area (which ended up a locked-down high school gym) was my destination.
When there, I found a friend of mine, and she had somehow formed a relationships with the DragonBall Z character Vegeta, who was in the 'real' world as though he always had been. Otherwise, the camp (called an 'internment camp') was full of adults who had been there for far too long, many acting like cavemen (though still wearing moderately normal clothes). The only strange thing was that these two baby-esque muppet-like characters were watching a movie on a small TV, and if anyone got close, they'd be attacked.
The movie was similar to Disney's production of "The Fox and the Hound," with many differences as I watched while perching atop the bleachers above. The movie was darker, and followed a somewhat different plot, involving more human-esque pranks, with two major differences I can recall:
It was an interesting take on Disney's movie, and made me want to watch their production. It's fortunate that we have it on VHS, isn't it?
My life has been anything but homogeneous through the years. I can easily section it off into a few parts, with common themes within each one.
During this time, I was in elementary school and didn't really have anyone outside of my family and certain teachers. Despite this, I wasn't all-that-lonely, and made the best of it. During recess, for example, I'd try to spend my time in the classroom reading or drawing. During this time, I drew the most of all, with likely hundreds of creations. I learned how to draw a basic 3-D perspective in second grade.
Also during this time, I read many books about Science, and learned to love it, mainly between second and fifth grade. Since I didn't have any interest in sports, I was shunned by the others are was unable to make many friends; usually a couple at a time before something caused us to separate (usually out of my control). A common phrase I'd hear was "Neil germs, no returns."
This second part of my life started when I got my first cat, Sophie, who was only my cat in many respects. We also got broadband during the same Summer, which was just before I started junior high. This time was characterized by my first set of friends I saw often, and the times were good. I drew my first comic series, consisting of ten volumes. The basis was a never-ending story about Kirby, inspired and encouraged by my friends.
However, it wasn't meant to last. As more joined our group, there was dissonance from time to time, and I was eventually ejected (although I heard that they really weren't mad at me a while later). I fell into the first real depression of my life, when I realized I really was lonely after all those years. I spent lunch alone, and socialized with very few. Although, one person stands out from this time, I haven't seen her since the time towards the end of the Late Sophie Era.
I also gained my first interest in Linux and the BSDs during the mid-Early Sophie Era, which took up a large part of my life and still does to this day.
This time really started with high school, where I was alone and ate at random places over the campus. Some of my better friends were from my Math course, which was a year ahead of where I was intended to be initially (which I fixed over the previous Summer). Still, I don't remember much from this early period in the Late Sophie Era other than I was very involved with the Symphonic Band, and played Euphonium, Baritone, Trombone, and Bass Trombone. I also made tight friendships with others in low brass, which haven't lasted the test of time.
Then I started Running Start at the college, taking only third-year Japanese at the high school (I had studied and passed the second year final with a pretty good grade over the Summer). My time at Cascadia was great: I met a lot of new people who accepted me and shared my interests, learned a whole lot about many different subjects, and found out how much I really loved to learn. During my time there, I took the first year of Physics, Calculus, and Chemistry, along with a slew of other classes.
I celebrated my first real Pi Day during my last Winter quarter of Cascadia, which turned out to be the day of the Physics Open House, where I showed off my ballista. Since it was Pi Day, I also shared two pies with my comrades. During this time, I also devised Pi Man (long before my first Pi Day), who was the alter-ego of my Math teacher. We all took delight in a different Pi Man strip for each set of homework assignments turned in.
During my first year of Running Start, I also had my first romantic relationship. She was very intelligent, and we fit together fairly we (especially since we both enjoyed riding buses). It mainly ended because she left for college on the other side of the mountains, which isn't so easy to access without a car.
Although I had been using Linux/*BSD for a few years, I hadn't been much into programming until my first year of college. In the spare time between my arrival at the high school in the morning and my first class, I began to write small C programs to do various things. Ever since then, programming's been a huge part of my life.
The Sophie Era ended sadly, when while interning at Microsoft, Sophie ran out of the house. She lingered around for a while, but would never enter the house again. Despite putting up posters, we never got her back.
I missed my cat, but I eventually moved to finding a new companion. I picked Fiona up from the animal shelter, since she seemed very nice, and am glad I did. I still miss Sophie sometimes, though.
This started the Fiona Era, which continues to today. It started with the conclusion of my internship at Microsoft and starting at the University of Washington in Seattle. I commute, mainly because I love Fiona too much, and I enjoy buses anyway. I've found UW to not be as conducive to learning as Cascadia, but far better for research and a breadth of programs.
My first quarter came with meeting old friends again, and making new ones. The presence of Linux is far greater at UW than any other place I've seen, and I've found many to associate with. My first favorite class here was Special Relativity, in which I learned a whole lot about the topic, from time dilation in flat spacetime to the curvature of space by matter in General Relativity.
This past quarter is the most recent chapter in the Fiona Era. Although I didn't enjoy it as much due to not managing my time effectively, I still learned a lot on both the course-related and life-related fronts.
That's the basic summary of what I remember of my life. I can't comment much on it, since I've had to deal with it for so long.
It's an amazing amount of relief that the quarter's finally over. I didn't enjoy this one so much, mainly because of my work to play ratio being too high. At least I learned my lesson in the end.
With it all over, I'll be able to do what I want, which includes putting some more of my thoughts on here aside from programming and so on.
To say goodbye to those days, here's one of my favorite songs. It's one of the few I'd call "sparkly."
I'm sad to say, but there are no lyrics available online.
I'm not sure which is right, but Miyuki-Lab seems to conflict with Amazon Japan, LyricWiki.org, Goo Music, and wherever I grabbed the titles from when I ripped the CD. What's more, the song talks about both rain and hurting, so it's ambiguous.
In order to make it easier on myself, I'll stick with "PAIN" as I've been calling it.
Ah, it looks like I was mistaken. Although the songs RAIN and PAIN are strikingly similar, they aren't the same. Check out the lyrics.
They both share the repeated 「笑え雨よ 笑え雨よ」 and 「救いのない人の 愚かさを」. Now I'm interested.
After checking up on Amazon Japan, I found it to be on 夜会VOL.8 問う女, a night performance which is conveniently on DVD. However, the price tag is a bit high, so whether or not I get it will really depend on my reserves. Still, if you look at the list I linked to above, you'll see that both songs are back-to-back, which means their similarities are not coincidental in the least.
I've come across Miyuki-Lab, again. It's a great place to find the lyrics of 中島みゆき's songs, though you have to be careful on where to look in order to get them. Just like Goo's music databases, only the first listing of the song contains lyrics.
Free Walkin's a much more rock-ish song than many I've put up here so far. I bought my first Every Little Thing CD just for this song, and as it turns out it was a bonus track. Unfortunately, that also means no lyrics. Still, I really like this song.
坂本真綾's songs are a fairly recent addition to my collection, at least in CD form. I've been listening to her for years, and this song (シマシマ: shima shima) is what brought me to buying my first album of hers. Unlike much of my other music, it has a light feel, and its melodic nature can be soothing.
Although it may not be obvious, I'm a pretty big mass transit nerd, and have been since public education's school buses were my conveyance. The folks at the Seattle Transit Blog are a good source for pro-transit news in the tri-county area. I check up on it regularly.
On a side note, they have some pretty cool photos, too.
アイツを振り向かせる方法 (アイツをふりむかせるほうほう, aitsu wo furimukaseru houhou, "How to get Them to Face You") is one of my favorite songs of all time. The jazzy feel is unmatched by most other songs I have, despite the instruments not sounding as good as some others. Finding it was a real challenge, since it's on a MAXI single, which can only be bought from third-parties (such as Amazon's sellers).
命のリレー (いのちのリレー, inochi no riree, "Relay of Life") is a song I didn't initially like so much. My first hearing was of the one on the single, and it lacked the power I liked. However, the version on the album suited me a whole lot more, and shows that 6/8 timing can work in rock music as much as 4/4 can.
This (歌姫:うたひめ, utahime, "Song Princess") song was one of the first of hers that I found on YouTube, years ago. However, I had the song at least a year before then, but didn't appreciate it until I saw its PV. It's a beautiful song as well, though not as heavy in strings as PAIN.
Considering this song is on いまのきもち, there must've been an older version of it somewhere. After a little reserch, I found it on 寒水魚. It's a bit odd, that since Amazon's been listing the dates of these CDs as 2001, her recording company must be reproducing the older CDs. That would explain the availability of her original singles collection, although that was reproduced in 1994 (same time as her second one).
PAIN is one of the most beautiful songs I've ever heard. The arrangement is amazing, and is the most heavy in string instruments I've heard for a long time.
You know how certain programs may work for the longest time, but only fail once someone else uses them? Jabberd2's done that to me. It was on my server for months, giving me good service until a friend of mine tried to log into his Jabber account after months of not doing so. Since then, it segfaults at startup. Well, the router part does, anyway.
sx (io.c:234) decoded read data (71 bytes):
>>> NAD OP nad_new: 0xc832be10
>>> NAD OP nad_add_namespace: 0xc832be10
>>> NAD OP nad_find_scoped_namespace: 0xc832be10
>>> NAD OP nad_add_namespace: 0xc832be10
>>> NAD OP nad_find_scoped_namespace: 0xc832be10
>>> NAD OP nad_append_elem: 0xc832be10
>>> NAD OP nad_append_attr: 0xc832be10
>>> NAD OP nad_print: 0xc832be10
sx (io.c:89) completed nad:
sx (chain.c:119) calling nad read chain
>>> NAD OP nad_find_attr: 0xc832be10
sx (sasl_gsasl.c:291) auth request from client (mechanism=DIGEST-MD5)
sx (sasl_gsasl.c:334) sasl context initialised for 9
Program received signal SIGSEGV, Segmentation fault.
0x00002d46e72f1715 in ?? ()
(gdb) where
#0 0x00002d46e72f1715 in ?? ()
#1 0x0000000000000001 in ?? ()
#2 0x000004f5c81db5ad in ?? ()
#3 0x0000000000000008 in ?? ()
#4 0x000004f5c832bf10 in ?? ()
#5 0x00000071ffffffff in ?? ()
#6 0x000004f500000000 in ?? ()
#7 0x0000000000000000 in ?? ()
Changing CFLAGS/CXXFLAGS has no bearing on this. It looks like I'll finally get around to finding the problem in the code today, though.
It looks like I've located the problem, finally. I've modified their code to print lots of stuff:
puts("ANONYMOUS");
/*
* special case for SASL ANONYMOUS: ignore the initial
* response provided by the client and generate a random
* authzid for the user, as specified in XEP-0175
*/
(ctx->cb)(sx_sasl_cb_GEN_AUTHZID, NULL, (void **)&out, s, ctx->cbarg);
buf = strdup(out);
buflen = strlen(buf);
} else {
puts("NON-ANON");
/* decode and process */
_sx_sasl_decode(in, inlen, &buf, &buflen);
puts(buf);
puts("SASL_DECODE");
}
ret = gsasl_step(sd, buf, buflen, &out, (size_t *) &outlen);
puts("GSASL_STEP");
if(ret != GSASL_OK && ret != GSASL_NEEDS_MORE) {
puts("NOT NEEDS MORE");
_sx_debug(ZONE, "gsasl_step failed, no sasl for this conn; (%d): %s", ret, gsasl_strerror(ret));
_sx_nad_write(s, _sx_sasl_failure(s, _sasl_err_MALFORMED_REQUEST), 0);
puts("STARTFREE");
if(out != NULL) free(out);
if(buf != NULL) free(buf);
puts("ENDFREE");
return;
}
}
else {
/* decode and process */
_sx_sasl_decode(in, inlen, &buf, &buflen);
if(!sd) {
_sx_debug(ZONE, "response send before auth request enabling mechanism (decoded: %.*s)", buflen, buf);
_sx_nad_write(s, _sx_sasl_failure(s, _sasl_err_MECH_TOO_WEAK), 0);
if(buf != NULL) free(buf);
return;
}
_sx_debug(ZONE, "response from client (decoded: %.*s)", buflen, buf);
ret = gsasl_step(sd, buf, buflen, &out, (size_t *) &outlen);
}
puts("0:FREE BUF");
if(buf != NULL) free(buf);
puts("0:FREED BUFF");
/* auth completed */
if(ret == GSASL_OK) {
puts("GSASL_OK");
_sx_debug(ZONE, "sasl handshake completed");
puts("FREE OUT");
if(out != NULL) free(out);
puts("FREED OUT");
/* send success */
puts("SUCCESS!");
_sx_nad_write(s, _sx_sasl_success(s), 0);
sx (io.c:234) decoded read data (71 bytes):
sx (io.c:89) completed nad:
sx (chain.c:119) calling nad read chain
sx (sasl_gsasl.c:291) auth request from client (mechanism=DIGEST-MD5)
sx (sasl_gsasl.c:334) sasl context initialised for 6
SASL CONTEXT INIT
VOID SD
NON-ANON
SASL_DECODE
GSASL_STEP
0:FREE BUF
Program received signal SIGSEGV, Segmentation fault.
0x000031b7b4783715 in ?? ()
It looks like it's trying to free() memory it can't, but I've only seen "invalid double free()" in situations like this, so something else must also be at work. I've checked the beginning of their function, and they do initialize the pointers to NULL.
Poking around a bit more, I've removed the free()-related stuff, and get this in the resolver, rather than the router:
sx (io.c:210) passed 216 read bytes
sx (chain.c:93) calling io read chain
sx (io.c:234) decoded read data (216 bytes): cmVhbG09ImphYmJlcmQtcm91dGVyIiwgbm9uY2U9IkVnWGtwVTVaQ1pyZkpQNDhUUGtqYUE9PSIsIHFvcD0iYXV0aCwgYXV0aC1pbnQiLCBjaGFyc2V0PXV0Zi04LCBhbGdvcml0aG09bWQ1LXNlc3M=
sx (io.c:89) completed nad: cmVhbG09ImphYmJlcmQtcm91dGVyIiwgbm9uY2U9IkVnWGtwVTVaQ1pyZkpQNDhUUGtqYUE9PSIsIHFvcD0iYXV0aCwgYXV0aC1pbnQiLCBjaGFyc2V0PXV0Zi04LCBhbGdvcml0aG09bWQ1LXNlc3M=
sx (chain.c:119) calling nad read chain
sx (sasl_gsasl.c:448) data from client
sx (sasl_gsasl.c:452) decoded data: realm="jabberd-router", nonce="EgXkpU5ZCZrfJP48TPkjaA==", qop="auth, auth-int", charset=utf-8, algorithm=md5-sess
Program received signal SIGSEGV, Segmentation fault.
0x000039405831632b in ?? ()
Looking into that a bit more, I've added some more lines to the code.
}
/** process handshake packets from the server */
static void _sx_sasl_server_process(sx_t s, sx_plugin_t p, Gsasl_session *sd, char *in, int inlen) {
char *buf, *out;
int buflen, outlen, ret;
_sx_debug(ZONE, "data from client");
/* decode the response */
puts("DECODE");
_sx_sasl_decode(in, inlen, &buf, &buflen);
_sx_debug(ZONE, "decoded data: %.*s", buflen, buf);
puts("COMPLETE");
/* process the data */
puts("GSASL STEP");
ret = gsasl_step(sd, buf, buflen, &out, (size_t *) &outlen);
puts("0: FREE BUF");
if(buf != NULL) {
free(buf);
buf = NULL;
}
puts("0: FREED BUF");
/* in progress */
if(ret == GSASL_OK || ret == GSASL_NEEDS_MORE) {
puts("OK OR NEEDS MORE");
_sx_debug(ZONE, "sasl handshake in progress (response: %.*s)", outlen, out);
/* encode the response */
puts("ENCODE");
_sx_sasl_encode(out, outlen, &buf, &buflen);
puts("COMPLETE");
puts("1: FREE OUT");
if(out != NULL) free(out);
puts("1: FREED OUT");
_sx_nad_write(s, _sx_sasl_response(s, buf, buflen), 0);
puts("1: FREE BUF");
if(buf != NULL) free(buf);
puts("2: FREE BUF");
return;
}
puts("2: FREE OUT");
if(out != NULL) free(out);
puts("2: FREED OUT");
/* its over */
puts("ABORT!");
_sx_debug(ZONE, "sasl handshake aborted; (%d): %s", ret, gsasl_strerror(ret));
_sx_nad_write(s, _sx_sasl_abort(s), 0);
}
/** main nad processor */
It doesn't look good, as gsasl_step() fails here.
sx (io.c:89) completed nad: cmVhbG09ImphYmJlcmQtcm91dGVyIiwgbm9uY2U9IlgyQUdiVFpvaFdFQi9xV2tNeVNyS3c9PSIsIHFvcD0iYXV0aCwgYXV0aC1pbnQiLCBjaGFyc2V0PXV0Zi04LCBhbGdvcml0aG09bWQ1LXNlc3M=
sx (chain.c:119) calling nad read chain
sx (sasl_gsasl.c:448) data from client
DECODE
sx (sasl_gsasl.c:453) decoded data: realm="jabberd-router", nonce="X2AGbTZohWEB/qWkMySrKw==", qop="auth, auth-int", charset=utf-8, algorithm=md5-sess
COMPLETE
GSASL STEP
Program received signal SIGSEGV, Segmentation fault.
0x000035dc3dbbd32b in ?? ()
I'm going to try removing gSASL and switch back to Cyrus. As far as I can tell, that'll require a lot of ebuild tweaks.
My assumption was incorrect: I've been using gSASL since before it stopped working, and Cyrus isn't supported. It looks like I won't have a Jabberd on my server anytime soon. Even Ejabberd fails to work properly.
Before I started listening mainly to 中島みゆき, I really enjoyed aiko's music. Even now, songs such as this (ジェット: jet) still bring much enjoyment.
I thought I should at least have one photo of my beloved cat on here. Her name's Fiona, and we got her after Sophie (my previous cat for six years) ran away. Unlike Sophie, Fiona's a very wild cat, and goes nuts when I use this special bird-like lure. Like Sophie, she's a sweetheart and I don't know what I'd do with her (I still miss Sophie sometimes). She has this effect on me.
This song (akaikutsu, "Red Shoes") has been in my collection for over five years, predating many of them, and definitely predating my practice of purchasing the CDs. A few months ago, however, I did decide to purchase the CD which contains it (PURE).
Due to the obscurity of this artist, I can't find any lyrics for her songs.
These are a few of the more interesting scripts I use to organize my RockBox iPod. They're all located on the iPod, too, so it makes use of Perl's cross-platform aspects. In terms of actual use, these are some of my most-successful scripts.
This script splits a large playlist into smaller parts, named after the artist of the tracks in the playlist. Due to some of my collection having corrupt tags, it output a lot of errors when actually running, but redirecting stdout preserved the useful lines (if I recall correctly).
#!/usr/bin/perl -w
use strict;
use utf8;
use MP3::Tag;
use Ogg::Vorbis::Header::PurePerl;
use Audio::FLAC::Header;
scalar @ARGV >= 2 || die "Usage: $0 source.m3u rootdir/\n";
my %artists;
my ($infile, $rootdir) = (shift @ARGV, shift @ARGV);
open(FILE, "<$infile");
my @lines = <FILE>;
chop(@lines);
close(FILE);
foreach my $file (@lines) {
my %data;
if($file =~ /\.ogg$/i) {
%data = ogginfo("$rootdir/$file");
$data{filename} = $file;
}
elsif($file =~ /\.mp3/i) {
%data = mp3info("$rootdir/$file");
$data{filename} = $file;
}
elsif($file =~ /\.flac/i) {
%data = flacinfo("$rootdir/$file");
$data{filename} = $file;
}
else {
print "Unknown file type: $file\n";
}
if(!$data{artist}) {
defined $artists{uncategorized} and push(@{$artists{uncategorized}}, $file) or ($artists{uncategorized} = [ $file ]);
}
else {
defined $artists{$data{artist}} and push(@{$artists{$data{artist}}}, $file) or ($artists{$data{artist}} = [ $file ]);
}
}
mkdir('Artists');
foreach my $artist (keys %artists) {
open(FILE, ">Artists/$artist.m3u");
print FILE "$_\n" foreach(@{$artists{$artist}});
close(FILE);
}
sub mp3info {
my $mp3file = shift;
my $mp3 = MP3::Tag->new($mp3file);
my %data;
defined $mp3 || return %data;
$mp3->get_tags();
if(defined $mp3) {
if(exists $mp3->{ID3v2}) {
$data{filename} = $mp3file;
$data{artist} = $mp3->{ID3v2}->artist;
$data{title} = $mp3->{ID3v2}->title;
$data{album} = $mp3->{ID3v2}->album;
$data{genre} = $mp3->{ID3v2}->genre;
}
elsif(exists $mp3->{ID3v1}) {
$data{filename} = $mp3file;
$data{artist} = $mp3->{ID3v1}->artist;
$data{title} = $mp3->{ID3v1}->title;
$data{album} = $mp3->{ID3v1}->album;
$data{genre} = $mp3->{ID3v1}->genre;
}
}
return %data;
}
sub flacinfo {
my $flacfile = shift;
my %data;
my $flac = Audio::FLAC::Header->new($flacfile);
my %tags = %{$flac->tags()};
if(scalar %tags) {
$data{filename} = $flacfile;
$data{artist} = $tags{ARTIST};
$data{title} = $tags{TITLE};
$data{album} = $tags{ALBUM};
$data{genre} = $tags{GENRE};
}
return %data;
}
sub ogginfo {
my $oggfile = shift;
my $ogg = Ogg::Vorbis::Header::PurePerl->new($oggfile);
my %data;
if(defined $ogg) {
$data{filename} = $oggfile;
$data{artist} = '';
$data{title} = '';
$data{album} = '';
$data{genre} = '';
foreach my $t($ogg->comment("ARTIST")) {
$data{artist} = $t;
}
foreach my $t($ogg->comment("TITLE")) {
$data{title} = $t;
}
foreach my $t($ogg->comment("ALBUM")) {
$data{album} = $t;
}
foreach my $t($ogg->comment("GENRE")) {
$data{genre} = $t;
}
}
return %data;
}
The multi-album version of my playlist-sorting script. The original sort script isn't very interesting.
#!/usr/bin/perl -w
use strict;
use utf8;
use File::Basename;
my $sortmode = 'normal';
scalar @ARGV || die "Usage: $0 [ sortmode ] playlist\n";
my $pls;
if(scalar @ARGV > 1) {
($sortmode, $pls) = @ARGV;
$sortmode eq 'normal' || $sortmode eq 'collated' || ($sortmode = 'normal');
}
else {
$pls = shift @ARGV;
}
-e $pls || die "No such file: $pls\n";
open(FILE, "<$pls") || die "Unable to open file\n";
my @lines = <FILE>;
chop(@lines);
close(FILE);
my %sorted;
foreach my $line(@lines) {
my $file = basename($line);
my $album = basename(dirname($line));
($sorted{$album} = { }) if(!$sorted{$album});
$file =~ /^([0-9]+) -/;
${$sorted{$album}}{$1} = $line;
}
open(FILE, ">$pls") || die "Unable to open file";
if($sortmode eq 'normal') {
foreach(sort keys %sorted) {
my $rsubsorted = $sorted{$_};
if($rsubsorted) {
my %subsorted = %{$rsubsorted};
foreach my $key(sort keys %subsorted) {
print FILE "$subsorted{$key}\n" || die "Unable to write to file\n";
}
}
}
}
elsif($sortmode eq 'collated') {
my $maxlen = 0;
foreach(keys %sorted) {
my $rsubsorted = $sorted{$_};
if($rsubsorted) {
my $len = scalar keys(%{$rsubsorted});
$len > $maxlen && ($maxlen = $len);
}
}
for(my $i = 1; $i <= $maxlen; $i++) {
foreach(keys %sorted) {
my $rsubsorted = $sorted{$_};
if($rsubsorted) {
my %subsorted = %{$rsubsorted};
my $str = sprintf('%02d', $i);
$subsorted{$str} && (print FILE "$subsorted{$str}\n" || die "Unable to write to file\n");
}
}
}
}
close(FILE);
A script to check the existence of each file in the playlist, then suggest fixes based on similar album tracks. The plain checking script isn't very interesting, either.
#!/usr/bin/perl
use strict;
scalar @ARGV|| die "Usage: $0 m3ufile\n";
my $pls = shift @ARGV;
open(FILE, "<$pls");
my @files = <FILE>;
close(FILE);
chomp(@files);
my $len = scalar @files;
for(my $q = 0; $q < $len; $q++) {
my $file = $files[$q];
my $realfile = "/mnt/ipod/$file";
if(!-e "$realfile") {
print "NOT FOUND: $realfile\n";
if($file =~ /^(\/Music\/[^\/]+)\/([0-9]+)[ -]+(.*)\.(flac|ogg)/) {
my ($realdir, $track, $title, $ext) = ("/mnt/ipod/$1", $2, $3, $4);
if(-e "$realdir") {
my @found;
if($realdir =~ /\s/) {
@found = <"$realdir"/$track*>;
}
else {
@found = <$realdir/$track*>;
}
if(scalar @found) {
print "Closes matches are:\n";
my $slen = scalar @found;
for(my $i = 1; $i <= $slen; $i++) {
print "\t$i: " . $found[$i - 1] . "\n";
}
my $good = 0;
my $ans = 1;
do {
$good = 0;
print "Invalid number\n" if($ans > $slen);
print 'Replace with # (0 to skip):';
my $ans = <>;
$good = 1 if($ans > 0);
} while($ans > $slen);
if($good) {
my $foo = $found[$ans - 1];
$foo =~ s/^\/mnt\/ipod\///;
$files[$q] = $foo;
}
else {
print "Skipping\n";
}
}
else {
print "No matches found; skipping\n";
}
}
else {
print "No such directory: $realdir\n";
}
}
else {
print "Unable to repair\n";
}
}
}
open(FILE, ">$pls");
print FILE "$_\n" foreach(@files);
close(FILE);