#ifndef GLOBAL_DECL
#include "global.h" // Global data types and variables
#endif
#ifndef BROWSER_DECL
#include "browser.h"
#endif
#ifndef PLAYER_DECL
#include "player.h"
#endif
#ifndef PLAYLIST_DECL
#include "playlist.h"
#endif
#ifndef IR_DECL
#include "irc.h"
#endif
#include <stdarg.h>
#include <stdlib.h>
#include <time.h>
browser objBrowser; // Pointer to an instance of the browser class
player objPlayer; // Pointer to an instance of the player class
playlist objPlaylist; // Pointer to an instance of the playlist class
irc objIrc; // Pointer to an instance of the IR remote control class
int intMode = 1;
char *progname;
struct lirc_config *config;
char *code;
char *c;
int ret;
char ir_key[100];
int fd; /* File descriptor for the port */
void clean_up_child_process (int signal_number)
{
/* Clean up the child process. */
int status;
wait (&status);
if (objPlayer.intStopPressed == 1) // User has pressed stop, so stop
{
objPlayer.intStopPressed = 0;
objPlayer.is_playing = 0;
objPlayer.is_paused = 0;
}
else // Move to the next song in the playlist
{
if (objPlaylist.next(&objPlayer, 0) == 0)
{
// At the end of the playlist, so stop
objPlayer.is_playing = 0;
objPlayer.is_paused = 0;
}
}
}
void open_port(void)
{
fd = open("/dev/ttyS2", O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1)
{
perror("open_port: Unable to open /dev/ttyS2 - ");
}
else
fcntl(fd, F_SETFL, 0);
}
void send_text(char* strText, int intLineNo, int intPos)
{
char linesel[2];
int intLen;
char strTemp[50];
linesel[0] = 254;
if (intLineNo == 1)
{ linesel[1] = 128; }
else
{ linesel[1] = 192; }
write(fd, linesel, 2);
strncpy(strTemp, &strText[intPos], LCD_CHARACTERS + 1);
pad_space_to_eol(strTemp);
intLen = strlen(strTemp);
write(fd, strTemp, intLen);
#if OUTPUTDEBUG
// Simulate LCD output on standard output
// if (intLineNo == 1)
// { move(5, 5); }
// else
// { move(6, 5); }
printf("\n\n\n%s",strTemp);
//refresh();
#endif
}
void send_cls(void)
{
char clschars[2];
int n;
#if OUTPUTDEBUG
// Clear standard output also
//clear();
printf("\n\n\n\n\n\n\n\n\n\n\n\n\n");
#endif
clschars[0] = 254;
clschars[1] = 1;
write(fd, clschars, 2);
for (n=0;n<SCROLL_DELAY;n++);
}
void initialise(void)
{
char strText[100];
struct sigaction sigchld_action;
/* Set up signal handler to handle SIGCHLD by calling clean_up_child_process. */
memset (&sigchld_action, 0, sizeof (sigchld_action));
sigchld_action.sa_handler = &clean_up_child_process;
sigaction (SIGCHLD, &sigchld_action, NULL);
open_port();
send_cls();
strcpy(strText, " Welcome to Adam's ");
send_text(strText, 1, 0);
strcpy(strText, "--- mp3 machine! ---");
send_text(strText, 2, 0);
sleep(2);
// Debug info and on-screen prompts
printf("\n\n-----------------------------------------------------------------");
printf("\nmp3 Machine Initalised.\nHome directory: %s", HOME_DIR);
printf("\n-----------------------------------------------------------------");
printf("\nKeys:\nUP = Go up in menu or playlist\nDOWN = Go down in menu or playlist");
printf("\nLEFT = Go up a level in the hierarchy\nRIGHT = Enter a sub-directory or play an mp3");
printf("\n1 = Mode 1 - Song browsing mode\n2 = Mode 2 - Currently playing");
printf("\n3 = Mode 3 - Playlist editor\n4 = Mode 4 - Clock mode");
printf("\nS = Stop playback");
printf("\nP = Pause playback");
printf("\nE = Enqueue - add to end of playlist");
printf("\nQ = Shut down the computer");
printf("\nX = Exit application");
printf("\n-----------------------------------------------------------------\n\n");
}
int menu_loop(void)
{
char chrInputChar;
char chrIRChar;
int intScrollPos = 0;
int intDelayLoop = 0;
char strPath[400];
char strFile[400];
int return_code = 0;
intDelayLoop = PRE_SCROLL_DELAY;
objBrowser.update = 1;
objBrowser.display_menu(0);
do
{
if (intDelayLoop < 0)
{ intDelayLoop = SCROLL_DELAY; }
intDelayLoop--;
chrInputChar = '\0';
if (kbhit()) { chrInputChar = getch(); }
// Get IR inputs
chrIRChar = objIrc.get_key();
if (chrIRChar != 0) chrInputChar = chrIRChar;
return_code = common_keys(chrInputChar);
if (return_code != 0) { return(return_code); }
// Cursor keys = 27, 91 then LEFT=68, RIGHT=67, UP=65, DOWN=66
if (chrInputChar == 27) chrInputChar = getch();
if (chrInputChar == 91) chrInputChar = getch();
if (chrInputChar == 65) /* Go up in the menu */
{
objBrowser.go_up();
intScrollPos = 0;
intDelayLoop = PRE_SCROLL_DELAY;
}
if (chrInputChar == 66) /* Go down in the menu */
{
objBrowser.go_down();
intScrollPos = 0;
intDelayLoop = PRE_SCROLL_DELAY;
}
if (chrInputChar == 68) /* Go up a level */
{
objBrowser.leave_subdir();
intScrollPos = 0;
intDelayLoop = PRE_SCROLL_DELAY;
}
if (chrInputChar == 67) /* Enter a sub-directory, or play an mp3 */
{
if (objBrowser.is_directory()) // Enter directory
{
objBrowser.enter_subdir();
intScrollPos = 0;
intDelayLoop = PRE_SCROLL_DELAY;
}
else // Play mp3
{
objBrowser.get_path(strPath);
objBrowser.get_current(strFile);
objPlaylist.clear(); // Clear playlist
objPlaylist.add(strPath, strFile); // Add new song to playlist
objPlayer.play(strPath, strFile); // Play mp3
intMode = 2;
return(2); // switch to now playing mode
}
}
if (chrInputChar == 'e')
{
if (objBrowser.is_file())
{
objBrowser.get_path(strPath);
objBrowser.get_current(strFile);
objPlaylist.add(strPath, strFile); // Add new song to playlist
printf("\nEnqueued:\nPath = '%s'\nFile = '%s'\n", strPath, strFile);
}
}
if (intDelayLoop == 0) /* Scroll the bottom line of the display */
{
if (objBrowser.get_length() > (LCD_CHARACTERS + 4))
{
intScrollPos++;
if(intScrollPos >= objBrowser.get_length() - (LCD_CHARACTERS - 1) ) { intScrollPos = 0; }
objBrowser.update = 1;
}
}
// Update the display if necessary
objBrowser.display_menu(intScrollPos);
} while (chrInputChar != 'x');
return(-1);
}
int common_keys(char chrKey)
{
// Return: -1=exit, 0=do nothing, 1=dir menu, 2=playing, 3=play list
if (chrKey == 's') /* Stop playing */
{
if (objPlayer.is_playing == 1)
{
objPlayer.intStopPressed = 1;
objPlayer.stop();
intMode = 1;
return(1);
}
}
else if (chrKey == 'p') /* Pause playing */
{
if (objPlayer.is_playing == 1)
{
objPlayer.pause();
if (objPlayer.is_paused == 0)
{
if (intMode == 2) send_text("Paused...", 1, 0);
objPlayer.is_paused = 1;
}
else
{
if (intMode == 2) send_text("Now playing:", 1, 0);
objPlayer.is_paused = 0;
}
}
}
else if (chrKey == '.') // Go to next song in playlist
objPlaylist.next(&objPlayer, 1);
else if (chrKey == ',') // Go to previous song in playlist
objPlaylist.previous(&objPlayer, 1);
else if (chrKey == 'q') /* Shut the computer down */
{
popen("shutdown -h now", "w");
}
else if (chrKey == '1') { intMode = 1; objBrowser.update = 1; return(1); }
else if (chrKey == '2') { intMode = 2; return(2); }
else if (chrKey == '3') { intMode = 3; return(3); }
else if (chrKey == '4') { intMode = 4; return(4); }
#if USE_IR
#endif
return(0);
}
int play_loop(void)
{
char chrInputChar;
char chrIRChar;
// int intUpdate = 0;
int intScrollPos = 0;
int intDelayLoop = PRE_SCROLL_DELAY;
int return_code = 2;
char strTemp[255];
strTemp[0] = '\0';
if (objPlayer.is_paused == 1) send_text("Paused...", 1, 0);
else if (objPlayer.is_playing == 1) send_text("Now playing:", 1, 0);
else send_text("Stopped", 1, 0);
objPlayer.update = 1;
objPlayer.display_song(intScrollPos);
do
{
if (intDelayLoop < 0)
{ intDelayLoop = SCROLL_DELAY; }
intDelayLoop--;
chrInputChar = '\0';
if (kbhit()) { (unsigned)chrInputChar = getch(); }
// Get IR inputs
chrIRChar = objIrc.get_key();
if (chrIRChar != 0) chrInputChar = chrIRChar;
return_code = common_keys(chrInputChar);
if (return_code != 0) { return(return_code); }
if (intDelayLoop == 0) /* Scroll the bottom line of the display */
{
if (strlen(objPlaylist.current()) > (LCD_CHARACTERS + 4))
{
intScrollPos++;
if((unsigned)intScrollPos >= strlen(objPlaylist.current()) - (LCD_CHARACTERS - 1) ) { intScrollPos = 0; }
objPlayer.update = 1;
}
}
objPlayer.display_song(intScrollPos);
} while (chrInputChar != 'x');
return(-1);
}
int time_loop(void)
{
char chrInputChar;
char chrIRChar;
int intDelayLoop = 1;
int return_code = 4;
struct tm today;
time_t timTime;
char str[81];
do
{
if (intDelayLoop < 0)
{ intDelayLoop = (int)(SCROLL_DELAY / 2); }
intDelayLoop--;
chrInputChar = '\0';
if (kbhit()) { (unsigned)chrInputChar = getch(); }
// Get IR inputs
chrIRChar = objIrc.get_key();
if (chrIRChar != 0) chrInputChar = chrIRChar;
return_code = common_keys(chrInputChar);
if (return_code != 0) { return(return_code); }
if (intDelayLoop == 0) /* Update the display */
{
send_text("-Adam's MP3 Machine-", 1, 0);
timTime = time( NULL );
today = *localtime( &timTime );
strftime( str, sizeof(str)-1, " %I:%M:%S %p ", &today );
send_text(str, 2, 0);
}
} while (chrInputChar != 'x');
return(-1);
}
int list_loop(void)
{
char chrInputChar;
char chrIRChar;
int intUpdate = 0;
int intScroll = 0;
// char* strTemp;
// char strPath[100];
int intScrollPos = 0;
int intDelayLoop = PRE_SCROLL_DELAY;
// char strFname[250];
int return_code = 0;
// int intLine = 0;
objPlaylist.select_current();
objPlaylist.display(0);
do
{
intUpdate = 0; intScroll = 0;
if (intDelayLoop < 0)
{ intDelayLoop = SCROLL_DELAY; }
intDelayLoop--;
chrInputChar = '\0';
if (kbhit()) { chrInputChar = getch(); }
// Get IR inputs
chrIRChar = objIrc.get_key();
if (chrIRChar != 0) chrInputChar = chrIRChar;
return_code = common_keys(chrInputChar);
if (return_code != 0) { return(return_code); }
// Cursor keys = 27, 91 then LEFT=68, RIGHT=67, UP=65, DOWN=66
if (chrInputChar == 27) chrInputChar = getch();
if (chrInputChar == 91) chrInputChar = getch();
if (chrInputChar == 65) /* Go up in the menu */
{
objPlaylist.up();
intUpdate = 1;
intScrollPos = 0;
intDelayLoop = PRE_SCROLL_DELAY;
}
if (chrInputChar == 66) /* Go down in the menu */
{
objPlaylist.down();
intUpdate = 1;
intScrollPos = 0;
intDelayLoop = PRE_SCROLL_DELAY;
}
if (intDelayLoop == 0) /* Scroll the bottom line of the display */
{
if (strlen(objPlaylist.current_viewing()) > (LCD_CHARACTERS + 4))
{
intScrollPos++;
if((unsigned)intScrollPos >= strlen(objPlaylist.current_viewing()) - (LCD_CHARACTERS - 1) ) { intScrollPos = 0; }
intScroll = 1;
}
}
if((intUpdate == 1) || (intScroll == 1)) /* Refresh the display */
{
objPlaylist.display(intScrollPos);
}
} while (chrInputChar != 'x');
return(-1);
}
int main(void)
{
// intMode = -1=exit, 0=do nothing, 1=dir menu, 2=playing, 3=play list
int intReturnValue = 0;
initialise();
do
{
if (intMode == 1)
{ intReturnValue = menu_loop(); }
else if (intMode == 2)
{ intReturnValue = play_loop(); }
else if (intMode == 3)
{ intReturnValue = list_loop(); }
else if (intMode == 4)
{ intReturnValue = time_loop(); }
if (intReturnValue != 0) { intMode = intReturnValue; }
} while (intMode != -1);
send_cls();
objPlayer.killme();
close(fd);
#if USE_IR
lirc_freeconfig(config);
lirc_deinit();
#endif
return(0);
}
int pad_dash_to_eol(char* strText)
{
int n;
for(n=strlen(strText); n<(LCD_CHARACTERS + 4); n++)
{
strcat(strText, "-");
}
return(0);
}
int pad_space_to_eol(char* strText)
{
int n;
if (strlen(strText) < (LCD_CHARACTERS + 4))
{
for(n=strlen(strText); n<(LCD_CHARACTERS + 4); n++)
{
strcat(strText, " ");
}
}
return(0);
}
int is_mp3(char* strFname)
{
char* ext;
if (strlen(strFname) > 4)
{
ext = &strFname[strlen(strFname)-4];
if (strcasecmp(ext, ".mp3") == 0)
{
return 1;
}
else
{
return 0;
}
}
else
{
return 0;
}
}
int kbhit(void)
{
struct termios term, oterm;
int fd = 0;
int c = 0;
/* get the terminal settings */
tcgetattr(fd, &oterm);
/* get a copy of the settings, which we modify */
memcpy(&term, &oterm, sizeof(term));
/* put the terminal in non-canonical mode, any
reads timeout after 0.1 seconds or when a
single character is read */
term.c_lflag = term.c_lflag & (!ICANON);
term.c_cc[VMIN] = 0;
term.c_cc[VTIME] = 1;
tcsetattr(fd, TCSANOW, &term);
/* get input - timeout after 0.1 seconds or
when one character is read. If timed out
getchar() returns -1, otherwise it returns
the character */
c=getchar();
/* reset the terminal to original state */
tcsetattr(fd, TCSANOW, &oterm);
/* if we retrieved a character, put it back on
the input stream */
if (c != -1)
ungetc(c, stdin);
/* return 1 if the keyboard was hit, or 0 if it
was not hit */
return ((c!=-1)?1:0);
}
/********************************************************/
int getch()
{
int c, fd=0;
struct termios term, oterm;
/* get the terminal settings */
tcgetattr(fd, &oterm);
/* get a copy of the settings, which we modify */
memcpy(&term, &oterm, sizeof(term));
/* put the terminal in non-canonical mode, any
reads will wait until a character has been
pressed. This function will not time out */
term.c_lflag = term.c_lflag & (!ICANON);
term.c_cc[VMIN] = 1;
term.c_cc[VTIME] = 0;
tcsetattr(fd, TCSANOW, &term);
/* get a character. c is the character */
c=getchar();
/* reset the terminal to its original state */
tcsetattr(fd, TCSANOW, &oterm);
/* return the charcter */
return c;
}
syntax highlighted by Code2HTML, v. 0.9.1