/* argv[1] = adresse ip serveur argv[2] = nom du fichier audio argv[3] = éventuel filtre à appliquer */ int main(int argc, char const *argv[]) { struct sigaction arretSig; arretSig.sa_handler = arretClient; sigemptyset (&arretSig.sa_mask); arretSig.sa_flags = 0; sigaction(SIGINT, &arretSig, NULL); int rate, size, channels; int speaker; int lectureWav = -1; char buf[R_tailleMaxData]; if (argc < 3){ printf("nombre d'argument invalide %d\n",argc); exit(1); } char * adresseServ = (char *) argv[1]; char * fichierARecup = (char *) argv[2]; /* initialisation du client: ouverture d'une socket initialisation des variable du client */ if(initClient(&cl, adresseServ, AC_portServ)< 0){ exit(1); } /* demande de connexion auprès du serveur : envois d'une requête R_demandeCo */ if(demandeDeConnexion(&cl) < 0){ exit(2); }else{ /* demande au serveur s'il possède le fichier demander */ if(demanderFichierAudio(&cl,fichierARecup, &rate, &size, &channels)<0){ fermerConnexion(&cl); exit(3); } speaker = aud_writeinit(rate, size, channels); if (speaker < 0){ fermerConnexion(&cl); exit(4); } printf("Lecture du fichier son ...\n"); do{ /* lecture fichier */ lectureWav = partieSuivante(&cl, buf); if (lectureWav == -1){ /* fin fichier */ }else if (lectureWav < -1){ /* autre erreur */ fermerConnexion(&cl); exit(5); }else{ if(write(speaker, buf, lectureWav)<0){ perror("Erreur ecriture dans speaker"); fermerConnexion(&cl); exit(6); } } } while (lectureWav >=0); /* Fermeture de connexion : envois d'une requète R_fermerCo au serveur libère la mémoire alloué pour l'objet client */ fermerConnexion(&cl); } return 0; }
int main(int argc, char **argv) { char BUFFER[BUFFER_SIZE]; if(argc != 2){ printf("1 argument needed\n"); exit(1); } int fdaudio; int fdoutput; char* filename; int sample_rate; int sample_size; int channels; filename = argv[1]; fdaudio = aud_readinit(filename, &sample_rate, &sample_size, &channels); if(fdaudio < 0){ perror("Error aud_readinit"); exit(1); } fdoutput = aud_writeinit(sample_rate, sample_size, channels); if(fdoutput < 0){ perror("Error aud_writeinit"); exit(1); } int read_size; read_size = read(fdaudio, BUFFER, BUFFER_SIZE); if(read_size < 0){ perror("Error read"); exit(1); } int write_size; while(read_size == BUFFER_SIZE) { write_size = write(fdoutput, BUFFER, BUFFER_SIZE); bzero(BUFFER, BUFFER_SIZE); if(write_size < 0){ perror("Error write"); exit(1); } read_size = read(fdaudio, BUFFER, BUFFER_SIZE); if(read_size < 0){ perror("Error read"); exit(1); } } write_size = write(fdoutput, BUFFER, BUFFER_SIZE); if(write_size < 0){ perror("Error write"); exit(1); } close(fdaudio); close(fdoutput); return 0; }
/** * The main program * * Parameters: * - int argc => The number of arguments passed * - char** args => The arguments list * * Return: * - int => The result of the execution */ int main(int argc, char** args) { /* ##### Process parameters and get filter ##### */ int filter = process_params(argc, args); /* ##### Network structures ##### */ // Initialize the client socket struct sockaddr_in destination; int client_socket = init_socket(args[1], &destination); // Parameters for the packet transmission struct packet to_server; struct packet from_server; socklen_t destination_length = (socklen_t)sizeof(struct sockaddr); /* ##### Audio reader parameters ##### */ // Some more variables that we'll need for reading audio files int sample_rate, sample_size, channels; int write_init_audio = 0; /* ##### Timeout parameters ##### */ int nb; fd_set watch_over; struct timeval timeout; /* ##### Filter parameters ##### */ // For volume filter int volume_value; // For echo filter int nb_buffers_per_echo = 0, nb_samples_per_buffer, current_buffer_position, to_read_position; char* echo_buffer; char volume_buffer[BUFFER_SIZE]; /* ################################################## Sending the filename ################################################## */ // The first packet to send is the filename create_packet(&to_server, P_FILENAME, args[2]); // Send the packet containing the filename if (sendto(client_socket, &to_server, sizeof(struct packet), 0, (struct sockaddr*)&destination, destination_length) == -1) { perror("Error during the sending of the filename packet"); return 1; } /* ################################################## Talk with the server ################################################## */ do { // Clear and reinitialize the fd set FD_ZERO(&watch_over); FD_SET(client_socket, &watch_over); timeout.tv_sec = 0; timeout.tv_usec = TIMEOUT_CLIENT; // 200ms nb = select(client_socket+1, &watch_over, NULL, NULL, &timeout); // Clear packets clear_packet(&to_server); clear_packet(&from_server); // If error during the select if (nb < 0) { perror("Can't attach the select to the file descriptor"); return 1; } // Just request the same packet if timeout reached if (nb == 0) { to_server.type = P_REQ_SAME_PACKET; if (sendto(client_socket, &to_server, sizeof(struct packet), 0, (struct sockaddr*)&destination, destination_length) == -1) { perror("Can't request same packet"); return 1; } } // If open, just act normally if (FD_ISSET(client_socket, &watch_over)) { // Wait a packet if (recvfrom(client_socket, &from_server, sizeof(struct packet), 0, (struct sockaddr*)&destination, &destination_length) != -1) { // In function of the type of the packet received switch (from_server.type) { // --------------- An server error happened on the server --------------- case P_ERR_TRANSMISSION: case P_SERVER_ERROR: // Display the error printf("%s\n", from_server.message); // Close connection close_connection(client_socket, "Closing due to server error", 0); break; // --------------- The first response from the server is received --------------- case P_FILE_HEADER: // Get the informations about the audio file sample_rate = *((int*)(from_server.message)); sample_size = *((int*)(from_server.message + BUFFER_SPACE)); channels = *((int*)(from_server.message + 2*BUFFER_SPACE)); // ----- Filters initialisation ----- switch (filter) { // If none do nothing case F_NONE: break; // If mono, just force the channel to one case F_MONO: channels = 1; break; // If volume, get the value of the filter parameter case F_VOLUME: volume_value = atoi(args[4]); nb_samples_per_buffer = BUFFER_SIZE/(sample_size/8); break; // If echo, allocate the echo buffer case F_ECHO: // Calculate the number of bytes needed for one second nb_buffers_per_echo = (ECHO_IN_SCDS * sample_rate * (sample_size/8)) / BUFFER_SIZE; // Allocate the table of buffers echo_buffer = malloc(nb_buffers_per_echo * BUFFER_SIZE); // The buffer position and the buffer to read put to 0 current_buffer_position = 0; to_read_position = 0; break; // If speed case F_SPEED: // Multiply the framerate sample_rate = sample_rate * atoi(args[4]); break; // If unknown default: close_connection(client_socket, "Unknown filter", write_init_audio); break; } // Initialize the write end write_init_audio = aud_writeinit(sample_rate, sample_size, channels); // If an error happened if (write_init_audio < 1) { // If echo filter, free the buffer if (filter == F_ECHO) free(echo_buffer); // Close the connection close_connection(client_socket, "Error at getting the audio output device", 0); } // If everything's ok, request the first block clear_packet(&to_server); to_server.type = P_REQ_NEXT_BLOCK; // Send the request if (sendto(client_socket, &to_server, sizeof(struct packet), 0, (struct sockaddr*)&destination, destination_length) == -1) { // If echo filter, free the buffer if (filter == F_ECHO) free(echo_buffer); // Close the connection close_connection(client_socket, "Error at requesting the first block", write_init_audio); } break; // --------------- A block is received, read it --------------- case P_BLOCK: // Read the music on the audio output (in function of the filter passed) switch (filter) { // If none, mono or speed case F_NONE: case F_MONO: case F_SPEED: if (write(write_init_audio, from_server.message, BUFFER_SIZE) == -1) close_connection(client_socket, "Error at writing a block on audio output", write_init_audio); break; // If echo case F_ECHO: // Read the content of the buffer received if (write(write_init_audio, from_server.message, BUFFER_SIZE) == -1) { // Echo filter so free the buffer free(echo_buffer); // Close connection close_connection(client_socket, "Error at writing a block on audio output", write_init_audio); } // Then put this buffer into the echo buffer if the buffer isn't full if (current_buffer_position < nb_buffers_per_echo) { memcpy((echo_buffer + current_buffer_position*BUFFER_SIZE), from_server.message, BUFFER_SIZE); ++current_buffer_position; } // If the echo buffer is full else { // Read the current buffer position if (write(write_init_audio, (echo_buffer + to_read_position*BUFFER_SIZE), BUFFER_SIZE) == -1) { // Echo filter so free the buffer free(echo_buffer); // Close connection close_connection(client_socket, "Error at writing an echo block on audio output", write_init_audio); } // And replace it with the new one memcpy((echo_buffer + to_read_position*BUFFER_SIZE), from_server.message, BUFFER_SIZE); // Increment the flag to_read_position = (to_read_position+1)%nb_buffers_per_echo; } break; // If upper or lower volume case F_VOLUME: // Clear the temporary buffer memset(volume_buffer, 0, BUFFER_SIZE); // Variables used in the loop int i; // The increment var and a temporary value int tmp; // Temporary var // Get each sample and multiply its value for (i = 0; i < nb_samples_per_buffer; ++i) { // Multiply the value of the sample, get a double value tmp = *((int*)(from_server.message + i*sizeof(int))) * volume_value; // Then store it in the temporary buffer *((int*)(volume_buffer + i*sizeof(int))) = tmp; } // And in the end, read the whole buffer if (write(write_init_audio, volume_buffer, BUFFER_SIZE) == -1) close_connection(client_socket, "Error at writing a volume changed block on audio output", write_init_audio); break; // If an unknown filter, error! default: close_connection(client_socket, "Filter passed unknown", write_init_audio); break; } // End of filter's switch // If everything's ok, request the next block clear_packet(&to_server); to_server.type = P_REQ_NEXT_BLOCK; // Send the request if (sendto(client_socket, &to_server, sizeof(struct packet), 0, (struct sockaddr*)&destination, destination_length) == -1) { // If echo filter, free the buffer if (filter == F_ECHO) free(echo_buffer); // Close connection close_connection(client_socket, "Error at requesting a block", write_init_audio); } break; // --------------- The last block is received, read it --------------- case P_EOF: // Read the music on the audio output (in function of the filter passed) switch (filter) { // If none, mono or speed case F_NONE: case F_MONO: case F_SPEED: if (write(write_init_audio, from_server.message, BUFFER_SIZE) == -1) close_connection(client_socket, "Error at writing a block on audio output", write_init_audio); break; // If echo case F_ECHO: // Read the content of the buffer received if (write(write_init_audio, from_server.message, BUFFER_SIZE) == -1) { // Echo filter so free the buffer free(echo_buffer); // Close connection close_connection(client_socket, "Error at writing a block on audio output", write_init_audio); } // And in the end, just read the whole echo buffer left if (write(write_init_audio, (echo_buffer + to_read_position*BUFFER_SIZE), ((current_buffer_position - to_read_position)*BUFFER_SIZE)) == -1) { // Echo filter so free the buffer free(echo_buffer); // Close connection close_connection(client_socket, "Error at writing the last echo block on audio output", write_init_audio); } // Free the echo_buffer in the end free(echo_buffer); break; // If upper or lower volume case F_VOLUME: // Clear the temporary buffer memset(volume_buffer, 0, BUFFER_SIZE); // Variables used in the loop int i; // The increment var and a temporary value int tmp; // Temporary var // Get each sample and multiply its value for (i = 0; i < nb_samples_per_buffer; ++i) { // Multiply the value of the sample, get a double value tmp = *((int*)(from_server.message + i*sizeof(int))) * volume_value; // Then store it in the temporary buffer *((int*)(volume_buffer + i*sizeof(int))) = tmp; } // And in the end, read the whole buffer if (write(write_init_audio, volume_buffer, BUFFER_SIZE) == -1) close_connection(client_socket, "Error at writing a volume changed block on audio output", write_init_audio); break; // If an unknown filter, error! default: close_connection(client_socket, "Filter passed unknown", write_init_audio); break; } // If everything's ok, send the last packet clear_packet(&to_server); // Close the connection close_connection(client_socket, "The file was correctly read, close the connection, bye", write_init_audio); break; // --------------- Unknown type --------------- default: close_connection(client_socket, "Packet type unknown", write_init_audio); break; } } } // If an error during the receiving of a packet else { // If echo filter, free the buffer (only if it has been initialized) if ((filter == F_ECHO) && (nb_buffers_per_echo > 0)) free(echo_buffer); // Close connection perror("Error during the receiving of a packet, the server may be busy"); return 0; } } while (from_server.type != P_CLOSE_TRANSMISSION); // Close the connection close_connection(client_socket, "The reading is done, close connection now", write_init_audio); // If everything's was ok (but the server is normally just waiting for clients) return 0; }