view release on metacpan or search on metacpan
lib/App/Pimpd/Collection/Album.pm view on Meta::CPAN
use App::Pimpd::Validate;
use Term::ExtendedColor qw(fg);
sub delete_album {
  my $file = $mpd->current->file;
  my($path) = $file =~ m|(.+)/.+$|m;
  my @songs = $mpd->collection->all_items_simple($path);
  printf("Remove %s ? [y/N] ", fg('bold', $path));
  chomp(my $answer = <STDIN>);
  if(lc($answer) ne 'y') {
    return 1;
  }
  $path = "$config{music_directory}/$path";
  if(remote_host()) {
    open(OLD_STDOUT, '>&', STDOUT) or die("Cant dupe STDOUT: $!");
    close(STDOUT);
    system(
      'ssh', "-p $config{ssh_port}",
      "$config{ssh_user}\@$config{ssh_host}",
      "rm -rv '$path'",
    ) == 0 and do {
      open(STDOUT, '>&', OLD_STDOUT) or die("Cant reopen STDOUT: $!");
      printf("Removed %s successfully\n", fg('bold', $path));
      return;
    };
    open(STDOUT, '>&', OLD_STDOUT) or die("Cant reopen STDOUT: $!");
  }
  else {
    if(remove_path($path)) {
      printf("removed '%s'\n", fg('bold', $path));
      return;
    }
    print STDERR "remove_path($path): $!\n";
    return;
  }
  return;
}
sub albums_by_artist {
lib/App/Pimpd/Doc.pm view on Meta::CPAN
  if(exists($help{$cmd})) {
    return $help{$cmd}->();
  }
  else {
    return "No such topic.\n";
  }
}
sub _help_status {
  return << "EOF"
@{[fg('bold', 'Usage')]}: status
Display MPD status
EOF
}
sub _help_stats {
  return << "EOF"
@{[fg('bold', 'Usage')]}: stats
Display statistics about MPD
EOF
}
sub _help_unlove {
  return << "EOF"
@{[fg('bold', 'Usage')]}: unlove PATTERN
Un-love file(s) matching PATTERN.
EOF
}
sub _help_add_album {
  return << "EOF"
@{[fg('bold', 'Usage')]}: add-album ALBUM
Add all songs from ALBUM to playlist.
If ALBUM is omitted, use albumtag from the current song.
EOF
}
sub _help_add {
  return << "EOF"
@{[fg('bold', 'Usage')]}: add FILES || PLAYLIST
Argument can be either a playlist or a command that produces file lists.
Those commands include;
  songs   add all songs from the current album
  slove   add all songs matching pattern given to slove
EOF
}
sub _help_slove {
  return << "EOF"
@{[fg('bold', 'Usage')]}: slove PATTERN
Search the database with loved songs for PATTERN.
If PATTERN is omitted, returns all loved songs.
The results are added to the current playlist.
EOF
}
sub _help_random_track {
  return << "EOF"
@{[fg('bold', 'Usage')]}: randomtrack
Play a random song from the current playlist.
EOF
}
sub _help_stop {
  return << "EOF"
@{[fg('bold', 'Usage')]}: stop
Stop @{[fg('bold', 'local and remote')]} playback.
EOF
}
sub _help_kill {
  return << "EOF"
@{[fg('bold', 'Usage')]}: kill
Stop @{[fg('bold', 'local')]} playback.
EOF
}
sub _help_crop {
  return << "EOF"
@{[fg('bold', 'Usage')]}: crop
Remove all but the current song from the playlist.
EOF
}
sub _help_clear {
  return << "EOF"
@{[fg('bold', 'Usage')]}: clear
Clear the current playlist.
EOF
}
sub _help_random {
  return << "EOF"
@{[fg('bold', 'Usage')]}: random
Toggle random on/off.
EOF
}
sub _help_repeat {
  return << "EOF"
@{[fg('bold', 'Usage')]}: repeat
Toggle repeat on/off.
EOF
}
sub _help_pause {
  return << "EOF"
@{[fg('bold', 'Usage')]}: pause
Toggle playback status.
EOF
}
sub _help_previous {
  return << "EOF"
@{[fg('bold', 'Usage')]}: previous
Play the previous song in playlist.
EOF
}
sub _help_next {
  return << "EOF"
@{[fg('bold', 'Usage')]}: next
Play the next song in playlist.
EOF
}
sub _help_stitle {
  return << "EOF"
@{[fg('bold', 'Usage')]}: sartist TITLE
Search the collection for songs where the title tag
@{[fg('bold', 'partially')]} matches TITLE.
The results are added to the current playlist.
EOF
}
sub _help_salbum {
  return << "EOF"
@{[fg('bold', 'Usage')]}: sartist ALBUM
Search the collection for songs where the album tag
@{[fg('bold', 'partially')]} matches ALBUM.
The results are added to the current playlist.
EOF
}
sub _help_sartist {
  return << "EOF"
@{[fg('bold', 'Usage')]}: sartist ARTIST
Search the collection for songs where the artist tag
@{[fg('bold', 'partially')]} matches ARTIST.
The results are added to the current playlist.
EOF
}
sub _help_sany {
  return << "EOF"
@{[fg('bold', 'Usage')]}: sany PATTERN
Search the collection for filenams matching PATTERN.
The results are added to the current playlist.
EOF
}
sub _help_albums {
  return << "EOF"
@{[fg('bold', 'Usage')]}: albums [ARTIST]
List albums where ARTIST is featured.
If ARTIST is omitted, use the artist tag from the currently
playing song.
EOF
}
sub _help_songs {
  return << "EOF"
@{[fg('bold', 'Usage')]}: songs [ALBUM]
List songs on ALBUM.
If ALBUM is omitted, use the album tag from the currently playing
song.
EOF
}
sub _help_queue {
  return << "EOF"
@{[fg('bold', 'Usage')]}: queue INTEGERs
Put songs in a queue.
Arguments need to be valid playlist position IDs, as shown in
the 'playlist' output.
EOF
}
sub _help_splaylist {
  return << "EOF"
@{[fg('bold', 'Usage')]}: splaylist PATTERN
Search the current playlist for PATTERN.
If more then one result is found, queue up the results.
See 'help queue'.
EOF
}
sub _help_love {
  return << "EOF"
@{[fg('bold', 'Usage')]}: love [PLAYLIST]
Add the currently playing track to the library of loved songs.
If PLAYLIST is omitted, the song is added to a playlist following
this naming scheme:
  @{[fg($c[0], '%year-%month-%genre.m3u')]}
If a genre tag is missing, the string 'undef' is used in its place.
EOF
}
sub _help_loved {
  return << "EOF"
@{[fg('bold', 'Usage')]}: loved?
Check if the current song is already loved.
EOF
}
sub _help_delete_album {
  return << "EOF"
@{[fg('bold', 'Usage')]}: delete_album
Deletes the current album from disk.
EOF
}
sub _help_rm_album {
  return << "EOF"
@{[fg('bold', 'Usage')]}: rmalbum PATTERN
Search the current playlist for albums matching PATTERN and
removes the matches from the playlist.
EOF
}
sub _help_playlists {
  return << "EOF"
@{[fg('bold', 'Usage')]}: playlists
List all by MPD known playlists.
EOF
}
sub _help_playlist {
  return << "EOF"
@{[fg('bold', 'Usage')]}: playlist
Show the current playlist.
EOF
}
sub _help_shell {
  return sprintf("\n%s%s",
  "@{[fg('bold', fg($c[8], 'OPTIONS'))]}\t\t    " .
  "@{[fg('bold', fg($c[3], 'DESCRIPTION'))]} \t\t\t\t   "
,"
      np            show the current song
      info          show all current information
      copy          copy song to destination
      copya         copy album to destination
      queue         put songs in a queue
@{[fg('bold', fg($c[0], '  Playlist'))]}
      lsplaylists   list all known playlists
      add           add playlists or songs to the current playlist
      add-album     add songs from album to playlist
      rmalbum       remove album from playlist
      randomize     randomize a new playlist with n tracks
      randomalbum   and n random full albums
      love          love song
      loved?        check if the current song is loved
      unlove        unlove file(s) matching PATTERN
      splaylist     search the current playlist for str
@{[fg('bold', fg($c[0], '  Collection'))]}
      songs         list songs on album
      albums        list albums by artist
      sartist       search for artist str
      salbum        search for album str
      stitle        search for title str
      sany          search database for str
      slove         search the database with loved songs for pattern
@{[fg('bold', fg($c[0], '  Controls'))]}
      next          next track in playlist
      previous      previous track in playlist
      pause         toggle playback
      repeat        toggle repeat on/off
      random        toggle random on/off
      clear         clear playlist
      crop          remove all tracks but the current one
      kill          stop local playback
      help          show help for command
      exit          exit pimpd2
        \n", shift,
      );
}
sub _help_copy {
  return << "EOF"
@{[fg('bold', 'Usage')]}: copy [DESTINATION]
Copy the currently playing song to DESTINATION.
If DESTINATION is omitted, use the @{[fg($c[0], '$target_directory')]}
setting defined in @{[fg('bold', 'pimpd2.conf')]}.
EOF
}
sub _help_info {
  return << "EOF"
@{[fg('bold', 'Usage')]}: info
Show all available song metadata, as well as playback status
and various MPD settings.
EOF
}
sub _help_np {
  return << "EOF"
@{[fg('bold', 'Usage')]}: np
Show basic song metadata on a single line.
EOF
}
sub _help_randomize {
  return << "EOF"
@{[fg('bold', 'Usage')]}: randomize [INTEGER] [ARTIST]
Add n random songs from the collection to the current playlist.
The first, optional argument, is the number of songs to add.
The second, optional argument, is an artist name.
If a second argument is provided, add n random songs from that artist.
Defaults to 100 random songs.
EOF
}
sub _help_randomize_albums {
return << "EOF"
@{[fg('bold', 'Usage')]}: randomalbum [INTEGER]
Add n random full albums to the current playlist.
Defaults to 10 albums.
EOF
}
1;
__END__
lib/App/Pimpd/Info.pm view on Meta::CPAN
  }
  return;
}
sub current {
  _current_update();
  my $output;
  if(to_terminal()) {
    $output = sprintf("%s - %s on %s from %s [%s]",
        fg($c[3], fg('bold',  $current{artist})),
        fg($c[11], $current{title}),
        fg($c[0], $current{album}),
        fg($c[4], fg('bold', $current{date})),
        $current{genre},
      );
  }
  else {
    $output = sprintf("%s - %s on %s from %s [%s]",
      $current{artist},
      $current{title},
      $current{album},
      $current{date},
      $current{genre},
lib/App/Pimpd/Info.pm view on Meta::CPAN
  }
  $status{'state'} = 'Playing' if($status{'state'} eq 'play');
  $status{'state'} = 'Paused'  if($status{'state'} eq 'pause');
  $status{'state'} = 'Stopped' if($status{'state'} eq 'stop');
  if($status{volume} < 0) {
    $status{volume} = 'N/A (Software Mixer)';
  }
  printf("%s %8s: %.66s\n", fg('bold', fg('251', 'S')),
    'Artist', fg($c[3], fg('bold', $current{artist}))
  );
  printf("%s %8s: %.66s\n", fg('bold', fg('250', 'O')),
    'Album', fg($c[0], $current{album})
  );
  printf("%s %8s: %.66s\n", fg('bold', fg('249', 'N')),
    'Song', fg($c[11], fg('bold', $current{title}))
  );
  printf("%s %8s: %.66s\n", fg('bold', fg(248, 'G')),
    'Genre', fg($c[13], $current{genre})
  );
  printf("%s %9s: %s\n", fg('bold', undef),
    'File', fg($c[7], $current{file})
  );
  printf("%s %8s: %.66s\n", fg('bold', fg('247', 'I')),
    'Date', $current{date}
  );
  printf("%s %8s: %.66s\n", fg('bold', fg('246', 'N')),
    'Time', $current{time}
  );
  printf("%s %8s: %.66s\n", fg('bold', fg('245', 'F')),
    'Bitrate', $current{bitrate}
  );
  printf("%s %8s: %.66s\n", fg('bold', fg('244', 'O')),
    'Audio', $current{audio}
  );
  print fg($c[15]);
  print '-' x 25, clear(), "\n";
  printf("%s %8s: %.66s\n", fg('bold', fg('243', 'S')),
    'Repeat', $status{repeat}
  );
  printf("%s %8s: %.66s\n", fg('bold', fg('242', 'T')),
    'Shuffle', $status{shuffle}
  );
  printf("%s %8s: %.66s\n", fg('bold', fg('242', 'A')),
    'Xfade', $status{xfade}
  );
  printf("%s %8s: %.66s\n", fg('bold', fg('241', 'T')),
    'Volume', $status{volume}
  );
  printf("%s %8s: %.66s\n", fg('bold', fg('240', 'U')),
   'State', $status{state}
  );
  printf("%s %8s: %.66s\n", fg('bold', fg('239', 'S')),
   'List V', $status{list}
  );
  print fg($c[15]);
  print '-' x 25, clear(), "\n";
  printf("%s %8s: %.66s\n", fg('bold', fg('238', 'S')),
    'Song', $stats{song}
  );
  printf("%s %8s: %.66s\n", fg('bold', fg('237', 'T')),
    'List', $stats{length} . ' songs'
  );
  printf("%s %8s: %.66s\n", fg('bold', fg('236', 'A')),
    'Songs', $stats{songs}
  );
  printf("%s %8s: %.66s\n", fg('bold', fg('235', 'T')),
    'Albums', $stats{albums}
  );
  printf("%s %8s: %.66s\n", fg('bold', fg('234', 'S')),
   'Artists', $stats{artists}
  );
  return;
}
sub _on_off {
  my $state = shift;
  if($state > 1) {
    return "ON ($state)";
lib/App/Pimpd/Player.pm view on Meta::CPAN
  return;
}
sub player_destruct {
  open(my $fh, '<', $pidfile_pimpd) or return 1; # for now
  my $pimpd_player = <$fh>;
  close($fh);
  if(kill(9, $pimpd_player)) {
    unlink($player_tmp_log);
    #printf("%s %s\n", fg('bold', $pimpd_player), 'terminated');
  }
  open(my $fh, '<', $pidfile_player) or confess($!);
  my $pimpd_target = <$fh>;
  close($fh);
  if(kill(9, $pimpd_target)) {
    #printf("%s %s\n", fg('bold', $pimpd_target, 'terminated'));
  }
  if(kill(9, $pimpd_target+1)) {
    #printf("%s %s\n", fg('bold', $pimpd_target + 1), 'terminated');
  }
  return 0;
}
1;
__END__
=pod
lib/App/Pimpd/Playlist.pm view on Meta::CPAN
  $mpd->random(0);
  $mpd->play(shift(@to_play));
  $mpd->playlist->move($mpd->current->pos, 0);
  return 0 if(scalar(@to_play) == 0);
  my $next_pos = $mpd->current->pos + 1;
  print fg('bold', 'Queueing'), ":\n";
  for(@to_play) {
    printf("%-50.50s %s\n", fg($c[3], $list{$_}), "( $_ => $next_pos )");
    $mpd->playlist->move($_, $next_pos);
    $next_pos++;
  }
  return;
}
sub show_playlist {
lib/App/Pimpd/Playlist.pm view on Meta::CPAN
    my $crnt_title  = $mpd->current->title // undef;
    my $crnt_artist = $mpd->current->artist // undef;
    $title       =~ s/(\w+)/\u\L$1/gm;
    $artist      =~ s/(\w+)/\u\L$1/gm;
    $crnt_title  =~ s/(\w+)/\u\L$1/gm;
    $crnt_artist =~ s/(\w+)/\u\L$1/gm;
    if($mpd->current->pos == $i) {
      # bg('red4', $i) will add another 17 chars
      printf("%19s %51.51s |@{[fg('bold', 'x')]}| %-47.47s\n",
        bg($c[4], $i), fg($c[5], fg('bold',  $artist)), $title);
    }
    else {
      printf("%4d %25.25s | | %-47.47s\n",
        $i, $artist, $title);
    }
    $i++;
  }
  return;
}
lib/App/Pimpd/Playlist/Favorite.pm view on Meta::CPAN
      printf("%s by %s is already loved!\n",
        fg($c[11], $title), fg($c[2], $artist),
      );
      return;
    }
  }
  else {
    if(already_loved($file, $favlist_m3u)) {
      printf("%s by %s is already loved in %s\n",
        fg($c[11], $title), fg($c[2], $artist), fg('bold', $favlist_m3u),
      );
      return;
    }
  }
  $genre =~ s/\s+/_/gm; # evil whitespace
  my(undef, undef, undef, undef, $month, $year) = localtime(time);
  $month += 1;
lib/App/Pimpd/Playlist/Favorite.pm view on Meta::CPAN
      return 0;
    };
    return 1;
  } # Nope, not remote
  open(my $fh, '>>', $favlist_m3u)
    or die("Could not open '$favlist_m3u' in append mode: $!");
  print $fh "$file\n";
  close($fh);
  print fg($c[8], fg('bold', $title)), ' => ', fg($c[6], $favlist_m3u), "\n";
  return;
}
1;
__END__
=pod
lib/App/Pimpd/Shell.pm view on Meta::CPAN
  $opts = {
    'randomize'      => sub {
      if(!defined($_[0])) {
        $_[0] = 100;
      }
      elsif(defined($_[0]) and $_[0] !~ /^\d+$/m) {
        print STDERR "Need a valid integer\n";
        $_[0] = 100;
      }
      print 'Adding ' . fg('bold', @_) . " random tracks...\n";
      my @random = randomize(@_);
      print "$_\n" for @random;
      clear_playlist();
      add_to_playlist(@random);
    },
    'randomalbum'   => sub {
      $_[0] = 10 if(!$_[0]);
      print 'Adding ' . fg('bold', $_[0]) . " random albums...\n\n";
      my @albums = randomize_albums($_[0]);
      my $old = undef;
      for(@albums) {
        my($album_dir) = $_ =~ m|(.+)/.+|m;
        if($old ne $album_dir) {
          print "> $album_dir\n";
          $old = $album_dir;
        }
      }
lib/App/Pimpd/Shell.pm view on Meta::CPAN
      add_to_playlist(@albums);
    },
    'playlist'       => sub {
      if(empty_playlist()) {
        print STDERR "Playlist is empty\n";
        return 1;
      }
      show_playlist();
      print fg('bold', ' >'), '> ', current(), "\n";
    },
    'love'           => sub {
      if(empty_playlist()) {
        print STDERR "Nothing is playing - playlist is empty\n";
        return 1;
      }
      add_to_favlist(@_);
    },
    'loved?'          => sub {
      if(already_loved($mpd->current->file)) {
        printf("%s, %s by %s is loved.\n",
          fg('bold', 'Yes'),
          fg($c[10], $mpd->current->title),
          fg($c[2],  fg('bold', $mpd->current->artist)),
        );
      }
      else {
        printf("%s, %s by %s is not loved yet.\n",
          fg('bold', 'No'),
          fg($c[10], $mpd->current->title),
          fg($c[2],  fg('bold', $mpd->current->artist)),
        );
      }
    },
    'unlove'            => sub {
      if(!@_) {
        print help('unlove');
        return;
      }
      remove_favorite(@_);
lib/App/Pimpd/Shell.pm view on Meta::CPAN
    'add-album'       => sub {
      add_to_playlist( map{ $_->file } get_album_songs(@_));
    },
    'lsplaylists'     => sub { print "$_\n" for list_all_playlists(); },
    'add'             => sub {
      if($_[0] eq 'songs') {
        local $\ = "\n";
        my @songs = map { $_->file } songs_on_album();
        printf("Adding %d songs from %s\n",
          scalar(@songs), fg('bold', $mpd->current->album),
        );
        add_to_playlist(@songs);
      }
      elsif($_[0] eq 'slove') {
        shift @_; # so we can grab the PATTERN
        my @result = search_favlist(@_);
        if(scalar(@result) > 0) {
          print "$_\n" for @result;
          add_to_playlist(@result);
          printf("\nAdded %s loved %s matching '%s'\n",
            fg('bold', scalar(@result)),
            (scalar(@result) > 1) ? 'songs' : 'song',
            fg($c[4], fg('bold', $_[0])),
          );
        }
        else {
          printf("No songs matching '%s' were found\n",
            fg($c[4], fg('bold', $_[0])),
          );
        }
      }
      else {
        add_playlist(@_);
      }
    },
    'next'            => sub {
lib/App/Pimpd/Shell.pm view on Meta::CPAN
      if(invalid_playlist_pos(@_)) {
        printf("No such song%s\n", (@_ < 1) ? 's' : '');
        return 1;
      }
      queue(@_);
    },
    'random'           => sub {
      $mpd->random;
      my $status =  ($mpd->status->random)
        ? "Random: " . fg('bold', 'On')
        : "Random: " . fg('bold', 'Off');
      print "$status\n";
    },
    'repeat'           => sub {
      $mpd->repeat;
      my $status = ($mpd->status->repeat)
        ? "Repeat: " . fg('bold', 'On')
        : "Repeat: " . fg('bold', 'Off');
      print "$status\n";
    },
    'stats'            => sub { stats(); },
    'status'           => sub { print status(), "\n"; },
    'randomtrack'      => sub {
      play_pos_from_playlist(random_track_in_playlist());
      print current(), "\n";
    },
lib/App/Pimpd/Shell.pm view on Meta::CPAN
      if( defined($opts->{$_[0]}) ) {
        print help($_[0]);
      }
      else {
        print help('shell');
      }
    },
  };
  while(1) {
    #print fg($c[6], 'pimpd'), fg('bold', '> ');
    #chomp(my $choice = <STDIN>);
    my @available_cmd = keys(%{$opts});
    push(@available_cmd, 'shell');
    my $term = Term::ReadLine->new('pimpd2');
    my $attr = $term->Attribs;
    $attr->{completion_function} = sub {
      my($text, $line, $start) = @_;
lib/App/Pimpd/Shell.pm view on Meta::CPAN
    };
    $attr->{autolist} = 0;
    $attr->{maxcomplete} = 0;
    # Sane keymap please.
    $term->set_keymap('vi');
    my $choice;
    while(1) {
      $choice = $term->readline(fg($c[6], 'pimpd') . fg('bold', '> '));
      $term->addhistory($choice) if $choice =~ /\S/m;
      ($cmd) = $choice =~ m/^(\S+)/m;
      ($arg) = $choice =~ m/\s+(.+)$/m;
      @cmd_args  = split(/\s+/m, $arg);
      if(defined($opts->{$cmd})) {
        $mpd->play;
        $opts->{$cmd}->(@cmd_args);
      }
lib/App/Pimpd/Validate.pm view on Meta::CPAN
      if(scalar(@choices) == 0) {
        print STDERR "No such playlist '" . fg($c[5], $list), "'\n";
        return;
      }
      print "'all' uses all playlists\n\n";
      my $i = 0;
      for my $choice(@choices) {
        print fg('bold', sprintf("%3d", $i)), " $choice\n";
        $i++;
      }
      print "choice: ";
      chomp(my $answer = <STDIN>);
      if( ($answer eq 'all') or ($answer eq '') ) {
        return @choices;
      }
      elsif($answer eq 'current') {
        return(undef);
  'cp|copy'              => sub { cp(@ARGV ? @ARGV : $config{target_directory}) },
  'cpa|copy-album'       => sub {
    cp_album(@ARGV ? @ARGV : $config{target_directory})
  },
  'fav|favorite|love'    => sub { add_to_favlist(@ARGV); }, # FIXME
  'loved'                => sub {
    if(already_loved($mpd->current->file)) {
      printf("%s, %s by %s is loved.\n",
        fg('bold', 'Yes'),
        fg($c[10], $mpd->current->title),
        fg($c[2],  fg('bold', $mpd->current->artist)),
      );
    }
    else {
      printf("%s, %s by %s is not loved yet.\n",
        fg('bold', 'No'),
        fg($c[10], $mpd->current->title),
        fg($c[2],  fg('bold', $mpd->current->artist)),
      );
    }
  },
  'unlove'               => sub { remove_favorite(@ARGV); },
  'aa|add-album'         => sub {
    add_to_playlist( map{ $_->file } get_album_songs(@ARGV) );
  },
  'slove'                => sub {