LinuxQuestions.org
Register a domain and help support LQ
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices



Reply
 
Search this Thread
Old 12-27-2005, 10:33 AM   #1
scuzzman
Senior Member
 
Registered: May 2004
Location: Hilliard, Ohio, USA
Distribution: Slackware, Kubuntu
Posts: 1,851

Rep: Reputation: 47
Can't call method "title" on undefined title in Perl script


I'm writing a short Perl script to rename a directory full of MP3 files and re-write some of their ID3 tags using the MP3::Tag module, but I'm having some trouble with it. Whenever I try to run it, I get this error:
Code:
[scuzzy@slackdell /home/scuzzy/music/young_jeezy/unknown_disc]$ ~/fixid3.pl 
Will every file in this directory have the same album and artist header (y/n)? y
What is the title of the album? Thug Motivation 101

Who is the artist? Young Jeezy

Filename: track_01.mp3
What is the track name? Go Crazy - Remix
Can't call method "title" on an undefined value at /home/scuzzy/fixid3.pl line 51, <STDIN> line 4.
This is the Perl script I'm running:
Code:
#!/usr/bin/perl
# fixid3.pl - Perl script to write MP3 ID3 tags to files
# Fields are title, ARTIST, ALBUM, YEAR, COMMENT, GENRE

# load the ID3 module
use MP3::Tag;

# get the filesname(s)
# We'll just use all files in the directory:
@filenames = <*.mp3>; # This glob gets all mp3 files in current dir

print "Will every file in this directory have the same ";
print "album and artist header (y/n)? ";
chomp ( $same_album_artist = <STDIN> );
if ( $same_album_artist == "y" ) {
  print "What is the title of the album? ";
  chomp ( $album = <STDIN> );
  print "\n";
  print "Who is the artist? ";
  chomp ( $artist = <STDIN> );
  print "\n";
  foreach (@filenames) { # since the album and artist are the same, just change song titles
    print "Filename: $_\n";
    $file = $_;
    &fix_id3($album, $artist, $file);
  }
} elsif ($same_album_artist == "n") {
  foreach (@filenames) { # ask album and artist on each song
    print "Filename: $_\n";
    $file = $_;
    print "What is the title of the album? ";
    chomp ( $album = <STDIN> );
    print "\n";
    print "Who is the artist? ";
    chomp ( $artist = <STDIN> );
    print "\n";
    &fix_id3($album, $artist, $file);
  }
} else {
  die "Unrecognized entry.\n";
}

sub fix_id3 {
# Here's where the magic is done
  $album = $_[0];
  $artist = $_[1];
  $file = $_[2];
  print "What is the track name? ";
  chomp ( $title = <STDIN> );
  $mp3 = MP3::Tag->new($file); # Creates new object
  $mp3->{ID3v1}->title("$title"); # adds element title
  $mp3->{ID3v1}->artist("$artist"); # adds element artist
  $mp3->{ID3v1}->album("$album"); # adds element album
  $mp3->{ID3v1}->write_tag(); # writes the tags
  $mp3->close(); # close the file
  # we'll also rename the files
  $oldname = "\"$file\"";
  $newname = "\"$artist - ${title}.mp3\"";
  rename $oldname, $newname;

  print "\n";
}
Is there anything I can do to figure out why this is detecting an undefined value, even though everything should be properly defined?
Edit: I have just tried it with and without the quotes on these lines (in red) and yielded the same results:
Quote:
$mp3->{ID3v1}->title("$title"); # adds element title
$mp3->{ID3v1}->artist("$artist"); # adds element artist
$mp3->{ID3v1}->album("$album"); # adds element album

Last edited by scuzzman; 12-27-2005 at 11:09 AM.
 
Old 12-27-2005, 12:03 PM   #2
wrj
Member
 
Registered: Aug 2003
Location: Canada/US
Distribution: Ubuntu, Arch
Posts: 84

Rep: Reputation: 15
The error you're getting means that you are trying to call your methods (title being the first one) on an undefined object. I don't think you can access ID3v1 methods like that. You need to use the get_tags() method first to fetch all the tags the mp3 object has access to and then call it directly via the MP3::Tag::ID3v1

I think it will work if you add this after your new() call:

$mp3->get_tags();

unless (exists $mp3->{ID3v1}) {
# handle error ...
}

$id3v1 = $mp3->{ID3v1};
$id3v1->title($title);


Hope that helps
 
Old 12-27-2005, 01:15 PM   #3
scuzzman
Senior Member
 
Registered: May 2004
Location: Hilliard, Ohio, USA
Distribution: Slackware, Kubuntu
Posts: 1,851

Original Poster
Rep: Reputation: 47
It's still not working, but now I at least have a clue why. This is the new segment of code:
Code:
  $mp3 = MP3::Tag->new($file); # Creates new object
  $mp3 -> get_tags();
  unless (exists $mp3->{ID3v1}) {
    die "Unable to read ID3 tags from file.\n";
  }
  $id3v1 = $mp3 -> {ID3V1};
  $id3v1 -> title( "$title" ); # adds element title
These are the errors from the console:
Code:
[scuzzy@slackdell /home/scuzzy/music/young_jeezy/unknown_disc]$ ~/fixid3.pl 
Will every file in this directory have the same album and artist header (y/n)? y
What is the title of the album? Thug Motivation 101

Who is the artist? Young Jeezy

Filename: track_01.mp3
What is the track name? Go Crazy - Remix
Unable to read ID3 tags from file.
But what could be causing it to be unable to read the ID3 tags? Perhaps because they do not yet exist? If that's the case, then why can I not write them (to make them exist)?
 
Old 12-27-2005, 01:37 PM   #4
wrj
Member
 
Registered: Aug 2003
Location: Canada/US
Distribution: Ubuntu, Arch
Posts: 84

Rep: Reputation: 15
Hmm ... how about dumping out the result of get_tags() and see what we actually get.

Code:
# add this to the top of your code
use Data::Dumper;

# add this somewhere in your function
$tags = [];
$tags = $mp3->get_tags;
print Dumper($tags)
Let me know what tags are available for your file.
 
Old 12-27-2005, 02:40 PM   #5
scuzzman
Senior Member
 
Registered: May 2004
Location: Hilliard, Ohio, USA
Distribution: Slackware, Kubuntu
Posts: 1,851

Original Poster
Rep: Reputation: 47
OK - This is the current code snippet:
Code:
  print "What is the track name? ";
  chomp ( $title = <STDIN> );
  $mp3 = MP3::Tag->new($file); # Creates new object
  ##ADDED DEBUG
  $tags = [];
  $tags = $mp3->get_tags;
  print Dumper($tags);
  ##END DEBUG
  $mp3 -> get_tags();
  unless (exists $mp3->{ID3v1}) {
    die "Unable to read ID3 tags from file.\n";
  }
And this is the output:
Code:
[scuzzy@slackdell /home/scuzzy/music/young_jeezy/unknown_disc]$ ~/fixid3.pl             
Will every file in this directory have the same album and artist header (y/n)? y
What is the title of the album? Thug Motivation 101

Who is the artist? Young Jeezy

Filename: track_01.mp3
What is the track name? Go Crazy - Remix
$VAR1 = 2;
Unable to read ID3 tags from file.
[scuzzy@slackdell /home/scuzzy/music/young_jeezy/unknown_disc]$
 
Old 12-27-2005, 04:07 PM   #6
wrj
Member
 
Registered: Aug 2003
Location: Canada/US
Distribution: Ubuntu, Arch
Posts: 84

Rep: Reputation: 15
Sorry I didn't realize get_tags just returns a list of strings.

Pleasse try the code snippet below and look at my comments for an explanation.

Code:
# wrap the object constructor call in an eval to 
# make sure we catch any weird errors and object was 
# created ok

eval {
  $mp3 = MP3::Tag->new($file);    # Creates new object
};

# make sure object was created ok
if ($@) {
  die qq{Error crating MP3 object, $@};
}

print qq{ MP3 Object created ok\n.};

# fetch list of tags
@tags = $mp3->get_tags();
print qq{tags\n}, Dumper(\@tags);

# no need to call get_tags again ...

# make sure ID3v1 is one ofthe choices on the list
# also make sure you have a little v not ID3V1 ... I
# know that's silly but I saw it in one off your earlier 
# posts.

unless ( exists $mp3->{ID3v1} ) {
  die "Unable to read ID3 tags from file.\n";
}

$id3v1 = $mp3->{ID3v1};

# ready to set element title ... the double quotes should 
# really be omitted since you are passing a variable not a 
# straight string ... but it may not make a diff 
$id3v1->title("$title");        # adds element title
Pardon me for any syntax errors, I don't have a computer I can test this on. Let me know how it works out.
 
Old 12-27-2005, 08:52 PM   #7
scuzzman
Senior Member
 
Registered: May 2004
Location: Hilliard, Ohio, USA
Distribution: Slackware, Kubuntu
Posts: 1,851

Original Poster
Rep: Reputation: 47
Still not working... I'm pretty sure I understand most of the code, and it looks as though it should function (when the Dump is removed that is...). This is the current fix_id3 subroutine:
Code:
sub fix_id3 {
  # Here's where the magic is done
  $album = $_[0];
  $artist = $_[1];
  $file = $_[2];
  print "What is the track name? ";
  chomp ( $title = <STDIN> );
  # wrap the object constructor call in an eval to 
  # make sure we catch any weird errors and object was 
  # created ok
  eval {
    $mp3 = MP3::Tag->new($file);    # Creates new object
  };
  # make sure object was created ok
  if ($@) {
    die qq{Error crating MP3 object, $@};
  }
  print qq{ MP3 Object created ok.\n};
  # fetch list of tags
  @tags = $mp3->get_tags();
  print qq{tags\n}, Dumper(\@tags);

  unless ( exists $mp3->{ID3v1} ) {
    die "Unable to read ID3 tags from file.\n";
  }
  $id3v1 = $mp3->{ID3v1};
  # ready to set element title ... the double quotes should 
  # really be omitted since you are passing a variable not a 
  # straight string ... but it may not make a diff 
  $id3v1->title("$title");        # adds element title
  $id3v1 -> artist( "$artist" ); # adds element artist
  $id3v1 -> album( "$album" ); # adds element album
  $id3v1 -> write_tag(); # writes the tags
  $mp3->close(); # close the file
  # we'll also rename the files
  $oldname = "$file";
  $newname = "$artist_-_${title}.mp3";
  rename $oldname, $newname;

  print "\n";
}
And this is the output from the console:
Code:
[scuzzy@slackdell /home/scuzzy/music/young_jeezy/unknown_disc]$ ~/fixid3.pl 
Will every file in this directory have the same album and artist header (y/n)? y
What is the title of the album? Thug Motivation 101

Who is the artist? Young Jeezy

Filename: track_01.mp3
What is the track name? Go Crazy - Remix
 MP3 Object created ok
.tags
$VAR1 = [
          'ParseData',
          'LastResort'
        ];
Unable to read ID3 tags from file.
[scuzzy@slackdell /home/scuzzy/music/young_jeezy/unknown_disc]$
Although, I don't understand the use of 'qq' - is that kind of like 'qw'?

Last edited by scuzzman; 12-27-2005 at 08:53 PM.
 
Old 12-27-2005, 09:22 PM   #8
wrj
Member
 
Registered: Aug 2003
Location: Canada/US
Distribution: Ubuntu, Arch
Posts: 84

Rep: Reputation: 15
qq is double quotes. The difference is that qq will interpret any variables for you unlike q.

For some reason the file you're using only has 'ParseData' and 'LastResort' available.
That's why any references to $mp3->{ID3v1} are undefined.

I copied the script and ran it on my computer with one of my mp3 files and it worked.

This is the output:
Code:
(host: waldemar)  (user: waldemar)  (time= 21:09:06)
 > ~ $ ./test.pl
Will every file in this directory have the same album and artist header (y/n)? yWhat is the title of the album? foo

Who is the artist? bar

Filename: bignic.mp3
What is the track name? baz
 MP3 Object created ok
.tags
$VAR1 = [
          'ParseData',
          'ID3v2',
          'ID3v1',
          'LastResort'
        ];
done!
I didn't change anything else so the only difference is the file being used. I don't know much about mp3's so I don't know why only those 2 tags are limited for your mp3-object-file. Maybe you can try and find out why your mp3 file doesn't have ID3v1? I looked over the perldoc briefly and it looks like ID3v1 and ID3v2 are the only ones that support reading and writing. You might be able to just create those tags.

From the perldoc
Code:
# create a new tag
$mp3->new_tag("ID3v2");
$mp3->{ID3v2}->add_frame("TALB", "Album title");
$mp3->{ID3v2}->write_tag
Let me know
 
Old 12-27-2005, 09:54 PM   #9
scuzzman
Senior Member
 
Registered: May 2004
Location: Hilliard, Ohio, USA
Distribution: Slackware, Kubuntu
Posts: 1,851

Original Poster
Rep: Reputation: 47
I cannot thank you enough for you help And for once, I understand what was not working. Here is the fully working code:
Code:
#!/usr/bin/perl
# fixid3.pl - Perl script to write MP3 ID3 tags to files
# Fields are title, ARTIST, ALBUM, YEAR, COMMENT, GENRE

# load the ID3 module
use MP3::Tag;

# get the filename(s)
# We'll just use all files in the directory:
@filenames = <*.mp3>; # This glob gets all mp3 files in current dir

print "Will every file in this directory have the same ";
print "album and artist header (y/n)? ";
chomp ( $same_album_artist = <STDIN> );
if ( $same_album_artist == "y" ) {
  print "What is the title of the album? ";
  chomp ( $album = <STDIN> );
  print "\n";
  print "Who is the artist? ";
  chomp ( $artist = <STDIN> );
  print "\n";
  foreach (@filenames) { # since the album and artist are the same, just change song titles
    print "Filename: $_\n";
    $file = $_;
    &fix_id3($album, $artist, $file);
  }
} elsif ($same_album_artist == "n") {
  foreach (@filenames) { # ask album and artist on each song
    print "Filename: $_\n";
    $file = $_;
    print "What is the title of the album? ";
    chomp ( $album = <STDIN> );
    print "\n";
    print "Who is the artist? ";
    chomp ( $artist = <STDIN> );
    print "\n";
    &fix_id3($album, $artist, $file);
  }
} else {
  die "Unrecognized entry.\n";
}

sub fix_id3 {
  # Here's where the magic is done
  $album = $_[0];
  $artist = $_[1];
  $file = $_[2];
  print "What is the track name? ";
  chomp ( $title = <STDIN> );
  # wrap the object constructor call in an eval to 
  # make sure we catch any weird errors and object was 
  # created ok
  eval {
    $mp3 = MP3::Tag->new($file);    # Creates new object
  };
  # Make sure the object was created OK
  if ($@) {
    die qq{Error creating MP3 object, $@}; # if not, die and tell us why
  }
  unless ( exists $mp3->{ID3v1} ) { # assure ID3v1 is a valid option
    $mp3 -> new_tag("ID3v1");
    $mp3 -> {ID3v1}->write_tag; # otherwise, create it
  }
  $mp3 -> {ID3v1} -> title("$title"); # adds element title
  $mp3 -> {ID3v1} -> artist("$artist"); # adds element artist
  $mp3 -> {ID3v1} -> album("$album"); # adds element album
  $mp3 -> {ID3v1} -> write_tag(); # writes the tags
  $mp3 -> close(); # close the file
  # we'll also rename the files
  $oldname = "$file";
  $newname = "${artist} - ${title}.mp3";
  rename $oldname, $newname;

  print "\n";
}
I think the problem was that all along the MP3 I was manipulating did not have any ID3 information - it simply needed the tags written
BTW: The extra variables $id3v1 and @tags were not needed - I've removed them. The code above works exactly as planned

Last edited by scuzzman; 12-27-2005 at 09:55 PM.
 
Old 12-30-2005, 04:53 AM   #10
scuzzman
Senior Member
 
Registered: May 2004
Location: Hilliard, Ohio, USA
Distribution: Slackware, Kubuntu
Posts: 1,851

Original Poster
Rep: Reputation: 47
As this is a learning exercise, I've been slowly adding more and more functionality to the script. Right now, I'm trying to add the functionality to verify the ID3's before rewriting them - but the function isn't running. This is the code:
Code:
#!/usr/bin/perl
# fixid3.pl - Perl script to verify and write MP3 ID3 tags to files
# Fields are TITLE, ARTIST, ALBUM, GENRE

# sub-routine definitions:
#  &get_id3: retrieves ID3 information from user
#  &show_id3: shows ID3 information to user and verifies accuracy
#  &fix_id3: sets ID3 tags based on user input

# load the ID3 module
use MP3::Tag;

# get the filename(s)
# We'll just use all files in the directory:
@filenames = <*.mp3>; # This glob gets all mp3 files in current dir

print "Will every file in this directory have the same ";
print "album and artist header (y/n)? ";
chomp ( $same_album_artist = <STDIN> );
print "Would you like to verify the ID3 information for each processed file? ";
chomp ( $verify = <STDIN> );
if ( $verify == "y" ) {
  $same_album_artist = "n"; # force this to no so it reveals and checks the information
}
if ( $same_album_artist == "y" ) {
  foreach (@filenames) {
    print "Filename: $_\n";
    $file = $_;
    my ( $artist , $album , $genre ) = &get_id3(); # get ID3 information from the user 
    &fix_id3($album, $artist, $genre, $file);
  }
} elsif ($same_album_artist == "n") {
  foreach (@filenames) { 
    print "Filename: $_\n";
    $file = $_;
    if ( ($verify == "y") && !(&show_id3($file)) ) {
      my ( $artist , $album , $genre ) = &get_id3();
      &fix_id3($album, $artist, $genre, $file);
    }
    if ( $verify == "n" ) {
     my ( $artist , $album , $genre ) = &get_id3();
     &fix_id3($album, $artist, $genre, $file);
    }
  }
} else {
  die "Unrecognized entry.\n";
}

sub get_id3 {
  print "What is the title of the album? ";
  chomp ( $album = <STDIN> ); # album name
  print "\n";
  print "Who is the artist? ";
  chomp ( $artist = <STDIN> ); # artist name
  print "\n";
  print "What is the Genre? ";
  chomp ( $genre = <STDIN> ); # music genre
  print "\n";
  @id3_tags = ($artist, $album, $genre); # load input into array for return
  return @id3_tags;  # return array
}

sub show_id3 {
  $file = $_[0];
  eval {
    $mp3 = MP3::Tag->new($file);    # Creates new object
  };
  # Make sure the object was created OK
  if ($@) {
    die qq{Error creating MP3 object, $@}; # if not, die and tell us why
  }
  unless ( exists $mp3->{ID3v1} ) { # assure ID3 tags exist
    print "No ID3 Information!\n"; # If no, exit sub with FALSE
    return 0;
  }
  print "Current ID3 Information:\n";
  print "Title: ";
  print $mp3 -> {ID3v1} -> title(); # retrieve title
  print "\n";
  print "Artist: ";
  print $mp3 -> {ID3v1} -> artist(); # retrieve artist
  print "\n";
  print "Album: ";
  print $mp3 -> {ID3v1} -> album(); # retrieve album
  print "\n";
  print "Genre: ";
  print $mp3 -> {ID3v1} -> genre(); # retrieve genre
  print "\n";
  print "Is this information correct (y/n)? ";
  chomp ( $correct = <STDIN> );
  if ($correct == "y") {
    return 1; # return true - information correct, skip file
  } elsif ($correct == "n") {
    return 0; # return false and rewrite data
  } else {
    die qq{Incorrect Input!\n};
  }
  print "\n";
}

sub fix_id3 {
  # Here's where the magic is done
  $album = $_[0];
  $artist = $_[1];
  $genre = $_[2];
  $file = $_[3];
  print "What is the track name? ";
  chomp ( $title = <STDIN> );
  # wrap the object constructor call in an eval to 
  # make sure we catch any weird errors and object was 
  # created ok
  eval {
    $mp3 = MP3::Tag->new($file);    # Creates new object
  };
  # Make sure the object was created OK
  if ($@) {
    die qq{Error creating MP3 object, $@}; # if not, die and tell us why
  }
  unless ( exists $mp3->{ID3v1} ) { # assure ID3v1 is a valid option
    $mp3 -> new_tag("ID3v1");
    $mp3 -> {ID3v1}->write_tag; # otherwise, create it
  }
  $mp3 -> {ID3v1} -> title("$title"); # adds element title
  $mp3 -> {ID3v1} -> artist("$artist"); # adds element artist
  $mp3 -> {ID3v1} -> album("$album"); # adds element album
  $mp3 -> {ID3v1} -> genre("$genre"); # adds element genre
  $mp3 -> {ID3v1} -> write_tag(); # writes the tags
  $mp3 -> close(); # close the file
  # we'll also rename the files
  $oldname = "$file";
  $newname = "${artist} - ${title}.mp3";
  rename $oldname, $newname;

  print "\n";
}
The function that isn't running (even if the appropriate options are entered) is the &show_id3 function. I'm not able to see anything I'm doing incorrect, so could someone please give this a look-over for me?
 
Old 12-30-2005, 09:48 AM   #11
wrj
Member
 
Registered: Aug 2003
Location: Canada/US
Distribution: Ubuntu, Arch
Posts: 84

Rep: Reputation: 15
You're welcome. I'm glad you got it working.

One thing I just noticed is that you're using "==" for your string comparison.
The comparison operator for strings is "eq" and "==" is for numeric values only. That may be causing the issue.
 
Old 12-10-2009, 11:13 PM   #12
ifeatu
Member
 
Registered: Sep 2008
Distribution: Fedora 9
Posts: 68

Rep: Reputation: 15
Same Error!! No Solution!

This is a great thread...I'm beginning to think that this issue is deeper than just a file without tags...I've been fighting the "Can't callmethod " " on undefined value..." error for the past few hours now and can't seem to get a handle on the issue. I actually created two files...one simply edits meta tags and the other takes the name of the actually mp3 and parses it into a foldername THEN edits the meta tag. My goal is to write a program that takes a directory full of uniformly formatted mp3s and parses the names into uniformly named folders and also edits the meta tag of each mp3 using the data collected from parsing the filename:

Here is the metatag part (the part relevant to this thread)

Code:
#!/usr/bin/perl 
use MP3::Tag;
@filename = <*.mp3>;

foreach (@filename) {

$filename = $_;
#$filename = $ARGV[0]; # you could hard code this to 

# Get existing tags
$mp3 = MP3::Tag->new($_);
# ($title, $track, $artist, $album, $comment, $year, $genre) = $mp3->autoinfo();

# print "$title \n $track \n $artist \n";

$mp3->get_tags; # read tags
  
#debug...
if (exists $mp3->{ID3v1}) { # print track information
    print "Filename: $filename\n";
    print "Artist: " . $mp3->{ID3v1}->artist . "\n";
    print "Title: " . $mp3->{ID3v1}->title . "\n";
    print "Album: " . $mp3->{ID3v1}->album . "\n";
    print "Year: " . $mp3->{ID3v1}->year . "\n";
    print "Genre: " . $mp3->{ID3v1}->genre . "\n";
    print "Track: " . $mp3->{ID3v1}->track. "\n";
} 
if (exists $mp3->{ID3v2}) { # print track information
    print "Filename: $filename\n";
    print "Artist: " . $mp3->{ID3v2}->artist . "\n";
    print "Title: " . $mp3->{ID3v2}->title . "\n";
    print "Album: " . $mp3->{ID3v2}->album . "\n";
    print "Year: " . $mp3->{ID3v2}->year . "\n";
    print "Genre: " . $mp3->{ID3v2}->genre . "\n";
    print "Track: " . $mp3->{ID3v2}->track. "\n";
} 

# $genre = foobar;
# $mp3->{ID3v2}->title("$title");
# $mp3->{ID3v2}->year("$year"); 
# $mp3->{ID3v2}->album("$album");
# $mp3->{ID3v2}->track("$track");
# $mp3->{ID3v2}->genre("$genre");


# write tags
# $mp3->{ID3v2}->write_tag();
I included the lines that I commented out to demonstrate what I'd eventually like to do...this code WORKED exactly how I want it to on ONE mp3 file...when I insert the code with EXACTLY the same syntax into the larger code I get that weird error!!!

Code:
#!/usr/bin/perl 
use MP3::Tag;
$file = <*.mp3>;
# open(MASTERFILE, "$file") or die ("Could not open log file.");
# while (<MASTERFILE>) {
$file = $_;
@array = /(.*)_([0-9]{2})_([0-9]{4}).{0,1}_(.*)_(.*)(_side)s*_s*([12])(.*)/;
#print "scalar(@array) \n";
$nums = @array;

mkdir "@array[4]-@array[2]-@array[0]-@array[1]- @array[3] -BLH";

$i =0;
while ($i < $nums){
print "Array element $i is: @array[$i] \n";

$i ++;
}

$mp3 = MP3::Tag->new($_);

$mp3->get_tags; # read tags

$genre = foobar;
$comment = "This is a test";

$mp3->{ID3v2}->write_tag(); 

if (exists $mp3->{ID3v1}) { # print track information
    print "Filename: $filename\n";
    print "Artist: " . $mp3->{ID3v1}->artist . "\n";
    print "Title: " . $mp3->{ID3v1}->title . "\n";
    print "Album: " . $mp3->{ID3v1}->album . "\n";
    print "Year: " . $mp3->{ID3v1}->year . "\n";
    print "Genre: " . $mp3->{ID3v1}->genre . "\n";
    print "Track: " . $mp3->{ID3v1}->track. "\n";
} 
if (exists $mp3->{ID3v2}) { # print track information
    print "Filename: $filename\n";
    print "Artist: " . $mp3->{ID3v2}->artist . "\n";
    print "Title: " . $mp3->{ID3v2}->title . "\n";
    print "Album: " . $mp3->{ID3v2}->album . "\n";
    print "Year: " . $mp3->{ID3v2}->year . "\n";
    print "Genre: " . $mp3->{ID3v2}->genre . "\n";
    print "Track: " . $mp3->{ID3v2}->track. "\n";
}

Error:

Code:
$ perl perlProg.pl
Can't call method "get_tags" on an undefined value at perlProg.pl line 22.
 
Old 12-11-2009, 05:40 AM   #13
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 453Reputation: 453Reputation: 453Reputation: 453Reputation: 453
Quote:
Originally Posted by scuzzman View Post
I'm writing a short Perl script to rename a directory full of MP3 files and re-write some of their ID3 tags using the MP3::Tag module, but I'm having some trouble with it. Whenever I try to run it, I get this error:
Code:
[scuzzy@slackdell /home/scuzzy/music/young_jeezy/unknown_disc]$ ~/fixid3.pl 
Will every file in this directory have the same album and artist header (y/n)? y
What is the title of the album? Thug Motivation 101

Who is the artist? Young Jeezy

Filename: track_01.mp3
What is the track name? Go Crazy - Remix
Can't call method "title" on an undefined value at /home/scuzzy/fixid3.pl line 51, <STDIN> line 4.
This is the Perl script I'm running:
Code:
#!/usr/bin/perl
# fixid3.pl - Perl script to write MP3 ID3 tags to files
# Fields are title, ARTIST, ALBUM, YEAR, COMMENT, GENRE

# load the ID3 module
use MP3::Tag;

# get the filesname(s)
# We'll just use all files in the directory:
@filenames = <*.mp3>; # This glob gets all mp3 files in current dir

print "Will every file in this directory have the same ";
print "album and artist header (y/n)? ";
chomp ( $same_album_artist = <STDIN> );
if ( $same_album_artist == "y" ) {
  print "What is the title of the album? ";
  chomp ( $album = <STDIN> );
  print "\n";
  print "Who is the artist? ";
  chomp ( $artist = <STDIN> );
  print "\n";
  foreach (@filenames) { # since the album and artist are the same, just change song titles
    print "Filename: $_\n";
    $file = $_;
    &fix_id3($album, $artist, $file);
  }
} elsif ($same_album_artist == "n") {
  foreach (@filenames) { # ask album and artist on each song
    print "Filename: $_\n";
    $file = $_;
    print "What is the title of the album? ";
    chomp ( $album = <STDIN> );
    print "\n";
    print "Who is the artist? ";
    chomp ( $artist = <STDIN> );
    print "\n";
    &fix_id3($album, $artist, $file);
  }
} else {
  die "Unrecognized entry.\n";
}

sub fix_id3 {
# Here's where the magic is done
  $album = $_[0];
  $artist = $_[1];
  $file = $_[2];
  print "What is the track name? ";
  chomp ( $title = <STDIN> );
  $mp3 = MP3::Tag->new($file); # Creates new object
  $mp3->{ID3v1}->title("$title"); # adds element title
  $mp3->{ID3v1}->artist("$artist"); # adds element artist
  $mp3->{ID3v1}->album("$album"); # adds element album
  $mp3->{ID3v1}->write_tag(); # writes the tags
  $mp3->close(); # close the file
  # we'll also rename the files
  $oldname = "\"$file\"";
  $newname = "\"$artist - ${title}.mp3\"";
  rename $oldname, $newname;

  print "\n";
}
Is there anything I can do to figure out why this is detecting an undefined value, even though everything should be properly defined?
Edit: I have just tried it with and without the quotes on these lines (in red) and yielded the same results:
Just don't waste your and our time trying to debug Perl scripts not having

Code:
use strict;
use warnings;
in the very beginning. First put the the above pragmas, achieve compilation without errors and run without warnings, then debug proper.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
add "Artist" and "Album Title" to mp3 files powah Linux - Software 2 04-05-2005 04:04 AM
under with title and sub title the "GTK devel" found in fc3? AKAKAK Fedora 3 02-27-2005 06:51 AM
Compiling KDE 3.2.0 - "Can't open perl script "/dcopidlng/kalyptus" linuxgamer09483 Linux - Software 3 04-09-2004 09:25 PM
Can you change the "title" under your name that says "member" or "newbie&qu Whitehat LQ Suggestions & Feedback 3 11-19-2003 07:32 PM
Undefined call to "_fxstat" Deadman Inc. Linux - Software 1 07-25-2002 10:11 AM


All times are GMT -5. The time now is 06:13 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration