Advertisement
Lyude

Incomplete XChat NP module for MPD

Mar 6th, 2012
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.66 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <errno.h>
  5. #include <string.h>
  6. #include <sys/stat.h>
  7. #include <libconfig.h>
  8.  
  9. //For getaddrinfo
  10. #include <sys/types.h>
  11. #include <sys/socket.h>
  12. #include <netdb.h>
  13.  
  14. #include <xchat/xchat-plugin.h>
  15.  
  16. #define PNAME "XChat MPD"
  17. #define PDESC "XChat MPD now playing plugin"
  18. #define PVERSION "0.1"
  19.  
  20. static xchat_plugin *ph;            //Plugin handle
  21.  
  22. static FILE * configfile;           //Pointer to config file
  23. static config_t config;             //Config struct for libconfig
  24. static config_setting_t * hostname; //Pointer to hostname in config
  25. static config_setting_t * port;     //Pointer to port in config
  26.  
  27. //Function for /set command
  28. static int set_setting_mpd_np(char * word[]) {
  29.     //If no setting is specified, simply print the current settings
  30.     if (word[2] == NULL) {
  31.         xchat_printf(ph, "Hostname: %s\n", config_setting_get_string(hostname));
  32.         xchat_printf(ph, "Port: %s\n", config_setting_get_string(port));
  33.     }
  34.  
  35.     if (strcasecmp(word[2], "HOSTNAME") == 0) {
  36.         //Set new value for hostname, then dump to file
  37.         config_setting_set_string(hostname, word[3]);
  38.         config_write(&config, configfile);
  39.     }
  40.    
  41.     else if (strcasecmp(word[2], "PORT") == 0) {
  42.         //Set new value for hostname, then dump to file
  43.         config_setting_set_string(port, word[3]);
  44.         config_write(&config, configfile);
  45.     }
  46.  
  47.     //Unknown setting! Return error
  48.     else {
  49.         xchat_printf(ph, "%s is not a valid setting\n", word[2]);
  50.     }
  51.     return XCHAT_EAT_ALL;
  52. }
  53.  
  54. static int mpd_np_show() {
  55.     //Structs for getaddrinfo
  56.     struct addrinfo hints;
  57.     struct addrinfo * results;
  58.    
  59.     int _socket;
  60.  
  61.     char buf[4096]; //Input buffer
  62.  
  63.     //Clear out the garbage from the hints structure
  64.     memset(&hints, 0, sizeof(struct addrinfo));
  65.     hints.ai_family = AF_UNSPEC;    //Allow IPv4 or 6
  66.     hints.ai_socktype = SOCK_DGRAM; //Datagram socket
  67.     hints.ai_flags = 0;
  68.     hints.ai_protocol = 0;          //Any protocol
  69.  
  70.     //If getaddrinfo fails to get the list of address structures, print a message
  71.     int s = getaddrinfo(config_setting_get_string(hostname), config_setting_get_string(port),
  72.                         &hints, &results);
  73.     if (s != 0) xchat_printf(ph, "ERROR: Could not connect (%s)\n", gai_strerror(s));
  74.  
  75.     //Try connecting to all the address structures returned by getaddrinfo
  76.     struct addrinfo * cs; //The current structure we're on
  77.     for (cs = results; cs != NULL; cs = cs->ai_next) {
  78.         _socket = socket(cs->ai_family, cs->ai_socktype, cs->ai_protocol);
  79.  
  80.         if (_socket == -1)
  81.             continue;
  82.  
  83.         if (connect(_socket, cs->ai_addr, cs->ai_addrlen) != -1)
  84.             break;
  85.  
  86.         close(_socket);
  87.     }
  88.  
  89.     //If none of the addresses worked
  90.     if (cs == NULL) {
  91.         xchat_print(ph, "Could not connect to MPD\n");
  92.         return XCHAT_EAT_ALL;
  93.     }
  94.  
  95.     freeaddrinfo(results); //Not needed now
  96.  
  97.     //Receive MPD's welcome message
  98.     recv(_socket, &buf, 4096, 0);
  99.    
  100.     //Ask MPD for information on the current song
  101.     send(_socket, "currentsong", sizeof("currentsong"), 0);
  102.  
  103.     //Receive and parse song info
  104.     recv(_socket, &buf, 4096, 0);
  105.  
  106.     //Find the beggining of the artist tag, along with the end of the line it's on
  107.     char * artistinfo_beg = strstr(buf, "Artist: ") + sizeof("Artist: ");
  108.     char * artistinfo_end = strstr(artistinfo_beg, "\n");
  109.     size_t artistinfo_len = artistinfo_end - artistinfo_beg;
  110.  
  111.     //Copy the artist info to a string
  112.     char * artistinfo = malloc(artistinfo_len + 1); //Add 1 to account for '\0'
  113.     strncpy(artistinfo, artistinfo_beg, artistinfo_len);
  114.    
  115.     xchat_commandf(ph, "say Artist: %s", artistinfo);
  116.     free(artistinfo);
  117.     return XCHAT_EAT_ALL;
  118. }
  119.  
  120. void xchat_plugin_get_info(char **name, char **desc, char **version, void **reserved)
  121. {
  122.    *name = PNAME;
  123.    *desc = PDESC;
  124.    *version = PVERSION;
  125. }
  126.  
  127. int xchat_plugin_init(xchat_plugin *plugin_handle,
  128.                         char **plugin_name,
  129.                         char **plugin_desc,
  130.                         char **plugin_version,
  131.                         char **arg)
  132. {
  133.     ph = plugin_handle; //Needed for use with any xchat_ functions
  134.  
  135.     //Tell XChat our info
  136.     *plugin_name = PNAME;
  137.     *plugin_desc = PDESC;
  138.     *plugin_version = PVERSION;
  139.  
  140.     //Make sure ~/.config exists and is a directory
  141.     struct stat *stat_s;
  142.     if (stat("~/.config/", stat_s) != 0) {
  143.         if (errno == ENOENT)
  144.             mkdir("~/.config", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
  145.         else {
  146.             xchat_printf(ph, "%s\n", strerror(errno));
  147.             return 0;
  148.         }
  149.     }
  150.    
  151.     //Initialize config structure
  152.     config_init(&config);
  153.  
  154.     //Make sure ~/.config/xchat.mpd exists, if not create it and use default config
  155.     if (stat("~/.config/xchatmpd.conf", stat_s) != 0) {
  156.         if (errno == ENOENT) {
  157.             //Create file
  158.             configfile = fopen("~/.config/xchatmpd.conf", "w+");
  159.  
  160.             //Add hostname and port settings
  161.             hostname = config_setting_add(config_root_setting(&config), "HOSTNAME", 4);
  162.             port = config_setting_add(config_root_setting(&config), "PORT", 4);
  163.            
  164.             //Set value of new settings
  165.             config_setting_set_string(hostname, "localhost");
  166.             config_setting_set_string(port, "6600");
  167.  
  168.             //Dump settings into config file
  169.             config_write(&config, configfile);
  170.         }
  171.         else {
  172.             xchat_printf(ph, "%s\n", strerror(errno));
  173.             return 0;
  174.         }
  175.     }
  176.     else {
  177.         //Open config file and retrieve settings
  178.         configfile = fopen("~/.config/xchatmpd.conf", "w+");
  179.         config_read(&config, configfile);
  180.  
  181.         //Set hostname and port pointers
  182.         hostname = config_lookup(&config, "HOSTNAME");
  183.         port = config_lookup(&config, "PORT");
  184.     }
  185.  
  186.     //Now hook the commands
  187.     xchat_hook_command(ph, "NP", XCHAT_PRI_NORM, mpd_np_show,
  188.                     "Usage: NP Shows the song currently playing in MPD", NULL);
  189.     xchat_hook_command(ph, "NP_SET", XCHAT_PRI_NORM, set_setting_mpd_np,
  190.                     "Usage: NP_SET <setting> <new value> Changes setting's value to a new value.", NULL);
  191.     xchat_print(ph, "X-Chat MPD Loaded!\n");
  192.     return 1;
  193. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement