sendtr.c

00001 #include "common.h"
00002 #include <string.h>
00003 #include <sys/stat.h>
00004 #ifdef HAVE_LIBGEN_H
00005 #include <libgen.h> /* basename() */
00006 #endif
00007 
00008 /*
00009  * This program is derived from the exact equivalent in libnjb.
00010  *
00011  * This is an improved commandline track transfer program
00012  * based on Enrique Jorreto Ledesma's work on the original program by 
00013  * Shaun Jackman and Linus Walleij.
00014  */
00015 
00016 /* Function that compensate for missing libgen.h on Windows */
00017 #ifndef HAVE_LIBGEN_H
00018 static char *basename(char *in) {
00019   char *p;
00020   if (in == NULL)
00021     return NULL;
00022   p = in + strlen(in) - 1;
00023   while (*p != '\\' && *p != '/' && *p != ':')
00024     { p--; }
00025   return ++p;
00026 }
00027 #endif
00028 
00029 static int progress (uint64_t const sent, uint64_t const total, void const * const data)
00030 {
00031   int percent = (sent*100)/total;
00032 #ifdef __WIN32__
00033   printf("Progress: %I64u of %I64u (%d%%)\r", sent, total, percent);
00034 #else
00035   printf("Progress: %llu of %llu (%d%%)\r", sent, total, percent);
00036 #endif
00037   fflush(stdout);
00038   return 0;
00039 }
00040 
00041 static char *prompt (const char *prompt, char *buffer, size_t bufsz, int required)
00042 {
00043   char *cp, *bp;
00044   
00045   while (1) {
00046     fprintf(stdout, "%s> ", prompt);
00047     if ( fgets(buffer, bufsz, stdin) == NULL ) {
00048       if (ferror(stdin)) {
00049         perror("fgets");
00050       } else {
00051         fprintf(stderr, "EOF on stdin\n");
00052       }
00053       return NULL;
00054     }
00055     
00056     cp = strrchr(buffer, '\n');
00057     if ( cp != NULL ) *cp = '\0';
00058     
00059     bp = buffer;
00060     while ( bp != cp ) {
00061       if ( *bp != ' ' && *bp != '\t' ) return bp;
00062       bp++;
00063     }
00064     
00065     if (! required) return bp;
00066   }
00067 }
00068 
00069 static void usage(void)
00070 {
00071   fprintf(stderr, "usage: sendtr [ -D debuglvl ] [ -q ] -t <title> -a <artist> -l <album>\n");
00072   fprintf(stderr, "       -c <codec> -g <genre> -n <track number> -y <year> \n");
00073   fprintf(stderr, "       -d <duration in seconds> -f \"Folder Name\" <path>\n");
00074   fprintf(stderr, "(-q means the program will not ask for missing information.)\n");
00075   exit(1);
00076 }
00077 
00078 static uint32_t find_folder_list(char *name, LIBMTP_folder_t *folderlist, int level)
00079 {
00080   uint32_t i;
00081 
00082   if(folderlist==NULL) {
00083     return 0;
00084   } 
00085 
00086   if(!strcasecmp(name, folderlist->name))
00087     return folderlist->folder_id;
00088 
00089   if ((i = (find_folder_list(name, folderlist->child, level+1))))
00090     return i;
00091   if ((i = (find_folder_list(name, folderlist->sibling, level))))
00092     return i;
00093 
00094   return 0;
00095 }
00096 
00097 int main(int argc, char **argv)
00098 {
00099   int opt;
00100   extern int optind;
00101   extern char *optarg;
00102   char *path, *filename;
00103   char artist[80], title[80], genre[80], codec[80], album[80];
00104   char num[80];
00105   char *partist = NULL;
00106   char *ptitle = NULL;
00107   char *pgenre = NULL;
00108   char *pcodec = NULL;
00109   char *palbum = NULL;
00110   char *pfolder = NULL;
00111   uint16_t tracknum = 0;
00112   uint16_t length = 0;
00113   uint16_t year = 0;
00114   uint16_t quiet = 0;
00115   uint64_t filesize;
00116   uint32_t parent_id = 0;
00117   struct stat sb;
00118   char *lang;
00119   LIBMTP_mtpdevice_t *device;
00120   LIBMTP_folder_t *folders = NULL;
00121   LIBMTP_track_t *trackmeta;
00122   int ret;
00123 
00124   LIBMTP_Init();
00125   
00126   while ( (opt = getopt(argc, argv, "qD:t:a:l:c:g:n:d:y:f:")) != -1 ) {
00127     switch (opt) {
00128     case 't':
00129       ptitle = strdup(optarg);
00130       break;
00131     case 'a':
00132       partist = strdup(optarg);
00133       break;
00134     case 'l':
00135       palbum = strdup(optarg);
00136       break;
00137     case 'c':
00138       pcodec = strdup(optarg); // FIXME: DSM check for MP3, WAV or WMA
00139       break;
00140     case 'g':
00141       pgenre = strdup(optarg);
00142       break;
00143     case 'n':
00144       tracknum = atoi(optarg);
00145       break;
00146     case 'd':
00147       length = atoi(optarg);
00148       break;
00149     case 'y':
00150       year = atoi(optarg);
00151       break;
00152     case 'f':
00153       pfolder = strdup(optarg);
00154       break;
00155     case 'q':
00156       quiet = 1;
00157       break;
00158     default:
00159       usage();
00160     }
00161   }
00162   argc -= optind;
00163   argv += optind;
00164   
00165   if ( argc != 1 ) {
00166     printf("You need to pass a filename.\n");
00167     usage();
00168   }
00169   
00170   /*
00171    * Check environment variables $LANG and $LC_CTYPE
00172    * to see if we want to support UTF-8 unicode
00173    */
00174   lang = getenv("LANG");
00175   if (lang != NULL) {
00176     if (strlen(lang) > 5) {
00177       char *langsuff = &lang[strlen(lang)-5];
00178       if (strcmp(langsuff, "UTF-8")) {
00179         printf("Your system does not appear to have UTF-8 enabled ($LANG=\"%s\")\n", lang);
00180         printf("If you want to have support for diacritics and Unicode characters,\n");
00181         printf("please switch your locale to an UTF-8 locale, e.g. \"en_US.UTF-8\".\n");
00182       }
00183     }
00184   }
00185   
00186   path = argv[0];
00187 
00188   filename = basename(path);
00189   if (filename == NULL) {
00190     printf("Error: filename could not be based.\n");
00191     exit(1);
00192   }
00193   if ( stat(path, &sb) == -1 ) {
00194     fprintf(stderr, "%s: ", path);
00195     perror("stat");
00196     exit(1);
00197   }
00198   filesize = (uint64_t) sb.st_size;
00199 
00200   /* Ask for missing parameters if not quiet */
00201   if (!quiet) {
00202     if (pcodec == NULL) {
00203       if ( (pcodec = prompt("Codec", codec, 80, 1)) == NULL ) {
00204         printf("A codec name is required.\n");
00205         usage();
00206       }
00207     }
00208     if (!strlen(pcodec)) {
00209       printf("A codec name is required.\n");
00210       usage();
00211     }
00212     
00213     if (ptitle == NULL) {
00214       if ( (ptitle = prompt("Title", title, 80, 0)) == NULL )
00215         usage();
00216     }
00217     if (!strlen(ptitle))
00218       ptitle = NULL;
00219     
00220     
00221     if (palbum == NULL) {
00222       if ( (palbum = prompt("Album", album, 80, 0)) == NULL )
00223         usage();
00224     }
00225     if (!strlen(palbum))
00226       palbum = NULL;
00227     
00228     if (partist == NULL) {
00229     if ( (partist = prompt("Artist", artist, 80, 0)) == NULL )
00230       usage();
00231     }
00232     if (!strlen(partist))
00233       partist = NULL;
00234     
00235     if (pgenre == NULL) {
00236       if ( (pgenre = prompt("Genre", genre, 80, 0)) == NULL )
00237         usage();
00238     }
00239     if (!strlen(pgenre))
00240       pgenre = NULL;
00241     
00242     if (tracknum == 0) {
00243       char *pnum;
00244       if ( (pnum = prompt("Track number", num, 80, 0)) == NULL )
00245       tracknum = 0;
00246       if ( strlen(pnum) ) {
00247         tracknum = strtoul(pnum, 0, 10);
00248       } else {
00249         tracknum = 0;
00250       }
00251     }
00252     
00253     if (year == 0) {
00254       char *pnum;
00255       if ( (pnum = prompt("Year", num, 80, 0)) == NULL )
00256         year = 0;
00257       if ( strlen(pnum) ) {
00258         year = strtoul(pnum, 0, 10);
00259       } else {
00260         year = 0;
00261       }
00262     }
00263     
00264     if (length == 0) {
00265       char *pnum;
00266       if ( (pnum = prompt("Length", num, 80, 0)) == NULL )
00267         length = 0;
00268       if ( strlen(pnum) ) {
00269         length = strtoul(pnum, 0, 10);
00270       } else {
00271         length = 0;
00272       }
00273     }
00274 
00275   }
00276   
00277   trackmeta = LIBMTP_new_track_t();
00278     
00279   printf("Sending track:\n");
00280   printf("Codec:     %s\n", pcodec);
00281   
00282   if (!strcasecmp(pcodec,"mp3")) {
00283     trackmeta->filetype = LIBMTP_FILETYPE_MP3;
00284   }  else if (!strcasecmp(pcodec,"wav")) {
00285     trackmeta->filetype = LIBMTP_FILETYPE_WAV;
00286   } else if (!strcasecmp(pcodec,"ogg")) {
00287     trackmeta->filetype = LIBMTP_FILETYPE_OGG;
00288   } else if (!strcasecmp(pcodec,"mp4")) {
00289     trackmeta->filetype = LIBMTP_FILETYPE_MP4;
00290   } else if (!strcasecmp(pcodec,"wma") || !strcasecmp(pcodec,"asf")) {
00291     trackmeta->filetype = LIBMTP_FILETYPE_WMA;
00292   } else {
00293     printf("Not a valid codec: \"%s\"\n", pcodec);
00294     printf("Supported formats: MP3, WAV, OGG, MP4, WMA\n");
00295     exit(1);
00296   }
00297   printf("Codec:     %s\n", LIBMTP_Get_Filetype_Description(trackmeta->filetype));
00298   if (ptitle) {
00299     printf("Title:     %s\n", ptitle);
00300     trackmeta->title = strdup(ptitle);
00301   }
00302   if (palbum) {
00303     printf("Album:     %s\n", palbum);
00304     trackmeta->album = strdup(palbum);
00305   }
00306   if (partist) {
00307     printf("Artist:    %s\n", partist);
00308     trackmeta->artist = strdup(partist);
00309   }
00310   if (pgenre) {
00311     printf("Genre:     %s\n", pgenre);
00312     trackmeta->genre = strdup(pgenre);
00313   }
00314   if (year > 0) {
00315     char tmp[80];
00316     printf("Year:      %d\n", year);
00317     snprintf(tmp, sizeof(tmp)-1, "%4d0101T0000.0", year);
00318     tmp[sizeof(tmp)-1] = '\0';
00319     trackmeta->date = strdup(tmp);
00320   }
00321   if (tracknum > 0) {
00322     printf("Track no:  %d\n", tracknum);
00323     trackmeta->tracknumber = tracknum;
00324   }
00325   if (length > 0) {
00326     printf("Length:    %d\n", length);
00327     // Multiply by 1000 since this is in milliseconds
00328     trackmeta->duration = length * 1000;
00329   }
00330   if (pfolder != NULL && parent_id != 0) {
00331     printf("Folder:    %s (ID: %d)\n", pfolder, parent_id);
00332   }
00333   // We should always have this
00334   if (filename != NULL) {
00335     trackmeta->filename = strdup(filename);
00336   }
00337   trackmeta->filesize = filesize;
00338     
00339   device = LIBMTP_Get_First_Device();
00340   if (device == NULL) {
00341     printf("No MTP device found.\n");
00342     LIBMTP_destroy_track_t(trackmeta);
00343     exit(1);
00344   }
00345 
00346   // If a folder argument was passed in, try to locate the folder.
00347   if (pfolder) {
00348     folders = LIBMTP_Get_Folder_List(device);
00349     if(folders == NULL) {
00350       printf("No folders found, ignoring folder argument.\n");
00351     } else {
00352       parent_id = find_folder_list(pfolder, folders, 0);
00353       if  (!parent_id) {
00354         printf("Parent folder could not be found, ignoring folder argument.\n");
00355       }
00356     }
00357   }
00358   
00359   printf("Sending track...\n");
00360   ret = LIBMTP_Send_Track_From_File(device, path, trackmeta, progress, NULL, parent_id);
00361   printf("\n");
00362   
00363   LIBMTP_Release_Device(device);
00364   
00365   printf("New track ID: %d\n", trackmeta->item_id);
00366 
00367   LIBMTP_destroy_track_t(trackmeta);
00368   
00369   printf("OK.\n");
00370 
00371   return 0;
00372 }

Generated on Tue Sep 12 03:22:55 2006 for libmtp by  doxygen 1.4.7